From ecdc5b3ffabb58e3a9fc3a55a2a44323644995fc Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 6 May 2022 12:31:21 +0100 Subject: win32: allow preference for applets to be disabled at runtime The default busybox-w32 configuration enables the PREFER_APPLETS and SH_STANDALONE features. Sometimes it may be desirable to override the default preference for applets, for example, if an applet needs to be replaced by an external program with additional features. Add support for the environment variable BB_OVERRIDE_APPLETS. Its value may be: - a single dash ('-'): all applets are overridden; - a space-separated list of names: only the specified applets are overridden. --- include/libbb.h | 8 ++++++++ libbb/appletlib.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ libbb/lineedit.c | 2 +- shell/ash.c | 10 ++++++---- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 740c25528..482fcce0c 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1320,6 +1320,14 @@ void run_noexec_applet_and_exit(int a, const char *name, char **argv) NORETURN F #ifndef BUILD_INDIVIDUAL int find_applet_by_name(const char *name) FAST_FUNC; void run_applet_no_and_exit(int a, const char *name, char **argv) NORETURN FAST_FUNC; +int find_preferred_applet_by_name(const char *name) FAST_FUNC; +int is_applet_preferred(const char *name) FAST_FUNC; +# if ENABLE_PLATFORM_MINGW32 && \ + (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE) +# define find_applet_by_name(n) find_preferred_applet_by_name(n) +# else +# define is_applet_preferred(n) (1) +# endif #endif void show_usage_if_dash_dash_help(int applet_no, char **argv) FAST_FUNC; #if defined(__linux__) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index aa442144a..8d58ce2ea 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -76,6 +76,13 @@ static inline int *get_perrno(void) { return &errno; } static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS }; #endif +#if defined(find_applet_by_name) +# undef find_applet_by_name +#endif +#if defined(is_applet_preferred) +# undef is_applet_preferred +#endif + /* "Do not compress usage text if uncompressed text is small * and we don't include bunzip2 code for other reasons" * @@ -254,6 +261,45 @@ int FAST_FUNC find_applet_by_name(const char *name) return -1; } +#if ENABLE_PLATFORM_MINGW32 && NUM_APPLETS > 1 && \ + (ENABLE_FEATURE_PREFER_APPLETS || ENABLE_FEATURE_SH_STANDALONE) +int FAST_FUNC is_applet_preferred(const char *name) +{ + const char *var, *s; + size_t len; + + var = getenv("BB_OVERRIDE_APPLETS"); + if (var && *var) { + /* '-' overrides all applets */ + if (var[0] == '-' && var[1] == '\0') + return FALSE; + + /* Override applets from a space-separated list */ + len = strlen(name); + s = var - 1; + while (1) { + s = strstr(s + 1, name); + if (!s) + break; + /* neither "name.." nor "xxx,name.."? */ + if (s != var && s[-1] != ' ') + continue; + /* neither "..name" nor "..name,xxx"? */ + if (s[len] != '\0' && s[len] != ' ') + continue; + return FALSE; + } + } + return TRUE; +} + +int FAST_FUNC find_preferred_applet_by_name(const char *name) +{ + int applet_no = find_applet_by_name(name); + return applet_no >= 0 && is_applet_preferred(name) ? applet_no : -1; +} +#endif + void lbb_prepare(const char *applet IF_FEATURE_INDIVIDUAL(, char **argv)) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 778511d16..4f68547eb 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -926,7 +926,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) # if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 const char *p = applet_names; while (*p) { - if (strncmp(basecmd, p, baselen) == 0) + if (strncmp(basecmd, p, baselen) == 0 && is_applet_preferred(p)) add_match(xstrdup(p)); while (*p++ != '\0') continue; diff --git a/shell/ash.c b/shell/ash.c index 6c1e58d6f..f42dc49c3 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -14961,10 +14961,12 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { const char *a = applet_names; while (*a) { - col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a); - if (col > 60) { - out1fmt("\n"); - col = 0; + if (is_applet_preferred(a)) { + col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a); + if (col > 60) { + out1fmt("\n"); + col = 0; + } } while (*a++ != '\0') continue; -- cgit v1.2.3-55-g6feb