diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-21 13:42:52 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-21 13:42:52 +0000 |
commit | 52881e9f23d1b02f75f2c1f5e704edc283be5cdf (patch) | |
tree | 06b88f81bb62ecdc2850705c1845ba9a963cc09b /shell | |
parent | 2f1bb36a557f4ce8e1f5abd177c34dadbc0fb534 (diff) | |
download | busybox-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/README | 8 | ||||
-rw-r--r-- | shell/hush.c | 32 |
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 @@ | |||
1 | Various bits of what is known about busybox shells, in no particular order. | 1 | Various bits of what is known about busybox shells, in no particular order. |
2 | 2 | ||
3 | 2007-04-22 | 3 | 2007-04-21 |
4 | hush: fixed non-backgrounding of "sleep 1 &" and totally broken | ||
5 | "sleep 1 | sleep 2 &". Noticed a bug where successive jobs | ||
6 | get numbers 1,2,3 even when job #1 has exited before job# 2 is started. | ||
7 | (bash reuses #1 in this case) | ||
8 | |||
9 | 2007-04-21 | ||
4 | hush: "sleep 1 | exit 3; echo $?" prints 0 because $? is substituted | 10 | hush: "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" |
6 | parsed and handed to it for execution, so it sees "pipe"; "echo 0". | 12 | parsed 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); | |||
384 | static int parse_file_outer(FILE *f); | 384 | static int parse_file_outer(FILE *f); |
385 | /* job management: */ | 385 | /* job management: */ |
386 | static int checkjobs(struct pipe* fg_pipe); | 386 | static int checkjobs(struct pipe* fg_pipe); |
387 | static int checkjobs_and_fg_shell(struct pipe* fg_pipe); | ||
387 | static void insert_bg_job(struct pipe *pi); | 388 | static void insert_bg_job(struct pipe *pi); |
388 | static void remove_bg_job(struct pipe *pi); | 389 | static 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 | ||
1358 | static 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 | } |