From 831a20f51246cd8d54a246ba7e239a062eeb002c Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Thu, 12 Apr 2007 12:27:32 +0000 Subject: [PATCH] pass a copy of argv[i] to NOFORK applets (they may permute it etc). set/save/restore more shared global variables whan call one applet from another --- applets/applets.c | 6 +++++- libbb/vfork_daemon_rexec.c | 32 ++++++++++++++++++-------------- shell/hush.c | 3 +-- shell/lash.c | 26 ++++++++++++++------------ shell/msh.c | 1 - 5 files changed, 38 insertions(+), 30 deletions(-) diff --git a/applets/applets.c b/applets/applets.c index bbb545a84..82a7eeea1 100644 --- a/applets/applets.c +++ b/applets/applets.c @@ -33,7 +33,7 @@ #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE /* Define usage_messages[] */ -static const char usage_messages[] = +static const char usage_messages[] = "" #define MAKE_USAGE #include "usage.h" #include "applets.h" @@ -590,6 +590,10 @@ static int busybox_main(int argc, char **argv) void run_current_applet_and_exit(int argc, char **argv) { + /* Reinit some shared global data */ + optind = 1; + xfunc_error_retval = EXIT_FAILURE; + applet_name = current_applet->name; if (argc == 2 && !strcmp(argv[1], "--help")) bb_show_usage(); diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index ce5a627ed..7dbc152e2 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -119,11 +119,16 @@ int spawn_and_wait(char **argv) if (a->nofork) #endif { - int old_sleep = die_sleep; + /* Save some shared globals */ + const struct bb_applet *old_a = current_applet; int old_x = xfunc_error_retval; uint32_t old_m = option_mask32; + int old_sleep = die_sleep; + current_applet = a; + applet_name = a->name; xfunc_error_retval = EXIT_FAILURE; + /*option_mask32 = 0; - not needed */ /* special flag for xfunc_die(). If xfunc will "die" * in NOFORK applet, xfunc_die() sees negative * die_sleep and longjmp here instead. */ @@ -131,25 +136,24 @@ int spawn_and_wait(char **argv) rc = setjmp(die_jmp); if (!rc) { - const struct bb_applet *old_a = current_applet; - current_applet = a; - applet_name = a->name; -// what else should we save/restore? -// TODO: what if applet will mangle argv vector? -// xargs needs argv untouched because it frees argv[i]! -// shouldn't we pass a copy? - rc = a->main(argc, argv); - current_applet = old_a; - applet_name = old_a->name; - } else { - /* xfunc died in NOFORK applet */ + /* Some callers (xargs) + * need argv untouched because they free argv[i]! */ + char *tmp_argv[argc+1]; + memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); + /* Finally we can call NOFORK applet's main() */ + rc = a->main(argc, tmp_argv); + } else { /* xfunc died in NOFORK applet */ + /* in case they meant to return 0... */ if (rc == -111) rc = 0; } - die_sleep = old_sleep; + /* Restoring globals */ + current_applet = old_a; + applet_name = old_a->name; xfunc_error_retval = old_x; option_mask32 = old_m; + die_sleep = old_sleep; return rc; } #if BB_MMU diff --git a/shell/hush.c b/shell/hush.c index 1ad61e54e..9af7f5105 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1119,8 +1119,7 @@ static void pseudo_exec(struct child_prog *child) /* Count argc for use in a second... */ for (argc_l = 0; *argv_l; argv_l++, argc_l++) - /**/; - optind = 1; + continue; debug_printf("running applet %s\n", name); run_applet_and_exit(name, argc_l, child->argv); } diff --git a/shell/lash.c b/shell/lash.c index c72a65639..5f2dacd18 100644 --- a/shell/lash.c +++ b/shell/lash.c @@ -32,6 +32,7 @@ #define ENABLE_LASH_PIPE_N_REDIRECTS 1 #define ENABLE_LASH_JOB_CONTROL 1 + enum { MAX_READ = 128 }; /* size of input buffer for 'read' builtin */ #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" @@ -310,7 +311,7 @@ static int builtin_help(struct child_prog ATTRIBUTE_UNUSED *dummy) const struct built_in_command *x; printf("\nBuilt-in commands:\n" - "-------------------\n"); + "-------------------\n"); for (x = bltins; x->cmd; x++) { if (x->descr == NULL) continue; @@ -408,12 +409,12 @@ static int builtin_read(struct child_prog *child) ** the string resides in a static buffer!) */ res = -1; - if ((s = strdup(string))) + s = strdup(string); + if (s) res = putenv(s); if (res) bb_perror_msg("read"); - } - else + } else fgets(string, sizeof(string), stdin); return res; @@ -1167,8 +1168,8 @@ static int pseudo_exec(struct child_prog *child) char **argv_l = child->argv; int argc_l; - for (argc_l = 0; *argv_l; argv_l++, argc_l++); - optind = 1; + for (argc_l = 0; *argv_l; argv_l++, argc_l++) + continue; run_applet_and_exit(child->argv[0], argc_l, child->argv); } @@ -1234,7 +1235,7 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) nextin = 0, nextout = 1; for (i = 0; i < newjob->num_progs; i++) { - child = & (newjob->progs[i]); + child = &(newjob->progs[i]); if ((i + 1) < newjob->num_progs) { if (pipe(pipefds) < 0) @@ -1275,11 +1276,11 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) } #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__) - if (!(child->pid = fork())) + child->pid = fork(); #else - if (!(child->pid = vfork())) + child->pid = vfork(); #endif - { + if (!child->pid) { /* Set the handling for job control signals back to the default. */ signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); @@ -1473,8 +1474,9 @@ static void setup_job_control(void) pid_t shell_pgrp; /* Loop until we are in the foreground. */ - while ((status = tcgetpgrp (shell_terminal)) >= 0) { - if (status == (shell_pgrp = getpgrp ())) { + while ((status = tcgetpgrp(shell_terminal)) >= 0) { + shell_pgrp = getpgrp(); + if (status == shell_pgrp) { break; } kill(- shell_pgrp, SIGTTIN); diff --git a/shell/msh.c b/shell/msh.c index 4d1e84cf0..861abe234 100644 --- a/shell/msh.c +++ b/shell/msh.c @@ -3065,7 +3065,6 @@ static const char *rexecve(char *c, char **v, char **envp) char *name = c; if (ENABLE_FEATURE_SH_STANDALONE) { - optind = 1; if (find_applet_by_name(name)) { /* We have to exec here since we vforked. Running * run_applet_and_exit() won't work and bad things