aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/functions.c66
-rw-r--r--lib/lib.h21
-rw-r--r--lib/llist.c21
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;
}
diff --git a/lib/lib.h b/lib/lib.h
index 10d33bde..d013af9d 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -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;
+}