diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2024-10-08 04:03:17 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2024-10-08 04:03:17 +0200 |
commit | 49d9e06fbab0b02a71deed57610edb0c8f4fb20c (patch) | |
tree | 6b5263bcdb0972eaf17f35dbb8c2ce65d13a790e /libbb/executable.c | |
parent | 8c4bccb83e5e2594f16310b7cbe07bf05fc9f13a (diff) | |
download | busybox-w32-49d9e06fbab0b02a71deed57610edb0c8f4fb20c.tar.gz busybox-w32-49d9e06fbab0b02a71deed57610edb0c8f4fb20c.tar.bz2 busybox-w32-49d9e06fbab0b02a71deed57610edb0c8f4fb20c.zip |
libbb: modify find_executable() to not temporarily write to PATH
This allows to simplify "which" applet code
function old new delta
find_executable 93 111 +18
which_main 191 177 -14
builtin_source 316 294 -22
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/2 up/down: 18/-36) Total: -18 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb/executable.c')
-rw-r--r-- | libbb/executable.c | 56 |
1 files changed, 30 insertions, 26 deletions
diff --git a/libbb/executable.c b/libbb/executable.c index a033b74d9..09bed1eaf 100644 --- a/libbb/executable.c +++ b/libbb/executable.c | |||
@@ -21,14 +21,11 @@ int FAST_FUNC file_is_executable(const char *name) | |||
21 | /* search (*PATHp) for an executable file; | 21 | /* search (*PATHp) for an executable file; |
22 | * return allocated string containing full path if found; | 22 | * return allocated string containing full path if found; |
23 | * PATHp points to the component after the one where it was found | 23 | * PATHp points to the component after the one where it was found |
24 | * (or NULL), | 24 | * (or NULL if found in last component), |
25 | * you may call find_executable again with this PATHp to continue | 25 | * you may call find_executable again with this PATHp to continue |
26 | * (if it's not NULL). | 26 | * return NULL otherwise (PATHp is undefined) |
27 | * return NULL otherwise; (PATHp is undefined) | ||
28 | * in all cases (*PATHp) contents are temporarily modified | ||
29 | * but are restored on return (s/:/NUL/ and back). | ||
30 | */ | 27 | */ |
31 | char* FAST_FUNC find_executable(const char *filename, char **PATHp) | 28 | char* FAST_FUNC find_executable(const char *name, const char **PATHp) |
32 | { | 29 | { |
33 | /* About empty components in $PATH: | 30 | /* About empty components in $PATH: |
34 | * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html | 31 | * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html |
@@ -38,38 +35,45 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp) | |||
38 | * initial colon preceding the rest of the list, or as a trailing colon | 35 | * initial colon preceding the rest of the list, or as a trailing colon |
39 | * following the rest of the list. | 36 | * following the rest of the list. |
40 | */ | 37 | */ |
41 | char *p, *n; | 38 | char *p = (char*) *PATHp; |
42 | 39 | ||
43 | p = *PATHp; | 40 | if (!p) |
44 | while (p) { | 41 | return NULL; |
45 | int ex; | 42 | while (1) { |
43 | const char *end = strchrnul(p, ':'); | ||
44 | int sz = end - p; | ||
46 | 45 | ||
47 | n = strchr(p, ':'); | 46 | if (sz != 0) { |
48 | if (n) *n = '\0'; | 47 | p = xasprintf("%.*s/%s", sz, p, name); |
49 | p = concat_path_file( | 48 | } else { |
50 | p[0] ? p : ".", /* handle "::" case */ | 49 | /* We have xxx::yyy in $PATH, |
51 | filename | 50 | * it means "use current dir" */ |
52 | ); | 51 | p = xstrdup(name); |
53 | ex = file_is_executable(p); | 52 | // A bit of discrepancy wrt the path used if file is found here. |
54 | if (n) *n++ = ':'; | 53 | // bash 5.2.15 "type" returns "./NAME". |
55 | if (ex) { | 54 | // GNU which v2.21 returns "/CUR/DIR/NAME". |
56 | *PATHp = n; | 55 | // With -a, both skip over all colons: xxx::::yyy is the same as xxx::yyy, |
56 | // current dir is not tried the second time. | ||
57 | } | ||
58 | if (file_is_executable(p)) { | ||
59 | *PATHp = (*end ? end+1 : NULL); | ||
57 | return p; | 60 | return p; |
58 | } | 61 | } |
59 | free(p); | 62 | free(p); |
60 | p = n; | 63 | if (*end == '\0') |
61 | } /* on loop exit p == NULL */ | 64 | return NULL; |
62 | return p; | 65 | p = (char *) end + 1; |
66 | } | ||
63 | } | 67 | } |
64 | 68 | ||
65 | /* search $PATH for an executable file; | 69 | /* search $PATH for an executable file; |
66 | * return 1 if found; | 70 | * return 1 if found; |
67 | * return 0 otherwise; | 71 | * return 0 otherwise; |
68 | */ | 72 | */ |
69 | int FAST_FUNC executable_exists(const char *filename) | 73 | int FAST_FUNC executable_exists(const char *name) |
70 | { | 74 | { |
71 | char *path = getenv("PATH"); | 75 | const char *path = getenv("PATH"); |
72 | char *ret = find_executable(filename, &path); | 76 | char *ret = find_executable(name, &path); |
73 | free(ret); | 77 | free(ret); |
74 | return ret != NULL; | 78 | return ret != NULL; |
75 | } | 79 | } |