Update email address
[wmaker-crm.git] / WINGs / findfile.c
blob70d1e47c89d0ff0f796c22969330c157354fbd76
1 /*
2 * Window Maker miscelaneous function library
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "wconfig.h"
23 #include "WUtil.h"
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <pwd.h>
30 #include <limits.h>
32 #ifndef PATH_MAX
33 #define PATH_MAX 1024
34 #endif
36 char *wgethomedir()
38 static char *home = NULL;
39 char *tmp;
40 struct passwd *user;
42 if (home)
43 return home;
45 tmp = getenv("HOME");
46 if (tmp) {
47 home = wstrdup(tmp);
48 return home;
51 user = getpwuid(getuid());
52 if (!user) {
53 werror(_("could not get password entry for UID %i"), getuid());
54 home = "/";
57 if (!user->pw_dir)
58 home = "/";
59 else
60 home = wstrdup(user->pw_dir);
62 return home;
65 static char *getuserhomedir(const char *username)
67 static char *home = NULL;
68 struct passwd *user;
70 if (home)
71 return home;
73 user = getpwnam(username);
74 if (!user) {
75 werror(_("could not get password entry for user %s"), username);
76 return NULL;
78 if (!user->pw_dir)
79 home = "/";
80 else
81 home = wstrdup(user->pw_dir);
83 return home;
86 char *wexpandpath(char *path)
88 char *origpath = path;
89 char buffer2[PATH_MAX + 2];
90 char buffer[PATH_MAX + 2];
91 int i;
93 memset(buffer, 0, PATH_MAX + 2);
95 if (*path == '~') {
96 char *home;
98 path++;
99 if (*path == '/' || *path == 0) {
100 home = wgethomedir();
101 if (strlen(home) > PATH_MAX ||
102 wstrlcpy(buffer, home, sizeof(buffer)) >= sizeof(buffer))
103 goto error;
104 } else {
105 int j;
106 j = 0;
107 while (*path != 0 && *path != '/') {
108 if (j > PATH_MAX)
109 goto error;
110 buffer2[j++] = *path;
111 buffer2[j] = 0;
112 path++;
114 home = getuserhomedir(buffer2);
115 if (!home || wstrlcat(buffer, home, sizeof(buffer)) >= sizeof(buffer))
116 goto error;
120 i = strlen(buffer);
122 while (*path != 0 && i <= PATH_MAX) {
123 char *tmp;
125 if (*path == '$') {
126 int j = 0;
127 path++;
128 /* expand $(HOME) or $HOME style environment variables */
129 if (*path == '(') {
130 path++;
131 while (*path != 0 && *path != ')') {
132 if (j > PATH_MAX)
133 goto error;
134 buffer2[j++] = *(path++);
135 buffer2[j] = 0;
137 if (*path == ')') {
138 path++;
139 tmp = getenv(buffer2);
140 } else {
141 tmp = NULL;
143 if (!tmp) {
144 if ((i += strlen(buffer2) + 2) > PATH_MAX)
145 goto error;
146 buffer[i] = 0;
147 if (wstrlcat(buffer, "$(", sizeof(buffer)) >= sizeof(buffer) ||
148 wstrlcat(buffer, buffer2, sizeof(buffer)) >= sizeof(buffer))
149 goto error;
150 if (*(path-1)==')') {
151 if (++i > PATH_MAX ||
152 wstrlcat(buffer, ")", sizeof(buffer)) >= sizeof(buffer))
153 goto error;
155 } else {
156 if ((i += strlen(tmp)) > PATH_MAX ||
157 wstrlcat(buffer, tmp, sizeof(buffer)) >= sizeof(buffer))
158 goto error;
160 } else {
161 while (*path != 0 && *path != '/') {
162 if (j > PATH_MAX)
163 goto error;
164 buffer2[j++] = *(path++);
165 buffer2[j] = 0;
167 tmp = getenv(buffer2);
168 if (!tmp) {
169 if ((i += strlen(buffer2) + 1) > PATH_MAX ||
170 wstrlcat(buffer, "$", sizeof(buffer)) >= sizeof(buffer) ||
171 wstrlcat(buffer, buffer2, sizeof(buffer)) >= sizeof(buffer))
172 goto error;
173 } else {
174 if ((i += strlen(tmp)) > PATH_MAX ||
175 wstrlcat(buffer, tmp, sizeof(buffer)) >= sizeof(buffer))
176 goto error;
179 } else {
180 buffer[i++] = *path;
181 path++;
185 if (*path!=0)
186 goto error;
188 return wstrdup(buffer);
190 error:
191 errno = ENAMETOOLONG;
192 werror(_("could not expand %s"), origpath);
194 return NULL;
197 /* return address of next char != tok or end of string whichever comes first */
198 static char *skipchar(char *string, char tok)
200 while (*string != 0 && *string == tok)
201 string++;
203 return string;
206 /* return address of next char == tok or end of string whichever comes first */
207 static char *nextchar(char *string, char tok)
209 while (*string != 0 && *string != tok)
210 string++;
212 return string;
216 *----------------------------------------------------------------------
217 * findfile--
218 * Finds a file in a : separated list of paths. ~ expansion is also
219 * done.
221 * Returns:
222 * The complete path for the file (in a newly allocated string) or
223 * NULL if the file was not found.
225 * Side effects:
226 * A new string is allocated. It must be freed later.
228 *----------------------------------------------------------------------
230 char *wfindfile(char *paths, char *file)
232 char *path;
233 char *tmp, *tmp2;
234 int len, flen;
235 char *fullpath;
237 if (!file)
238 return NULL;
240 if (*file == '/' || *file == '~' || *file == '$' || !paths || *paths == 0) {
241 if (access(file, F_OK) < 0) {
242 fullpath = wexpandpath(file);
243 if (!fullpath)
244 return NULL;
246 if (access(fullpath, F_OK) < 0) {
247 wfree(fullpath);
248 return NULL;
249 } else {
250 return fullpath;
252 } else {
253 return wstrdup(file);
257 flen = strlen(file);
258 tmp = paths;
259 while (*tmp) {
260 tmp = skipchar(tmp, ':');
261 if (*tmp == 0)
262 break;
263 tmp2 = nextchar(tmp, ':');
264 len = tmp2 - tmp;
265 path = wmalloc(len + flen + 2);
266 path = memcpy(path, tmp, len);
267 path[len] = 0;
268 if (path[len - 1] != '/' &&
269 wstrlcat(path, "/", len + flen + 2) >= len + flen + 2) {
270 wfree(path);
271 return NULL;
274 if (wstrlcat(path, file, len + flen + 2) >= len + flen + 2) {
275 wfree(path);
276 return NULL;
279 fullpath = wexpandpath(path);
280 wfree(path);
282 if (fullpath) {
283 if (access(fullpath, F_OK) == 0) {
284 return fullpath;
286 wfree(fullpath);
288 tmp = tmp2;
291 return NULL;
294 char *wfindfileinlist(char **path_list, char *file)
296 int i;
297 char *path;
298 int len, flen;
299 char *fullpath;
301 if (!file)
302 return NULL;
304 if (*file == '/' || *file == '~' || !path_list) {
305 if (access(file, F_OK) < 0) {
306 fullpath = wexpandpath(file);
307 if (!fullpath)
308 return NULL;
310 if (access(fullpath, F_OK) < 0) {
311 wfree(fullpath);
312 return NULL;
313 } else {
314 return fullpath;
316 } else {
317 return wstrdup(file);
321 flen = strlen(file);
322 for (i = 0; path_list[i] != NULL; i++) {
323 len = strlen(path_list[i]);
324 path = wmalloc(len + flen + 2);
325 path = memcpy(path, path_list[i], len);
326 path[len] = 0;
327 if (wstrlcat(path, "/", len + flen + 2) >= len + flen + 2 ||
328 wstrlcat(path, file, len + flen + 2) >= len + flen + 2) {
329 wfree(path);
330 return NULL;
332 /* expand tilde */
333 fullpath = wexpandpath(path);
334 wfree(path);
335 if (fullpath) {
336 /* check if file exists */
337 if (access(fullpath, F_OK) == 0) {
338 return fullpath;
340 wfree(fullpath);
344 return NULL;
347 char *wfindfileinarray(WMPropList * array, char *file)
349 int i;
350 char *path;
351 int len, flen;
352 char *fullpath;
354 if (!file)
355 return NULL;
357 if (*file == '/' || *file == '~' || !array) {
358 if (access(file, F_OK) < 0) {
359 fullpath = wexpandpath(file);
360 if (!fullpath)
361 return NULL;
363 if (access(fullpath, F_OK) < 0) {
364 wfree(fullpath);
365 return NULL;
366 } else {
367 return fullpath;
369 } else {
370 return wstrdup(file);
374 flen = strlen(file);
375 for (i = 0; i < WMGetPropListItemCount(array); i++) {
376 WMPropList *prop;
377 char *p;
379 prop = WMGetFromPLArray(array, i);
380 if (!prop)
381 continue;
382 p = WMGetFromPLString(prop);
384 len = strlen(p);
385 path = wmalloc(len + flen + 2);
386 path = memcpy(path, p, len);
387 path[len] = 0;
388 if (wstrlcat(path, "/", len + flen + 2) >= len + flen + 2 ||
389 wstrlcat(path, file, len + flen + 2) >= len + flen + 2) {
390 wfree(path);
391 return NULL;
393 /* expand tilde */
394 fullpath = wexpandpath(path);
395 wfree(path);
396 if (fullpath) {
397 /* check if file exists */
398 if (access(fullpath, F_OK) == 0) {
399 return fullpath;
401 wfree(fullpath);
404 return NULL;