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