I don't know if this is possible, but here's a scenerio..
# Call `mysql` from inside a running container named "db"
cargo run my-command "docker exec -it db mysql -u user -p my-database"
This will result in the mysql command pausing execution at a password prompt. However, upon typing the password and pressing enter, the Rust program should inject some other arguments (not shown) into the quoted command and the final output will be a bunch of text.
let args = [
"docker", "exec", "-it", "db", "mysql", "-u", "user", "-p"
];
// `sudo` only used for testing. It's needed for docker,
// but `sudo cargo run ...` doesn't work
let cmd = process::Command::new("sudo")
.args(&args)
.spawn() // stdout will be inherited
.expect("external cmd failed.")
.wait_with_output()?;
But, the output will be processed in my-command and shouldn't be displayed to the user.
Is there a way to pause the child command on the first input, and switch the stdout to be piped?
I tried to check for input before waiting on the child to finish
// ... snip
let mut cmd = process::Command::new("sudo")
.args(&args)
.spawn()
.expect("external cmd failed.");
let mut s = String::new();
// Trying to inspect the stdout for the if check below,
// but this will panic
let mut out = cmd.stdout.take().unwrap();
out.read_to_string(&mut s);
if s.contains("password") {
// From now on, don't display child's stdout
}
let output = cmd.wait_with_output()?;
let result = String::from_utf8_lossy(&output.stdout);
// do something with the result
But that just seems to pause all execution until pressing enter.
Update
Perhaps the child's stdin can remain inherited, but the child's stdout can be initialized with .stdout(process::stdio::piped()) and the parent can catch the output somehow and display it conditionally?