10f66f451Sopenharmony_ci/* which.c - Find executable files in $PATH.
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2006 Rob landley <rob@landley.net>
40f66f451Sopenharmony_ci
50f66f451Sopenharmony_ciUSE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
60f66f451Sopenharmony_ci
70f66f451Sopenharmony_ciconfig WHICH
80f66f451Sopenharmony_ci  bool "which"
90f66f451Sopenharmony_ci  default y
100f66f451Sopenharmony_ci  help
110f66f451Sopenharmony_ci    usage: which [-a] filename ...
120f66f451Sopenharmony_ci
130f66f451Sopenharmony_ci    Search $PATH for executable files matching filename(s).
140f66f451Sopenharmony_ci
150f66f451Sopenharmony_ci    -a	Show all matches
160f66f451Sopenharmony_ci*/
170f66f451Sopenharmony_ci#include "toys.h"
180f66f451Sopenharmony_ci
190f66f451Sopenharmony_ci// Find an exectuable file either at a path with a slash in it (absolute or
200f66f451Sopenharmony_ci// relative to current directory), or in $PATH.  Returns absolute path to file,
210f66f451Sopenharmony_ci// or NULL if not found.
220f66f451Sopenharmony_ci
230f66f451Sopenharmony_cistatic int which_in_path(char *filename)
240f66f451Sopenharmony_ci{
250f66f451Sopenharmony_ci  struct string_list *list;
260f66f451Sopenharmony_ci
270f66f451Sopenharmony_ci  // If they gave us a path, don't worry about $PATH or -a
280f66f451Sopenharmony_ci
290f66f451Sopenharmony_ci  if (strchr(filename, '/')) {
300f66f451Sopenharmony_ci    // Confirm it has the executable bit set, and it's not a directory.
310f66f451Sopenharmony_ci    if (!access(filename, X_OK)) {
320f66f451Sopenharmony_ci      struct stat st;
330f66f451Sopenharmony_ci
340f66f451Sopenharmony_ci      if (!stat(filename, &st) && S_ISREG(st.st_mode)) {
350f66f451Sopenharmony_ci        puts(filename);
360f66f451Sopenharmony_ci        return 0;
370f66f451Sopenharmony_ci      }
380f66f451Sopenharmony_ci      return 1;
390f66f451Sopenharmony_ci    }
400f66f451Sopenharmony_ci  }
410f66f451Sopenharmony_ci
420f66f451Sopenharmony_ci  // Search $PATH for matches.
430f66f451Sopenharmony_ci  list = find_in_path(getenv("PATH"), filename);
440f66f451Sopenharmony_ci  if (!list) return 1;
450f66f451Sopenharmony_ci
460f66f451Sopenharmony_ci  // Print out matches
470f66f451Sopenharmony_ci  while (list) {
480f66f451Sopenharmony_ci    if (!access(list->str, X_OK)) {
490f66f451Sopenharmony_ci      puts(list->str);
500f66f451Sopenharmony_ci      // If we should stop at one match, do so
510f66f451Sopenharmony_ci      if (!toys.optflags) {
520f66f451Sopenharmony_ci        llist_traverse(list, free);
530f66f451Sopenharmony_ci        break;
540f66f451Sopenharmony_ci      }
550f66f451Sopenharmony_ci    }
560f66f451Sopenharmony_ci    free(llist_pop(&list));
570f66f451Sopenharmony_ci  }
580f66f451Sopenharmony_ci
590f66f451Sopenharmony_ci  return 0;
600f66f451Sopenharmony_ci}
610f66f451Sopenharmony_ci
620f66f451Sopenharmony_civoid which_main(void)
630f66f451Sopenharmony_ci{
640f66f451Sopenharmony_ci  int i;
650f66f451Sopenharmony_ci
660f66f451Sopenharmony_ci  for (i=0; toys.optargs[i]; i++)
670f66f451Sopenharmony_ci    toys.exitval |= which_in_path(toys.optargs[i]);
680f66f451Sopenharmony_ci}
69