login: clear FD_CLOEXEC on stdio before spawning shell (+diag) so the login shell inherits console I/O

This commit is contained in:
2026-07-18 17:56:46 +09:00
parent 09d078a555
commit 1677bdd2c3
+20
View File
@@ -86,6 +86,26 @@ pub fn spawn_shell<T: Default>(user: &User<T>) -> IoResult<i32> {
}
}
// The relibc Redox spawn closes, in the child, every inherited fd that has
// FD_CLOEXEC set in the parent's filetable (see relibc
// platform/redox/mod.rs, the fds_to_close loop). A login shell MUST inherit
// its console stdio, but the pty-slave fds can arrive here still carrying
// FD_CLOEXEC (login itself keeps using them fine, since CLOEXEC only affects
// exec, not use) — which then silently drops the shell's stdin/stdout/stderr
// and leaves an interactive shell with no console. Explicitly clear
// FD_CLOEXEC on 0/1/2 so they survive the exec into the shell.
const F_GETFD: usize = 1;
const F_SETFD: usize = 2;
const FD_CLOEXEC: usize = 1;
for fd in 0..=2 {
let fl = fcntl(fd, F_GETFL, 0);
let fd_fl = fcntl(fd, F_GETFD, 0);
eprintln!("login-diag: fd{fd} F_GETFL={fl:?} F_GETFD={fd_fl:?}");
if let Ok(flags) = fd_fl {
let _ = fcntl(fd, F_SETFD, flags & !FD_CLOEXEC);
}
}
// 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