1 /* which.c - Find executable files in $PATH.
2  *
3  * Copyright 2006 Rob landley <rob@landley.net>
4 
5 USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
6 
7 config WHICH
8   bool "which"
9   default y
10   help
11     usage: which [-a] filename ...
12 
13     Search $PATH for executable files matching filename(s).
14 
15     -a	Show all matches
16 */
17 #include "toys.h"
18 
19 // Find an exectuable file either at a path with a slash in it (absolute or
20 // relative to current directory), or in $PATH.  Returns absolute path to file,
21 // or NULL if not found.
22 
which_in_path(char * filename)23 static int which_in_path(char *filename)
24 {
25   struct string_list *list;
26 
27   // If they gave us a path, don't worry about $PATH or -a
28 
29   if (strchr(filename, '/')) {
30     // Confirm it has the executable bit set, and it's not a directory.
31     if (!access(filename, X_OK)) {
32       struct stat st;
33 
34       if (!stat(filename, &st) && S_ISREG(st.st_mode)) {
35         puts(filename);
36         return 0;
37       }
38       return 1;
39     }
40   }
41 
42   // Search $PATH for matches.
43   list = find_in_path(getenv("PATH"), filename);
44   if (!list) return 1;
45 
46   // Print out matches
47   while (list) {
48     if (!access(list->str, X_OK)) {
49       puts(list->str);
50       // If we should stop at one match, do so
51       if (!toys.optflags) {
52         llist_traverse(list, free);
53         break;
54       }
55     }
56     free(llist_pop(&list));
57   }
58 
59   return 0;
60 }
61 
which_main(void)62 void which_main(void)
63 {
64   int i;
65 
66   for (i=0; toys.optargs[i]; i++)
67     toys.exitval |= which_in_path(toys.optargs[i]);
68 }
69