commit 51c54dfaf33ba42ba6fe1268f17ff926d5d0949a Author: Luke Shumaker Date: Tue Oct 8 11:36:05 2013 -0400 nspawn: Set the size of the PTY based on the size of stdout, not stdin. This was probably originally coded with the assumption that stdin and stdout were the same device, but this clearly is the wrong thing if stdout has been redirected. diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index fc4a8a3..ae4c80d 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1319,7 +1319,7 @@ int main(int argc, char *argv[]) { log_info("Spawning namespace container on %s (console is %s).", arg_directory, console); - if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0) + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0) ioctl(master, TIOCSWINSZ, &ws); if (unlockpt(master) < 0) { commit f3ec07e5de3d200ef7128ae6aa834ed6e8d59386 Author: Luke Shumaker Date: Tue Oct 8 14:22:08 2013 -0400 nspawn: Don't set the output prop of stdin, nor the input props of stdout. It was calling cfmakeraw(3) on the properties for STDIN_FILENO; cfmakeraw sets both input and output properties. If (and only if) stdin and stdout are the same device is this correct. Otherwise, we must change only the input properties of stdin, and only the output properties of stdout. This is mostly straight-forward, but in order to still correctly handle them being the same device, we must apply the changes to the first one (of stdin and stdout) immediately, so that changing one doesn't reset the other. So this means that we have to move the code that actually applies the changes. diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index ae4c80d..5736b06 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1218,9 +1218,11 @@ int main(int argc, char *argv[]) { _cleanup_close_ int master = -1; int n_fd_passed; const char *console = NULL; - struct termios saved_attr, raw_attr; + struct termios saved_stdin_attr, raw_stdin_attr; + struct termios saved_stdout_attr, raw_stdout_attr; sigset_t mask; - bool saved_attr_valid = false; + bool saved_stdin_attr_valid = false; + bool saved_stdout_attr_valid = false; struct winsize ws; int kmsg_socket_pair[2] = { -1, -1 }; FDSet *fds = NULL; @@ -1327,14 +1329,29 @@ int main(int argc, char *argv[]) { goto finish; } - if (tcgetattr(STDIN_FILENO, &saved_attr) >= 0) { - saved_attr_valid = true; + if (tcgetattr(STDIN_FILENO, &saved_stdin_attr) >= 0) { + saved_stdin_attr_valid = true; - raw_attr = saved_attr; - cfmakeraw(&raw_attr); - raw_attr.c_lflag &= ~ECHO; + raw_stdin_attr = saved_stdin_attr; + cfmakeraw(&raw_stdin_attr); + raw_stdin_attr.c_oflag = saved_stdin_attr.c_oflag; + if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr) < 0) { + log_error("Failed to set stdin terminal attributes: %m"); + goto finish; + } + } + if (tcgetattr(STDOUT_FILENO, &saved_stdout_attr) >= 0) { + saved_stdout_attr_valid = true; + + raw_stdout_attr = saved_stdout_attr; + cfmakeraw(&raw_stdout_attr); + raw_stdout_attr.c_iflag = saved_stdout_attr.c_iflag; + raw_stdout_attr.c_lflag = saved_stdout_attr.c_lflag; + if (tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr) < 0) { + log_error("Failed to set stdout terminal attributes: %m"); + goto finish; + } } - if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) { log_error("Failed to create kmsg socket pair."); goto finish; @@ -1402,13 +1419,6 @@ int main(int argc, char *argv[]) { close_nointr_nofail(master); master = -1; - if (saved_attr_valid) { - if (tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr) < 0) { - log_error("Failed to set terminal attributes: %m"); - goto child_fail; - } - } - close_nointr(STDIN_FILENO); close_nointr(STDOUT_FILENO); close_nointr(STDERR_FILENO); @@ -1673,8 +1683,10 @@ int main(int argc, char *argv[]) { if (process_pty(master, pid, &mask) < 0) goto finish; - if (saved_attr_valid) - tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr); + if (saved_stdout_attr_valid) + tcsetattr(STDOUT_FILENO, TCSANOW, &saved_stdout_attr); + if (saved_stdin_attr_valid) + tcsetattr(STDIN_FILENO, TCSANOW, &saved_stdin_attr); k = wait_for_terminate(pid, &status); if (k < 0) { @@ -1714,8 +1726,10 @@ int main(int argc, char *argv[]) { } finish: - if (saved_attr_valid) - tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr); + if (saved_stdout_attr_valid) + tcsetattr(STDOUT_FILENO, TCSANOW, &saved_stdout_attr); + if (saved_stdin_attr_valid) + tcsetattr(STDIN_FILENO, TCSANOW, &saved_stdin_attr); close_pipe(kmsg_socket_pair);