aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-04-21 13:42:52 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-04-21 13:42:52 +0000
commit52881e9f23d1b02f75f2c1f5e704edc283be5cdf (patch)
tree06b88f81bb62ecdc2850705c1845ba9a963cc09b /shell
parent2f1bb36a557f4ce8e1f5abd177c34dadbc0fb534 (diff)
downloadbusybox-w32-52881e9f23d1b02f75f2c1f5e704edc283be5cdf.tar.gz
busybox-w32-52881e9f23d1b02f75f2c1f5e704edc283be5cdf.tar.bz2
busybox-w32-52881e9f23d1b02f75f2c1f5e704edc283be5cdf.zip
hush: fix more backgrounding bugs. Plenty of them remains still.
Diffstat (limited to 'shell')
-rw-r--r--shell/README8
-rw-r--r--shell/hush.c32
2 files changed, 29 insertions, 11 deletions
diff --git a/shell/README b/shell/README
index bcd84dcad..b78d651a5 100644
--- a/shell/README
+++ b/shell/README
@@ -1,6 +1,12 @@
1Various bits of what is known about busybox shells, in no particular order. 1Various bits of what is known about busybox shells, in no particular order.
2 2
32007-04-22 32007-04-21
4hush: fixed non-backgrounding of "sleep 1 &" and totally broken
5"sleep 1 | sleep 2 &". Noticed a bug where successive jobs
6get numbers 1,2,3 even when job #1 has exited before job# 2 is started.
7(bash reuses #1 in this case)
8
92007-04-21
4hush: "sleep 1 | exit 3; echo $?" prints 0 because $? is substituted 10hush: "sleep 1 | exit 3; echo $?" prints 0 because $? is substituted
5_before_ pipe gets executed!! run_list_real() already has "pipe;echo" 11_before_ pipe gets executed!! run_list_real() already has "pipe;echo"
6parsed and handed to it for execution, so it sees "pipe"; "echo 0". 12parsed and handed to it for execution, so it sees "pipe"; "echo 0".
diff --git a/shell/hush.c b/shell/hush.c
index db93f8dcb..046e098d9 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -384,6 +384,7 @@ static int parse_string_outer(const char *s, int flag);
384static int parse_file_outer(FILE *f); 384static int parse_file_outer(FILE *f);
385/* job management: */ 385/* job management: */
386static int checkjobs(struct pipe* fg_pipe); 386static int checkjobs(struct pipe* fg_pipe);
387static int checkjobs_and_fg_shell(struct pipe* fg_pipe);
387static void insert_bg_job(struct pipe *pi); 388static void insert_bg_job(struct pipe *pi);
388static void remove_bg_job(struct pipe *pi); 389static void remove_bg_job(struct pipe *pi);
389/* local variable support */ 390/* local variable support */
@@ -648,6 +649,8 @@ static int builtin_fg_bg(struct child_prog *child)
648 bb_error_msg("%s: %d: no such job", child->argv[0], jobnum); 649 bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
649 return EXIT_FAILURE; 650 return EXIT_FAILURE;
650 found: 651 found:
652 // TODO: bash prints a string representation
653 // of job being foregrounded (like "sleep 1 | cat")
651 if (*child->argv[0] == 'f') { 654 if (*child->argv[0] == 'f') {
652 /* Put the job into the foreground. */ 655 /* Put the job into the foreground. */
653 tcsetpgrp(interactive_fd, pi->pgrp); 656 tcsetpgrp(interactive_fd, pi->pgrp);
@@ -658,6 +661,7 @@ static int builtin_fg_bg(struct child_prog *child)
658 pi->progs[i].is_stopped = 0; 661 pi->progs[i].is_stopped = 0;
659 662
660 i = kill(- pi->pgrp, SIGCONT); 663 i = kill(- pi->pgrp, SIGCONT);
664 pi->stopped_progs = 0;
661 if (i < 0) { 665 if (i < 0) {
662 if (errno == ESRCH) { 666 if (errno == ESRCH) {
663 remove_bg_job(pi); 667 remove_bg_job(pi);
@@ -666,7 +670,8 @@ static int builtin_fg_bg(struct child_prog *child)
666 } 670 }
667 } 671 }
668 672
669 pi->stopped_progs = 0; 673 if (*child->argv[0] == 'f')
674 return checkjobs_and_fg_shell(pi);
670 return EXIT_SUCCESS; 675 return EXIT_SUCCESS;
671} 676}
672 677
@@ -1350,6 +1355,18 @@ static int checkjobs(struct pipe* fg_pipe)
1350 return rcode; 1355 return rcode;
1351} 1356}
1352 1357
1358static int checkjobs_and_fg_shell(struct pipe* fg_pipe)
1359{
1360 pid_t p;
1361 int rcode = checkjobs(fg_pipe);
1362 /* Job finished, move the shell to the foreground */
1363 p = getpgid(0);
1364 debug_printf("fg'ing ourself: getpgid(0)=%d\n", (int)p);
1365 if (tcsetpgrp(interactive_fd, p) && errno != ENOTTY)
1366 bb_perror_msg("tcsetpgrp-4a");
1367 return rcode;
1368}
1369
1353/* run_pipe_real() starts all the jobs, but doesn't wait for anything 1370/* run_pipe_real() starts all the jobs, but doesn't wait for anything
1354 * to finish. See checkjobs(). 1371 * to finish. See checkjobs().
1355 * 1372 *
@@ -1377,6 +1394,7 @@ static int run_pipe_real(struct pipe *pi)
1377 /* it is not always needed, but we aim to smaller code */ 1394 /* it is not always needed, but we aim to smaller code */
1378 int squirrel[] = { -1, -1, -1 }; 1395 int squirrel[] = { -1, -1, -1 };
1379 int rcode; 1396 int rcode;
1397 const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG);
1380 1398
1381 nextin = 0; 1399 nextin = 0;
1382 pi->pgrp = -1; 1400 pi->pgrp = -1;
@@ -1386,7 +1404,7 @@ static int run_pipe_real(struct pipe *pi)
1386 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. 1404 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
1387 */ 1405 */
1388 child = &(pi->progs[0]); 1406 child = &(pi->progs[0]);
1389 if (pi->num_progs == 1 && child->group && child->subshell == 0) { 1407 if (single_fg && child->group && child->subshell == 0) {
1390 debug_printf("non-subshell grouping\n"); 1408 debug_printf("non-subshell grouping\n");
1391 setup_redirects(child, squirrel); 1409 setup_redirects(child, squirrel);
1392 /* XXX could we merge code with following builtin case, 1410 /* XXX could we merge code with following builtin case,
@@ -1396,7 +1414,7 @@ static int run_pipe_real(struct pipe *pi)
1396 return rcode; 1414 return rcode;
1397 } 1415 }
1398 1416
1399 if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { 1417 if (single_fg && pi->progs[0].argv != NULL) {
1400 for (i = 0; is_assignment(child->argv[i]); i++) 1418 for (i = 0; is_assignment(child->argv[i]); i++)
1401 continue; 1419 continue;
1402 if (i != 0 && child->argv[i] == NULL) { 1420 if (i != 0 && child->argv[i] == NULL) {
@@ -1675,13 +1693,7 @@ static int run_list_real(struct pipe *pi)
1675 rcode = EXIT_SUCCESS; 1693 rcode = EXIT_SUCCESS;
1676 } else { 1694 } else {
1677 if (interactive_fd) { 1695 if (interactive_fd) {
1678 pid_t p; 1696 rcode = checkjobs_and_fg_shell(pi);
1679 rcode = checkjobs(pi);
1680 /* move the shell to the foreground */
1681 p = getpgid(0);
1682 if (tcsetpgrp(interactive_fd, p) && errno != ENOTTY)
1683 bb_perror_msg("tcsetpgrp-4");
1684 debug_printf("getpgid(0)=%d\n", (int)p);
1685 } else { 1697 } else {
1686 rcode = checkjobs(pi); 1698 rcode = checkjobs(pi);
1687 } 1699 }