Can't rely on the shell sending us SIGCONT when transitioning from

backgroup to foreground process.
This commit is contained in:
Todd C. Miller
2009-11-22 15:58:37 +00:00
parent 850990b88d
commit 453d055b4c

View File

@@ -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
*/