diff options
author | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2000-12-21 18:31:36 +0000 |
---|---|---|
committer | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2000-12-21 18:31:36 +0000 |
commit | 3c7e7e11b41d4a421bcf42fd1bf72a537e051d4a (patch) | |
tree | 6b210f42ee013ee32d23e5999fba72cc69443a3d | |
parent | d42b1ee1cf7c37aaed8dc062cb97cbace3f3dacc (diff) | |
download | busybox-w32-3c7e7e11b41d4a421bcf42fd1bf72a537e051d4a.tar.gz busybox-w32-3c7e7e11b41d4a421bcf42fd1bf72a537e051d4a.tar.bz2 busybox-w32-3c7e7e11b41d4a421bcf42fd1bf72a537e051d4a.zip |
Another sh.c patch from Larry Doolittle. This makes redirects work properly
with non-forking shell builtins. Especially helpful for "read". This patch
also beautifies builtin_fg_bg, clarifies the problems with
run_command_predicate, makes if/then/else support the default, and corrects the
sense of the BB_FEATURE_SH_ENVIRONMENT comment.
git-svn-id: svn://busybox.net/trunk/busybox@1487 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r-- | lash.c | 108 | ||||
-rw-r--r-- | sh.c | 108 | ||||
-rw-r--r-- | shell/lash.c | 108 |
3 files changed, 213 insertions, 111 deletions
@@ -26,7 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | // | 28 | // |
29 | //This works pretty well now, and is not on by default. | 29 | //This works pretty well now, and is now on by default. |
30 | #define BB_FEATURE_SH_ENVIRONMENT | 30 | #define BB_FEATURE_SH_ENVIRONMENT |
31 | // | 31 | // |
32 | //Backtick support has some problems, use at your own risk! | 32 | //Backtick support has some problems, use at your own risk! |
@@ -34,7 +34,7 @@ | |||
34 | // | 34 | // |
35 | //If, then, else, etc. support.. This should now behave basically | 35 | //If, then, else, etc. support.. This should now behave basically |
36 | //like any other Bourne shell... | 36 | //like any other Bourne shell... |
37 | //#define BB_FEATURE_SH_IF_EXPRESSIONS | 37 | #define BB_FEATURE_SH_IF_EXPRESSIONS |
38 | // | 38 | // |
39 | /* This is currently a little broken... */ | 39 | /* This is currently a little broken... */ |
40 | //#define HANDLE_CONTINUATION_CHARS | 40 | //#define HANDLE_CONTINUATION_CHARS |
@@ -316,22 +316,23 @@ static int builtin_fg_bg(struct child_prog *child) | |||
316 | int i, jobNum; | 316 | int i, jobNum; |
317 | struct job *job=NULL; | 317 | struct job *job=NULL; |
318 | 318 | ||
319 | if (!child->argv[1] || child->argv[2]) { | ||
320 | error_msg("%s: exactly one argument is expected\n", | ||
321 | child->argv[0]); | ||
322 | return EXIT_FAILURE; | ||
323 | } | ||
319 | 324 | ||
320 | if (!child->argv[1] || child->argv[2]) { | 325 | if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) { |
321 | error_msg("%s: exactly one argument is expected\n", | 326 | error_msg("%s: bad argument '%s'\n", |
322 | child->argv[0]); | 327 | child->argv[0], child->argv[1]); |
323 | return EXIT_FAILURE; | 328 | return EXIT_FAILURE; |
324 | } | 329 | } |
325 | if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) { | 330 | |
326 | error_msg("%s: bad argument '%s'\n", | 331 | for (job = child->family->job_list->head; job; job = job->next) { |
327 | child->argv[0], child->argv[1]); | 332 | if (job->jobid == jobNum) { |
328 | return EXIT_FAILURE; | 333 | break; |
329 | } | ||
330 | for (job = child->family->job_list->head; job; job = job->next) { | ||
331 | if (job->jobid == jobNum) { | ||
332 | break; | ||
333 | } | ||
334 | } | 334 | } |
335 | } | ||
335 | 336 | ||
336 | if (!job) { | 337 | if (!job) { |
337 | error_msg("%s: unknown job %d\n", | 338 | error_msg("%s: unknown job %d\n", |
@@ -524,7 +525,7 @@ static int builtin_else(struct child_prog *child) | |||
524 | } | 525 | } |
525 | 526 | ||
526 | cmd->job_context |= ELSE_EXP_CONTEXT; | 527 | cmd->job_context |= ELSE_EXP_CONTEXT; |
527 | debug_printf("job=%p builtin_else set job context to %x\n", child->family, cmd->job_context); | 528 | debug_printf("job=%p builtin_else set job context to %x\n", cmd, cmd->job_context); |
528 | 529 | ||
529 | /* Now run the 'else' command */ | 530 | /* Now run the 'else' command */ |
530 | debug_printf( "'else' now running '%s'\n", charptr1); | 531 | debug_printf( "'else' now running '%s'\n", charptr1); |
@@ -583,12 +584,13 @@ static int builtin_unset(struct child_prog *child) | |||
583 | 584 | ||
584 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS | 585 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS |
585 | /* currently used by if/then/else. | 586 | /* currently used by if/then/else. |
586 | * Needlessly (?) forks and reparses the command line. | 587 | * |
587 | * But pseudo_exec on the pre-parsed args doesn't have the | 588 | * Reparsing the command line for this purpose is gross, |
588 | * "fork, stick around until the child exits, and find it's return code" | 589 | * incorrect, and fundamentally unfixable; in particular, |
589 | * functionality. The fork is not needed if the predicate is | 590 | * think about what happens with command substitution. |
590 | * non-forking builtin, and maybe not even if it's a forking builtin. | 591 | * We really need to pull out the run, wait, return status |
591 | * applets pretty clearly need the fork. | 592 | * functionality out of busy_loop so we can child->argv++ |
593 | * and use that, without going back through parse_command. | ||
592 | */ | 594 | */ |
593 | static int run_command_predicate(char *cmd) | 595 | static int run_command_predicate(char *cmd) |
594 | { | 596 | { |
@@ -684,7 +686,9 @@ static void checkjobs(struct jobset *job_list) | |||
684 | perror("waitpid"); | 686 | perror("waitpid"); |
685 | } | 687 | } |
686 | 688 | ||
687 | static int setup_redirects(struct child_prog *prog) | 689 | /* squirrel != NULL means we squirrel away copies of stdin, stdout, |
690 | * and stderr if they are redirected. */ | ||
691 | static int setup_redirects(struct child_prog *prog, int squirrel[]) | ||
688 | { | 692 | { |
689 | int i; | 693 | int i; |
690 | int openfd; | 694 | int openfd; |
@@ -714,6 +718,9 @@ static int setup_redirects(struct child_prog *prog) | |||
714 | } | 718 | } |
715 | 719 | ||
716 | if (openfd != redir->fd) { | 720 | if (openfd != redir->fd) { |
721 | if (squirrel && redir->fd < 3) { | ||
722 | squirrel[redir->fd] = dup(redir->fd); | ||
723 | } | ||
717 | dup2(openfd, redir->fd); | 724 | dup2(openfd, redir->fd); |
718 | close(openfd); | 725 | close(openfd); |
719 | } | 726 | } |
@@ -722,6 +729,19 @@ static int setup_redirects(struct child_prog *prog) | |||
722 | return 0; | 729 | return 0; |
723 | } | 730 | } |
724 | 731 | ||
732 | static void restore_redirects(int squirrel[]) | ||
733 | { | ||
734 | int i, fd; | ||
735 | for (i=0; i<3; i++) { | ||
736 | fd = squirrel[i]; | ||
737 | if (fd != -1) { | ||
738 | /* No error checking. I sure wouldn't know what | ||
739 | * to do with an error if I found one! */ | ||
740 | dup2(fd, i); | ||
741 | close(fd); | ||
742 | } | ||
743 | } | ||
744 | } | ||
725 | 745 | ||
726 | static int get_command(FILE * source, char *command) | 746 | static int get_command(FILE * source, char *command) |
727 | { | 747 | { |
@@ -1304,11 +1324,18 @@ static int pseudo_exec(struct child_prog *child) | |||
1304 | struct BB_applet search_applet, *applet; | 1324 | struct BB_applet search_applet, *applet; |
1305 | #endif | 1325 | #endif |
1306 | 1326 | ||
1307 | /* Check if the command matches any of the forking builtins. | 1327 | /* Check if the command matches any of the non-forking builtins. |
1308 | * XXX It would probably be wise to check for non-forking builtins | 1328 | * Depending on context, this might be redundant. But it's |
1309 | * here as well, since in some context the non-forking path | 1329 | * easier to waste a few CPU cycles than it is to figure out |
1310 | * is disabled or bypassed. See comment in run_command. | 1330 | * if this is one of those cases. |
1311 | */ | 1331 | */ |
1332 | for (x = bltins; x->cmd; x++) { | ||
1333 | if (strcmp(child->argv[0], x->cmd) == 0 ) { | ||
1334 | exit(x->function(child)); | ||
1335 | } | ||
1336 | } | ||
1337 | |||
1338 | /* Check if the command matches any of the forking builtins. */ | ||
1312 | for (x = bltins_forking; x->cmd; x++) { | 1339 | for (x = bltins_forking; x->cmd; x++) { |
1313 | if (strcmp(child->argv[0], x->cmd) == 0) { | 1340 | if (strcmp(child->argv[0], x->cmd) == 0) { |
1314 | applet_name=x->cmd; | 1341 | applet_name=x->cmd; |
@@ -1435,15 +1462,22 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1435 | } | 1462 | } |
1436 | #endif | 1463 | #endif |
1437 | 1464 | ||
1438 | /* Check if the command matches any non-forking builtins. | 1465 | /* Check if the command matches any non-forking builtins, |
1439 | * XXX should probably skip this test, and fork anyway, if | 1466 | * but only if this is a simple command. |
1440 | * there redirects of some kind demand forking to work right. | 1467 | * Non-forking builtins within pipes have to fork anyway, |
1441 | * pseudo_exec would then need to handle the non-forking command | 1468 | * and are handled in pseudo_exec. "echo foo | read bar" |
1442 | * in a forked context. | 1469 | * is doomed to failure, and doesn't work on bash, either. |
1443 | */ | 1470 | */ |
1444 | for (x = bltins; x->cmd; x++) { | 1471 | if (newjob->num_progs == 1) { |
1445 | if (strcmp(child->argv[0], x->cmd) == 0 ) { | 1472 | for (x = bltins; x->cmd; x++) { |
1446 | return(x->function(child)); | 1473 | if (strcmp(child->argv[0], x->cmd) == 0 ) { |
1474 | int squirrel[] = {-1, -1, -1}; | ||
1475 | int rcode; | ||
1476 | setup_redirects(child, squirrel); | ||
1477 | rcode = x->function(child); | ||
1478 | restore_redirects(squirrel); | ||
1479 | return rcode; | ||
1480 | } | ||
1447 | } | 1481 | } |
1448 | } | 1482 | } |
1449 | 1483 | ||
@@ -1466,7 +1500,7 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1466 | } | 1500 | } |
1467 | 1501 | ||
1468 | /* explicit redirects override pipes */ | 1502 | /* explicit redirects override pipes */ |
1469 | setup_redirects(child); | 1503 | setup_redirects(child,NULL); |
1470 | 1504 | ||
1471 | pseudo_exec(child); | 1505 | pseudo_exec(child); |
1472 | } | 1506 | } |
@@ -26,7 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | // | 28 | // |
29 | //This works pretty well now, and is not on by default. | 29 | //This works pretty well now, and is now on by default. |
30 | #define BB_FEATURE_SH_ENVIRONMENT | 30 | #define BB_FEATURE_SH_ENVIRONMENT |
31 | // | 31 | // |
32 | //Backtick support has some problems, use at your own risk! | 32 | //Backtick support has some problems, use at your own risk! |
@@ -34,7 +34,7 @@ | |||
34 | // | 34 | // |
35 | //If, then, else, etc. support.. This should now behave basically | 35 | //If, then, else, etc. support.. This should now behave basically |
36 | //like any other Bourne shell... | 36 | //like any other Bourne shell... |
37 | //#define BB_FEATURE_SH_IF_EXPRESSIONS | 37 | #define BB_FEATURE_SH_IF_EXPRESSIONS |
38 | // | 38 | // |
39 | /* This is currently a little broken... */ | 39 | /* This is currently a little broken... */ |
40 | //#define HANDLE_CONTINUATION_CHARS | 40 | //#define HANDLE_CONTINUATION_CHARS |
@@ -316,22 +316,23 @@ static int builtin_fg_bg(struct child_prog *child) | |||
316 | int i, jobNum; | 316 | int i, jobNum; |
317 | struct job *job=NULL; | 317 | struct job *job=NULL; |
318 | 318 | ||
319 | if (!child->argv[1] || child->argv[2]) { | ||
320 | error_msg("%s: exactly one argument is expected\n", | ||
321 | child->argv[0]); | ||
322 | return EXIT_FAILURE; | ||
323 | } | ||
319 | 324 | ||
320 | if (!child->argv[1] || child->argv[2]) { | 325 | if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) { |
321 | error_msg("%s: exactly one argument is expected\n", | 326 | error_msg("%s: bad argument '%s'\n", |
322 | child->argv[0]); | 327 | child->argv[0], child->argv[1]); |
323 | return EXIT_FAILURE; | 328 | return EXIT_FAILURE; |
324 | } | 329 | } |
325 | if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) { | 330 | |
326 | error_msg("%s: bad argument '%s'\n", | 331 | for (job = child->family->job_list->head; job; job = job->next) { |
327 | child->argv[0], child->argv[1]); | 332 | if (job->jobid == jobNum) { |
328 | return EXIT_FAILURE; | 333 | break; |
329 | } | ||
330 | for (job = child->family->job_list->head; job; job = job->next) { | ||
331 | if (job->jobid == jobNum) { | ||
332 | break; | ||
333 | } | ||
334 | } | 334 | } |
335 | } | ||
335 | 336 | ||
336 | if (!job) { | 337 | if (!job) { |
337 | error_msg("%s: unknown job %d\n", | 338 | error_msg("%s: unknown job %d\n", |
@@ -524,7 +525,7 @@ static int builtin_else(struct child_prog *child) | |||
524 | } | 525 | } |
525 | 526 | ||
526 | cmd->job_context |= ELSE_EXP_CONTEXT; | 527 | cmd->job_context |= ELSE_EXP_CONTEXT; |
527 | debug_printf("job=%p builtin_else set job context to %x\n", child->family, cmd->job_context); | 528 | debug_printf("job=%p builtin_else set job context to %x\n", cmd, cmd->job_context); |
528 | 529 | ||
529 | /* Now run the 'else' command */ | 530 | /* Now run the 'else' command */ |
530 | debug_printf( "'else' now running '%s'\n", charptr1); | 531 | debug_printf( "'else' now running '%s'\n", charptr1); |
@@ -583,12 +584,13 @@ static int builtin_unset(struct child_prog *child) | |||
583 | 584 | ||
584 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS | 585 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS |
585 | /* currently used by if/then/else. | 586 | /* currently used by if/then/else. |
586 | * Needlessly (?) forks and reparses the command line. | 587 | * |
587 | * But pseudo_exec on the pre-parsed args doesn't have the | 588 | * Reparsing the command line for this purpose is gross, |
588 | * "fork, stick around until the child exits, and find it's return code" | 589 | * incorrect, and fundamentally unfixable; in particular, |
589 | * functionality. The fork is not needed if the predicate is | 590 | * think about what happens with command substitution. |
590 | * non-forking builtin, and maybe not even if it's a forking builtin. | 591 | * We really need to pull out the run, wait, return status |
591 | * applets pretty clearly need the fork. | 592 | * functionality out of busy_loop so we can child->argv++ |
593 | * and use that, without going back through parse_command. | ||
592 | */ | 594 | */ |
593 | static int run_command_predicate(char *cmd) | 595 | static int run_command_predicate(char *cmd) |
594 | { | 596 | { |
@@ -684,7 +686,9 @@ static void checkjobs(struct jobset *job_list) | |||
684 | perror("waitpid"); | 686 | perror("waitpid"); |
685 | } | 687 | } |
686 | 688 | ||
687 | static int setup_redirects(struct child_prog *prog) | 689 | /* squirrel != NULL means we squirrel away copies of stdin, stdout, |
690 | * and stderr if they are redirected. */ | ||
691 | static int setup_redirects(struct child_prog *prog, int squirrel[]) | ||
688 | { | 692 | { |
689 | int i; | 693 | int i; |
690 | int openfd; | 694 | int openfd; |
@@ -714,6 +718,9 @@ static int setup_redirects(struct child_prog *prog) | |||
714 | } | 718 | } |
715 | 719 | ||
716 | if (openfd != redir->fd) { | 720 | if (openfd != redir->fd) { |
721 | if (squirrel && redir->fd < 3) { | ||
722 | squirrel[redir->fd] = dup(redir->fd); | ||
723 | } | ||
717 | dup2(openfd, redir->fd); | 724 | dup2(openfd, redir->fd); |
718 | close(openfd); | 725 | close(openfd); |
719 | } | 726 | } |
@@ -722,6 +729,19 @@ static int setup_redirects(struct child_prog *prog) | |||
722 | return 0; | 729 | return 0; |
723 | } | 730 | } |
724 | 731 | ||
732 | static void restore_redirects(int squirrel[]) | ||
733 | { | ||
734 | int i, fd; | ||
735 | for (i=0; i<3; i++) { | ||
736 | fd = squirrel[i]; | ||
737 | if (fd != -1) { | ||
738 | /* No error checking. I sure wouldn't know what | ||
739 | * to do with an error if I found one! */ | ||
740 | dup2(fd, i); | ||
741 | close(fd); | ||
742 | } | ||
743 | } | ||
744 | } | ||
725 | 745 | ||
726 | static int get_command(FILE * source, char *command) | 746 | static int get_command(FILE * source, char *command) |
727 | { | 747 | { |
@@ -1304,11 +1324,18 @@ static int pseudo_exec(struct child_prog *child) | |||
1304 | struct BB_applet search_applet, *applet; | 1324 | struct BB_applet search_applet, *applet; |
1305 | #endif | 1325 | #endif |
1306 | 1326 | ||
1307 | /* Check if the command matches any of the forking builtins. | 1327 | /* Check if the command matches any of the non-forking builtins. |
1308 | * XXX It would probably be wise to check for non-forking builtins | 1328 | * Depending on context, this might be redundant. But it's |
1309 | * here as well, since in some context the non-forking path | 1329 | * easier to waste a few CPU cycles than it is to figure out |
1310 | * is disabled or bypassed. See comment in run_command. | 1330 | * if this is one of those cases. |
1311 | */ | 1331 | */ |
1332 | for (x = bltins; x->cmd; x++) { | ||
1333 | if (strcmp(child->argv[0], x->cmd) == 0 ) { | ||
1334 | exit(x->function(child)); | ||
1335 | } | ||
1336 | } | ||
1337 | |||
1338 | /* Check if the command matches any of the forking builtins. */ | ||
1312 | for (x = bltins_forking; x->cmd; x++) { | 1339 | for (x = bltins_forking; x->cmd; x++) { |
1313 | if (strcmp(child->argv[0], x->cmd) == 0) { | 1340 | if (strcmp(child->argv[0], x->cmd) == 0) { |
1314 | applet_name=x->cmd; | 1341 | applet_name=x->cmd; |
@@ -1435,15 +1462,22 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1435 | } | 1462 | } |
1436 | #endif | 1463 | #endif |
1437 | 1464 | ||
1438 | /* Check if the command matches any non-forking builtins. | 1465 | /* Check if the command matches any non-forking builtins, |
1439 | * XXX should probably skip this test, and fork anyway, if | 1466 | * but only if this is a simple command. |
1440 | * there redirects of some kind demand forking to work right. | 1467 | * Non-forking builtins within pipes have to fork anyway, |
1441 | * pseudo_exec would then need to handle the non-forking command | 1468 | * and are handled in pseudo_exec. "echo foo | read bar" |
1442 | * in a forked context. | 1469 | * is doomed to failure, and doesn't work on bash, either. |
1443 | */ | 1470 | */ |
1444 | for (x = bltins; x->cmd; x++) { | 1471 | if (newjob->num_progs == 1) { |
1445 | if (strcmp(child->argv[0], x->cmd) == 0 ) { | 1472 | for (x = bltins; x->cmd; x++) { |
1446 | return(x->function(child)); | 1473 | if (strcmp(child->argv[0], x->cmd) == 0 ) { |
1474 | int squirrel[] = {-1, -1, -1}; | ||
1475 | int rcode; | ||
1476 | setup_redirects(child, squirrel); | ||
1477 | rcode = x->function(child); | ||
1478 | restore_redirects(squirrel); | ||
1479 | return rcode; | ||
1480 | } | ||
1447 | } | 1481 | } |
1448 | } | 1482 | } |
1449 | 1483 | ||
@@ -1466,7 +1500,7 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1466 | } | 1500 | } |
1467 | 1501 | ||
1468 | /* explicit redirects override pipes */ | 1502 | /* explicit redirects override pipes */ |
1469 | setup_redirects(child); | 1503 | setup_redirects(child,NULL); |
1470 | 1504 | ||
1471 | pseudo_exec(child); | 1505 | pseudo_exec(child); |
1472 | } | 1506 | } |
diff --git a/shell/lash.c b/shell/lash.c index b8ddc87c1..22a696785 100644 --- a/shell/lash.c +++ b/shell/lash.c | |||
@@ -26,7 +26,7 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | // | 28 | // |
29 | //This works pretty well now, and is not on by default. | 29 | //This works pretty well now, and is now on by default. |
30 | #define BB_FEATURE_SH_ENVIRONMENT | 30 | #define BB_FEATURE_SH_ENVIRONMENT |
31 | // | 31 | // |
32 | //Backtick support has some problems, use at your own risk! | 32 | //Backtick support has some problems, use at your own risk! |
@@ -34,7 +34,7 @@ | |||
34 | // | 34 | // |
35 | //If, then, else, etc. support.. This should now behave basically | 35 | //If, then, else, etc. support.. This should now behave basically |
36 | //like any other Bourne shell... | 36 | //like any other Bourne shell... |
37 | //#define BB_FEATURE_SH_IF_EXPRESSIONS | 37 | #define BB_FEATURE_SH_IF_EXPRESSIONS |
38 | // | 38 | // |
39 | /* This is currently a little broken... */ | 39 | /* This is currently a little broken... */ |
40 | //#define HANDLE_CONTINUATION_CHARS | 40 | //#define HANDLE_CONTINUATION_CHARS |
@@ -316,22 +316,23 @@ static int builtin_fg_bg(struct child_prog *child) | |||
316 | int i, jobNum; | 316 | int i, jobNum; |
317 | struct job *job=NULL; | 317 | struct job *job=NULL; |
318 | 318 | ||
319 | if (!child->argv[1] || child->argv[2]) { | ||
320 | error_msg("%s: exactly one argument is expected\n", | ||
321 | child->argv[0]); | ||
322 | return EXIT_FAILURE; | ||
323 | } | ||
319 | 324 | ||
320 | if (!child->argv[1] || child->argv[2]) { | 325 | if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) { |
321 | error_msg("%s: exactly one argument is expected\n", | 326 | error_msg("%s: bad argument '%s'\n", |
322 | child->argv[0]); | 327 | child->argv[0], child->argv[1]); |
323 | return EXIT_FAILURE; | 328 | return EXIT_FAILURE; |
324 | } | 329 | } |
325 | if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) { | 330 | |
326 | error_msg("%s: bad argument '%s'\n", | 331 | for (job = child->family->job_list->head; job; job = job->next) { |
327 | child->argv[0], child->argv[1]); | 332 | if (job->jobid == jobNum) { |
328 | return EXIT_FAILURE; | 333 | break; |
329 | } | ||
330 | for (job = child->family->job_list->head; job; job = job->next) { | ||
331 | if (job->jobid == jobNum) { | ||
332 | break; | ||
333 | } | ||
334 | } | 334 | } |
335 | } | ||
335 | 336 | ||
336 | if (!job) { | 337 | if (!job) { |
337 | error_msg("%s: unknown job %d\n", | 338 | error_msg("%s: unknown job %d\n", |
@@ -524,7 +525,7 @@ static int builtin_else(struct child_prog *child) | |||
524 | } | 525 | } |
525 | 526 | ||
526 | cmd->job_context |= ELSE_EXP_CONTEXT; | 527 | cmd->job_context |= ELSE_EXP_CONTEXT; |
527 | debug_printf("job=%p builtin_else set job context to %x\n", child->family, cmd->job_context); | 528 | debug_printf("job=%p builtin_else set job context to %x\n", cmd, cmd->job_context); |
528 | 529 | ||
529 | /* Now run the 'else' command */ | 530 | /* Now run the 'else' command */ |
530 | debug_printf( "'else' now running '%s'\n", charptr1); | 531 | debug_printf( "'else' now running '%s'\n", charptr1); |
@@ -583,12 +584,13 @@ static int builtin_unset(struct child_prog *child) | |||
583 | 584 | ||
584 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS | 585 | #ifdef BB_FEATURE_SH_IF_EXPRESSIONS |
585 | /* currently used by if/then/else. | 586 | /* currently used by if/then/else. |
586 | * Needlessly (?) forks and reparses the command line. | 587 | * |
587 | * But pseudo_exec on the pre-parsed args doesn't have the | 588 | * Reparsing the command line for this purpose is gross, |
588 | * "fork, stick around until the child exits, and find it's return code" | 589 | * incorrect, and fundamentally unfixable; in particular, |
589 | * functionality. The fork is not needed if the predicate is | 590 | * think about what happens with command substitution. |
590 | * non-forking builtin, and maybe not even if it's a forking builtin. | 591 | * We really need to pull out the run, wait, return status |
591 | * applets pretty clearly need the fork. | 592 | * functionality out of busy_loop so we can child->argv++ |
593 | * and use that, without going back through parse_command. | ||
592 | */ | 594 | */ |
593 | static int run_command_predicate(char *cmd) | 595 | static int run_command_predicate(char *cmd) |
594 | { | 596 | { |
@@ -684,7 +686,9 @@ static void checkjobs(struct jobset *job_list) | |||
684 | perror("waitpid"); | 686 | perror("waitpid"); |
685 | } | 687 | } |
686 | 688 | ||
687 | static int setup_redirects(struct child_prog *prog) | 689 | /* squirrel != NULL means we squirrel away copies of stdin, stdout, |
690 | * and stderr if they are redirected. */ | ||
691 | static int setup_redirects(struct child_prog *prog, int squirrel[]) | ||
688 | { | 692 | { |
689 | int i; | 693 | int i; |
690 | int openfd; | 694 | int openfd; |
@@ -714,6 +718,9 @@ static int setup_redirects(struct child_prog *prog) | |||
714 | } | 718 | } |
715 | 719 | ||
716 | if (openfd != redir->fd) { | 720 | if (openfd != redir->fd) { |
721 | if (squirrel && redir->fd < 3) { | ||
722 | squirrel[redir->fd] = dup(redir->fd); | ||
723 | } | ||
717 | dup2(openfd, redir->fd); | 724 | dup2(openfd, redir->fd); |
718 | close(openfd); | 725 | close(openfd); |
719 | } | 726 | } |
@@ -722,6 +729,19 @@ static int setup_redirects(struct child_prog *prog) | |||
722 | return 0; | 729 | return 0; |
723 | } | 730 | } |
724 | 731 | ||
732 | static void restore_redirects(int squirrel[]) | ||
733 | { | ||
734 | int i, fd; | ||
735 | for (i=0; i<3; i++) { | ||
736 | fd = squirrel[i]; | ||
737 | if (fd != -1) { | ||
738 | /* No error checking. I sure wouldn't know what | ||
739 | * to do with an error if I found one! */ | ||
740 | dup2(fd, i); | ||
741 | close(fd); | ||
742 | } | ||
743 | } | ||
744 | } | ||
725 | 745 | ||
726 | static int get_command(FILE * source, char *command) | 746 | static int get_command(FILE * source, char *command) |
727 | { | 747 | { |
@@ -1304,11 +1324,18 @@ static int pseudo_exec(struct child_prog *child) | |||
1304 | struct BB_applet search_applet, *applet; | 1324 | struct BB_applet search_applet, *applet; |
1305 | #endif | 1325 | #endif |
1306 | 1326 | ||
1307 | /* Check if the command matches any of the forking builtins. | 1327 | /* Check if the command matches any of the non-forking builtins. |
1308 | * XXX It would probably be wise to check for non-forking builtins | 1328 | * Depending on context, this might be redundant. But it's |
1309 | * here as well, since in some context the non-forking path | 1329 | * easier to waste a few CPU cycles than it is to figure out |
1310 | * is disabled or bypassed. See comment in run_command. | 1330 | * if this is one of those cases. |
1311 | */ | 1331 | */ |
1332 | for (x = bltins; x->cmd; x++) { | ||
1333 | if (strcmp(child->argv[0], x->cmd) == 0 ) { | ||
1334 | exit(x->function(child)); | ||
1335 | } | ||
1336 | } | ||
1337 | |||
1338 | /* Check if the command matches any of the forking builtins. */ | ||
1312 | for (x = bltins_forking; x->cmd; x++) { | 1339 | for (x = bltins_forking; x->cmd; x++) { |
1313 | if (strcmp(child->argv[0], x->cmd) == 0) { | 1340 | if (strcmp(child->argv[0], x->cmd) == 0) { |
1314 | applet_name=x->cmd; | 1341 | applet_name=x->cmd; |
@@ -1435,15 +1462,22 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1435 | } | 1462 | } |
1436 | #endif | 1463 | #endif |
1437 | 1464 | ||
1438 | /* Check if the command matches any non-forking builtins. | 1465 | /* Check if the command matches any non-forking builtins, |
1439 | * XXX should probably skip this test, and fork anyway, if | 1466 | * but only if this is a simple command. |
1440 | * there redirects of some kind demand forking to work right. | 1467 | * Non-forking builtins within pipes have to fork anyway, |
1441 | * pseudo_exec would then need to handle the non-forking command | 1468 | * and are handled in pseudo_exec. "echo foo | read bar" |
1442 | * in a forked context. | 1469 | * is doomed to failure, and doesn't work on bash, either. |
1443 | */ | 1470 | */ |
1444 | for (x = bltins; x->cmd; x++) { | 1471 | if (newjob->num_progs == 1) { |
1445 | if (strcmp(child->argv[0], x->cmd) == 0 ) { | 1472 | for (x = bltins; x->cmd; x++) { |
1446 | return(x->function(child)); | 1473 | if (strcmp(child->argv[0], x->cmd) == 0 ) { |
1474 | int squirrel[] = {-1, -1, -1}; | ||
1475 | int rcode; | ||
1476 | setup_redirects(child, squirrel); | ||
1477 | rcode = x->function(child); | ||
1478 | restore_redirects(squirrel); | ||
1479 | return rcode; | ||
1480 | } | ||
1447 | } | 1481 | } |
1448 | } | 1482 | } |
1449 | 1483 | ||
@@ -1466,7 +1500,7 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2]) | |||
1466 | } | 1500 | } |
1467 | 1501 | ||
1468 | /* explicit redirects override pipes */ | 1502 | /* explicit redirects override pipes */ |
1469 | setup_redirects(child); | 1503 | setup_redirects(child,NULL); |
1470 | 1504 | ||
1471 | pseudo_exec(child); | 1505 | pseudo_exec(child); |
1472 | } | 1506 | } |