From 282ca3d87b4ab2e3f077c959fd5e0f87980120d6 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 6 Mar 2019 11:54:51 +0100 Subject: [PATCH] su: fix --pty terminal initialization * 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 --- login-utils/su-common.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/login-utils/su-common.c b/login-utils/su-common.c index 0e44eb87cb..bf4a471261 100644 --- a/login-utils/su-common.c +++ b/login-utils/su-common.c @@ -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) -- 2.39.2