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
No binary (build failed)
—
(log yok)
| @@ -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(); | |
| @@ -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 | |
| @@ -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); | |
| } | |
| @@ -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); | |
| @@ -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 | |