- s/sprintf/snprintf
[wmaker-crm.git] / WINGs / findfile.c
blobeb804b584f2d9581053aa9c1811d09aae156d752
1 /*
2 * Window Maker miscelaneous function library
3 *
4 * Copyright (c) 1997 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.
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.
22 #include "../src/config.h"
24 #include "wconfig.h"
26 #include "WUtil.h"
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <pwd.h>
32 #include <limits.h>
34 #ifndef PATH_MAX
35 #define PATH_MAX 1024
36 #endif
39 char*
40 wgethomedir()
42 char *home = getenv("HOME");
43 struct passwd *user;
45 if (home)
46 return home;
48 user = getpwuid(getuid());
49 if (!user) {
50 wsyserror(_("could not get password entry for UID %i"), getuid());
51 return "/";
53 if (!user->pw_dir) {
54 return "/";
55 } else {
56 return user->pw_dir;
61 static char*
62 getuserhomedir(char *username)
64 struct passwd *user;
66 user = getpwnam(username);
67 if (!user) {
68 wsyserror(_("could not get password entry for user %s"), username);
69 return NULL;
71 if (!user->pw_dir) {
72 return "/";
73 } else {
74 return user->pw_dir;
81 char*
82 wexpandpath(char *path)
84 char buffer2[PATH_MAX+2];
85 char buffer[PATH_MAX+2];
86 int i;
88 memset(buffer, 0, PATH_MAX+2);
90 if (*path=='~') {
91 char *home;
93 path++;
94 if (*path=='/' || *path==0) {
95 home = wgethomedir();
96 strcat(buffer, home);
97 } else {
98 int j;
99 j = 0;
100 while (*path!=0 && *path!='/') {
101 buffer2[j++] = *path;
102 buffer2[j] = 0;
103 path++;
105 home = getuserhomedir(buffer2);
106 if (!home)
107 return NULL;
108 strcat(buffer, home);
112 i = strlen(buffer);
114 while (*path!=0) {
115 char *tmp;
117 if (*path=='$') {
118 int j = 0;
119 path++;
120 /* expand $(HOME) or $HOME style environment variables */
121 if (*path=='(') {
122 path++;
123 while (*path!=0 && *path!=')') {
124 buffer2[j++] = *(path++);
125 buffer2[j] = 0;
127 if (*path==')')
128 path++;
129 tmp = getenv(buffer2);
130 if (!tmp) {
131 buffer[i] = 0;
132 strcat(buffer, "$(");
133 strcat(buffer, buffer2);
134 strcat(buffer, ")");
135 i += strlen(buffer2)+3;
136 } else {
137 strcat(buffer, tmp);
138 i += strlen(tmp);
140 } else {
141 while (*path!=0 && *path!='/') {
142 buffer2[j++] = *(path++);
143 buffer2[j] = 0;
145 tmp = getenv(buffer2);
146 if (!tmp) {
147 strcat(buffer, "$");
148 strcat(buffer, buffer2);
149 i += strlen(buffer2)+1;
150 } else {
151 strcat(buffer, tmp);
152 i += strlen(tmp);
155 } else {
156 buffer[i++] = *path;
157 path++;
161 return wstrdup(buffer);
167 *----------------------------------------------------------------------
168 * findfile--
169 * Finds a file in a : separated list of paths. ~ expansion is also
170 * done.
172 * Returns:
173 * The complete path for the file (in a newly allocated string) or
174 * NULL if the file was not found.
176 * Side effects:
177 * A new string is allocated. It must be freed later.
179 *----------------------------------------------------------------------
181 char*
182 wfindfile(char *paths, char *file)
184 char *path;
185 char *tmp;
186 int done;
187 int len, flen;
188 char *fullpath;
190 if (!file)
191 return NULL;
193 if (*file=='/' || *file=='~' || *file=='$' || !paths) {
194 if (access(file, F_OK)<0) {
195 fullpath = wexpandpath(file);
196 if (!fullpath)
197 return NULL;
199 if (access(fullpath, F_OK)<0) {
200 wfree(fullpath);
201 return NULL;
202 } else {
203 return fullpath;
205 } else {
206 return wstrdup(file);
210 flen = strlen(file);
211 tmp = paths;
212 done = 0;
213 while (!done) {
214 len = strcspn(tmp, ":");
215 if (len==0) done=1;
216 path = wmalloc(len+flen+2);
217 path = memcpy(path, tmp, len);
218 path[len]=0;
219 strcat(path, "/");
220 strcat(path, file);
221 fullpath = wexpandpath(path);
222 wfree(path);
223 if (fullpath) {
224 if (access(fullpath, F_OK)==0) {
225 return fullpath;
227 wfree(fullpath);
229 tmp=&(tmp[len+1]);
230 if (*tmp==0) break;
232 return NULL;
236 char*
237 wfindfileinlist(char **path_list, char *file)
239 int i;
240 char *path;
241 int len, flen;
242 char *fullpath;
244 if (!file)
245 return NULL;
247 if (*file=='/' || *file=='~' || !path_list) {
248 if (access(file, F_OK)<0) {
249 fullpath = wexpandpath(file);
250 if (!fullpath)
251 return NULL;
253 if (access(fullpath, F_OK)<0) {
254 wfree(fullpath);
255 return NULL;
256 } else {
257 return fullpath;
259 } else {
260 return wstrdup(file);
264 flen = strlen(file);
265 for (i=0; path_list[i]!=NULL; i++) {
266 len = strlen(path_list[i]);
267 path = wmalloc(len+flen+2);
268 path = memcpy(path, path_list[i], len);
269 path[len]=0;
270 strcat(path, "/");
271 strcat(path, file);
272 /* expand tilde */
273 fullpath = wexpandpath(path);
274 wfree(path);
275 if (fullpath) {
276 /* check if file exists */
277 if (access(fullpath, F_OK)==0) {
278 return fullpath;
280 wfree(fullpath);
283 return NULL;
288 char*
289 wfindfileinarray(proplist_t array, char *file)
291 int i;
292 char *path;
293 int len, flen;
294 char *fullpath;
296 if (!file)
297 return NULL;
299 if (*file=='/' || *file=='~' || !array) {
300 if (access(file, F_OK)<0) {
301 fullpath = wexpandpath(file);
302 if (!fullpath)
303 return NULL;
305 if (access(fullpath, F_OK)<0) {
306 wfree(fullpath);
307 return NULL;
308 } else {
309 return fullpath;
311 } else {
312 return wstrdup(file);
316 flen = strlen(file);
317 for (i=0; i<PLGetNumberOfElements(array); i++) {
318 proplist_t prop;
319 char *p;
321 prop = PLGetArrayElement(array, i);
322 if (!prop)
323 continue;
324 p = PLGetString(prop);
326 len = strlen(p);
327 path = wmalloc(len+flen+2);
328 path = memcpy(path, p, len);
329 path[len]=0;
330 strcat(path, "/");
331 strcat(path, file);
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);
343 return NULL;