diff --git a/script.c b/script.c index 880e45f07..732f25cab 100644 --- a/script.c +++ b/script.c @@ -100,13 +100,13 @@ static int script_fds[6]; static sig_atomic_t alive = 1; static sig_atomic_t recvsig = 0; static sig_atomic_t ttymode = TERM_COOKED; -static sig_atomic_t foreground = 0; static sig_atomic_t tty_initialized = 0; static sigset_t ttyblock; static pid_t parent, child; static int child_status; +static int foreground; static char slavename[PATH_MAX]; @@ -118,7 +118,6 @@ static void handler __P((int s)); static void script_child __P((char *path, char *argv[], int, int)); static void script_run __P((char *path, char *argv[], int)); static void sigchild __P((int s)); -static void sigcont __P((int s)); static void sigwinch __P((int s)); static void sync_winsize __P((int src, int dst)); @@ -352,6 +351,18 @@ log_output(buf, n, then, now, ofile, tfile) sigprocmask(SIG_SETMASK, &omask, NULL); } +static void +check_foreground() +{ + foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == parent; + if (foreground && !tty_initialized) { + if (term_copy(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE], 0)) { + tty_initialized = 1; + sync_winsize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]); + } + } +} + /* * Suspend sudo if the underlying command is suspended. * Returns SIGUSR1 if the child should be resume in foreground else SIGUSR2. @@ -375,6 +386,8 @@ suspend_parent(signo, output, then, now, ofile, tfile) * If we are the foreground process, just resume the child. * Otherwise, re-send the signal with the handler disabled. */ + if (!foreground) + check_foreground(); if (foreground) { if (ttymode != TERM_RAW) { do { @@ -406,6 +419,9 @@ suspend_parent(signo, output, then, now, ofile, tfile) #endif kill(parent, signo); + /* Check foreground/background status on resume. */ + check_foreground(); + /* * Only modify term if we are foreground process and either * the old tty mode was not cooked or child got SIGTT{IN,OU} @@ -508,10 +524,6 @@ script_execv(path, argv) sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); - /* To update foreground/background state. */ - sa.sa_handler = sigcont; - sigaction(SIGCONT, &sa, NULL); - /* Signals to relay from parent to child. */ sa.sa_flags = 0; /* do not restart syscalls for these */ sa.sa_handler = handler; @@ -615,7 +627,7 @@ script_execv(path, argv) zero_bytes(&input, sizeof(input)); zero_bytes(&output, sizeof(output)); while (alive) { - /* XXX */ + /* XXX - racey */ if (!relaysig && recvsig != SIGCHLD) { relaysig = recvsig; recvsig = 0; @@ -966,7 +978,7 @@ script_child(path, argv, backchannel, rbac_enabled) killpg(child, SIGCONT); break; default: - /* XXX - warn? */ + warningx("unexpected signal from child: %d", signo); break; } } @@ -1063,28 +1075,6 @@ sync_winsize(src, dst) #endif } -/* - * Handler for SIGCONT in parent - */ -static void -sigcont(s) - int s; -{ - int serrno = errno; - - /* Did we get continued in the foreground or background? */ - foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == parent; - - if (foreground && !tty_initialized) { - if (term_copy(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE], 0)) { - tty_initialized = 1; - sync_winsize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]); - } - } - - errno = serrno; -} - /* * Handler for SIGCHLD in parent */