oysh/crates/oyster_runtime/tests/it/main.rs

60 lines
1.5 KiB
Rust
Raw Normal View History

mod builtins;
2022-09-15 20:16:37 +00:00
mod pipeline;
use std::{
ffi::OsString,
fs::File,
io::{BufRead, BufReader, Write},
os::unix::{ffi::OsStringExt, io::FromRawFd},
process,
};
use nix::{
ioctl_write_int_bad, libc,
pty::{self, OpenptyResult},
sys,
unistd::{self, ForkResult},
};
ioctl_write_int_bad!(tiocsctty, libc::TIOCSCTTY);
/// Forks to redirect stdin, stderr, stdout, then run the commands.
/// Relies on inserting a NUL byte in the end, so there shouldn't be NUL in the output.
fn collect_output<F>(mut f: F) -> OsString
where
F: FnMut(),
{
let OpenptyResult { master, slave } = pty::openpty(None, None).unwrap();
match unsafe { unistd::fork() }.unwrap() {
ForkResult::Parent { child } => {
sys::wait::waitpid(child, None).unwrap();
}
ForkResult::Child => {
unistd::setsid().unwrap();
unsafe { tiocsctty(slave, 0) }.unwrap();
unistd::dup2(slave, libc::STDIN_FILENO).unwrap();
unistd::dup2(slave, libc::STDOUT_FILENO).unwrap();
unistd::dup2(slave, libc::STDERR_FILENO).unwrap();
let _ = unistd::close(master);
let _ = unistd::close(slave);
f();
process::exit(0);
}
}
let master = unsafe { File::from_raw_fd(master) };
let mut slave = unsafe { File::from_raw_fd(slave) };
slave.write_all(&[0]).unwrap();
let mut r = BufReader::new(master);
let mut buf = vec![];
r.read_until(0, &mut buf).unwrap();
OsString::from_vec(buf[..buf.len() - 1].to_vec())
}