1/* vi: set sw=4 ts=4: */ 2/* 3 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 4 * Copyright (C) 2006 Gabriel Somlo <somlo at cmu.edu> 5 * 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 */ 8//config:config WHICH 9//config: bool "which (3.8 kb)" 10//config: default y 11//config: help 12//config: which is used to find programs in your PATH and 13//config: print out their pathnames. 14 15//applet:IF_WHICH(APPLET_NOFORK(which, which, BB_DIR_USR_BIN, BB_SUID_DROP, which)) 16 17//kbuild:lib-$(CONFIG_WHICH) += which.o 18 19//usage:#define which_trivial_usage 20//usage: "[-a] COMMAND..." 21//usage:#define which_full_usage "\n\n" 22//usage: "Locate COMMAND\n" 23//usage: "\n -a Show all matches" 24//usage: 25//usage:#define which_example_usage 26//usage: "$ which login\n" 27//usage: "/bin/login\n" 28 29#include "libbb.h" 30 31int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 32int which_main(int argc UNUSED_PARAM, char **argv) 33{ 34 char *env_path; 35 int status = 0; 36 /* This sizeof(): bb_default_root_path is shorter than BB_PATH_ROOT_PATH */ 37 char buf[sizeof(BB_PATH_ROOT_PATH)]; 38 39 env_path = getenv("PATH"); 40 if (!env_path) 41 /* env_path must be writable, and must not alloc, so... */ 42 env_path = strcpy(buf, bb_default_root_path); 43 44 getopt32(argv, "^" "a" "\0" "-1"/*at least one arg*/); 45 argv += optind; 46 47 do { 48 int missing = 1; 49 50 /* If file contains a slash don't use PATH */ 51 if (strchr(*argv, '/')) { 52 if (file_is_executable(*argv)) { 53 missing = 0; 54 puts(*argv); 55 } 56 } else { 57 char *path; 58 char *p; 59 60 path = env_path; 61 /* NOFORK NB: xmalloc inside find_executable(), must have no allocs above! */ 62 while ((p = find_executable(*argv, &path)) != NULL) { 63 missing = 0; 64 puts(p); 65 free(p); 66 if (!option_mask32) /* -a not set */ 67 break; 68 } 69 } 70 status |= missing; 71 } while (*++argv); 72 73 return status; 74} 75