diff --git a/src/exec_monitor.c b/src/exec_monitor.c index a92ed4099..2f2e0bd83 100644 --- a/src/exec_monitor.c +++ b/src/exec_monitor.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -35,7 +34,6 @@ #include #include #include -#include #include "sudo.h" #include "sudo_exec.h" @@ -62,8 +60,6 @@ struct monitor_closure { int backchannel; }; -static bool tty_initialized; - /* * Deliver a signal to the running command. * The signal was either forwarded to us by the parent sudo process @@ -103,11 +99,6 @@ deliver_signal(struct monitor_closure *mc, int signo, bool from_parent) "%s: unable to set foreground pgrp to %d (command)", __func__, (int)mc->cmnd_pgrp); } - /* Lazily initialize the pty if needed. */ - if (!tty_initialized) { - if (sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_FOLLOWER])) - tty_initialized = true; - } killpg(mc->cmnd_pid, SIGCONT); break; case SIGCONT_BG: @@ -130,34 +121,6 @@ deliver_signal(struct monitor_closure *mc, int signo, bool from_parent) debug_return; } -/* - * Unpack rows and cols from a CMD_TTYWINCH value, set the new window - * size on the pty follower and inform the command of the change. - */ -static void -handle_winch(struct monitor_closure *mc, unsigned int wsize_packed) -{ - struct winsize wsize, owsize; - debug_decl(handle_winch, SUDO_DEBUG_EXEC); - - /* Rows and columns are stored as two shorts packed into a single int. */ - wsize.ws_row = wsize_packed & 0xffff; - wsize.ws_col = (wsize_packed >> 16) & 0xffff; - - if (ioctl(io_fds[SFD_FOLLOWER], TIOCGWINSZ, &owsize) == 0 && - (wsize.ws_row != owsize.ws_row || wsize.ws_col != owsize.ws_col)) { - - sudo_debug_printf(SUDO_DEBUG_INFO, - "window size change %dx%d -> %dx%d", - owsize.ws_col, owsize.ws_row, wsize.ws_col, wsize.ws_row); - - (void)ioctl(io_fds[SFD_FOLLOWER], TIOCSWINSZ, &wsize); - deliver_signal(mc, SIGWINCH, true); - } - - debug_return; -} - /* * Send status to parent over socketpair. * Return value is the same as send(2). @@ -368,16 +331,11 @@ mon_backchannel_cb(int fd, int what, void *v) mc->cstat->val = n ? EIO : ECONNRESET; sudo_ev_loopbreak(mc->evbase); } else { - switch (cstmp.type) { - case CMD_TTYWINCH: - handle_winch(mc, cstmp.val); - break; - case CMD_SIGNO: + if (cstmp.type == CMD_SIGNO) { deliver_signal(mc, cstmp.val, true); - break; - default: - sudo_warnx(U_("unexpected reply type on backchannel: %d"), cstmp.type); - break; + } else { + sudo_warnx(U_("unexpected reply type on backchannel: %d"), + cstmp.type); } } debug_return; @@ -556,9 +514,11 @@ exec_monitor(struct command_details *details, sigset_t *oset, int errpipe[2]; debug_decl(exec_monitor, SUDO_DEBUG_EXEC); - /* The pty leader is not used by the monitor. */ + /* Close fds the monitor doesn't use. */ if (io_fds[SFD_LEADER] != -1) close(io_fds[SFD_LEADER]); + if (io_fds[SFD_USERTTY] != -1) + close(io_fds[SFD_USERTTY]); /* Ignore any SIGTTIN or SIGTTOU we receive (shouldn't be possible). */ memset(&sa, 0, sizeof(sa)); @@ -570,10 +530,6 @@ exec_monitor(struct command_details *details, sigset_t *oset, if (sudo_sigaction(SIGTTOU, &sa, NULL) != 0) sudo_warn(U_("unable to set handler for signal %d"), SIGTTOU); - /* If we are starting in the foreground, the pty was already initialized. */ - if (foreground) - tty_initialized = true; - /* * Start a new session with the parent as the session leader * and the follower device as the controlling terminal. @@ -630,8 +586,6 @@ exec_monitor(struct command_details *details, sigset_t *oset, /* child */ close(backchannel); close(errpipe[0]); - if (io_fds[SFD_USERTTY] != -1) - close(io_fds[SFD_USERTTY]); /* setup tty and exec command */ exec_cmnd_pty(details, oset, foreground, intercept_fd, errpipe[1]); if (write(errpipe[1], &errno, sizeof(int)) == -1) diff --git a/src/exec_pty.c b/src/exec_pty.c index 9a8ddfab1..e764564aa 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -59,6 +59,7 @@ static struct monitor_message_list monitor_messages = static char ptyname[PATH_MAX]; static bool foreground, pipeline; +static bool tty_initialized; static const char *utmp_user; static void sync_ttysize(struct exec_closure *ec); @@ -159,6 +160,10 @@ check_foreground(struct exec_closure *ec) if (io_fds[SFD_USERTTY] != -1) { if ((ret = tcgetpgrp(io_fds[SFD_USERTTY])) != -1) { foreground = ret == ec->ppgrp; + if (foreground && !tty_initialized) { + if (sudo_term_copy(io_fds[SFD_USERTTY], io_fds[SFD_FOLLOWER])) + tty_initialized = true; + } /* Also check for window size changes. */ sync_ttysize(ec); @@ -840,11 +845,6 @@ fwdchannel_cb(int sock, int what, void *v) sudo_debug_printf(SUDO_DEBUG_INFO, "sending SIG%s to monitor over backchannel", signame); break; - case CMD_TTYWINCH: - sudo_debug_printf(SUDO_DEBUG_INFO, "sending window size change " - "to monitor over backchannelL %d x %d", - msg->cstat.val & 0xffff, (msg->cstat.val >> 16) & 0xffff); - break; default: sudo_debug_printf(SUDO_DEBUG_INFO, "sending cstat type %d, value %d to monitor over backchannel", @@ -1192,6 +1192,7 @@ exec_pty(struct command_details *details, struct command_status *cstat) if (sudo_term_raw(io_fds[SFD_USERTTY], 0)) ttymode = TERM_RAW; } + tty_initialized = true; } } @@ -1347,8 +1348,8 @@ exec_pty(struct command_details *details, struct command_status *cstat) } /* - * Check for tty size changes. - * Passes the new window size to the I/O plugin and to the monitor. + * Propagate tty size change to pty being used by the command, pass + * new window size to I/O plugins and deliver SIGWINCH to the command. */ static void sync_ttysize(struct exec_closure *ec) @@ -1358,14 +1359,12 @@ sync_ttysize(struct exec_closure *ec) if (ioctl(io_fds[SFD_USERTTY], TIOCGWINSZ, &wsize) == 0) { if (wsize.ws_row != ec->rows || wsize.ws_col != ec->cols) { - const unsigned int wsize_packed = (wsize.ws_row & 0xffff) | - ((wsize.ws_col & 0xffff) << 16); - /* Log window change event. */ log_winchange(ec, wsize.ws_row, wsize.ws_col); - /* Send window change event to monitor process. */ - send_command_status(ec, CMD_TTYWINCH, wsize_packed); + /* Update pty window size and send command SIGWINCH. */ + (void)ioctl(io_fds[SFD_LEADER], TIOCSWINSZ, &wsize); + killpg(ec->cmnd_pid, SIGWINCH); /* Update rows/cols. */ ec->rows = wsize.ws_row; diff --git a/src/sudo.h b/src/sudo.h index acb89b751..204c3e76e 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -225,7 +225,6 @@ struct command_status { #define CMD_WSTATUS 2 #define CMD_SIGNO 3 #define CMD_PID 4 -#define CMD_TTYWINCH 5 int type; int val; };