In standalone shell mode applets can be run from the shell without having to install symlinks to them. You don't even need to set PATH. Tab-completion also works. This makes minimal deployments of BusyBox very easy to set up. For example, a container can be created with just the BusyBox binary installed as /bin/sh.
There's one exception: since 'busybox' isn't an applet it won't run in standalone shell mode without being installed on the path. This patch adds special treatment for 'busybox' in standalone shell mode so tab-completion and execution from the shell both work. function old new delta tryexec - 175 +175 add_partial_match - 35 +35 find_command 952 978 +26 complete_cmd_dir_file 891 882 -9 shellexec 498 316 -182 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 1/2 up/down: 236/-191) Total: 45 bytes These extra bytes are only required if standalone shell mode is enabled, which it isn't in the default configuration. Signed-off-by: Ron Yorston <[email protected]> --- libbb/lineedit.c | 12 ++++++++++-- shell/ash.c | 15 +++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 2a5d4e704..c0e36d8b4 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -638,6 +638,14 @@ static void add_match(char *matched) num_matches++; } +#if ENABLE_FEATURE_SH_STANDALONE && NUM_APPLETS != 1 +static void add_partial_match(const char *part, const char *full, int plen) +{ + if (strncmp(part, full, plen) == 0) + add_match(xstrdup(full)); + } +#endif + # if ENABLE_FEATURE_USERNAME_COMPLETION /* Replace "~user/..." with "/homedir/...". * The parameter is malloced, free it or return it @@ -781,11 +789,11 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) const char *p = applet_names; while (*p) { - if (strncmp(pfind, p, pf_len) == 0) - add_match(xstrdup(p)); + add_partial_match(pfind, p, pf_len); while (*p++ != '\0') continue; } + add_partial_match(pfind, "busybox", pf_len); } #endif diff --git a/shell/ash.c b/shell/ash.c index c96ec939e..199040c16 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -7690,7 +7690,8 @@ static int builtinloc = -1; /* index in path of %builtin, or -1 */ static void -tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp) +tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, + char **argv, char **envp) { #if ENABLE_FEATURE_SH_STANDALONE if (applet_no >= 0) { @@ -7715,7 +7716,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** #else execve(cmd, argv, envp); #endif - if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) { + if (cmd != bb_busybox_exec_path && errno == ENOEXEC) { /* Run "cmd" as a shell script: * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html * "If the execve() function fails with ENOEXEC, the shell @@ -7732,7 +7733,7 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char ** * message and exit code 126. For one, this prevents attempts * to interpret foreign ELF binaries as shell scripts. */ - argv[0] = cmd; + argv[0] = (char*) cmd; cmd = (char*) bb_busybox_exec_path; /* NB: this is only possible because all callers of shellexec() * ensure that the argv[-1] slot exists! @@ -7772,6 +7773,11 @@ static void shellexec(char *prog, char **argv, const char *path, int idx) goto try_PATH; } e = errno; +#if ENABLE_FEATURE_SH_STANDALONE + } else if (is_prefixed_with(argv[0], "busybox")) { + tryexec(-1, bb_busybox_exec_path, argv, envp); + e = errno; +#endif } else { try_PATH: e = ENOENT; @@ -12839,7 +12845,8 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) #if ENABLE_FEATURE_SH_STANDALONE { int applet_no = find_applet_by_name(name); - if (applet_no >= 0) { + /* applet_no is -1 on no match so u.index is -1 for busybox */ + if (applet_no >= 0 || is_prefixed_with(name, "busybox")) { entry->cmdtype = CMDNORMAL; entry->u.index = -2 - applet_no; return; -- 2.13.3 _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
