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
This commit is contained in:
Denis Vlasenko 2007-04-12 12:27:32 +00:00
parent c98c31783c
commit 831a20f512
5 changed files with 38 additions and 30 deletions

View File

@ -33,7 +33,7 @@
#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
/* Define usage_messages[] */ /* Define usage_messages[] */
static const char usage_messages[] = static const char usage_messages[] = ""
#define MAKE_USAGE #define MAKE_USAGE
#include "usage.h" #include "usage.h"
#include "applets.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) 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; applet_name = current_applet->name;
if (argc == 2 && !strcmp(argv[1], "--help")) if (argc == 2 && !strcmp(argv[1], "--help"))
bb_show_usage(); bb_show_usage();

View File

@ -119,11 +119,16 @@ int spawn_and_wait(char **argv)
if (a->nofork) if (a->nofork)
#endif #endif
{ {
int old_sleep = die_sleep; /* Save some shared globals */
const struct bb_applet *old_a = current_applet;
int old_x = xfunc_error_retval; int old_x = xfunc_error_retval;
uint32_t old_m = option_mask32; uint32_t old_m = option_mask32;
int old_sleep = die_sleep;
current_applet = a;
applet_name = a->name;
xfunc_error_retval = EXIT_FAILURE; xfunc_error_retval = EXIT_FAILURE;
/*option_mask32 = 0; - not needed */
/* special flag for xfunc_die(). If xfunc will "die" /* special flag for xfunc_die(). If xfunc will "die"
* in NOFORK applet, xfunc_die() sees negative * in NOFORK applet, xfunc_die() sees negative
* die_sleep and longjmp here instead. */ * die_sleep and longjmp here instead. */
@ -131,25 +136,24 @@ int spawn_and_wait(char **argv)
rc = setjmp(die_jmp); rc = setjmp(die_jmp);
if (!rc) { if (!rc) {
const struct bb_applet *old_a = current_applet; /* Some callers (xargs)
current_applet = a; * need argv untouched because they free argv[i]! */
applet_name = a->name; char *tmp_argv[argc+1];
// what else should we save/restore? memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
// TODO: what if applet will mangle argv vector? /* Finally we can call NOFORK applet's main() */
// xargs needs argv untouched because it frees argv[i]! rc = a->main(argc, tmp_argv);
// shouldn't we pass a copy? } else { /* xfunc died in NOFORK applet */
rc = a->main(argc, argv); /* in case they meant to return 0... */
current_applet = old_a;
applet_name = old_a->name;
} else {
/* xfunc died in NOFORK applet */
if (rc == -111) if (rc == -111)
rc = 0; rc = 0;
} }
die_sleep = old_sleep; /* Restoring globals */
current_applet = old_a;
applet_name = old_a->name;
xfunc_error_retval = old_x; xfunc_error_retval = old_x;
option_mask32 = old_m; option_mask32 = old_m;
die_sleep = old_sleep;
return rc; return rc;
} }
#if BB_MMU #if BB_MMU

View File

@ -1119,8 +1119,7 @@ static void pseudo_exec(struct child_prog *child)
/* Count argc for use in a second... */ /* Count argc for use in a second... */
for (argc_l = 0; *argv_l; argv_l++, argc_l++) for (argc_l = 0; *argv_l; argv_l++, argc_l++)
/**/; continue;
optind = 1;
debug_printf("running applet %s\n", name); debug_printf("running applet %s\n", name);
run_applet_and_exit(name, argc_l, child->argv); run_applet_and_exit(name, argc_l, child->argv);
} }

View File

@ -32,6 +32,7 @@
#define ENABLE_LASH_PIPE_N_REDIRECTS 1 #define ENABLE_LASH_PIPE_N_REDIRECTS 1
#define ENABLE_LASH_JOB_CONTROL 1 #define ENABLE_LASH_JOB_CONTROL 1
enum { MAX_READ = 128 }; /* size of input buffer for 'read' builtin */ enum { MAX_READ = 128 }; /* size of input buffer for 'read' builtin */
#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
@ -408,12 +409,12 @@ static int builtin_read(struct child_prog *child)
** the string resides in a static buffer!) ** the string resides in a static buffer!)
*/ */
res = -1; res = -1;
if ((s = strdup(string))) s = strdup(string);
if (s)
res = putenv(s); res = putenv(s);
if (res) if (res)
bb_perror_msg("read"); bb_perror_msg("read");
} } else
else
fgets(string, sizeof(string), stdin); fgets(string, sizeof(string), stdin);
return res; return res;
@ -1167,8 +1168,8 @@ static int pseudo_exec(struct child_prog *child)
char **argv_l = child->argv; char **argv_l = child->argv;
int argc_l; int argc_l;
for (argc_l = 0; *argv_l; argv_l++, argc_l++); for (argc_l = 0; *argv_l; argv_l++, argc_l++)
optind = 1; continue;
run_applet_and_exit(child->argv[0], argc_l, child->argv); run_applet_and_exit(child->argv[0], argc_l, child->argv);
} }
@ -1275,11 +1276,11 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
} }
#if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__) #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
if (!(child->pid = fork())) child->pid = fork();
#else #else
if (!(child->pid = vfork())) child->pid = vfork();
#endif #endif
{ if (!child->pid) {
/* Set the handling for job control signals back to the default. */ /* Set the handling for job control signals back to the default. */
signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL); signal(SIGQUIT, SIG_DFL);
@ -1474,7 +1475,8 @@ static void setup_job_control(void)
/* Loop until we are in the foreground. */ /* Loop until we are in the foreground. */
while ((status = tcgetpgrp(shell_terminal)) >= 0) { while ((status = tcgetpgrp(shell_terminal)) >= 0) {
if (status == (shell_pgrp = getpgrp ())) { shell_pgrp = getpgrp();
if (status == shell_pgrp) {
break; break;
} }
kill(- shell_pgrp, SIGTTIN); kill(- shell_pgrp, SIGTTIN);

View File

@ -3065,7 +3065,6 @@ static const char *rexecve(char *c, char **v, char **envp)
char *name = c; char *name = c;
if (ENABLE_FEATURE_SH_STANDALONE) { if (ENABLE_FEATURE_SH_STANDALONE) {
optind = 1;
if (find_applet_by_name(name)) { if (find_applet_by_name(name)) {
/* We have to exec here since we vforked. Running /* We have to exec here since we vforked. Running
* run_applet_and_exit() won't work and bad things * run_applet_and_exit() won't work and bad things