Implemented bb_system using spawn_and_wait in conjuction with "sh", to allow bb_system to execute the internal shell when using the FEATURE_PREFER_APPLETS config option.
This feature requires "sh" to be masked to some shell applet, as many applets use system to execute commands, and this call should be handled by the internal shell to allow for further applet execution. This requirement is enforced using a new dependency for FEATURE_PREFER_APPLETS, which is !SH_IS_NONE. When FEATURE_PREFER_APPLETS is disabled, libc "system()" is used. Signed-off-by: Nadav Tasher <tasherna...@gmail.com> --- Config.in | 1 + include/libbb.h | 1 + libbb/vfork_daemon_rexec.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/Config.in b/Config.in index bdf55b412..9fd5f3d7c 100644 --- a/Config.in +++ b/Config.in @@ -298,6 +298,7 @@ config FEATURE_SUID_CONFIG_QUIET config FEATURE_PREFER_APPLETS bool "exec prefers applets" default n + depends on !SH_IS_NONE help This is an experimental option which directs applets about to call 'exec' to try and find an applicable busybox applet before diff --git a/include/libbb.h b/include/libbb.h index e482cdd12..ada034c63 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1304,6 +1304,7 @@ int wait_for_exitstatus(pid_t pid) FAST_FUNC; /************************************************************************/ /* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */ int spawn_and_wait(char **argv) FAST_FUNC; +int bb_system(const char *command) FAST_FUNC; /* Does NOT check that applet is NOFORK, just blindly runs it */ int run_nofork_applet(int applet_no, char **argv) FAST_FUNC; void run_noexec_applet_and_exit(int a, const char *name, char **argv) NORETURN FAST_FUNC; diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index a3de7e742..9587f2716 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -249,6 +249,42 @@ int FAST_FUNC spawn_and_wait(char **argv) return wait4pid(rc); } +int FAST_FUNC bb_system(const char *command) { +#if ENABLE_FEATURE_PREFER_APPLETS + int exit_code; + char *system_argv[4]; + + /* when command is NULL, return a nonzero value, + * This indicates there is a shell available. + */ + if (command == NULL) + return 1; + + /* we use sh because it might launch ash or hush, + * and this is also what system() does. */ + system_argv[0] = xstrdup("sh"); + system_argv[1] = xstrdup("-c"); + + /* we must ensure command stays unchanged. */ + system_argv[2] = xstrdup(command); + + /* terminate array for good measure */ + system_argv[3] = NULL; + + /* spawn the shell and wait for it to return. */ + exit_code = spawn_and_wait(system_argv); + + /* free the duplicated strings */ + free(system_argv[0]); + free(system_argv[1]); + free(system_argv[2]); + + return exit_code; +#else + return system(command); +#endif +} + #if !BB_MMU void FAST_FUNC re_exec(char **argv) { -- 2.43.0 _______________________________________________ busybox mailing list busybox@busybox.net https://lists.busybox.net/mailman/listinfo/busybox