aboutsummaryrefslogtreecommitdiff
path: root/toys/which.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/which.c')
-rw-r--r--toys/which.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/toys/which.c b/toys/which.c
new file mode 100644
index 00000000..6d00bc82
--- /dev/null
+++ b/toys/which.c
@@ -0,0 +1,72 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * which.c -
+ *
+ * Copyright 2006 Rob landley <rob@landley.net>
+ */
+
+#include "toys.h"
+
+#define OPTIONS "a"
+#define OPT_a 1
+
+// 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.
+
+static int which_in_path(char *filename)
+{
+ struct string_list *list;
+
+ // If they gave us a path, don't worry about $PATH or -a
+
+ if (index(filename, '/')) {
+ // Confirm it has the executable bit set, and it's not a directory.
+ if (!access(filename, X_OK)) {
+ struct stat st;
+
+ if (!stat(filename, &st) && S_ISREG(st.st_mode)) {
+ puts(filename);
+ return 0;
+ }
+ return 1;
+ }
+ }
+
+ // Search $PATH for matches.
+ list = find_in_path(getenv("PATH"), filename);
+ if (!list) return 1;
+
+ // Print out matches
+ while (list) {
+ if (!access(list->str, X_OK)) {
+ puts(list->str);
+ // If we should stop at one match, do so
+ if (toys.optflags & OPT_a) {
+ llist_free(list, NULL);
+ break;
+ }
+ }
+ free(llist_pop(&list));
+ }
+
+ return 0;
+}
+
+int which_main(void)
+{
+ char **argv;
+ int rc = 0;
+
+ // get_optflags(OPTIONS);
+ argv = toys.argv+1;
+
+ if (!*argv) rc++;
+ else {
+ int i;
+ for (i=0; argv[i]; i++) rc |= which_in_path(argv[i]);
+ }
+ // if (CFG_TOYS_FREE) free(argv);
+
+ return rc;
+}