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
);
70 static char *getuserhomedir(const char *username
)
72 static char *home
= NULL
;
78 user
= getpwnam(username
);
80 werror(_("could not get password entry for user %s"), username
);
86 home
= wstrdup(user
->pw_dir
);
91 char *wexpandpath(const char *path
)
93 const char *origpath
= path
;
94 char buffer2
[PATH_MAX
+ 2];
95 char buffer
[PATH_MAX
+ 2];
98 memset(buffer
, 0, PATH_MAX
+ 2);
104 if (*path
== '/' || *path
== 0) {
105 home
= wgethomedir();
106 if (strlen(home
) > PATH_MAX
||
107 wstrlcpy(buffer
, home
, sizeof(buffer
)) >= sizeof(buffer
))
112 while (*path
!= 0 && *path
!= '/') {
115 buffer2
[j
++] = *path
;
119 home
= getuserhomedir(buffer2
);
120 if (!home
|| wstrlcat(buffer
, home
, sizeof(buffer
)) >= sizeof(buffer
))
127 while (*path
!= 0 && i
<= PATH_MAX
) {
133 /* expand $(HOME) or $HOME style environment variables */
136 while (*path
!= 0 && *path
!= ')') {
139 buffer2
[j
++] = *(path
++);
144 tmp
= getenv(buffer2
);
149 if ((i
+= strlen(buffer2
) + 2) > PATH_MAX
)
152 if (wstrlcat(buffer
, "$(", sizeof(buffer
)) >= sizeof(buffer
) ||
153 wstrlcat(buffer
, buffer2
, sizeof(buffer
)) >= sizeof(buffer
))
155 if (*(path
-1)==')') {
156 if (++i
> PATH_MAX
||
157 wstrlcat(buffer
, ")", sizeof(buffer
)) >= sizeof(buffer
))
161 if ((i
+= strlen(tmp
)) > PATH_MAX
||
162 wstrlcat(buffer
, tmp
, sizeof(buffer
)) >= sizeof(buffer
))
166 while (*path
!= 0 && *path
!= '/') {
169 buffer2
[j
++] = *(path
++);
172 tmp
= getenv(buffer2
);
174 if ((i
+= strlen(buffer2
) + 1) > PATH_MAX
||
175 wstrlcat(buffer
, "$", sizeof(buffer
)) >= sizeof(buffer
) ||
176 wstrlcat(buffer
, buffer2
, sizeof(buffer
)) >= sizeof(buffer
))
179 if ((i
+= strlen(tmp
)) > PATH_MAX
||
180 wstrlcat(buffer
, tmp
, sizeof(buffer
)) >= sizeof(buffer
))
193 return wstrdup(buffer
);
196 errno
= ENAMETOOLONG
;
197 werror(_("could not expand %s"), origpath
);
202 /* return address of next char != tok or end of string whichever comes first */
203 static const char *skipchar(const char *string
, char tok
)
205 while (*string
!= 0 && *string
== tok
)
211 /* return address of next char == tok or end of string whichever comes first */
212 static const char *nextchar(const char *string
, char tok
)
214 while (*string
!= 0 && *string
!= tok
)
221 *----------------------------------------------------------------------
223 * Finds a file in a : separated list of paths. ~ expansion is also
227 * The complete path for the file (in a newly allocated string) or
228 * NULL if the file was not found.
231 * A new string is allocated. It must be freed later.
233 *----------------------------------------------------------------------
235 char *wfindfile(const char *paths
, const char *file
)
238 const char *tmp
, *tmp2
;
245 if (*file
== '/' || *file
== '~' || *file
== '$' || !paths
|| *paths
== 0) {
246 if (access(file
, F_OK
) < 0) {
247 fullpath
= wexpandpath(file
);
251 if (access(fullpath
, F_OK
) < 0) {
258 return wstrdup(file
);
265 tmp
= skipchar(tmp
, ':');
268 tmp2
= nextchar(tmp
, ':');
270 path
= wmalloc(len
+ flen
+ 2);
271 path
= memcpy(path
, tmp
, len
);
273 if (path
[len
- 1] != '/' &&
274 wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2) {
279 if (wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
284 fullpath
= wexpandpath(path
);
288 if (access(fullpath
, F_OK
) == 0) {
299 char *wfindfileinlist(char *const *path_list
, const char *file
)
309 if (*file
== '/' || *file
== '~' || !path_list
) {
310 if (access(file
, F_OK
) < 0) {
311 fullpath
= wexpandpath(file
);
315 if (access(fullpath
, F_OK
) < 0) {
322 return wstrdup(file
);
327 for (i
= 0; path_list
[i
] != NULL
; i
++) {
328 len
= strlen(path_list
[i
]);
329 path
= wmalloc(len
+ flen
+ 2);
330 path
= memcpy(path
, path_list
[i
], len
);
332 if (wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2 ||
333 wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
338 fullpath
= wexpandpath(path
);
341 /* check if file exists */
342 if (access(fullpath
, F_OK
) == 0) {
352 char *wfindfileinarray(WMPropList
*array
, const char *file
)
362 if (*file
== '/' || *file
== '~' || !array
) {
363 if (access(file
, F_OK
) < 0) {
364 fullpath
= wexpandpath(file
);
368 if (access(fullpath
, F_OK
) < 0) {
375 return wstrdup(file
);
380 for (i
= 0; i
< WMGetPropListItemCount(array
); i
++) {
384 prop
= WMGetFromPLArray(array
, i
);
387 p
= WMGetFromPLString(prop
);
390 path
= wmalloc(len
+ flen
+ 2);
391 path
= memcpy(path
, p
, len
);
393 if (wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2 ||
394 wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
399 fullpath
= wexpandpath(path
);
402 /* check if file exists */
403 if (access(fullpath
, F_OK
) == 0) {
412 int wcopy_file(const char *dir
, const char *src_file
, const char *dest_file
)
415 size_t nread
, nwritten
;
420 /* only to a directory */
421 if (stat(dir
, &st
) != 0 || !S_ISDIR(st
.st_mode
))
423 /* only copy files */
424 if (stat(src_file
, &st
) != 0 || !S_ISREG(st
.st_mode
))
427 RETRY( src
= fopen(src_file
, "rb") )
429 werror(_("Could not open %s"), src_file
);
433 dstpath
= wstrconcat(dir
, dest_file
);
434 RETRY( dst
= fopen(dstpath
, "wb") )
436 werror(_("Could not create %s"), dstpath
);
443 RETRY( nread
= fread(buf
, 1, sizeof(buf
), src
) )
447 RETRY( nwritten
= fwrite(buf
, 1, nread
, dst
) )
448 if (ferror(dst
) || feof(src
) || nread
!= nwritten
)
453 if (ferror(src
) || ferror(dst
))
457 fchmod(fileno(dst
), st
.st_mode
);