]> granicus.if.org Git - sudo/commitdiff
No need to use pseudo-cbreak mode now that we use pipes when stdout is
authorTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 10 May 2010 21:23:35 +0000 (17:23 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 10 May 2010 21:23:35 +0000 (17:23 -0400)
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
src/script.c
src/sudo.h
src/term.c

index ad484f936e34158206ff467623212a5df005b362..cba33a103f437763f22745839804fa6da310b842 100644 (file)
@@ -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),
index 7c1e9cc450b3d393bf77d3582fcd856cfc44d35c..3d8527cc298bc3f361fc78a4330f84a89d1a8920 100644 (file)
@@ -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])
index 6ff8db20f12519d15ab5ca653d074e7eddcf4c68..0dbdf50130b91778bb39df8e68f271c78ab7750a 100644 (file)
@@ -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 */
index 20d7c6b77b34c8e2eb9ac4de882b0a37bd53b842..be59ba708aef0c9ebe8dbaf44d1f4fa9ff0280c1 100644 (file)
@@ -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);