1use std::io::{Result, Write};
6use std::process::{Command, Stdio};
7
8pub fn exec(cmd: &str, output: bool, input: &[u8]) -> Result<String> {
9 debug!("exec `{}`", cmd);
10 let has_input = !input.is_empty();
11 let mut basic_cmd = Command::new("sh");
12 let mut cmd_object = basic_cmd.arg("-c").arg(cmd).env("RUST_BACKTRACE", "1");
13
14 if has_input {
15 cmd_object = cmd_object.stdin(Stdio::piped());
16 } else {
17 cmd_object = cmd_object.stdin(Stdio::null());
18 }
19
20 if output {
21 cmd_object = cmd_object.stdout(Stdio::piped()).stderr(Stdio::piped());
22 } else {
23 cmd_object = cmd_object.stdout(Stdio::inherit()).stderr(Stdio::inherit())
24 }
25 let mut child = cmd_object.spawn()?;
26
27 if has_input {
28 let mut input_stream = child.stdin.take().unwrap();
29 input_stream.write_all(input)?;
30 drop(input_stream);
31 }
32
33 if output {
34 let output = child.wait_with_output()?;
35 if !output.status.success() {
36 return Err(eother!("exit with non-zero status"));
37 }
38 let stdout = std::str::from_utf8(&output.stdout).map_err(|e| einval!(e))?;
39 return Ok(stdout.to_string());
40 }
41
42 let status = child.wait()?;
43 if !status.success() {
44 return Err(eother!("exit with non-zero status"));
45 }
46
47 Ok(String::from(""))
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn test_exec() {
56 let val = exec("echo hello", true, b"").unwrap();
57 assert_eq!(val, "hello\n");
58
59 let val = exec("echo hello", false, b"").unwrap();
60 assert_eq!(val, "");
61
62 let val = exec("cat -", true, b"test").unwrap();
63 assert_eq!(val, "test");
64
65 let val = exec("cat -", false, b"test").unwrap();
66 assert_eq!(val, "");
67 }
68}