From e45c504ab04c21da47bf6dbfde27d6ebc824ae23 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Thu, 3 Apr 2025 23:58:06 +0200 Subject: [PATCH] Don't reopen stdout on startup If it's not a TTY we should just exit, because then the user probably ran edit by accident anyway. It doesn't make much sense to redirect the output of any interactive application. --- src/sys/unix.rs | 6 ++---- src/sys/windows.rs | 49 ++++++++++++++++++++++++---------------------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/sys/unix.rs b/src/sys/unix.rs index a712908..081f776 100644 --- a/src/sys/unix.rs +++ b/src/sys/unix.rs @@ -45,9 +45,6 @@ pub fn init() -> apperr::Result { if libc::isatty(STATE.stdin) == 0 { STATE.stdin = check_int_return(libc::open(c"/dev/tty".as_ptr(), libc::O_RDONLY))?; } - if libc::isatty(STATE.stdout) == 0 { - STATE.stdout = check_int_return(libc::open(c"/dev/tty".as_ptr(), libc::O_WRONLY))?; - } // Store the stdin flags so we can more easily toggle `O_NONBLOCK` later on. STATE.stdin_flags = check_int_return(libc::fcntl(STATE.stdin, libc::F_GETFL))?; @@ -288,7 +285,8 @@ pub fn write_stdout(text: &str) { pub fn open_stdin_if_redirected() -> Option { unsafe { - if libc::isatty(libc::STDIN_FILENO) == 0 { + // Did we reopen stdin during `init()`? + if STATE.stdin != libc::STDIN_FILENO { Some(File::from_raw_fd(libc::STDIN_FILENO)) } else { None diff --git a/src/sys/windows.rs b/src/sys/windows.rs index 1168d4c..097c08e 100644 --- a/src/sys/windows.rs +++ b/src/sys/windows.rs @@ -80,24 +80,27 @@ pub fn init() -> apperr::Result { let kernel32 = LibraryLoader::GetModuleHandleW(w!("kernel32.dll")); STATE.read_console_input_ex = get_proc_address(kernel32, c"ReadConsoleInputExW")?; - STATE.stdin = FileSystem::CreateFileW( - w!("CONIN$"), - Foundation::GENERIC_READ | Foundation::GENERIC_WRITE, - FileSystem::FILE_SHARE_READ | FileSystem::FILE_SHARE_WRITE, - null_mut(), - FileSystem::OPEN_EXISTING, - 0, - null_mut(), - ); - STATE.stdout = FileSystem::CreateFileW( - w!("CONOUT$"), - Foundation::GENERIC_READ | Foundation::GENERIC_WRITE, - FileSystem::FILE_SHARE_READ | FileSystem::FILE_SHARE_WRITE, - null_mut(), - FileSystem::OPEN_EXISTING, - 0, - null_mut(), - ); + STATE.stdin = Console::GetStdHandle(Console::STD_INPUT_HANDLE); + STATE.stdout = Console::GetStdHandle(Console::STD_OUTPUT_HANDLE); + + // Reopen stdin if it's redirected (= piped input). + if !ptr::eq(STATE.stdin, Foundation::INVALID_HANDLE_VALUE) + && matches!( + FileSystem::GetFileType(STATE.stdin), + FileSystem::FILE_TYPE_DISK | FileSystem::FILE_TYPE_PIPE + ) + { + STATE.stdin = FileSystem::CreateFileW( + w!("CONIN$"), + Foundation::GENERIC_READ | Foundation::GENERIC_WRITE, + FileSystem::FILE_SHARE_READ | FileSystem::FILE_SHARE_WRITE, + null_mut(), + FileSystem::OPEN_EXISTING, + 0, + null_mut(), + ); + } + if ptr::eq(STATE.stdin, Foundation::INVALID_HANDLE_VALUE) || ptr::eq(STATE.stdout, Foundation::INVALID_HANDLE_VALUE) { @@ -379,11 +382,11 @@ pub fn write_stdout(text: &str) { pub fn open_stdin_if_redirected() -> Option { unsafe { let handle = Console::GetStdHandle(Console::STD_INPUT_HANDLE); - match FileSystem::GetFileType(handle) { - FileSystem::FILE_TYPE_DISK | FileSystem::FILE_TYPE_PIPE => { - Some(File::from_raw_handle(handle)) - } - _ => None, + // Did we reopen stdin during `init()`? + if !std::ptr::eq(STATE.stdin, handle) { + Some(File::from_raw_handle(handle)) + } else { + None } } }