summaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-04-28 16:43:18 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-04-28 16:43:18 +0000
commit18e19f2b0d36c0d9566d871942dfe282e9cf5a28 (patch)
tree22d3da65f1031bac1833c4f53c24b4f7876d5d6b /shell/hush.c
parenta6a1785a30d6fe011eeabec3c19e154dc475b1b0 (diff)
downloadbusybox-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.c40
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
444struct nofork_save_area nofork_save;
444static sigjmp_buf nofork_jb; 445static sigjmp_buf nofork_jb;
445static smallint nofork_flag;
446static struct pipe *nofork_pipe; 446static struct pipe *nofork_pipe;
447 447
448static void handler_ctrl_z(int sig) 448static 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
3028int hush_main(int argc, char **argv); 3022int hush_main(int argc, char **argv);