1use std::ffi::OsString;
4use std::process::{Child, Command, Stdio};
5
6pub fn spawn_one(cmd: &str) -> std::io::Result<Child> {
13 let mut command = build_command(cmd);
14 command.stdin(Stdio::piped());
15 command.stdout(Stdio::inherit());
16 command.stderr(Stdio::inherit());
17 command.spawn()
18}
19
20pub fn spawn_one_piped_stdout(cmd: &str) -> std::io::Result<Child> {
22 let mut command = build_command(cmd);
23 command.stdin(Stdio::piped());
24 command.stdout(Stdio::piped());
25 command.stderr(Stdio::inherit());
26 command.spawn()
27}
28
29#[cfg(unix)]
30fn build_command(cmd: &str) -> Command {
31 let mut c = Command::new("/bin/sh");
32 c.arg("-c");
33 c.arg(OsString::from(cmd));
34 c
35}
36
37#[cfg(windows)]
38fn build_command(cmd: &str) -> Command {
39 let mut c = Command::new("cmd");
40 c.arg("/C");
41 c.arg(OsString::from(cmd));
42 c
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use std::io::Write;
49
50 #[test]
51 fn spawn_one_echo_then_close() {
52 #[cfg(unix)]
54 let cmd = "true";
55 #[cfg(windows)]
56 let cmd = "exit /b 0";
57 let mut child = spawn_one(cmd).expect("spawn should succeed");
58 drop(child.stdin.take());
60 let status = child.wait().expect("wait should succeed");
61 assert!(status.success(), "expected success exit");
62 }
63
64 #[test]
65 fn spawn_one_with_piped_stdin_accepts_writes() {
66 #[cfg(unix)]
68 let cmd = "cat > /dev/null";
69 #[cfg(windows)]
70 let cmd = "more > NUL";
71 let mut child = spawn_one(cmd).expect("spawn should succeed");
72 if let Some(mut stdin) = child.stdin.take() {
73 let _ = stdin.write_all(b"some bytes\n");
74 }
75 let status = child.wait().expect("wait should succeed");
76 let _ = status;
78 }
79}