]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
su: fix --pty terminal initialization
authorKarel Zak <kzak@redhat.com>
Wed, 6 Mar 2019 10:54:51 +0000 (11:54 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 6 Mar 2019 11:01:18 +0000 (12:01 +0100)
* use proper winsize rather than uninitialized variable (Oops...)

* set the current terminal to the raw mode

* disable ECHO for non-terminal execution to be compatible with
  non-pty output

Addresses: https://github.com/karelzak/util-linux/issues/767
Signed-off-by: Karel Zak <kzak@redhat.com>
login-utils/su-common.c

index 0e44eb87cbd662e3f68db2fdfcb426561b4cc32e..bf4a47126177c9a748e7a99347a68531f78d88e0 100644 (file)
@@ -276,29 +276,26 @@ static void pty_create(struct su_context *su)
 
        if (su->isterm) {
                DBG(PTY, ul_debug("create for terminal"));
-               struct winsize win;
 
                /* original setting of the current terminal */
                if (tcgetattr(STDIN_FILENO, &su->stdin_attrs) != 0)
                        err(EXIT_FAILURE, _("failed to get terminal attributes"));
-
-               /* reuse the current terminal setting for slave */
-               slave_attrs = su->stdin_attrs;
-               cfmakeraw(&slave_attrs);
-
                ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&su->win);
-
                /* create master+slave */
-               rc = openpty(&su->pty_master, &su->pty_slave, NULL, &slave_attrs, &win);
+               rc = openpty(&su->pty_master, &su->pty_slave, NULL, &su->stdin_attrs, &su->win);
 
+               /* set the current terminal to raw mode; pty_cleanup() reverses this change on exit */
+               slave_attrs = su->stdin_attrs;
+               cfmakeraw(&slave_attrs);
+               slave_attrs.c_lflag &= ~ECHO;
+               tcsetattr(STDIN_FILENO, TCSANOW, &slave_attrs);
        } else {
                DBG(PTY, ul_debug("create for non-terminal"));
                rc = openpty(&su->pty_master, &su->pty_slave, NULL, NULL, NULL);
 
-               /* set slave attributes */
                if (!rc) {
                        tcgetattr(su->pty_slave, &slave_attrs);
-                       cfmakeraw(&slave_attrs);
+                       slave_attrs.c_lflag &= ~ECHO;
                        tcsetattr(su->pty_slave, TCSANOW, &slave_attrs);
                }
        }
@@ -311,12 +308,14 @@ static void pty_create(struct su_context *su)
 
 static void pty_cleanup(struct su_context *su)
 {
-       if (su->pty_master == -1)
+       struct termios rtt;
+
+       if (su->pty_master == -1 || !su->isterm)
                return;
 
        DBG(PTY, ul_debug("cleanup"));
-       if (su->isterm)
-               tcsetattr(STDIN_FILENO, TCSADRAIN, &su->stdin_attrs);
+       rtt = su->stdin_attrs;
+       tcsetattr(STDIN_FILENO, TCSADRAIN, &rtt);
 }
 
 static int write_output(char *obuf, ssize_t bytes)