1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Bounded control-channel IO primitives. Only explicitly enabled callers read stdin.
/// Read bytes from the process standard input. Zero denotes clean EOF.
/// Diagnostics use `write_stderr`; protocol responses use `write_stdout`.
#[cfg(windows)]
pub fn read_stdin(bytes: &mut [u8]) -> Result<usize, u32> {
#[link(name = "kernel32", kind = "raw-dylib")]
unsafe extern "system" {
fn GetStdHandle(kind: u32) -> isize;
fn ReadFile(handle: isize, buffer: *mut u8, count: u32, read: *mut u32, overlapped: *mut crate::win::Overlapped) -> i32;
fn GetLastError() -> u32;
}
let mut read = 0;
// SAFETY: buffer is writable for count bytes, the synchronous call cannot outlive it.
unsafe {
let handle = GetStdHandle(-10i32 as u32);
if ReadFile(handle, bytes.as_mut_ptr(), bytes.len().min(u32::MAX as usize) as u32, &mut read, core::ptr::null_mut()) != 0 {
Ok(read as usize)
} else {
let error = GetLastError();
if error == 109 { Ok(0) } else { Err(error) }
}
}
}
/// Read bytes from the process standard input, retrying interrupted system calls and waiting
/// on a descriptor inherited non-blocking.
#[cfg(target_os = "linux")]
pub fn read_stdin(bytes: &mut [u8]) -> Result<usize, u32> {
loop {
// SAFETY: fd 0, a live writable slice, read cannot exceed the passed length.
let count = unsafe { rt::os::syscall3(rt::os::SYS_READ, 0, bytes.as_mut_ptr() as usize, bytes.len()) };
if count == -4 { continue; }
if count == -11 {
// EAGAIN: stdin was inherited non-blocking -- wait for data instead of failing
let mut pfd = [0i32, 1]; // struct pollfd: fd 0, events POLLIN, revents 0
// SAFETY: one pollfd record, no timeout.
unsafe { rt::os::poll(pfd.as_mut_ptr() as usize, 1, -1) };
continue;
}
return if count < 0 { Err((-count) as u32) } else { Ok(count as usize) };
}
}