diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-05 13:33:59 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-05 13:33:59 +0000 |
| commit | f592aa36f33430b866e9d7c975c6b9c356100d4b (patch) | |
| tree | f7a8c565817ce331c6e18a2a399074c6c615cd79 | |
| parent | f0d6068086b701522b92a7dd941739cf4fbb71e8 (diff) | |
| download | busybox-w32-f592aa36f33430b866e9d7c975c6b9c356100d4b.tar.gz busybox-w32-f592aa36f33430b866e9d7c975c6b9c356100d4b.tar.bz2 busybox-w32-f592aa36f33430b866e9d7c975c6b9c356100d4b.zip | |
which: -a support (needed for bfin uclibc build script)
real support (with CONFIG_DESKTOP=y): 120+ bytes:
text data bss dec hex filename
807958 624 7036 815618 c7202 busybox_old
808085 624 7036 815745 c7281 busybox_unstripped
"fake" support (with CONFIG_DESKTOP unset): ~45 bytes:
text data bss dec hex filename
797790 611 6996 805397 c4a15 busybox_old
797834 611 6996 805441 c4a41 busybox_unstripped
| -rw-r--r-- | debianutils/which.c | 64 | ||||
| -rw-r--r-- | include/libbb.h | 2 | ||||
| -rw-r--r-- | libbb/execable.c | 27 |
3 files changed, 70 insertions, 23 deletions
diff --git a/debianutils/which.c b/debianutils/which.c index 5ab67194d..41a864cfa 100644 --- a/debianutils/which.c +++ b/debianutils/which.c | |||
| @@ -13,30 +13,69 @@ | |||
| 13 | #include "libbb.h" | 13 | #include "libbb.h" |
| 14 | 14 | ||
| 15 | int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 15 | int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 16 | int which_main(int argc, char **argv) | 16 | int which_main(int argc ATTRIBUTE_UNUSED, char **argv) |
| 17 | { | 17 | { |
| 18 | USE_DESKTOP(int opt;) | ||
| 18 | int status = EXIT_SUCCESS; | 19 | int status = EXIT_SUCCESS; |
| 20 | char *path; | ||
| 19 | char *p; | 21 | char *p; |
| 20 | 22 | ||
| 21 | if (argc <= 1 || argv[1][0] == '-') { | 23 | opt_complementary = "-1"; /* at least one argument */ |
| 22 | bb_show_usage(); | 24 | USE_DESKTOP(opt =) getopt32(argv, "a"); |
| 23 | } | 25 | argv += optind; |
| 24 | 26 | ||
| 25 | /* This matches what is seen on e.g. ubuntu | 27 | /* This matches what is seen on e.g. ubuntu. |
| 26 | * "which" there is a shell script */ | 28 | * "which" there is a shell script. */ |
| 27 | if (!getenv("PATH")) { | 29 | path = getenv("PATH"); |
| 28 | putenv((char*)bb_PATH_root_path); | 30 | if (!path) { |
| 31 | path = (char*)bb_PATH_root_path; | ||
| 32 | putenv(path); | ||
| 33 | path += 5; /* skip "PATH=" */ | ||
| 29 | } | 34 | } |
| 30 | 35 | ||
| 31 | while (--argc > 0) { | 36 | do { |
| 32 | argv++; | 37 | #if ENABLE_DESKTOP |
| 38 | /* Much bloat just to support -a */ | ||
| 33 | if (strchr(*argv, '/')) { | 39 | if (strchr(*argv, '/')) { |
| 34 | if (execable_file(*argv)) { | 40 | if (execable_file(*argv)) { |
| 35 | puts(*argv); | 41 | puts(*argv); |
| 36 | continue; | 42 | continue; |
| 37 | } | 43 | } |
| 44 | status = EXIT_FAILURE; | ||
| 38 | } else { | 45 | } else { |
| 39 | p = find_execable(*argv); | 46 | char *path2 = xstrdup(path); |
| 47 | char *tmp = path2; | ||
| 48 | |||
| 49 | p = find_execable(*argv, &tmp); | ||
| 50 | if (!p) | ||
| 51 | status = EXIT_FAILURE; | ||
| 52 | else { | ||
| 53 | print: | ||
| 54 | puts(p); | ||
| 55 | free(p); | ||
| 56 | if (opt) { | ||
| 57 | /* -a: show matches in all PATH components */ | ||
| 58 | if (tmp) { | ||
| 59 | p = find_execable(*argv, &tmp); | ||
| 60 | if (p) | ||
| 61 | goto print; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | free(path2); | ||
| 66 | } | ||
| 67 | #else | ||
| 68 | /* Just ignoring -a */ | ||
| 69 | if (strchr(*argv, '/')) { | ||
| 70 | if (execable_file(*argv)) { | ||
| 71 | puts(*argv); | ||
| 72 | continue; | ||
| 73 | } | ||
| 74 | } else { | ||
| 75 | char *path2 = xstrdup(path); | ||
| 76 | char *tmp = path2; | ||
| 77 | p = find_execable(*argv, &tmp); | ||
| 78 | free(path2); | ||
| 40 | if (p) { | 79 | if (p) { |
| 41 | puts(p); | 80 | puts(p); |
| 42 | free(p); | 81 | free(p); |
| @@ -44,7 +83,8 @@ int which_main(int argc, char **argv) | |||
| 44 | } | 83 | } |
| 45 | } | 84 | } |
| 46 | status = EXIT_FAILURE; | 85 | status = EXIT_FAILURE; |
| 47 | } | 86 | #endif |
| 87 | } while (*(++argv) != NULL); | ||
| 48 | 88 | ||
| 49 | fflush_stdout_and_exit(status); | 89 | fflush_stdout_and_exit(status); |
| 50 | } | 90 | } |
diff --git a/include/libbb.h b/include/libbb.h index 492a561a9..1e4968bfa 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
| @@ -700,7 +700,7 @@ void die_if_bad_username(const char* name); | |||
| 700 | #endif | 700 | #endif |
| 701 | 701 | ||
| 702 | int execable_file(const char *name); | 702 | int execable_file(const char *name); |
| 703 | char *find_execable(const char *filename); | 703 | char *find_execable(const char *filename, char **PATHp); |
| 704 | int exists_execable(const char *filename); | 704 | int exists_execable(const char *filename); |
| 705 | 705 | ||
| 706 | /* BB_EXECxx always execs (it's not doing NOFORK/NOEXEC stuff), | 706 | /* BB_EXECxx always execs (it's not doing NOFORK/NOEXEC stuff), |
diff --git a/libbb/execable.c b/libbb/execable.c index 2649a6cfe..5c2b4505c 100644 --- a/libbb/execable.c +++ b/libbb/execable.c | |||
| @@ -19,15 +19,20 @@ int execable_file(const char *name) | |||
| 19 | return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); | 19 | return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | /* search $PATH for an executable file; | 22 | /* search (*PATHp) for an executable file; |
| 23 | * return allocated string containing full path if found; | 23 | * return allocated string containing full path if found; |
| 24 | * return NULL otherwise; | 24 | * PATHp points to the component after the one where it was found |
| 25 | * (or NULL), | ||
| 26 | * you may call find_execable again with this PATHp to continue | ||
| 27 | * (if it's not NULL). | ||
| 28 | * return NULL otherwise; (PATHp is undefined) | ||
| 29 | * in all cases (*PATHp) contents will be trashed (s/:/NUL/). | ||
| 25 | */ | 30 | */ |
| 26 | char *find_execable(const char *filename) | 31 | char *find_execable(const char *filename, char **PATHp) |
| 27 | { | 32 | { |
| 28 | char *path, *p, *n; | 33 | char *p, *n; |
| 29 | 34 | ||
| 30 | p = path = xstrdup(getenv("PATH")); | 35 | p = *PATHp; |
| 31 | while (p) { | 36 | while (p) { |
| 32 | n = strchr(p, ':'); | 37 | n = strchr(p, ':'); |
| 33 | if (n) | 38 | if (n) |
| @@ -35,15 +40,14 @@ char *find_execable(const char *filename) | |||
| 35 | if (*p != '\0') { /* it's not a PATH="foo::bar" situation */ | 40 | if (*p != '\0') { /* it's not a PATH="foo::bar" situation */ |
| 36 | p = concat_path_file(p, filename); | 41 | p = concat_path_file(p, filename); |
| 37 | if (execable_file(p)) { | 42 | if (execable_file(p)) { |
| 38 | free(path); | 43 | *PATHp = n; |
| 39 | return p; | 44 | return p; |
| 40 | } | 45 | } |
| 41 | free(p); | 46 | free(p); |
| 42 | } | 47 | } |
| 43 | p = n; | 48 | p = n; |
| 44 | } | 49 | } /* on loop exit p == NULL */ |
| 45 | free(path); | 50 | return p; |
| 46 | return NULL; | ||
| 47 | } | 51 | } |
| 48 | 52 | ||
| 49 | /* search $PATH for an executable file; | 53 | /* search $PATH for an executable file; |
| @@ -52,7 +56,10 @@ char *find_execable(const char *filename) | |||
| 52 | */ | 56 | */ |
| 53 | int exists_execable(const char *filename) | 57 | int exists_execable(const char *filename) |
| 54 | { | 58 | { |
| 55 | char *ret = find_execable(filename); | 59 | char *path = xstrdup(getenv("PATH")); |
| 60 | char *tmp = path; | ||
| 61 | char *ret = find_execable(filename, &tmp); | ||
| 62 | free(path); | ||
| 56 | if (ret) { | 63 | if (ret) { |
| 57 | free(ret); | 64 | free(ret); |
| 58 | return 1; | 65 | return 1; |
