xref: /third_party/toybox/toys/other/which.c (revision 0f66f451)
1/* which.c - Find executable files in $PATH.
2 *
3 * Copyright 2006 Rob landley <rob@landley.net>
4
5USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
6
7config 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
23static 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
62void 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