diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/appletlib.c | 6 | ||||
-rw-r--r-- | libbb/executable.c | 52 |
2 files changed, 32 insertions, 26 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 27ce8a6e8..d6e042775 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -284,12 +284,12 @@ int FAST_FUNC find_applet_by_name(const char *name) | |||
284 | # if ENABLE_FEATURE_SH_STANDALONE || ENABLE_FEATURE_PREFER_APPLETS | 284 | # if ENABLE_FEATURE_SH_STANDALONE || ENABLE_FEATURE_PREFER_APPLETS |
285 | static int external_exists(const char *name, const char *path) | 285 | static int external_exists(const char *name, const char *path) |
286 | { | 286 | { |
287 | char *path0, *path1, *ret; | 287 | const char *path0, *path1, *ret; |
288 | 288 | ||
289 | path0 = path1 = xstrdup(path ?: getenv("PATH")); | 289 | path0 = path1 = xstrdup(path ?: getenv("PATH")); |
290 | ret = find_executable(name, &path1); | 290 | ret = find_executable(name, &path1); |
291 | free(ret); | 291 | free((void *)ret); |
292 | free(path0); | 292 | free((void *)path0); |
293 | return ret != NULL; | 293 | return ret != NULL; |
294 | } | 294 | } |
295 | 295 | ||
diff --git a/libbb/executable.c b/libbb/executable.c index 606bec986..263141912 100644 --- a/libbb/executable.c +++ b/libbb/executable.c | |||
@@ -26,14 +26,11 @@ int FAST_FUNC file_is_executable(const char *name) | |||
26 | /* search (*PATHp) for an executable file; | 26 | /* search (*PATHp) for an executable file; |
27 | * return allocated string containing full path if found; | 27 | * return allocated string containing full path if found; |
28 | * PATHp points to the component after the one where it was found | 28 | * PATHp points to the component after the one where it was found |
29 | * (or NULL), | 29 | * (or NULL if found in last component), |
30 | * you may call find_executable again with this PATHp to continue | 30 | * you may call find_executable again with this PATHp to continue |
31 | * (if it's not NULL). | 31 | * return NULL otherwise (PATHp is undefined) |
32 | * return NULL otherwise; (PATHp is undefined) | ||
33 | * in all cases (*PATHp) contents are temporarily modified | ||
34 | * but are restored on return (s/:/NUL/ and back). | ||
35 | */ | 32 | */ |
36 | char* FAST_FUNC find_executable(const char *filename, char **PATHp) | 33 | char* FAST_FUNC find_executable(const char *name, const char **PATHp) |
37 | { | 34 | { |
38 | /* About empty components in $PATH: | 35 | /* About empty components in $PATH: |
39 | * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html | 36 | * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html |
@@ -43,18 +40,27 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp) | |||
43 | * initial colon preceding the rest of the list, or as a trailing colon | 40 | * initial colon preceding the rest of the list, or as a trailing colon |
44 | * following the rest of the list. | 41 | * following the rest of the list. |
45 | */ | 42 | */ |
46 | char *p, *n; | 43 | char *p = (char*) *PATHp; |
47 | 44 | ||
48 | p = *PATHp; | 45 | if (!p) |
49 | while (p) { | 46 | return NULL; |
47 | while (1) { | ||
48 | const char *end = strchrnul(p, PATH_SEP); | ||
49 | int sz = end - p; | ||
50 | int ex; | 50 | int ex; |
51 | 51 | ||
52 | n = strchr(p, PATH_SEP); | 52 | if (sz != 0) { |
53 | if (n) *n = '\0'; | 53 | p = xasprintf("%.*s/%s", sz, p, name); |
54 | p = concat_path_file( | 54 | } else { |
55 | p[0] ? p : ".", /* handle "::" case */ | 55 | /* We have xxx::yyy in $PATH, |
56 | filename | 56 | * it means "use current dir" */ |
57 | ); | 57 | p = xstrdup(name); |
58 | // A bit of discrepancy wrt the path used if file is found here. | ||
59 | // bash 5.2.15 "type" returns "./NAME". | ||
60 | // GNU which v2.21 returns "/CUR/DIR/NAME". | ||
61 | // With -a, both skip over all colons: xxx::::yyy is the same as xxx::yyy, | ||
62 | // current dir is not tried the second time. | ||
63 | } | ||
58 | #if ENABLE_PLATFORM_MINGW32 | 64 | #if ENABLE_PLATFORM_MINGW32 |
59 | { | 65 | { |
60 | char *w = file_is_win32_exe(p); | 66 | char *w = file_is_win32_exe(p); |
@@ -67,25 +73,25 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp) | |||
67 | #else | 73 | #else |
68 | ex = file_is_executable(p); | 74 | ex = file_is_executable(p); |
69 | #endif | 75 | #endif |
70 | if (n) *n++ = PATH_SEP; | ||
71 | if (ex) { | 76 | if (ex) { |
72 | *PATHp = n; | 77 | *PATHp = (*end ? end+1 : NULL); |
73 | return p; | 78 | return p; |
74 | } | 79 | } |
75 | free(p); | 80 | free(p); |
76 | p = n; | 81 | if (*end == '\0') |
77 | } /* on loop exit p == NULL */ | 82 | return NULL; |
78 | return p; | 83 | p = (char *) end + 1; |
84 | } | ||
79 | } | 85 | } |
80 | 86 | ||
81 | /* search $PATH for an executable file; | 87 | /* search $PATH for an executable file; |
82 | * return 1 if found; | 88 | * return 1 if found; |
83 | * return 0 otherwise; | 89 | * return 0 otherwise; |
84 | */ | 90 | */ |
85 | int FAST_FUNC executable_exists(const char *filename) | 91 | int FAST_FUNC executable_exists(const char *name) |
86 | { | 92 | { |
87 | char *path = getenv("PATH"); | 93 | const char *path = getenv("PATH"); |
88 | char *ret = find_executable(filename, &path); | 94 | char *ret = find_executable(name, &path); |
89 | free(ret); | 95 | free(ret); |
90 | return ret != NULL; | 96 | return ret != NULL; |
91 | } | 97 | } |