which.c 1.4 KB

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