diff options
Diffstat (limited to 'src/password.rs')
-rw-r--r-- | src/password.rs | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/src/password.rs b/src/password.rs index 49d98c1..1cd0158 100644 --- a/src/password.rs +++ b/src/password.rs @@ -4,6 +4,7 @@ use std::process::{Command, Stdio}; use anyhow::{Context, Result}; use log::info; +use crate::log::write_log_line; use crate::utils::current_username; /// Different kind of password @@ -84,38 +85,54 @@ impl PasswordHolder { } } -/// run a sudo command requiring a password (generally to establish the password.) -/// Since I can't send 2 passwords at a time, it will only work with the sudo password -/// It requires a path to establish CWD. -pub fn execute_sudo_command_with_password<S, P>( - args: &[S], - password: &str, - path: P, -) -> Result<(bool, String, String)> +/// Spawn a sudo command with stdin, stdout and stderr piped. +/// sudo is run with -S argument to read the passworo from stdin +/// Args are sent. +/// CWD is set to `path`. +/// No password is set yet. +/// A password should be sent with `inject_password`. +fn new_sudo_command_awaiting_password<S, P>(args: &[S], path: P) -> Result<std::process::Child> where S: AsRef<std::ffi::OsStr> + std::fmt::Debug, P: AsRef<std::path::Path> + std::fmt::Debug, { - info!("sudo_with_password {args:?} CWD {path:?}"); - info!( - target: "special", - "running sudo command with passwod. args: {args:?}, CWD: {path:?}" - ); - let mut child = Command::new("sudo") + Ok(Command::new("sudo") .arg("-S") .args(args) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .current_dir(path) - .spawn()?; + .spawn()?) +} +/// Send password to a sudo command through its stdin. +fn inject_password(password: &str, child: &mut std::process::Child) -> Result<()> { let child_stdin = child .stdin .as_mut() .context("run_privileged_command: couldn't open child stdin")?; child_stdin.write_all(format!("{password}\n").as_bytes())?; + Ok(()) +} +/// run a sudo command requiring a password (generally to establish the password.) +/// Since I can't send 2 passwords at a time, it will only work with the sudo password +/// It requires a path to establish CWD. +pub fn execute_sudo_command_with_password<S, P>( + args: &[S], + password: &str, + path: P, +) -> Result<(bool, String, String)> +where + S: AsRef<std::ffi::OsStr> + std::fmt::Debug, + P: AsRef<std::path::Path> + std::fmt::Debug, +{ + info!("sudo_with_password {args:?} CWD {path:?}"); + let log_line = format!("running sudo command with password. args: {args:?}, CWD: {path:?}"); + write_log_line(log_line); + let mut child = new_sudo_command_awaiting_password(args, path)?; + inject_password(password, &mut child)?; let output = child.wait_with_output()?; Ok(( output.status.success(), @@ -124,20 +141,30 @@ where )) } -/// Runs a passwordless sudo command. -/// Returns stdout & stderr -pub fn execute_sudo_command<S>(args: &[S]) -> Result<(bool, String, String)> +/// Spawn a sudo command which shouldn't require a password. +/// The command is executed immediatly and we return an handle to it. +fn new_sudo_command_passwordless<S>(args: &[S]) -> Result<std::process::Child> where S: AsRef<std::ffi::OsStr> + std::fmt::Debug, { - info!("running sudo {:?}", args); - info!(target: "special", "running sudo command. {args:?}"); - let child = Command::new("sudo") + Ok(Command::new("sudo") .args(args) .stdin(Stdio::null()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) - .spawn()?; + .spawn()?) +} + +/// Runs a passwordless sudo command. +/// Returns stdout & stderr +pub fn execute_sudo_command<S>(args: &[S]) -> Result<(bool, String, String)> +where + S: AsRef<std::ffi::OsStr> + std::fmt::Debug, +{ + info!("running sudo {:?}", args); + let log_line = format!("running sudo command. {args:?}"); + write_log_line(log_line); + let child = new_sudo_command_passwordless(args)?; let output = child.wait_with_output()?; Ok(( output.status.success(), |