aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/appletlib.c6
-rw-r--r--libbb/executable.c52
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
285static int external_exists(const char *name, const char *path) 285static 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 */
36char* FAST_FUNC find_executable(const char *filename, char **PATHp) 33char* 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 */
85int FAST_FUNC executable_exists(const char *filename) 91int 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}