1 diff --git a/libetc.c b/libetc.c
2 index 79ba1ae..57041b7 100644
6 #include <sys/socket.h>
13 @@ -79,11 +80,11 @@ static int (*orig_mkstemp64) (char *template);
15 static char *ETCDIR = ".config";
16 static char *orig, *home, *etcdir;
17 -static int started = 0;
18 -static int blacklisted = 0;
19 +static int do_translate = 0;
20 +static int prefix_size = 0;
22 // is the running exec blacklisted ?
23 -static void am_i_blacklisted () {
24 +static int am_i_blacklisted () {
25 char running_exec[4096], *exec_blacklist, *str;
28 @@ -94,18 +95,20 @@ static void am_i_blacklisted () {
29 PRINT_DEBUG ("blacklist: %s\n", exec_blacklist);
30 while ((str = strrchr (exec_blacklist, ':'))) {
31 if (0 == strcmp (++str, running_exec)) {
33 PRINT_DEBUG ("I am blacklisted !\n");
39 if (0 == strcmp (exec_blacklist, running_exec)) {
41 PRINT_DEBUG ("I am blacklisted !\n");
50 // find where to put the dotfiles
51 @@ -170,10 +173,7 @@ static void xauthority_hack (const char* etcdir) {
54 // called only once on program startup
55 -static void start_up () {
56 - if (LIKELY (started))
59 +static void __attribute__ ((constructor)) start_up () {
60 orig_fopen = dlsym (RTLD_NEXT, "fopen");
61 orig_fopen64 = dlsym (RTLD_NEXT, "fopen64");
62 orig_freopen = dlsym (RTLD_NEXT, "freopen");
63 @@ -211,13 +211,12 @@ static void start_up () {
64 orig_mkstemp = dlsym (RTLD_NEXT, "mkstemp");
65 orig_mkstemp64 = dlsym (RTLD_NEXT, "mkstemp64");
67 - am_i_blacklisted ();
68 + if (am_i_blacklisted ())
71 home = getenv ("HOME");
78 orig = malloc (strlen (home) + 3);
79 sprintf (orig, "%s/.", home);
80 @@ -229,20 +228,22 @@ static void start_up () {
83 PRINT_DEBUG("etcdir: %s\n", etcdir);
85 + prefix_size = strlen (etcdir);
89 // rename filename if it's a dotfile in $HOME
90 -static char *translate (const char *filename) {
91 - char *wd, *newfilename;
93 - if (UNLIKELY (!started)) start_up();
94 - if (UNLIKELY (home == NULL)) return strdup (filename);
95 - if (UNLIKELY (blacklisted)) return strdup (filename);
96 +static void translate (const char *filename, char *newfilename, const char **dest) {
101 + if (UNLIKELY (do_translate == 0)) return;
103 if (UNLIKELY (!filename)) {
104 PRINT_DEBUG("Filename is NULL !\n");
110 wd = get_current_dir_name ();
111 @@ -254,85 +255,80 @@ static char *translate (const char *filename) {
112 && (0 != strncmp (filename, "..", 2))) {
113 char tmpfilename [strlen (home) + strlen (filename) + 2];
114 sprintf (tmpfilename, "%s/%s", home, filename);
115 - if (0 == strncmp (tmpfilename, etcdir, strlen(etcdir))) { // do not translate if trying to read/write in $XDG_CONFIG_HOME
116 - newfilename = strdup (filename);
118 + if (0 != strncmp (tmpfilename, etcdir, strlen(etcdir))) { // do not translate if trying to read/write in $XDG_CONFIG_HOME
119 filename++; // remove the dot
120 - newfilename = malloc (strlen (filename) + strlen (etcdir) + 2);
121 sprintf (newfilename, "%s/%s", etcdir, filename);
122 + *dest = newfilename;
123 PRINT_DEBUG("RENAMED IN $HOME --> %s\n", newfilename);
125 } else if (0 == strncmp (filename, orig, strlen (orig)) // if file name is $HOME/.something
126 && 0!= strncmp (filename, etcdir, strlen (etcdir)) ) { // do not translate if trying to read/write in $XDG_CONFIG_HOME
127 filename += strlen (home) + 2; // remove "$HOME/." from the filename
128 - newfilename = malloc (strlen (filename) + strlen (etcdir) + 2);
129 sprintf (newfilename, "%s/%s", etcdir, filename);
130 + *dest = newfilename;
131 PRINT_DEBUG("RENAMED --> %s\n", newfilename);
132 - } else { // not a dotfile
133 - newfilename = strdup (filename);
137 - return newfilename;
140 -#define REWRITE_FUNCTION_SIMPLE(return_type, function_name, signature, orig_call) \
141 +#define REWRITE_FUNCTION_SIMPLE(return_type, function_name, signature, orig_call, error_return) \
142 return_type function_name signature { \
143 - return_type return_value; \
145 + char *rewritten_path; \
146 + const char *new_path; \
148 PRINT_DEBUG(#function_name ": %s\n", path); \
150 - new_path = translate (path); \
151 - return_value = orig_##function_name orig_call; \
153 - return return_value; \
154 + if (UNLIKELY (orig_##function_name == NULL)) return error_return; \
155 + rewritten_path = alloca (prefix_size + strlen (path) + 2); \
156 + translate (path, rewritten_path, &new_path); \
157 + return orig_##function_name orig_call; \
159 //#define NPATH NEWPATH(new_path, path)
161 -REWRITE_FUNCTION_SIMPLE(FILE*, fopen, (const char *path, const char *mode), (new_path, mode))
162 -REWRITE_FUNCTION_SIMPLE(FILE*, fopen64, (const char *path, const char *mode), (new_path, mode))
163 -REWRITE_FUNCTION_SIMPLE(FILE*, freopen, (const char *path, const char *mode, FILE *stream), (new_path, mode, stream))
164 -REWRITE_FUNCTION_SIMPLE(FILE*, freopen64, (const char *path, const char *mode, FILE *stream), (new_path, mode, stream))
165 -REWRITE_FUNCTION_SIMPLE(int, open, (const char *path, int flags, mode_t mode), (new_path, flags, mode))
166 -REWRITE_FUNCTION_SIMPLE(int, open64, (const char *path, int flags, mode_t mode), (new_path, flags, mode))
167 -REWRITE_FUNCTION_SIMPLE(int, mkdir, (const char *path, mode_t mode), (new_path, mode))
168 -REWRITE_FUNCTION_SIMPLE(int, unlink, (const char *path), (new_path))
169 -REWRITE_FUNCTION_SIMPLE(int, remove, (const char *path), (new_path))
170 -REWRITE_FUNCTION_SIMPLE(DIR*, opendir, (const char *path), (new_path))
171 -REWRITE_FUNCTION_SIMPLE(int, chdir, (const char *path), (new_path))
172 -REWRITE_FUNCTION_SIMPLE(int, __xstat, (int ver, const char *path, struct stat *buf), (ver, new_path, buf))
173 -REWRITE_FUNCTION_SIMPLE(int, __xstat64, (int ver, const char *path, struct stat64 *buf), (ver, new_path, buf))
174 -REWRITE_FUNCTION_SIMPLE(int, __lxstat, (int ver, const char *path, struct stat *buf), (ver, new_path, buf))
175 -REWRITE_FUNCTION_SIMPLE(int, __lxstat64, (int ver, const char *path, struct stat64 *buf), (ver, new_path, buf))
176 -REWRITE_FUNCTION_SIMPLE(int, access, (const char *path, int mode), (new_path, mode))
177 -REWRITE_FUNCTION_SIMPLE(int, chmod, (const char *path, mode_t mode), (new_path, mode))
178 -REWRITE_FUNCTION_SIMPLE(int, chown, (const char *path, uid_t owner, gid_t group), (new_path, owner, group))
179 -REWRITE_FUNCTION_SIMPLE(int, lchown, (const char *path, uid_t owner, gid_t group), (new_path, owner, group))
180 -REWRITE_FUNCTION_SIMPLE(int, utime, (const char *path, struct utimbuf *buf), (new_path, buf))
181 -REWRITE_FUNCTION_SIMPLE(int, utimes, (const char *path, struct timeval *tvp), (new_path, tvp))
182 -REWRITE_FUNCTION_SIMPLE(int, truncate, (const char *path, off_t length), (new_path, length))
183 -REWRITE_FUNCTION_SIMPLE(int, truncate64, (const char *path, off_t length), (new_path, length))
184 -REWRITE_FUNCTION_SIMPLE(int, __xmknod, (int ver, const char *path, mode_t mode, dev_t dev), (ver, new_path, mode, dev))
185 -REWRITE_FUNCTION_SIMPLE(int, mkfifo, (const char *path, mode_t mode), (new_path, mode))
186 -REWRITE_FUNCTION_SIMPLE(int, creat, (const char *path, mode_t mode), (new_path, mode))
187 -REWRITE_FUNCTION_SIMPLE(int, creat64, (const char *path, mode_t mode), (new_path, mode))
188 -REWRITE_FUNCTION_SIMPLE(int, readlink, (const char *path, char *buf, size_t bufsize), (new_path, buf, bufsize))
189 -REWRITE_FUNCTION_SIMPLE(int, rmdir, (const char *path), (new_path))
190 +REWRITE_FUNCTION_SIMPLE(FILE*, fopen, (const char *path, const char *mode), (new_path, mode), NULL)
191 +REWRITE_FUNCTION_SIMPLE(FILE*, fopen64, (const char *path, const char *mode), (new_path, mode), NULL)
192 +REWRITE_FUNCTION_SIMPLE(FILE*, freopen, (const char *path, const char *mode, FILE *stream), (new_path, mode, stream), NULL)
193 +REWRITE_FUNCTION_SIMPLE(FILE*, freopen64, (const char *path, const char *mode, FILE *stream), (new_path, mode, stream), NULL)
194 +REWRITE_FUNCTION_SIMPLE(int, open, (const char *path, int flags, mode_t mode), (new_path, flags, mode), -1)
195 +REWRITE_FUNCTION_SIMPLE(int, open64, (const char *path, int flags, mode_t mode), (new_path, flags, mode), -1)
196 +REWRITE_FUNCTION_SIMPLE(int, mkdir, (const char *path, mode_t mode), (new_path, mode), -1)
197 +REWRITE_FUNCTION_SIMPLE(int, unlink, (const char *path), (new_path), -1)
198 +REWRITE_FUNCTION_SIMPLE(int, remove, (const char *path), (new_path), -1)
199 +REWRITE_FUNCTION_SIMPLE(DIR*, opendir, (const char *path), (new_path), NULL)
200 +REWRITE_FUNCTION_SIMPLE(int, chdir, (const char *path), (new_path), -1)
201 +REWRITE_FUNCTION_SIMPLE(int, __xstat, (int ver, const char *path, struct stat *buf), (ver, new_path, buf), -1)
202 +REWRITE_FUNCTION_SIMPLE(int, __xstat64, (int ver, const char *path, struct stat64 *buf), (ver, new_path, buf), -1)
203 +REWRITE_FUNCTION_SIMPLE(int, __lxstat, (int ver, const char *path, struct stat *buf), (ver, new_path, buf), -1)
204 +REWRITE_FUNCTION_SIMPLE(int, __lxstat64, (int ver, const char *path, struct stat64 *buf), (ver, new_path, buf), -1)
205 +REWRITE_FUNCTION_SIMPLE(int, access, (const char *path, int mode), (new_path, mode), -1)
206 +REWRITE_FUNCTION_SIMPLE(int, chmod, (const char *path, mode_t mode), (new_path, mode), -1)
207 +REWRITE_FUNCTION_SIMPLE(int, chown, (const char *path, uid_t owner, gid_t group), (new_path, owner, group), -1)
208 +REWRITE_FUNCTION_SIMPLE(int, lchown, (const char *path, uid_t owner, gid_t group), (new_path, owner, group), -1)
209 +REWRITE_FUNCTION_SIMPLE(int, utime, (const char *path, struct utimbuf *buf), (new_path, buf), -1)
210 +REWRITE_FUNCTION_SIMPLE(int, utimes, (const char *path, struct timeval *tvp), (new_path, tvp), -1)
211 +REWRITE_FUNCTION_SIMPLE(int, truncate, (const char *path, off_t length), (new_path, length), -1)
212 +REWRITE_FUNCTION_SIMPLE(int, truncate64, (const char *path, off_t length), (new_path, length), -1)
213 +REWRITE_FUNCTION_SIMPLE(int, __xmknod, (int ver, const char *path, mode_t mode, dev_t dev), (ver, new_path, mode, dev), -1)
214 +REWRITE_FUNCTION_SIMPLE(int, mkfifo, (const char *path, mode_t mode), (new_path, mode), -1)
215 +REWRITE_FUNCTION_SIMPLE(int, creat, (const char *path, mode_t mode), (new_path, mode), -1)
216 +REWRITE_FUNCTION_SIMPLE(int, creat64, (const char *path, mode_t mode), (new_path, mode), -1)
217 +REWRITE_FUNCTION_SIMPLE(int, readlink, (const char *path, char *buf, size_t bufsize), (new_path, buf, bufsize), -1)
218 +REWRITE_FUNCTION_SIMPLE(int, rmdir, (const char *path), (new_path), -1)
220 #define REWRITE_FUNCTION_DOUBLE(return_type, function_name, signature, orig_call) \
221 return_type function_name signature { \
222 - return_type return_value; \
223 - char *new_path1, *new_path2; \
224 + const char *new_path1, *new_path2; \
225 + char *rewritten_path1, *rewritten_path2; \
227 PRINT_DEBUG(#function_name ": %s %s\n", path1, path2); \
229 - new_path1 = translate (path1); \
230 - new_path2 = translate (path2); \
231 - return_value = orig_##function_name orig_call; \
232 - free (new_path1); \
233 - free (new_path2); \
234 - return return_value; \
235 + if (UNLIKELY (orig_##function_name == NULL)) return -1; \
236 + rewritten_path1 = alloca (prefix_size + strlen (path1) + 2); \
237 + rewritten_path2 = alloca (prefix_size + strlen (path2) + 2); \
238 + translate (path1, rewritten_path1, &new_path1); \
239 + translate (path2, rewritten_path2, &new_path2); \
240 + return orig_##function_name orig_call; \
243 REWRITE_FUNCTION_DOUBLE(int, rename, (const char *path1, const char *path2), (new_path1, new_path2))
244 @@ -342,20 +338,22 @@ REWRITE_FUNCTION_DOUBLE(int, symlink, (const char *path1, const char *path2), (n
245 #define REWRITE_FUNCTION_MKSTEMP(function_name) \
246 int function_name(char *path) { \
247 int return_value, i; \
249 + char *rewritten_path; \
250 + const char *new_path; \
251 size_t size, new_size; \
253 PRINT_DEBUG(#function_name ": %s\n", path); \
255 - new_path = translate (path); \
256 + if (UNLIKELY (orig_##function_name == NULL)) return -1; \
257 + rewritten_path = alloca (prefix_size + strlen (path) + 2); \
258 + translate (path, rewritten_path, &new_path); \
259 if(LIKELY(new_path != NULL)) { \
260 - return_value = orig_##function_name (new_path); \
261 + return_value = orig_##function_name ((char*)new_path); \
262 size = strlen (path); \
263 new_size = strlen (new_path); \
264 for (i = 0; i <= 6; i++) { \
265 path[size - i] = new_path[new_size - i]; \
268 return return_value; \
271 @@ -370,14 +368,16 @@ REWRITE_FUNCTION_MKSTEMP(mkstemp64);
272 int function_name(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) { \
274 struct sockaddr_un newaddr; \
275 - char *path, *new_path; \
276 - int return_value; \
277 + char *path, *rewritten_path; \
278 + const char *new_path; \
280 + if (UNLIKELY (orig_##function_name == NULL)) return -1; \
281 if (serv_addr->sa_family == AF_LOCAL) { \
282 path = ((struct sockaddr_un*)serv_addr)->sun_path; \
283 offset = (path[0] == '\0'); \
285 - new_path = translate (path); \
286 + rewritten_path = alloca (prefix_size + strlen (path) + 2); \
287 + translate (path, rewritten_path, &new_path); \
289 PRINT_DEBUG(#function_name": %s\n", path); \
291 @@ -386,16 +386,13 @@ int function_name(int sockfd, const struct sockaddr *serv_addr, socklen_t addrle
292 newaddr.sun_path[0] = '\0'; \
293 strncpy (newaddr.sun_path + offset, new_path, sizeof (newaddr.sun_path) - offset); \
294 newaddr.sun_path[sizeof (newaddr.sun_path) - 1] = '\0'; \
295 - return_value = orig_##function_name (sockfd, (struct sockaddr*) &newaddr, \
296 + return orig_##function_name (sockfd, (struct sockaddr*) &newaddr, \
297 offsetof (struct sockaddr_un, sun_path) + strlen(new_path) + offset); \
299 - return return_value; \
302 return orig_##function_name (sockfd, serv_addr, addrlen); \
305 - if (UNLIKELY (!started)) start_up(); \
306 return orig_##function_name (sockfd, serv_addr, addrlen); \