I want to invoke some commands, which require the caller to input a password, such as sudo or git pull, these commands will prompt users to input the username and password. I tried to use Rust's Command to implement the functionality, which can automatically input this information, however, the code doesn't work.
use std::{process::{Command,Stdio}, io::Write};
fn main(){
let mut child =Command::new("sh").stdin(Stdio::piped()).arg("-c").arg("sudo -i").spawn().unwrap();
child.stdin.as_mut().unwrap().write(b"123456").unwrap();
let w = child.wait_with_output().unwrap();
println!("{w:?}");
}
Running this code will observe the terminal line will prompt the user to type a password, and the code child.stdin.as_mut().unwrap().write(b"123456").unwrap(); that would automatically input the password to respond the asking does not work.
The sudo command goes to great lengths to make sure the password prompt goes to the original terminal (and therefore, the user) rather than some intermediate program.
I've found the best strategy is to not invoke sudo from your program, directly. Instead, write your program assuming you have super user access and rely on the user running it with sudo.
That said, running things this way does increase your attack surface, so there's always a security/convenience tradeoff.
I just show you a similar scene that requires us to input a password in the terminal line. The general requirement is when we invoke the third-part program by Command and that program requires us to input a password in the terminal line, in this case, I want to make the calling program automatically answer the asking input.