1/* vi: set sw=4 ts=4: */ 2/* 3 * Which implementation for busybox 4 * 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 * Copyright (C) 2006 Gabriel Somlo <somlo at cmu.edu> 7 * 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 * 10 * Based on which from debianutils 11 */ 12 13//usage:#define which_trivial_usage 14//usage: "[COMMAND]..." 15//usage:#define which_full_usage "\n\n" 16//usage: "Locate a COMMAND" 17//usage: 18//usage:#define which_example_usage 19//usage: "$ which login\n" 20//usage: "/bin/login\n" 21 22#include "libbb.h" 23 24int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 25int which_main(int argc UNUSED_PARAM, char **argv) 26{ 27 IF_DESKTOP(int opt;) 28 int status = EXIT_SUCCESS; 29 char *path; 30 char *p; 31 32 opt_complementary = "-1"; /* at least one argument */ 33 IF_DESKTOP(opt =) getopt32(argv, "a"); 34 argv += optind; 35 36 /* This matches what is seen on e.g. ubuntu. 37 * "which" there is a shell script. */ 38 path = getenv("PATH"); 39 if (!path) { 40 path = (char*)bb_PATH_root_path; 41 putenv(path); 42 path += 5; /* skip "PATH=" */ 43 } 44 45 do { 46#if ENABLE_DESKTOP 47/* Much bloat just to support -a */ 48 if (strchr(*argv, '/')) { 49 if (execable_file(*argv)) { 50 puts(*argv); 51 continue; 52 } 53 status = EXIT_FAILURE; 54 } else { 55 char *path2 = xstrdup(path); 56 char *tmp = path2; 57 58 p = find_execable(*argv, &tmp); 59 if (!p) 60 status = EXIT_FAILURE; 61 else { 62 print: 63 puts(p); 64 free(p); 65 if (opt) { 66 /* -a: show matches in all PATH components */ 67 if (tmp) { 68 p = find_execable(*argv, &tmp); 69 if (p) 70 goto print; 71 } 72 } 73 } 74 free(path2); 75 } 76#else 77/* Just ignoring -a */ 78 if (strchr(*argv, '/')) { 79 if (execable_file(*argv)) { 80 puts(*argv); 81 continue; 82 } 83 } else { 84 char *path2 = xstrdup(path); 85 char *tmp = path2; 86 p = find_execable(*argv, &tmp); 87 free(path2); 88 if (p) { 89 puts(p); 90 free(p); 91 continue; 92 } 93 } 94 status = EXIT_FAILURE; 95#endif 96 } while (*(++argv) != NULL); 97 98 fflush_stdout_and_exit(status); 99} 100