From 1cce5020ad62bcac5f4e54d2f23d3e6d86757090 Mon Sep 17 00:00:00 2001 From: vasilito Date: Sat, 18 Jul 2026 14:33:37 +0900 Subject: [PATCH] login: reset the console terminal to canonical mode before the shell The username is read with the liner line editor, which puts the console pty into raw mode (ICANON/ECHO cleared) and does not restore it. In raw mode the pty line discipline never flushes a completed line into the slave read buffer the way a shell's canonical read_line expects, so the interactive shell (brush) never receives a typed command even though getty forwards it to the pty master. Reset stdin to sane cooked settings (ICANON|ECHO|ISIG, ICRNL, OPOST|ONLCR, VMIN=1/VTIME=0) via tcsetattr before spawning the shell. --- src/lib.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 3dd8d4ec5b..52a8d90b7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,6 +86,30 @@ pub fn spawn_shell(user: &User) -> IoResult { } } + // The login name is read with the `liner` line editor, which switches the + // console pty into raw mode (ICANON/ECHO cleared) and does not restore it. + // In raw mode the pty's line discipline never flushes a completed line to + // the slave's read buffer the way a shell's canonical `read_line` expects, + // so the interactive shell can never receive a typed command. Reset the + // terminal to sane canonical/cooked settings before exec'ing the shell. + #[cfg(target_os = "redox")] + unsafe { + let mut t: libc::termios = core::mem::zeroed(); + if libc::tcgetattr(0, &mut t) == 0 { + t.c_iflag |= (libc::ICRNL | libc::IXON) as _; + t.c_oflag |= (libc::OPOST | libc::ONLCR) as _; + t.c_lflag |= (libc::ICANON + | libc::ECHO + | libc::ECHOE + | libc::ECHOK + | libc::ISIG + | libc::IEXTEN) as _; + t.c_cc[libc::VMIN] = 1; + t.c_cc[libc::VTIME] = 0; + let _ = libc::tcsetattr(0, libc::TCSANOW, &t); + } + } + let mut command = user.shell_cmd(); let mut child = command.spawn()?;