lash: recognize and use NOFORK applets
authorDenis Vlasenko <vda.linux@googlemail.com>
Sat, 14 Apr 2007 11:16:29 +0000 (11:16 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sat, 14 Apr 2007 11:16:29 +0000 (11:16 -0000)
lash,hush: fix kill buglet (didn't properly recognize ESRCH)

shell/hush.c
shell/lash.c

index 9362e59164c33f6cf52e52e0dbd677948494a60e..0b5e2a5de7960742cfa20307eda18e74ae367d83 100644 (file)
@@ -547,7 +547,7 @@ static int builtin_export(struct child_prog *child)
 static int builtin_fg_bg(struct child_prog *child)
 {
        int i, jobnum;
-       struct pipe *pi = NULL;
+       struct pipe *pi;
 
        if (!interactive)
                return EXIT_FAILURE;
@@ -555,29 +555,24 @@ static int builtin_fg_bg(struct child_prog *child)
        if (!child->argv[1]) {
                for (pi = job_list; pi; pi = pi->next) {
                        if (pi->jobid == last_jobid) {
-                               break;
-                       }
-               }
-               if (!pi) {
-                       bb_error_msg("%s: no current job", child->argv[0]);
-                       return EXIT_FAILURE;
-               }
-       } else {
-               if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
-                       bb_error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
-                       return EXIT_FAILURE;
-               }
-               for (pi = job_list; pi; pi = pi->next) {
-                       if (pi->jobid == jobnum) {
-                               break;
+                               goto found;
                        }
                }
-               if (!pi) {
-                       bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
-                       return EXIT_FAILURE;
+               bb_error_msg("%s: no current job", child->argv[0]);
+               return EXIT_FAILURE;
+       }
+       if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
+               bb_error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
+               return EXIT_FAILURE;
+       }
+       for (pi = job_list; pi; pi = pi->next) {
+               if (pi->jobid == jobnum) {
+                       goto found;
                }
        }
-
+       bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
+       return EXIT_FAILURE;
+ found:
        if (*child->argv[0] == 'f') {
                /* Put the job into the foreground.  */
                tcsetpgrp(shell_terminal, pi->pgrp);
@@ -589,7 +584,7 @@ static int builtin_fg_bg(struct child_prog *child)
 
        i = kill(- pi->pgrp, SIGCONT);
        if (i < 0) {
-               if (i == ESRCH) {
+               if (errno == ESRCH) {
                        remove_bg_job(pi);
                } else {
                        bb_perror_msg("kill (SIGCONT)");
index 6fe2ddc7627aa6f6313fc31cae93460d9d2ac8db..24e48c337d61fb83c6f4c2bc4803bd3c2da19af1 100644 (file)
@@ -257,35 +257,30 @@ static int builtin_exit(struct child_prog *child)
 static int builtin_fg_bg(struct child_prog *child)
 {
        int i, jobnum;
-       struct job *job = NULL;
+       struct job *job;
 
        /* If they gave us no args, assume they want the last backgrounded task */
        if (!child->argv[1]) {
                for (job = child->family->job_list->head; job; job = job->next) {
                        if (job->jobid == last_jobid) {
-                               break;
+                               goto found;
                        }
                }
-               if (!job) {
-                       bb_error_msg("%s: no current job", child->argv[0]);
-                       return EXIT_FAILURE;
-               }
-       } else {
-               if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
-                       bb_error_msg(bb_msg_invalid_arg, child->argv[1], child->argv[0]);
-                       return EXIT_FAILURE;
-               }
-               for (job = child->family->job_list->head; job; job = job->next) {
-                       if (job->jobid == jobnum) {
-                               break;
-                       }
-               }
-               if (!job) {
-                       bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
-                       return EXIT_FAILURE;
+               bb_error_msg("%s: no current job", child->argv[0]);
+               return EXIT_FAILURE;
+       }
+       if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
+               bb_error_msg(bb_msg_invalid_arg, child->argv[1], child->argv[0]);
+               return EXIT_FAILURE;
+       }
+       for (job = child->family->job_list->head; job; job = job->next) {
+               if (job->jobid == jobnum) {
+                       goto found;
                }
        }
-
+       bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
+       return EXIT_FAILURE;
+ found:
        if (*child->argv[0] == 'f') {
                /* Put the job into the foreground.  */
                tcsetpgrp(shell_terminal, job->pgrp);
@@ -301,7 +296,7 @@ static int builtin_fg_bg(struct child_prog *child)
 
        i = kill(- job->pgrp, SIGCONT);
        if (i < 0) {
-               if (i == ESRCH) {
+               if (errno == ESRCH) {
                        remove_job(&job_list, job);
                } else {
                        bb_perror_msg("kill (SIGCONT)");
@@ -1241,6 +1236,9 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
                 * is doomed to failure, and doesn't work on bash, either.
                 */
                if (newjob->num_progs == 1) {
+                       int rcode;
+                       int squirrel[] = {-1, -1, -1};
+
                        /* Check if the command sets an environment variable. */
                        if (strchr(child->argv[0], '=') != NULL) {
                                child->argv[1] = child->argv[0];
@@ -1249,14 +1247,23 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
 
                        for (x = bltins; x <= &VEC_LAST(bltins); x++) {
                                if (strcmp(child->argv[0], x->cmd) == 0) {
-                                       int rcode;
-                                       int squirrel[] = {-1, -1, -1};
                                        setup_redirects(child, squirrel);
                                        rcode = x->function(child);
                                        restore_redirects(squirrel);
                                        return rcode;
                                }
                        }
+#if ENABLE_FEATURE_SH_STANDALONE
+                       {
+                               const struct bb_applet *a = find_applet_by_name(child->argv[i]);
+                               if (a && a->nofork) {
+                                       setup_redirects(child, squirrel);
+                                       rcode = run_nofork_applet(a, child->argv + i);
+                                       restore_redirects(squirrel);
+                                       return rcode;
+                               }
+                       }
+#endif
                }
 
 #if BB_MMU