diff --git a/changelog/new.txt b/changelog/new.txt index 17df6fe05..30ea692c1 100644 --- a/changelog/new.txt +++ b/changelog/new.txt @@ -10,3 +10,4 @@ New features: - restore: The restore algorithm has been improved and should now be faster for remote repositories. - restore: Files are now allocated just before being first processed. This allows easier resumed restores. - New option: `no-require-git` for backup - if enabled, a git repository is not required to apply `git-ignore` rule. +- fix: wait for password-command to successfully exit, allowing to input something into the command, and read password from stdout. diff --git a/crates/rustic_core/src/repository.rs b/crates/rustic_core/src/repository.rs index 973b18fbf..aab3e2af2 100644 --- a/crates/rustic_core/src/repository.rs +++ b/crates/rustic_core/src/repository.rs @@ -3,12 +3,12 @@ use std::{ fs::File, io::{BufRead, BufReader}, path::PathBuf, - process::Command, + process::{Command, Stdio}, }; use bytes::Bytes; use derive_more::Add; -use log::{debug, info}; +use log::{debug, error, info}; use nom::{ branch::alt, @@ -106,7 +106,7 @@ pub struct RepositoryOptions { )] pub password_file: Option, - /// Command to read the password from + /// Command to read the password from. Password is read from stdout #[cfg_attr(feature = "clap", clap( long, global = true, @@ -267,10 +267,22 @@ impl

Repository

{ .map_err(RepositoryErrorKind::FromNomError)? .1; debug!("commands: {commands:?}"); - let Ok(output) = Command::new(commands[0]).args(&commands[1..]).output() else { - return Err( - RepositoryErrorKind::PasswordCommandParsingFailed.into()); + let command = Command::new(commands[0]) + .args(&commands[1..]) + .stdout(Stdio::piped()) + .spawn()?; + let Ok(output) = command.wait_with_output() else { + return Err(RepositoryErrorKind::PasswordCommandParsingFailed.into()); + }; + if !output.status.success() { + #[allow(clippy::option_if_let_else)] + let s = match output.status.code() { + Some(c) => format!("exited with status code {c}"), + None => "was terminated".into(), }; + error!("password-command {s}"); + return Err(RepositoryErrorKind::ReadingPasswordFromCommandFailed.into()); + } let mut pwd = BufReader::new(&*output.stdout); Ok(Some(match read_password_from_reader(&mut pwd) {