Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / findfile.c
1 /*
2 * Window Maker miscelaneous function library
3 *
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
5 *
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.
10 *
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.
15 *
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.
19 */
20
21 #include "wconfig.h"
22
23 #include "WUtil.h"
24
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <pwd.h>
29 #include <limits.h>
30
31 #ifndef PATH_MAX
32 #define PATH_MAX 1024
33 #endif
34
35 char *wgethomedir()
36 {
37 char *home = getenv("HOME");
38 struct passwd *user;
39
40 if (home)
41 return home;
42
43 user = getpwuid(getuid());
44 if (!user) {
45 wsyserror(_("could not get password entry for UID %i"), getuid());
46 return "/";
47 }
48 if (!user->pw_dir) {
49 return "/";
50 } else {
51 return user->pw_dir;
52 }
53 }
54
55 static char *getuserhomedir(char *username)
56 {
57 struct passwd *user;
58
59 user = getpwnam(username);
60 if (!user) {
61 wsyserror(_("could not get password entry for user %s"), username);
62 return NULL;
63 }
64 if (!user->pw_dir) {
65 return "/";
66 } else {
67 return user->pw_dir;
68 }
69 }
70
71 char *wexpandpath(char *path)
72 {
73 char buffer2[PATH_MAX + 2];
74 char buffer[PATH_MAX + 2];
75 int i;
76
77 memset(buffer, 0, PATH_MAX + 2);
78
79 if (*path == '~') {
80 char *home;
81
82 path++;
83 if (*path == '/' || *path == 0) {
84 home = wgethomedir();
85 strcat(buffer, home);
86 } else {
87 int j;
88 j = 0;
89 while (*path != 0 && *path != '/') {
90 buffer2[j++] = *path;
91 buffer2[j] = 0;
92 path++;
93 }
94 home = getuserhomedir(buffer2);
95 if (!home)
96 return NULL;
97 strcat(buffer, home);
98 }
99 }
100
101 i = strlen(buffer);
102
103 while (*path != 0) {
104 char *tmp;
105
106 if (*path == '$') {
107 int j = 0;
108 path++;
109 /* expand $(HOME) or $HOME style environment variables */
110 if (*path == '(') {
111 path++;
112 while (*path != 0 && *path != ')') {
113 buffer2[j++] = *(path++);
114 buffer2[j] = 0;
115 }
116 if (*path == ')')
117 path++;
118 tmp = getenv(buffer2);
119 if (!tmp) {
120 buffer[i] = 0;
121 strcat(buffer, "$(");
122 strcat(buffer, buffer2);
123 strcat(buffer, ")");
124 i += strlen(buffer2) + 3;
125 } else {
126 strcat(buffer, tmp);
127 i += strlen(tmp);
128 }
129 } else {
130 while (*path != 0 && *path != '/') {
131 buffer2[j++] = *(path++);
132 buffer2[j] = 0;
133 }
134 tmp = getenv(buffer2);
135 if (!tmp) {
136 strcat(buffer, "$");
137 strcat(buffer, buffer2);
138 i += strlen(buffer2) + 1;
139 } else {
140 strcat(buffer, tmp);
141 i += strlen(tmp);
142 }
143 }
144 } else {
145 buffer[i++] = *path;
146 path++;
147 }
148 }
149
150 return wstrdup(buffer);
151 }
152
153 /* return address of next char != tok or end of string whichever comes first */
154 static char *skipchar(char *string, char tok)
155 {
156 while (*string != 0 && *string == tok)
157 string++;
158
159 return string;
160 }
161
162 /* return address of next char == tok or end of string whichever comes first */
163 static char *nextchar(char *string, char tok)
164 {
165 while (*string != 0 && *string != tok)
166 string++;
167
168 return string;
169 }
170
171 /*
172 *----------------------------------------------------------------------
173 * findfile--
174 * Finds a file in a : separated list of paths. ~ expansion is also
175 * done.
176 *
177 * Returns:
178 * The complete path for the file (in a newly allocated string) or
179 * NULL if the file was not found.
180 *
181 * Side effects:
182 * A new string is allocated. It must be freed later.
183 *
184 *----------------------------------------------------------------------
185 */
186 char *wfindfile(char *paths, char *file)
187 {
188 char *path;
189 char *tmp, *tmp2;
190 int len, flen;
191 char *fullpath;
192
193 if (!file)
194 return NULL;
195
196 if (*file == '/' || *file == '~' || *file == '$' || !paths || *paths == 0) {
197 if (access(file, F_OK) < 0) {
198 fullpath = wexpandpath(file);
199 if (!fullpath)
200 return NULL;
201
202 if (access(fullpath, F_OK) < 0) {
203 wfree(fullpath);
204 return NULL;
205 } else {
206 return fullpath;
207 }
208 } else {
209 return wstrdup(file);
210 }
211 }
212
213 flen = strlen(file);
214 tmp = paths;
215 while (*tmp) {
216 tmp = skipchar(tmp, ':');
217 if (*tmp == 0)
218 break;
219 tmp2 = nextchar(tmp, ':');
220 len = tmp2 - tmp;
221 path = wmalloc(len + flen + 2);
222 path = memcpy(path, tmp, len);
223 path[len] = 0;
224 if (path[len - 1] != '/')
225 strcat(path, "/");
226 strcat(path, file);
227 fullpath = wexpandpath(path);
228 wfree(path);
229 if (fullpath) {
230 if (access(fullpath, F_OK) == 0) {
231 return fullpath;
232 }
233 wfree(fullpath);
234 }
235 tmp = tmp2;
236 }
237
238 return NULL;
239 }
240
241 char *wfindfileinlist(char **path_list, char *file)
242 {
243 int i;
244 char *path;
245 int len, flen;
246 char *fullpath;
247
248 if (!file)
249 return NULL;
250
251 if (*file == '/' || *file == '~' || !path_list) {
252 if (access(file, F_OK) < 0) {
253 fullpath = wexpandpath(file);
254 if (!fullpath)
255 return NULL;
256
257 if (access(fullpath, F_OK) < 0) {
258 wfree(fullpath);
259 return NULL;
260 } else {
261 return fullpath;
262 }
263 } else {
264 return wstrdup(file);
265 }
266 }
267
268 flen = strlen(file);
269 for (i = 0; path_list[i] != NULL; i++) {
270 len = strlen(path_list[i]);
271 path = wmalloc(len + flen + 2);
272 path = memcpy(path, path_list[i], len);
273 path[len] = 0;
274 strcat(path, "/");
275 strcat(path, file);
276 /* expand tilde */
277 fullpath = wexpandpath(path);
278 wfree(path);
279 if (fullpath) {
280 /* check if file exists */
281 if (access(fullpath, F_OK) == 0) {
282 return fullpath;
283 }
284 wfree(fullpath);
285 }
286 }
287 return NULL;
288 }
289
290 char *wfindfileinarray(WMPropList * array, char *file)
291 {
292 int i;
293 char *path;
294 int len, flen;
295 char *fullpath;
296
297 if (!file)
298 return NULL;
299
300 if (*file == '/' || *file == '~' || !array) {
301 if (access(file, F_OK) < 0) {
302 fullpath = wexpandpath(file);
303 if (!fullpath)
304 return NULL;
305
306 if (access(fullpath, F_OK) < 0) {
307 wfree(fullpath);
308 return NULL;
309 } else {
310 return fullpath;
311 }
312 } else {
313 return wstrdup(file);
314 }
315 }
316
317 flen = strlen(file);
318 for (i = 0; i < WMGetPropListItemCount(array); i++) {
319 WMPropList *prop;
320 char *p;
321
322 prop = WMGetFromPLArray(array, i);
323 if (!prop)
324 continue;
325 p = WMGetFromPLString(prop);
326
327 len = strlen(p);
328 path = wmalloc(len + flen + 2);
329 path = memcpy(path, p, len);
330 path[len] = 0;
331 strcat(path, "/");
332 strcat(path, file);
333 /* expand tilde */
334 fullpath = wexpandpath(path);
335 wfree(path);
336 if (fullpath) {
337 /* check if file exists */
338 if (access(fullpath, F_OK) == 0) {
339 return fullpath;
340 }
341 wfree(fullpath);
342 }
343 }
344 return NULL;
345 }