From c2d0888bf9f68c8ebe472c6f2534d48c30907e55 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 10 May 2010 17:23:35 -0400 Subject: [PATCH] No need to use pseudo-cbreak mode now that we use pipes when stdout is not a tty. Instead, check whether stdin is a tty and if not, delay setting the tty to raw mode until the command tries to access it itself (and receives SIGTTIN or SIGTTOU). --- plugins/sudoers/sudoreplay.c | 4 ++-- src/script.c | 42 ++++++++++++++++++++---------------- src/sudo.h | 2 +- src/term.c | 5 +---- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/plugins/sudoers/sudoreplay.c b/plugins/sudoers/sudoreplay.c index ad484f936..cba33a103 100644 --- a/plugins/sudoers/sudoreplay.c +++ b/plugins/sudoers/sudoreplay.c @@ -150,7 +150,7 @@ static int stack_top; extern time_t get_date(char *); extern char *get_timestr(time_t, int); -extern int term_raw(int, int, int); +extern int term_raw(int, int); extern int term_restore(int, int); extern void zero_bytes(volatile void *, size_t); void cleanup(int); @@ -297,7 +297,7 @@ main(int argc, char *argv[]) ch = fcntl(STDIN_FILENO, F_GETFL, 0); if (ch != -1) (void) fcntl(STDIN_FILENO, F_SETFL, ch | O_NONBLOCK); - if (!term_raw(STDIN_FILENO, 0, 1)) + if (!term_raw(STDIN_FILENO, 1)) error(1, "cannot set tty to raw mode"); } fdsr = (fd_set *)emalloc2(howmany(STDOUT_FILENO + 1, NFDBITS), diff --git a/src/script.c b/src/script.c index 7c1e9cc45..3d8527cc2 100644 --- a/src/script.c +++ b/src/script.c @@ -87,8 +87,7 @@ #define SFD_USERTTY 5 #define TERM_COOKED 0 -#define TERM_CBREAK 1 -#define TERM_RAW 2 +#define TERM_RAW 1 #if !defined(TIOCGSIZE) && defined(TIOCGWINSZ) # define TIOCGSIZE TIOCGWINSZ @@ -108,7 +107,7 @@ struct io_buffer { }; static int script_fds[6] = { -1, -1, -1, -1, -1, -1}; -static int ttyout = TRUE; +static int ttyin = TRUE; static sig_atomic_t recvsig[NSIG]; static sig_atomic_t ttymode = TERM_COOKED; @@ -296,7 +295,7 @@ suspend_parent(int signo, int fd, struct io_buffer *iobufs) if (foreground) { if (ttymode != TERM_RAW) { do { - n = term_raw(script_fds[SFD_USERTTY], !ttyout, 0); + n = term_raw(script_fds[SFD_USERTTY], 0); } while (!n && errno == EINTR); ttymode = TERM_RAW; } @@ -335,10 +334,9 @@ suspend_parent(int signo, int fd, struct io_buffer *iobufs) if (ttymode != TERM_COOKED) { if (foreground) { - /* Set raw/cbreak mode. */ + /* Set raw mode. */ do { - n = term_raw(script_fds[SFD_USERTTY], !ttyout, - ttymode == TERM_CBREAK); + n = term_raw(script_fds[SFD_USERTTY], 0); } while (!n && errno == EINTR); } else { /* Background process, no access to tty. */ @@ -565,6 +563,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[], */ memset(io_pipe, 0, sizeof(io_pipe)); if (!isatty(STDIN_FILENO)) { + ttyin = FALSE; if (pipe(io_pipe[STDIN_FILENO]) != 0) error(1, "unable to create pipe"); iobufs = io_buf_new(STDIN_FILENO, io_pipe[STDIN_FILENO][1], @@ -572,7 +571,6 @@ script_execve(struct command_details *details, char *argv[], char *envp[], script_fds[SFD_STDIN] = io_pipe[STDIN_FILENO][0]; } if (!isatty(STDOUT_FILENO)) { - ttyout = FALSE; if (pipe(io_pipe[STDOUT_FILENO]) != 0) error(1, "unable to create pipe"); iobufs = io_buf_new(io_pipe[STDOUT_FILENO][0], STDOUT_FILENO, @@ -603,14 +601,15 @@ script_execve(struct command_details *details, char *argv[], char *envp[], sync_ttysize(script_fds[SFD_USERTTY], script_fds[SFD_SLAVE]); } - /* Start out in raw mode is stdout is a tty. */ - ttymode = ttyout ? TERM_RAW : TERM_CBREAK; - do { - n = term_raw(script_fds[SFD_USERTTY], !ttyout, - ttymode == TERM_CBREAK); - } while (!n && errno == EINTR); - if (!n) - error(1, "Can't set terminal to raw mode"); + /* Start out in raw mode is stdin is a tty. */ + if (ttyin) { + ttymode = TERM_RAW; + do { + n = term_raw(script_fds[SFD_USERTTY], 0); + } while (!n && errno == EINTR); + if (!n) + error(1, "Can't set terminal to raw mode"); + } } } @@ -738,7 +737,7 @@ script_execve(struct command_details *details, char *argv[], char *envp[], FD_SET(iob->rfd, fdsr); } if (iob->wfd != -1 && - (ttymode == TERM_RAW || iob->wfd != script_fds[SFD_USERTTY])) { + (foreground || iob->wfd != script_fds[SFD_USERTTY])) { if (iob->len > iob->off) FD_SET(iob->wfd, fdsw); } @@ -971,7 +970,13 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int close(n); #endif - if (foreground && !ttyout) + /* + * If stdin is not a tty, start command in the background since + * it might be part of a pipeline that reads from /dev/tty. + * In this case, we rely on the command receiving SIGTTOU or SIGTTIN + * when it needs access to the controlling tty. + */ + if (foreground && !ttyin) foreground = 0; /* Start command and wait for it to stop or exit */ @@ -1012,7 +1017,6 @@ script_child(const char *path, char *argv[], char *envp[], int backchannel, int close(errpipe[1]); /* If any of stdin/stdout/stderr are pipes, close them in parent. */ - /* XXX - close other end too */ if (script_fds[SFD_STDIN] != script_fds[SFD_SLAVE]) close(script_fds[SFD_STDIN]); if (script_fds[SFD_STDOUT] != script_fds[SFD_SLAVE]) diff --git a/src/sudo.h b/src/sudo.h index 6ff8db20f..0dbdf5013 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -178,7 +178,7 @@ void script_setup(uid_t); int term_cbreak(int); int term_copy(int, int); int term_noecho(int); -int term_raw(int, int, int); +int term_raw(int, int); int term_restore(int, int); /* fmt_string.h */ diff --git a/src/term.c b/src/term.c index 20d7c6b77..be59ba708 100644 --- a/src/term.c +++ b/src/term.c @@ -116,7 +116,7 @@ term_noecho(int fd) } int -term_raw(int fd, int opost, int isig) +term_raw(int fd, int isig) { struct termios term; @@ -130,9 +130,6 @@ term_raw(int fd, int opost, int isig) if (isig) SET(term.c_lflag, ISIG); CLR(term.c_iflag, ICRNL | IGNCR | INLCR | IUCLC | IXON); - /* Only retain output post-processing opost flag set. */ - if (!opost) - CLR(term.c_oflag, OPOST); if (tcsetattr(fd, TCSADRAIN|TCSASOFT, &term) == 0) { changed = 1; return(1); -- 2.40.0