which: -a support (needed for bfin uclibc build script)
No binary (build failed)
—
(log yok)
| @@ -13,30 +13,69 @@ | |
| #include "libbb.h" | |
| int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| - | int which_main(int argc, char **argv) |
| + | int which_main(int argc ATTRIBUTE_UNUSED, char **argv) |
| { | |
| + | USE_DESKTOP(int opt;) |
| int status = EXIT_SUCCESS; | |
| + | char *path; |
| char *p; | |
| - | if (argc <= 1 || argv[1][0] == '-') { |
| - | bb_show_usage(); |
| - | } |
| + | opt_complementary = "-1"; /* at least one argument */ |
| + | USE_DESKTOP(opt =) getopt32(argv, "a"); |
| + | argv += optind; |
| - | /* This matches what is seen on e.g. ubuntu |
| - | * "which" there is a shell script */ |
| - | if (!getenv("PATH")) { |
| - | putenv((char*)bb_PATH_root_path); |
| + | /* This matches what is seen on e.g. ubuntu. |
| + | * "which" there is a shell script. */ |
| + | path = getenv("PATH"); |
| + | if (!path) { |
| + | path = (char*)bb_PATH_root_path; |
| + | putenv(path); |
| + | path += 5; /* skip "PATH=" */ |
| } | |
| - | while (--argc > 0) { |
| - | argv++; |
| + | do { |
| + | #if ENABLE_DESKTOP |
| + | /* Much bloat just to support -a */ |
| if (strchr(*argv, '/')) { | |
| if (execable_file(*argv)) { | |
| puts(*argv); | |
| continue; | |
| } | |
| + | status = EXIT_FAILURE; |
| } else { | |
| - | p = find_execable(*argv); |
| + | char *path2 = xstrdup(path); |
| + | char *tmp = path2; |
| + | |
| + | p = find_execable(*argv, &tmp); |
| + | if (!p) |
| + | status = EXIT_FAILURE; |
| + | else { |
| + | print: |
| + | puts(p); |
| + | free(p); |
| + | if (opt) { |
| + | /* -a: show matches in all PATH components */ |
| + | if (tmp) { |
| + | p = find_execable(*argv, &tmp); |
| + | if (p) |
| + | goto print; |
| + | } |
| + | } |
| + | } |
| + | free(path2); |
| + | } |
| + | #else |
| + | /* Just ignoring -a */ |
| + | if (strchr(*argv, '/')) { |
| + | if (execable_file(*argv)) { |
| + | puts(*argv); |
| + | continue; |
| + | } |
| + | } else { |
| + | char *path2 = xstrdup(path); |
| + | char *tmp = path2; |
| + | p = find_execable(*argv, &tmp); |
| + | free(path2); |
| if (p) { | |
| puts(p); | |
| free(p); | |
| @@ -44,7 +83,8 @@ int which_main(int argc, char **argv) | |
| } | |
| } | |
| status = EXIT_FAILURE; | |
| - | } |
| + | #endif |
| + | } while (*(++argv) != NULL); |
| fflush_stdout_and_exit(status); | |
| } | |
| @@ -700,7 +700,7 @@ void die_if_bad_username(const char* name); | |
| #endif | |
| int execable_file(const char *name); | |
| - | char *find_execable(const char *filename); |
| + | char *find_execable(const char *filename, char **PATHp); |
| int exists_execable(const char *filename); | |
| /* BB_EXECxx always execs (it's not doing NOFORK/NOEXEC stuff), | |
| @@ -19,15 +19,20 @@ int execable_file(const char *name) | |
| return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); | |
| } | |
| - | /* search $PATH for an executable file; |
| + | /* search (*PATHp) for an executable file; |
| * return allocated string containing full path if found; | |
| - | * return NULL otherwise; |
| + | * PATHp points to the component after the one where it was found |
| + | * (or NULL), |
| + | * you may call find_execable again with this PATHp to continue |
| + | * (if it's not NULL). |
| + | * return NULL otherwise; (PATHp is undefined) |
| + | * in all cases (*PATHp) contents will be trashed (s/:/NUL/). |
| */ | |
| - | char *find_execable(const char *filename) |
| + | char *find_execable(const char *filename, char **PATHp) |
| { | |
| - | char *path, *p, *n; |
| + | char *p, *n; |
| - | p = path = xstrdup(getenv("PATH")); |
| + | p = *PATHp; |
| while (p) { | |
| n = strchr(p, ':'); | |
| if (n) | |
| @@ -35,15 +40,14 @@ char *find_execable(const char *filename) | |
| if (*p != '\0') { /* it's not a PATH="foo::bar" situation */ | |
| p = concat_path_file(p, filename); | |
| if (execable_file(p)) { | |
| - | free(path); |
| + | *PATHp = n; |
| return p; | |
| } | |
| free(p); | |
| } | |
| p = n; | |
| - | } |
| - | free(path); |
| - | return NULL; |
| + | } /* on loop exit p == NULL */ |
| + | return p; |
| } | |
| /* search $PATH for an executable file; | |
| @@ -52,7 +56,10 @@ char *find_execable(const char *filename) | |
| */ | |
| int exists_execable(const char *filename) | |
| { | |
| - | char *ret = find_execable(filename); |
| + | char *path = xstrdup(getenv("PATH")); |
| + | char *tmp = path; |
| + | char *ret = find_execable(filename, &tmp); |
| + | free(path); |
| if (ret) { | |
| free(ret); | |
| return 1; | |