From: Todd C. Miller Date: Fri, 11 Jan 2013 15:09:06 +0000 (-0500) Subject: Always resume the command in the foreground if sudo itself is the X-Git-Tag: SUDO_1_8_7~1^2~288 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8b3edcc4a83ccc80aef8fd6aaef731069d4edcd4;p=sudo Always resume the command in the foreground if sudo itself is the foreground process. This helps work around poorly behaved programs that catch SIGTTOU/SIGTTIN but suspend themselves with SIGSTOP. At worst, sudo will go into the background but upon resume the command will be runnable. Otherwise, we can get into a situation where the command will immediately suspend itself. --- diff --git a/src/exec_pty.c b/src/exec_pty.c index a80dbb20d..cb5c11dc1 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -348,15 +348,15 @@ suspend_parent(int signo) { char signame[SIG2STR_MAX]; sigaction_t sa, osa; - int n, oldmode = ttymode, rval = 0; + int n, rval = 0; debug_decl(suspend_parent, SUDO_DEBUG_EXEC); switch (signo) { case SIGTTOU: case SIGTTIN: /* - * If we are the foreground process, just resume the command. - * Otherwise, re-send the signal with the handler disabled. + * If sudo is already the foreground process, just resume the command + * in the foreground. If not, we'll suspend sudo and resume later. */ if (!foreground) check_foreground(); @@ -370,7 +370,6 @@ suspend_parent(int signo) rval = SIGCONT_FG; /* resume command in foreground */ break; } - ttymode = TERM_RAW; /* FALLTHROUGH */ case SIGSTOP: case SIGTSTP: @@ -378,7 +377,7 @@ suspend_parent(int signo) flush_output(); /* Restore original tty mode before suspending. */ - if (oldmode != TERM_COOKED) { + if (ttymode != TERM_COOKED) { do { n = term_restore(io_fds[SFD_USERTTY], 0); } while (!n && errno == EINTR); @@ -403,22 +402,26 @@ suspend_parent(int signo) check_foreground(); /* - * Only modify term if we are foreground process and either - * the old tty mode was not cooked or command got SIGTT{IN,OU} + * We always resume the command in the foreground if sudo itself + * is the foreground process. This helps work around poorly behaved + * programs that catch SIGTTOU/SIGTTIN but suspend themselves with + * SIGSTOP. At worst, sudo will go into the background but upon + * resume the command will be runnable. Otherwise, we can get into + * a situation where the command will immediately suspend itself. */ sudo_debug_printf(SUDO_DEBUG_INFO, "parent is in %s, ttymode %d -> %d", - foreground ? "foreground" : "background", oldmode, ttymode); + foreground ? "foreground" : "background", ttymode, + foreground ? TERM_RAW : TERM_COOKED); - if (ttymode != TERM_COOKED) { - if (foreground) { - /* Set raw mode. */ - do { - n = term_raw(io_fds[SFD_USERTTY], 0); - } while (!n && errno == EINTR); - } else { - /* Background process, no access to tty. */ - ttymode = TERM_COOKED; - } + if (foreground) { + /* Foreground process, set tty to raw mode. */ + do { + n = term_raw(io_fds[SFD_USERTTY], 0); + } while (!n && errno == EINTR); + ttymode = TERM_RAW; + } else { + /* Background process, no access to tty. */ + ttymode = TERM_COOKED; } if (signo != SIGSTOP)