pass a copy of argv[i] to NOFORK applets (they may permute it etc).
authorDenis Vlasenko <vda.linux@googlemail.com>
Thu, 12 Apr 2007 12:27:32 +0000 (12:27 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Thu, 12 Apr 2007 12:27:32 +0000 (12:27 -0000)
set/save/restore more shared global variables whan call one applet from another

applets/applets.c
libbb/vfork_daemon_rexec.c
shell/hush.c
shell/lash.c
shell/msh.c

index bbb545a..82a7eee 100644 (file)
@@ -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();
index ce5a627..7dbc152 100644 (file)
@@ -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
index 1ad61e5..9af7f51 100644 (file)
@@ -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);
                }
index c72a656..5f2dacd 100644 (file)
@@ -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);
index 4d1e84c..861abe2 100644 (file)
@@ -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