use std::process::{Child, Command, Output, Stdio};
pub type CmdResult = Result<(), std::io::Error>;
pub fn run_no_redirect(cmd: &str, args: &[String]) -> CmdResult {
Command::new(cmd)
.args(args)
.stdout(Stdio::inherit())
.stdin(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()?
.wait_with_output()?;
Ok(())
}
pub fn run_cmd_line(line: &str) -> Result<Output, std::io::Error> {
let mut cmds: Vec<_> = line.split('|').collect();
let first_cmd = cmds.remove(0);
let mut args: Vec<_> = first_cmd.split(' ').filter(|s| !s.is_empty()).collect();
let cmd = args.remove(0);
if cmds.len() == 0 {
match _run_cmd(cmd, args, None, None) {
Ok(child) => {
return Ok(child.wait_with_output().unwrap());
}
Err(err) => return Err(err),
}
}
let mut child = _run_cmd(cmd, args, Some(Stdio::piped()), Some(Stdio::piped()))?;
for cmd_idx in 0..cmds.len() {
let line = cmds[cmd_idx];
let mut args: Vec<_> = line.split(' ').filter(|s| !s.is_empty()).collect();
let cmd = args.remove(0);
let previous_stdout = child.stdout.unwrap();
let new_child = _run_cmd(
cmd,
args,
Some(previous_stdout.into()),
Some(Stdio::piped()),
)?;
child = new_child;
}
let output = child.wait_with_output().unwrap();
Ok(output)
}
fn _run_cmd(
cmd: &str,
args: Vec<&str>,
stdin_redirect: Option<Stdio>,
stdout_redirect: Option<Stdio>,
) -> Result<Child, std::io::Error> {
let stdout: Stdio = match stdout_redirect {
Some(s) => s,
None => Stdio::inherit(),
};
let stdin: Stdio = match stdin_redirect {
Some(s) => s,
None => Stdio::inherit(),
};
let child = Command::new(cmd)
.args(args)
.stdout(stdout)
.stdin(stdin)
.spawn()?;
Ok(child)
}