diff options
author | Ron Yorston <rmy@pobox.com> | 2023-06-04 08:00:51 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-06-04 08:00:51 +0100 |
commit | bd7018350d7e816a90dde97fa0a4abf41be17b4d (patch) | |
tree | f28f42c8139dd1b9aae339ef0c9b69356c6c9acc | |
parent | e013876e1dc0ce8e3a36abea9390d35a7053bd84 (diff) | |
download | busybox-w32-bd7018350d7e816a90dde97fa0a4abf41be17b4d.tar.gz busybox-w32-bd7018350d7e816a90dde97fa0a4abf41be17b4d.tar.bz2 busybox-w32-bd7018350d7e816a90dde97fa0a4abf41be17b4d.zip |
win32: another BB_OVERRIDE_APPLETS fix
Support for conditionally replacing applets with external commands
requires the ability to check whether a given command name is
present on PATH. This was being done using the PATH environment
variable, which works in commands run by the shell but not in the
shell itself.
- The shell uses the *shell* variable PATH to look for executables.
This may not be the same as the *environment* variable.
- 'command -p' uses an entirely different PATH.
Applet look-up in the shell is now treated as a special case, with
the actual PATH being used passed to the look-up code in a global
variable.
This doesn't affect tab completion in the shell: whether a
completion is an applet or an external command is irrelevant.
Costs 152-288 bytes.
(GitHub issue #329)
-rw-r--r-- | include/libbb.h | 3 | ||||
-rw-r--r-- | libbb/appletlib.c | 9 | ||||
-rw-r--r-- | shell/ash.c | 42 |
3 files changed, 48 insertions, 6 deletions
diff --git a/include/libbb.h b/include/libbb.h index a4eebab99..1200e636a 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1330,6 +1330,9 @@ int find_preferred_applet_by_name(const char *name) FAST_FUNC; | |||
1330 | int is_applet_preferred(const char *name) FAST_FUNC; | 1330 | int is_applet_preferred(const char *name) FAST_FUNC; |
1331 | # if ENABLE_PLATFORM_MINGW32 && \ | 1331 | # if ENABLE_PLATFORM_MINGW32 && \ |
1332 | (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE) | 1332 | (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE) |
1333 | # if ENABLE_ASH | ||
1334 | extern const char *ash_path; | ||
1335 | # endif | ||
1333 | # define find_applet_by_name(n) find_preferred_applet_by_name(n) | 1336 | # define find_applet_by_name(n) find_preferred_applet_by_name(n) |
1334 | # else | 1337 | # else |
1335 | # define is_applet_preferred(n) (1) | 1338 | # define is_applet_preferred(n) (1) |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index b5ea90ffd..10268b982 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -263,9 +263,16 @@ int FAST_FUNC find_applet_by_name(const char *name) | |||
263 | 263 | ||
264 | #if ENABLE_PLATFORM_MINGW32 && NUM_APPLETS > 1 && \ | 264 | #if ENABLE_PLATFORM_MINGW32 && NUM_APPLETS > 1 && \ |
265 | (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE) | 265 | (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE) |
266 | # if ENABLE_ASH | ||
267 | const char *ash_path = NULL; | ||
268 | # else | ||
269 | # define ash_path NULL | ||
270 | # endif | ||
271 | |||
266 | static int external_exists(const char *name) | 272 | static int external_exists(const char *name) |
267 | { | 273 | { |
268 | char *ret = find_first_executable(name); | 274 | char *path = ash_path ? auto_string(xstrdup(ash_path)) : getenv("PATH"); |
275 | char *ret = find_executable(name, &path); | ||
269 | free(ret); | 276 | free(ret); |
270 | return ret != NULL; | 277 | return ret != NULL; |
271 | } | 278 | } |
diff --git a/shell/ash.c b/shell/ash.c index 07319dbdf..7fa75721e 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -426,6 +426,38 @@ static void forkshell_print(FILE *fp0, struct forkshell *fs, const char **notes) | |||
426 | # endif | 426 | # endif |
427 | #endif | 427 | #endif |
428 | 428 | ||
429 | #if ENABLE_PLATFORM_MINGW32 && NUM_APPLETS > 1 && \ | ||
430 | (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE) | ||
431 | static int | ||
432 | ash_preferred_applet_by_name(const char *name, const char *path) | ||
433 | { | ||
434 | int ret; | ||
435 | |||
436 | ash_path = path; | ||
437 | ret = find_preferred_applet_by_name(name); | ||
438 | ash_path = NULL; | ||
439 | |||
440 | return ret; | ||
441 | } | ||
442 | |||
443 | static int | ||
444 | ash_applet_preferred(const char *name, const char *path) | ||
445 | { | ||
446 | int ret; | ||
447 | |||
448 | ash_path = path; | ||
449 | ret = is_applet_preferred(name); | ||
450 | ash_path = NULL; | ||
451 | |||
452 | return ret; | ||
453 | } | ||
454 | # undef find_applet_by_name | ||
455 | # define find_applet_by_name(n, p) ash_preferred_applet_by_name(n, p) | ||
456 | # define is_applet_preferred(n, p) ash_applet_preferred(n, p) | ||
457 | #else | ||
458 | # define find_applet_by_name(n, p) find_applet_by_name(n) | ||
459 | #endif | ||
460 | |||
429 | /* ============ Hash table sizes. Configurable. */ | 461 | /* ============ Hash table sizes. Configurable. */ |
430 | 462 | ||
431 | #define VTABSIZE 39 | 463 | #define VTABSIZE 39 |
@@ -9113,7 +9145,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) | |||
9113 | if (has_path(prog) | 9145 | if (has_path(prog) |
9114 | #endif | 9146 | #endif |
9115 | #if ENABLE_FEATURE_SH_STANDALONE | 9147 | #if ENABLE_FEATURE_SH_STANDALONE |
9116 | || (applet_no = find_applet_by_name(prog)) >= 0 | 9148 | || (applet_no = find_applet_by_name(prog, path)) >= 0 |
9117 | #endif | 9149 | #endif |
9118 | ) { | 9150 | ) { |
9119 | #if ENABLE_PLATFORM_MINGW32 | 9151 | #if ENABLE_PLATFORM_MINGW32 |
@@ -9134,7 +9166,7 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) | |||
9134 | if (unix_path(prog)) { | 9166 | if (unix_path(prog)) { |
9135 | const char *name = bb_basename(prog); | 9167 | const char *name = bb_basename(prog); |
9136 | # if ENABLE_FEATURE_SH_STANDALONE | 9168 | # if ENABLE_FEATURE_SH_STANDALONE |
9137 | if ((applet_no = find_applet_by_name(name)) >= 0) { | 9169 | if ((applet_no = find_applet_by_name(name, path)) >= 0) { |
9138 | tryexec(applet_no, name, argv, envp); | 9170 | tryexec(applet_no, name, argv, envp); |
9139 | e = errno; | 9171 | e = errno; |
9140 | } | 9172 | } |
@@ -14939,7 +14971,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
14939 | name = (char *)bb_basename(name); | 14971 | name = (char *)bb_basename(name); |
14940 | if ( | 14972 | if ( |
14941 | # if ENABLE_FEATURE_SH_STANDALONE | 14973 | # if ENABLE_FEATURE_SH_STANDALONE |
14942 | find_applet_by_name(name) >= 0 || | 14974 | find_applet_by_name(name, path) >= 0 || |
14943 | # endif | 14975 | # endif |
14944 | !find_builtin(bb_basename(name)) | 14976 | !find_builtin(bb_basename(name)) |
14945 | ) { | 14977 | ) { |
@@ -15010,7 +15042,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
15010 | 15042 | ||
15011 | #if ENABLE_FEATURE_SH_STANDALONE | 15043 | #if ENABLE_FEATURE_SH_STANDALONE |
15012 | { | 15044 | { |
15013 | int applet_no = find_applet_by_name(name); | 15045 | int applet_no = find_applet_by_name(name, path); |
15014 | if (applet_no >= 0) { | 15046 | if (applet_no >= 0) { |
15015 | entry->cmdtype = CMDNORMAL; | 15047 | entry->cmdtype = CMDNORMAL; |
15016 | entry->u.index = -2 - applet_no; | 15048 | entry->u.index = -2 - applet_no; |
@@ -15259,7 +15291,7 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
15259 | { | 15291 | { |
15260 | const char *a = applet_names; | 15292 | const char *a = applet_names; |
15261 | while (*a) { | 15293 | while (*a) { |
15262 | if (is_applet_preferred(a)) { | 15294 | if (is_applet_preferred(a, pathval())) { |
15263 | col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a); | 15295 | col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a); |
15264 | if (col > 60) { | 15296 | if (col > 60) { |
15265 | out1fmt("\n"); | 15297 | out1fmt("\n"); |