aboutsummaryrefslogtreecommitdiff
path: root/toys
diff options
context:
space:
mode:
Diffstat (limited to 'toys')
-rw-r--r--toys/Config.in16
-rw-r--r--toys/which.c72
2 files changed, 88 insertions, 0 deletions
diff --git a/toys/Config.in b/toys/Config.in
index d9b1da10..89481bde 100644
--- a/toys/Config.in
+++ b/toys/Config.in
@@ -28,6 +28,12 @@ config DF_PEDANTIC
-k Sets units back to 1024 bytes (the default without -P)
+config HELLO
+ bool "hello"
+ default n
+ help
+ A hello world program. You don't need this.
+
config TOYSH
bool "sh (toysh)"
default n
@@ -146,5 +152,15 @@ config TOYSH_BUILTINS
Adds the commands exec, fg, bg, help, jobs, pwd, export, source, set,
unset, read, alias.
+config WHICH
+ bool "Which"
+ default n
+ help
+ usage: which [-a] filename ...
+
+ Search $PATH for executable files matching filename(s).
+
+ -a Show all matches
+
endmenu
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;
+}