aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2000-12-21 18:31:36 +0000
committerandersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277>2000-12-21 18:31:36 +0000
commit3c7e7e11b41d4a421bcf42fd1bf72a537e051d4a (patch)
tree6b210f42ee013ee32d23e5999fba72cc69443a3d
parentd42b1ee1cf7c37aaed8dc062cb97cbace3f3dacc (diff)
downloadbusybox-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.c108
-rw-r--r--sh.c108
-rw-r--r--shell/lash.c108
3 files changed, 213 insertions, 111 deletions
diff --git a/lash.c b/lash.c
index b8ddc87c1..22a696785 100644
--- a/lash.c
+++ b/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 */
593static int run_command_predicate(char *cmd) 595static 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
687static 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. */
691static 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
732static 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
726static int get_command(FILE * source, char *command) 746static 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/sh.c b/sh.c
index b8ddc87c1..22a696785 100644
--- a/sh.c
+++ b/sh.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 */
593static int run_command_predicate(char *cmd) 595static 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
687static 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. */
691static 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
732static 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
726static int get_command(FILE * source, char *command) 746static 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 */
593static int run_command_predicate(char *cmd) 595static 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
687static 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. */
691static 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
732static 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
726static int get_command(FILE * source, char *command) 746static 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 }