diff options
author | Karel Zak | 2019-03-06 11:54:51 +0100 |
---|---|---|
committer | Karel Zak | 2019-03-06 12:01:18 +0100 |
commit | 282ca3d87b4ab2e3f077c959fd5e0f87980120d6 (patch) | |
tree | cce5ab6512597f2b9f5eaee112d9e2695f73aeb9 /login-utils | |
parent | tests: add missing ts_check_test_command call (diff) | |
download | kernel-qcow2-util-linux-282ca3d87b4ab2e3f077c959fd5e0f87980120d6.tar.gz kernel-qcow2-util-linux-282ca3d87b4ab2e3f077c959fd5e0f87980120d6.tar.xz kernel-qcow2-util-linux-282ca3d87b4ab2e3f077c959fd5e0f87980120d6.zip |
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 <kzak@redhat.com>
Diffstat (limited to 'login-utils')
-rw-r--r-- | login-utils/su-common.c | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/login-utils/su-common.c b/login-utils/su-common.c index 0e44eb87c..bf4a47126 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) |