diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/functions.c | 66 | ||||
-rw-r--r-- | lib/lib.h | 21 | ||||
-rw-r--r-- | lib/llist.c | 21 |
3 files changed, 47 insertions, 61 deletions
diff --git a/lib/functions.c b/lib/functions.c index 0b003fd6..bcdaa0e0 100644 --- a/lib/functions.c +++ b/lib/functions.c @@ -241,69 +241,45 @@ char *xabspath(char *path) return path; } -// Check whether a file exists, or is executable, or... -int is_file_type(char *path, int type) -{ - // Is there a file here we can execute? - if (!access(path, type)) { - struct stat st; - // Confirm it's not a directory. - if (!stat(path, &st) && S_ISREG(st.st_mode)) return 1; - } - - return 0; -} - - -// Find an exectuable file either at a path with a slash in it (absolute or -// relative to current directory), or in $PATH. Returns absolute path to file, -// or NULL if not found. - +// Find all file in a colon-separated path with access type "type" (generally +// X_OK or R_OK). Returns a list of absolute paths to each file found, in +// order. -char *which_in_path(char *filename) +struct string_list *find_in_path(char *path, char *filename) { - char *res; - - if (index(filename, '/')) { - res = xabspath(filename); - if (is_file_type(filename, X_OK)) return res; - free(res); - return NULL; - } - return find_in_path(getenv("PATH"), filename, X_OK); -} - -// Find file in a colon-separated path with access type "type" (generally -// X_OK or R_OK). Returns absolute path to file, or NULL if not found. - -char *find_in_path(char *path, char *filename, int type) -{ - char *res = NULL, *cwd = xgetcwd(); + struct string_list *rlist = NULL; + char *cwd = xgetcwd(); for (;;) { char *next = path ? index(path, ':') : NULL; int len = next ? next-path : strlen(path); + struct string_list *rnext; + struct stat st; - if (!len) res = xmsprintf("%s/%s", cwd, filename); + rnext = xmalloc(sizeof(void *) + strlen(filename) + + (len ? len : strlen(cwd)) + 2); + if (!len) sprintf(rnext->str, "%s/%s", cwd, filename); else { - res = xmalloc(len+strlen(filename)+2); + char *res = rnext->str; strncpy(res, path, len); - res[len] = '/'; - strcpy(res+len+1, filename); + res += len; + *(res++) = '/'; + strcpy(res, filename); } - // Is there a file here we can execute? - if (is_file_type(res, type)) break; + // Confirm it's not a directory. + if (!stat(rnext->str, &st) && S_ISREG(st.st_mode)) { + rnext->next = rlist; + rlist = rnext; + } else free(rnext); - free(res); - res = NULL; if (!next) break; path += len; path++; } free(cwd); - return res; + return rlist; } @@ -4,6 +4,15 @@ * Copyright 2006 Rob Landley <rob@landley.net> */ +// llist.c +void llist_free(void *list, void (*freeit)(void *data)); +void *llist_pop(void *list); // actually void **list, but the compiler's dumb + +struct string_list { + struct string_list *next; + char str[0]; +}; + // functions.c void verror_msg(char *msg, int err, va_list va); void error_msg(char *msg, ...); @@ -25,22 +34,12 @@ ssize_t readall(int fd, void *buf, size_t count); void xread(int fd, char *buf, size_t count); char *xgetcwd(void); char *xabspath(char *path); -int is_file_type(char *path, int type); -char *which_in_path(char *filename); -char *find_in_path(char *path, char *filename, int type); +struct string_list *find_in_path(char *path, char *filename); void utoa_to_buf(unsigned n, char *buf, unsigned buflen); void itoa_to_buf(int n, char *buf, unsigned buflen); char *utoa(unsigned n); char *itoa(int n); -// llist.c -void llist_free(void *list, void (*freeit)(void *data)); - -struct string_list { - struct string_list *next; - char *str; -}; - // getmountlist.c struct mtab_list { struct mtab_list *next; diff --git a/lib/llist.c b/lib/llist.c index 9047e8b5..8d6fd265 100644 --- a/lib/llist.c +++ b/lib/llist.c @@ -12,10 +12,21 @@ void llist_free(void *list, void (*freeit)(void *data)) { while (list) { - void **next = (void **)list; - void *list_next = *next; - if (freeit) freeit(list); - free(list); - list = list_next; + void *pop = llist_pop(&list); + if (freeit) freeit(pop); } } + +// Return the first item from the list, advancing the list (which must be called +// as &list) +void *llist_pop(void *list) +{ + // I'd use a void ** for the argument, and even accept the typecast in all + // callers as documentation you need the &, except the stupid compiler + // would then scream about type-punned pointers. Screw it. + void **llist = (void **)list; + void **next = (void **)*llist; + *llist = *next; + + return (void *)next; +} |