Can't rely on the shell sending us SIGCONT when transitioning from
backgroup to foreground process.
This commit is contained in:
50
script.c
50
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
|
||||
*/
|
||||
|
Reference in New Issue
Block a user