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., 51 Franklin St, Fifth Floor, Boston,
39 #define RETRY( x ) do { x; } while (errno == EINTR);
43 static char *home
= NULL
;
56 user
= getpwuid(getuid());
58 werror(_("could not get password entry for UID %i"), getuid());
65 home
= wstrdup(user
->pw_dir
);
71 * Return the home directory for the specified used
73 * If user not found, returns NULL, otherwise always returns a path that is
76 * Please note you must use the path before any other call to 'getpw*' or it
77 * may be erased. This is a design choice to avoid duplication considering
78 * the use case for this function.
80 static const char *getuserhomedir(const char *username
)
82 static const char default_home
[] = "/";
85 user
= getpwnam(username
);
87 werror(_("could not get password entry for user %s"), username
);
97 char *wexpandpath(const char *path
)
99 const char *origpath
= path
;
100 char buffer2
[PATH_MAX
+ 2];
101 char buffer
[PATH_MAX
+ 2];
104 memset(buffer
, 0, PATH_MAX
+ 2);
110 if (*path
== '/' || *path
== 0) {
111 home
= wgethomedir();
112 if (strlen(home
) > PATH_MAX
||
113 wstrlcpy(buffer
, home
, sizeof(buffer
)) >= sizeof(buffer
))
118 while (*path
!= 0 && *path
!= '/') {
121 buffer2
[j
++] = *path
;
125 home
= getuserhomedir(buffer2
);
126 if (!home
|| wstrlcat(buffer
, home
, sizeof(buffer
)) >= sizeof(buffer
))
133 while (*path
!= 0 && i
<= PATH_MAX
) {
139 /* expand $(HOME) or $HOME style environment variables */
142 while (*path
!= 0 && *path
!= ')') {
145 buffer2
[j
++] = *(path
++);
150 tmp
= getenv(buffer2
);
155 if ((i
+= strlen(buffer2
) + 2) > PATH_MAX
)
158 if (wstrlcat(buffer
, "$(", sizeof(buffer
)) >= sizeof(buffer
) ||
159 wstrlcat(buffer
, buffer2
, sizeof(buffer
)) >= sizeof(buffer
))
161 if (*(path
-1)==')') {
162 if (++i
> PATH_MAX
||
163 wstrlcat(buffer
, ")", sizeof(buffer
)) >= sizeof(buffer
))
167 if ((i
+= strlen(tmp
)) > PATH_MAX
||
168 wstrlcat(buffer
, tmp
, sizeof(buffer
)) >= sizeof(buffer
))
172 while (*path
!= 0 && *path
!= '/') {
175 buffer2
[j
++] = *(path
++);
178 tmp
= getenv(buffer2
);
180 if ((i
+= strlen(buffer2
) + 1) > PATH_MAX
||
181 wstrlcat(buffer
, "$", sizeof(buffer
)) >= sizeof(buffer
) ||
182 wstrlcat(buffer
, buffer2
, sizeof(buffer
)) >= sizeof(buffer
))
185 if ((i
+= strlen(tmp
)) > PATH_MAX
||
186 wstrlcat(buffer
, tmp
, sizeof(buffer
)) >= sizeof(buffer
))
199 return wstrdup(buffer
);
202 errno
= ENAMETOOLONG
;
203 werror(_("could not expand %s"), origpath
);
208 /* return address of next char != tok or end of string whichever comes first */
209 static const char *skipchar(const char *string
, char tok
)
211 while (*string
!= 0 && *string
== tok
)
217 /* return address of next char == tok or end of string whichever comes first */
218 static const char *nextchar(const char *string
, char tok
)
220 while (*string
!= 0 && *string
!= tok
)
227 *----------------------------------------------------------------------
229 * Finds a file in a : separated list of paths. ~ expansion is also
233 * The complete path for the file (in a newly allocated string) or
234 * NULL if the file was not found.
237 * A new string is allocated. It must be freed later.
239 *----------------------------------------------------------------------
241 char *wfindfile(const char *paths
, const char *file
)
244 const char *tmp
, *tmp2
;
251 if (*file
== '/' || *file
== '~' || *file
== '$' || !paths
|| *paths
== 0) {
252 if (access(file
, F_OK
) < 0) {
253 fullpath
= wexpandpath(file
);
257 if (access(fullpath
, F_OK
) < 0) {
264 return wstrdup(file
);
271 tmp
= skipchar(tmp
, ':');
274 tmp2
= nextchar(tmp
, ':');
276 path
= wmalloc(len
+ flen
+ 2);
277 path
= memcpy(path
, tmp
, len
);
279 if (path
[len
- 1] != '/' &&
280 wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2) {
285 if (wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
290 fullpath
= wexpandpath(path
);
294 if (access(fullpath
, F_OK
) == 0) {
305 char *wfindfileinlist(char *const *path_list
, const char *file
)
315 if (*file
== '/' || *file
== '~' || !path_list
) {
316 if (access(file
, F_OK
) < 0) {
317 fullpath
= wexpandpath(file
);
321 if (access(fullpath
, F_OK
) < 0) {
328 return wstrdup(file
);
333 for (i
= 0; path_list
[i
] != NULL
; i
++) {
334 len
= strlen(path_list
[i
]);
335 path
= wmalloc(len
+ flen
+ 2);
336 path
= memcpy(path
, path_list
[i
], len
);
338 if (wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2 ||
339 wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
344 fullpath
= wexpandpath(path
);
347 /* check if file exists */
348 if (access(fullpath
, F_OK
) == 0) {
358 char *wfindfileinarray(WMPropList
*array
, const char *file
)
368 if (*file
== '/' || *file
== '~' || !array
) {
369 if (access(file
, F_OK
) < 0) {
370 fullpath
= wexpandpath(file
);
374 if (access(fullpath
, F_OK
) < 0) {
381 return wstrdup(file
);
386 for (i
= 0; i
< WMGetPropListItemCount(array
); i
++) {
390 prop
= WMGetFromPLArray(array
, i
);
393 p
= WMGetFromPLString(prop
);
396 path
= wmalloc(len
+ flen
+ 2);
397 path
= memcpy(path
, p
, len
);
399 if (wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2 ||
400 wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
405 fullpath
= wexpandpath(path
);
408 /* check if file exists */
409 if (access(fullpath
, F_OK
) == 0) {
418 int wcopy_file(const char *dir
, const char *src_file
, const char *dest_file
)
421 size_t nread
, nwritten
;
426 /* only to a directory */
427 if (stat(dir
, &st
) != 0 || !S_ISDIR(st
.st_mode
))
429 /* only copy files */
430 if (stat(src_file
, &st
) != 0 || !S_ISREG(st
.st_mode
))
433 RETRY( src
= fopen(src_file
, "rb") )
435 werror(_("Could not open %s"), src_file
);
439 dstpath
= wstrconcat(dir
, dest_file
);
440 RETRY( dst
= fopen(dstpath
, "wb") )
442 werror(_("Could not create %s"), dstpath
);
449 RETRY( nread
= fread(buf
, 1, sizeof(buf
), src
) )
453 RETRY( nwritten
= fwrite(buf
, 1, nread
, dst
) )
454 if (ferror(dst
) || feof(src
) || nread
!= nwritten
)
459 if (ferror(src
) || ferror(dst
))
463 fchmod(fileno(dst
), st
.st_mode
);