summaryrefslogtreecommitdiffstats
path: root/src/password.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/password.rs')
-rw-r--r--src/password.rs71
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(),