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.
38 #define RETRY( x ) do { x; } while (errno == EINTR);
42 static char *home
= NULL
;
55 user
= getpwuid(getuid());
57 werror(_("could not get password entry for UID %i"), getuid());
64 home
= wstrdup(user
->pw_dir
);
69 static char *getuserhomedir(const char *username
)
71 static char *home
= NULL
;
77 user
= getpwnam(username
);
79 werror(_("could not get password entry for user %s"), username
);
85 home
= wstrdup(user
->pw_dir
);
90 char *wexpandpath(char *path
)
92 char *origpath
= path
;
93 char buffer2
[PATH_MAX
+ 2];
94 char buffer
[PATH_MAX
+ 2];
97 memset(buffer
, 0, PATH_MAX
+ 2);
103 if (*path
== '/' || *path
== 0) {
104 home
= wgethomedir();
105 if (strlen(home
) > PATH_MAX
||
106 wstrlcpy(buffer
, home
, sizeof(buffer
)) >= sizeof(buffer
))
111 while (*path
!= 0 && *path
!= '/') {
114 buffer2
[j
++] = *path
;
118 home
= getuserhomedir(buffer2
);
119 if (!home
|| wstrlcat(buffer
, home
, sizeof(buffer
)) >= sizeof(buffer
))
126 while (*path
!= 0 && i
<= PATH_MAX
) {
132 /* expand $(HOME) or $HOME style environment variables */
135 while (*path
!= 0 && *path
!= ')') {
138 buffer2
[j
++] = *(path
++);
143 tmp
= getenv(buffer2
);
148 if ((i
+= strlen(buffer2
) + 2) > PATH_MAX
)
151 if (wstrlcat(buffer
, "$(", sizeof(buffer
)) >= sizeof(buffer
) ||
152 wstrlcat(buffer
, buffer2
, sizeof(buffer
)) >= sizeof(buffer
))
154 if (*(path
-1)==')') {
155 if (++i
> PATH_MAX
||
156 wstrlcat(buffer
, ")", sizeof(buffer
)) >= sizeof(buffer
))
160 if ((i
+= strlen(tmp
)) > PATH_MAX
||
161 wstrlcat(buffer
, tmp
, sizeof(buffer
)) >= sizeof(buffer
))
165 while (*path
!= 0 && *path
!= '/') {
168 buffer2
[j
++] = *(path
++);
171 tmp
= getenv(buffer2
);
173 if ((i
+= strlen(buffer2
) + 1) > PATH_MAX
||
174 wstrlcat(buffer
, "$", sizeof(buffer
)) >= sizeof(buffer
) ||
175 wstrlcat(buffer
, buffer2
, sizeof(buffer
)) >= sizeof(buffer
))
178 if ((i
+= strlen(tmp
)) > PATH_MAX
||
179 wstrlcat(buffer
, tmp
, sizeof(buffer
)) >= sizeof(buffer
))
192 return wstrdup(buffer
);
195 errno
= ENAMETOOLONG
;
196 werror(_("could not expand %s"), origpath
);
201 /* return address of next char != tok or end of string whichever comes first */
202 static char *skipchar(char *string
, char tok
)
204 while (*string
!= 0 && *string
== tok
)
210 /* return address of next char == tok or end of string whichever comes first */
211 static char *nextchar(char *string
, char tok
)
213 while (*string
!= 0 && *string
!= tok
)
220 *----------------------------------------------------------------------
222 * Finds a file in a : separated list of paths. ~ expansion is also
226 * The complete path for the file (in a newly allocated string) or
227 * NULL if the file was not found.
230 * A new string is allocated. It must be freed later.
232 *----------------------------------------------------------------------
234 char *wfindfile(char *paths
, char *file
)
244 if (*file
== '/' || *file
== '~' || *file
== '$' || !paths
|| *paths
== 0) {
245 if (access(file
, F_OK
) < 0) {
246 fullpath
= wexpandpath(file
);
250 if (access(fullpath
, F_OK
) < 0) {
257 return wstrdup(file
);
264 tmp
= skipchar(tmp
, ':');
267 tmp2
= nextchar(tmp
, ':');
269 path
= wmalloc(len
+ flen
+ 2);
270 path
= memcpy(path
, tmp
, len
);
272 if (path
[len
- 1] != '/' &&
273 wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2) {
278 if (wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
283 fullpath
= wexpandpath(path
);
287 if (access(fullpath
, F_OK
) == 0) {
298 char *wfindfileinlist(char **path_list
, char *file
)
308 if (*file
== '/' || *file
== '~' || !path_list
) {
309 if (access(file
, F_OK
) < 0) {
310 fullpath
= wexpandpath(file
);
314 if (access(fullpath
, F_OK
) < 0) {
321 return wstrdup(file
);
326 for (i
= 0; path_list
[i
] != NULL
; i
++) {
327 len
= strlen(path_list
[i
]);
328 path
= wmalloc(len
+ flen
+ 2);
329 path
= memcpy(path
, path_list
[i
], len
);
331 if (wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2 ||
332 wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
337 fullpath
= wexpandpath(path
);
340 /* check if file exists */
341 if (access(fullpath
, F_OK
) == 0) {
351 char *wfindfileinarray(WMPropList
* array
, char *file
)
361 if (*file
== '/' || *file
== '~' || !array
) {
362 if (access(file
, F_OK
) < 0) {
363 fullpath
= wexpandpath(file
);
367 if (access(fullpath
, F_OK
) < 0) {
374 return wstrdup(file
);
379 for (i
= 0; i
< WMGetPropListItemCount(array
); i
++) {
383 prop
= WMGetFromPLArray(array
, i
);
386 p
= WMGetFromPLString(prop
);
389 path
= wmalloc(len
+ flen
+ 2);
390 path
= memcpy(path
, p
, len
);
392 if (wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2 ||
393 wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
398 fullpath
= wexpandpath(path
);
401 /* check if file exists */
402 if (access(fullpath
, F_OK
) == 0) {
411 int wcopy_file(char *dir
, char *src_file
, char *dest_file
)
414 size_t nread
, nwritten
;
419 /* only to a directory */
420 if (stat(dir
, &st
) != 0 || !S_ISDIR(st
.st_mode
))
422 /* only copy files */
423 if (stat(src_file
, &st
) != 0 || !S_ISREG(st
.st_mode
))
426 RETRY( src
= fopen(src_file
, "rb") )
428 werror(_("Could not open %s"), src_file
);
432 dstpath
= wstrconcat(dir
, dest_file
);
433 RETRY( dst
= fopen(dstpath
, "wb") )
435 werror(_("Could not create %s"), dstpath
);
442 RETRY( nread
= fread(buf
, 1, sizeof(buf
), src
) )
446 RETRY( nwritten
= fwrite(buf
, 1, nread
, dst
) )
447 if (ferror(dst
) || feof(src
) || nread
!= nwritten
)
452 if (ferror(src
) || ferror(dst
))
456 fchmod(fileno(dst
), st
.st_mode
);