diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-28 16:43:18 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-28 16:43:18 +0000 |
commit | 18e19f2b0d36c0d9566d871942dfe282e9cf5a28 (patch) | |
tree | 22d3da65f1031bac1833c4f53c24b4f7876d5d6b /shell/hush.c | |
parent | a6a1785a30d6fe011eeabec3c19e154dc475b1b0 (diff) | |
download | busybox-w32-18e19f2b0d36c0d9566d871942dfe282e9cf5a28.tar.gz busybox-w32-18e19f2b0d36c0d9566d871942dfe282e9cf5a28.tar.bz2 busybox-w32-18e19f2b0d36c0d9566d871942dfe282e9cf5a28.zip |
hush: fix nofork + ctrl-Z clobbering of globals
Diffstat (limited to '')
-rw-r--r-- | shell/hush.c | 40 |
1 files changed, 17 insertions, 23 deletions
diff --git a/shell/hush.c b/shell/hush.c index c87f3b566..b2ff0cb2e 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -441,30 +441,28 @@ static void signal_SA_RESTART(int sig, void (*handler)(int)) | |||
441 | sigaction(sig, &sa, NULL); | 441 | sigaction(sig, &sa, NULL); |
442 | } | 442 | } |
443 | 443 | ||
444 | struct nofork_save_area nofork_save; | ||
444 | static sigjmp_buf nofork_jb; | 445 | static sigjmp_buf nofork_jb; |
445 | static smallint nofork_flag; | ||
446 | static struct pipe *nofork_pipe; | 446 | static struct pipe *nofork_pipe; |
447 | 447 | ||
448 | static void handler_ctrl_z(int sig) | 448 | static void handler_ctrl_z(int sig) |
449 | { | 449 | { |
450 | pid_t pid; | 450 | pid_t pid; |
451 | 451 | ||
452 | fprintf(stderr, "got tty sig %d\n", sig); | 452 | debug_jobs_printf("got tty sig %d\n", sig); |
453 | if (!nofork_flag) | ||
454 | return; | ||
455 | pid = fork(); | 453 | pid = fork(); |
456 | if (pid < 0) /* can't fork. Pretend there were no Ctrl-Z */ | 454 | if (pid < 0) /* can't fork. Pretend there were no Ctrl-Z */ |
457 | return; | 455 | return; |
458 | fprintf(stderr, "bg'ing nofork\n"); | 456 | debug_jobs_printf("bg'ing nofork\n"); |
459 | nofork_flag = 0; | 457 | nofork_save.saved = 0; /* flag the fact that Ctrl-Z was handled */ |
460 | nofork_pipe->running_progs = 1; | 458 | nofork_pipe->running_progs = 1; |
461 | nofork_pipe->stopped_progs = 0; | 459 | nofork_pipe->stopped_progs = 0; |
462 | if (!pid) { /* child */ | 460 | if (!pid) { /* child */ |
463 | fprintf(stderr, "setting pgrp for child\n"); | 461 | debug_jobs_printf("setting pgrp for child\n"); |
464 | setpgrp(); | 462 | setpgrp(); |
465 | signal(sig, SIG_DFL); /* make child do default action (stop) */ | 463 | signal(SIGTSTP, SIG_DFL); /* make child do default action (stop) */ |
466 | raise(sig); /* resend TSTP so that child will be stopped */ | 464 | raise(SIGTSTP); /* resend TSTP so that child will be stopped */ |
467 | fprintf(stderr, "returning to child\n"); | 465 | debug_jobs_printf("returning to child\n"); |
468 | /* return to nofork, it will eventually exit now, | 466 | /* return to nofork, it will eventually exit now, |
469 | * not return back to shell */ | 467 | * not return back to shell */ |
470 | return; | 468 | return; |
@@ -1588,25 +1586,23 @@ static int run_pipe_real(struct pipe *pi) | |||
1588 | const struct bb_applet *a = find_applet_by_name(argv[i]); | 1586 | const struct bb_applet *a = find_applet_by_name(argv[i]); |
1589 | if (a && a->nofork) { | 1587 | if (a && a->nofork) { |
1590 | setup_redirects(child, squirrel); | 1588 | setup_redirects(child, squirrel); |
1589 | /* TSTP handler will store pid etc in pi */ | ||
1590 | nofork_pipe = pi; | ||
1591 | save_nofork_data(&nofork_save); | ||
1591 | if (sigsetjmp(nofork_jb, 1) == 0) { | 1592 | if (sigsetjmp(nofork_jb, 1) == 0) { |
1592 | // enable ctrl_z here, not globally? | 1593 | signal_SA_RESTART(SIGTSTP, handler_ctrl_z); |
1593 | nofork_flag = 1; | 1594 | rcode = run_nofork_applet_prime(&nofork_save, a, argv + i); |
1594 | /* TSTP handler will store pid there etc */ | 1595 | if (--nofork_save.saved != 0) |
1595 | nofork_pipe = pi; | ||
1596 | rcode = run_nofork_applet(a, argv + i); | ||
1597 | if (--nofork_flag != 0) | ||
1598 | /* Ctrl-Z! forked, we are child */ | 1596 | /* Ctrl-Z! forked, we are child */ |
1599 | exit(rcode); | 1597 | exit(rcode); |
1600 | restore_redirects(squirrel); | 1598 | restore_redirects(squirrel); |
1601 | return rcode; | 1599 | return rcode; |
1602 | } else { | 1600 | } else { |
1603 | fprintf(stderr, "Exiting nofork early\n"); | ||
1604 | /* Ctrl-Z, forked, we are parent. | 1601 | /* Ctrl-Z, forked, we are parent. |
1605 | * Sighandler has longjmped us here */ | 1602 | * Sighandler has longjmped us here */ |
1606 | //problem: run_nofork_applet did not do the | 1603 | signal(SIGTSTP, SIG_IGN); |
1607 | // "restore" trick and globals are trashed: | 1604 | debug_jobs_printf("Exiting nofork early\n"); |
1608 | // for one, applet_name is not "hush" :) | 1605 | restore_nofork_data(&nofork_save); |
1609 | // need to split run_nofork_applet into setup/run/restore... | ||
1610 | restore_redirects(squirrel); | 1606 | restore_redirects(squirrel); |
1611 | insert_bg_job(pi); | 1607 | insert_bg_job(pi); |
1612 | return 0; | 1608 | return 0; |
@@ -3021,8 +3017,6 @@ static void setup_job_control(void) | |||
3021 | 3017 | ||
3022 | /* Grab control of the terminal. */ | 3018 | /* Grab control of the terminal. */ |
3023 | tcsetpgrp(interactive_fd, shell_pgrp); | 3019 | tcsetpgrp(interactive_fd, shell_pgrp); |
3024 | |||
3025 | signal_SA_RESTART(SIGTSTP, handler_ctrl_z); | ||
3026 | } | 3020 | } |
3027 | 3021 | ||
3028 | int hush_main(int argc, char **argv); | 3022 | int hush_main(int argc, char **argv); |