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,
42 static char *home
= NULL
;
49 #ifdef HAVE_SECURE_GETENV
50 tmp
= secure_getenv("HOME");
59 user
= getpwuid(getuid());
61 werror(_("could not get password entry for UID %i"), getuid());
69 home
= wstrdup(user
->pw_dir
);
75 * Return the home directory for the specified used
77 * If user not found, returns NULL, otherwise always returns a path that is
80 * Please note you must use the path before any other call to 'getpw*' or it
81 * may be erased. This is a design choice to avoid duplication considering
82 * the use case for this function.
84 static const char *getuserhomedir(const char *username
)
86 static const char default_home
[] = "/";
89 user
= getpwnam(username
);
91 werror(_("could not get password entry for user %s"), username
);
101 char *wexpandpath(const char *path
)
103 const char *origpath
= path
;
104 char buffer2
[PATH_MAX
+ 2];
105 char buffer
[PATH_MAX
+ 2];
108 memset(buffer
, 0, PATH_MAX
+ 2);
114 if (*path
== '/' || *path
== 0) {
115 home
= wgethomedir();
116 if (strlen(home
) > PATH_MAX
||
117 wstrlcpy(buffer
, home
, sizeof(buffer
)) >= sizeof(buffer
))
122 while (*path
!= 0 && *path
!= '/') {
125 buffer2
[j
++] = *path
;
129 home
= getuserhomedir(buffer2
);
130 if (!home
|| wstrlcat(buffer
, home
, sizeof(buffer
)) >= sizeof(buffer
))
137 while (*path
!= 0 && i
<= PATH_MAX
) {
144 /* expand $(HOME) or $HOME style environment variables */
148 while (*path
!= 0 && *path
!= ')') {
151 buffer2
[j
++] = *(path
++);
156 tmp
= getenv(buffer2
);
161 if ((i
+= strlen(buffer2
) + 2) > PATH_MAX
)
164 if (wstrlcat(buffer
, "$(", sizeof(buffer
)) >= sizeof(buffer
) ||
165 wstrlcat(buffer
, buffer2
, sizeof(buffer
)) >= sizeof(buffer
))
167 if (*(path
-1)==')') {
168 if (++i
> PATH_MAX
||
169 wstrlcat(buffer
, ")", sizeof(buffer
)) >= sizeof(buffer
))
173 if ((i
+= strlen(tmp
)) > PATH_MAX
||
174 wstrlcat(buffer
, tmp
, sizeof(buffer
)) >= sizeof(buffer
))
179 while (*path
!= 0 && *path
!= '/') {
182 buffer2
[j
++] = *(path
++);
185 tmp
= getenv(buffer2
);
187 if ((i
+= strlen(buffer2
) + 1) > PATH_MAX
||
188 wstrlcat(buffer
, "$", sizeof(buffer
)) >= sizeof(buffer
) ||
189 wstrlcat(buffer
, buffer2
, sizeof(buffer
)) >= sizeof(buffer
))
192 if ((i
+= strlen(tmp
)) > PATH_MAX
||
193 wstrlcat(buffer
, tmp
, sizeof(buffer
)) >= sizeof(buffer
))
206 return wstrdup(buffer
);
209 errno
= ENAMETOOLONG
;
210 werror(_("could not expand %s"), origpath
);
215 /* return address of next char != tok or end of string whichever comes first */
216 static const char *skipchar(const char *string
, char tok
)
218 while (*string
!= 0 && *string
== tok
)
224 /* return address of next char == tok or end of string whichever comes first */
225 static const char *nextchar(const char *string
, char tok
)
227 while (*string
!= 0 && *string
!= tok
)
234 *----------------------------------------------------------------------
236 * Finds a file in a : separated list of paths. ~ expansion is also
240 * The complete path for the file (in a newly allocated string) or
241 * NULL if the file was not found.
244 * A new string is allocated. It must be freed later.
246 *----------------------------------------------------------------------
248 char *wfindfile(const char *paths
, const char *file
)
251 const char *tmp
, *tmp2
;
258 if (*file
== '/' || *file
== '~' || *file
== '$' || !paths
|| *paths
== 0) {
259 if (access(file
, F_OK
) < 0) {
260 fullpath
= wexpandpath(file
);
264 if (access(fullpath
, F_OK
) < 0) {
271 return wstrdup(file
);
278 tmp
= skipchar(tmp
, ':');
281 tmp2
= nextchar(tmp
, ':');
283 path
= wmalloc(len
+ flen
+ 2);
284 path
= memcpy(path
, tmp
, len
);
286 if (path
[len
- 1] != '/' &&
287 wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2) {
292 if (wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
297 fullpath
= wexpandpath(path
);
301 if (access(fullpath
, F_OK
) == 0) {
312 char *wfindfileinlist(char *const *path_list
, const char *file
)
322 if (*file
== '/' || *file
== '~' || !path_list
) {
323 if (access(file
, F_OK
) < 0) {
324 fullpath
= wexpandpath(file
);
328 if (access(fullpath
, F_OK
) < 0) {
335 return wstrdup(file
);
340 for (i
= 0; path_list
[i
] != NULL
; i
++) {
341 len
= strlen(path_list
[i
]);
342 path
= wmalloc(len
+ flen
+ 2);
343 path
= memcpy(path
, path_list
[i
], len
);
345 if (wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2 ||
346 wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
351 fullpath
= wexpandpath(path
);
354 /* check if file exists */
355 if (access(fullpath
, F_OK
) == 0) {
365 char *wfindfileinarray(WMPropList
*array
, const char *file
)
375 if (*file
== '/' || *file
== '~' || !array
) {
376 if (access(file
, F_OK
) < 0) {
377 fullpath
= wexpandpath(file
);
381 if (access(fullpath
, F_OK
) < 0) {
388 return wstrdup(file
);
393 for (i
= 0; i
< WMGetPropListItemCount(array
); i
++) {
397 prop
= WMGetFromPLArray(array
, i
);
400 p
= WMGetFromPLString(prop
);
403 path
= wmalloc(len
+ flen
+ 2);
404 path
= memcpy(path
, p
, len
);
406 if (wstrlcat(path
, "/", len
+ flen
+ 2) >= len
+ flen
+ 2 ||
407 wstrlcat(path
, file
, len
+ flen
+ 2) >= len
+ flen
+ 2) {
412 fullpath
= wexpandpath(path
);
415 /* check if file exists */
416 if (access(fullpath
, F_OK
) == 0) {
425 int wcopy_file(const char *dir
, const char *src_file
, const char *dest_file
)
428 size_t nread
, nwritten
;
433 /* only to a directory */
434 if (stat(dir
, &st
) != 0 || !S_ISDIR(st
.st_mode
))
436 /* only copy files */
437 if (stat(src_file
, &st
) != 0 || !S_ISREG(st
.st_mode
))
441 src
= fopen(src_file
, "rb");
442 } while ((src
== NULL
) && (errno
== EINTR
));
444 werror(_("Could not open input file \"%s\""), src_file
);
448 dstpath
= wstrconcat(dir
, dest_file
);
450 dst
= fopen(dstpath
, "wb");
451 } while ((dst
== NULL
) && (errno
== EINTR
));
453 werror(_("Could not create target file \"%s\""), dstpath
);
460 nread
= fread(buf
, 1, sizeof(buf
), src
);
464 nwritten
= fwrite(buf
, 1, nread
, dst
);
465 if (ferror(dst
) || feof(src
) || nread
!= nwritten
)
470 if (ferror(src
) || ferror(dst
))
474 fchmod(fileno(dst
), st
.st_mode
);
477 wwarning("error occured during fclose(\"%s\")", dstpath
);