From fed265252d5fb8e1bfc7d8304135bb2cd0340eb6 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Sat, 31 Jan 2026 04:17:11 +0700 Subject: [PATCH] Unify password prompt code --- src/bin/installer_tui.rs | 24 +++--------- src/installer.rs | 81 +++++++++++++--------------------------- 2 files changed, 32 insertions(+), 73 deletions(-) diff --git a/src/bin/installer_tui.rs b/src/bin/installer_tui.rs index e9a2774f8e..eb00f997a1 100644 --- a/src/bin/installer_tui.rs +++ b/src/bin/installer_tui.rs @@ -255,29 +255,17 @@ fn choose_disk() -> PathBuf { } } -fn choose_password() -> Option { - eprint!("installer_tui: redoxfs password (empty for none): "); - - let password = io::stdin() - .read_passwd(&mut io::stderr()) - .unwrap() - .unwrap_or(String::new()); - - eprintln!(); - - if password.is_empty() { - return None; - } - - Some(password) -} - fn main() { let root_path = Path::new("/"); let disk_path = choose_disk(); - let password_opt = choose_password(); + let Ok(password_opt) = redox_installer::prompt_password( + "redox_installer_tui: redoxfs password (empty for none)", + "redox_installer_tui: confirm password", + ) else { + process::exit(1); + }; let instant = std::time::Instant::now(); diff --git a/src/installer.rs b/src/installer.rs index 1b78403f8b..58d876b8c5 100644 --- a/src/installer.rs +++ b/src/installer.rs @@ -56,23 +56,31 @@ fn syscall_error(err: syscall::Error) -> io::Error { } /// Returns a password collected from the user (plaintext) -fn prompt_password(prompt: &str, confirm_prompt: &str) -> Result { +pub fn prompt_password(prompt: &str, confirm_prompt: &str) -> Result> { let stdin = io::stdin(); let mut stdin = stdin.lock(); let stdout = io::stdout(); let mut stdout = stdout.lock(); - print!("{}", prompt); - let password = stdin.read_passwd(&mut stdout)?; + for i in 0..3 { + print!("{}", prompt); + let mut password = stdin.read_passwd(&mut stdout)?; + if let Some(password) = password.as_mut() { + *password = password.trim().to_string(); + } + password.take_if(|s| s.is_empty()); - print!("\n{}", confirm_prompt); - let confirm_password = stdin.read_passwd(&mut stdout)?; + print!("\n{}", confirm_prompt); + let confirm_password = stdin.read_passwd(&mut stdout)?; - // Note: Actually comparing two Option values - if confirm_password != password { - bail!("passwords do not match"); + // Note: Actually comparing two Option values + if confirm_password == password { + return Ok(password); + } else if i < 2 { + eprintln!("passwords do not match, please try again"); + } } - Ok(password.unwrap_or("".to_string())) + bail!("passwords do not match, giving up"); } fn install_local_pkgar(cookbook: &str, target: &str, packagename: &str, dest: &Path) -> Result<()> { @@ -149,29 +157,6 @@ pub fn install_dir( output_dir: impl AsRef, cookbook: Option<&str>, ) -> Result<()> { - //let mut context = liner::Context::new(); - - macro_rules! prompt { - ($dst:expr, $def:expr, $($arg:tt)*) => { - if config.general.prompt.unwrap_or(true) { - Err(io::Error::new( - io::ErrorKind::Other, - "prompt not currently supported", - )) - // match unwrap_or_prompt($dst, &mut context, &format!($($arg)*)) { - // Ok(res) => if res.is_empty() { - // Ok($def) - // } else { - // Ok(res) - // }, - // Err(err) => Err(err) - // } - } else { - Ok($dst.unwrap_or($def)) - } - }; - } - let output_dir = output_dir.as_ref(); let output_dir = output_dir.to_owned(); @@ -222,29 +207,16 @@ pub fn install_dir( next_gid = gid + 1; } - let name = prompt!( - user.name, - username.clone(), - "{}: name (GECOS) [{}]: ", - username, - username - )?; - let home = prompt!( - user.home, - format!("/home/{}", username), - "{}: home [/home/{}]: ", - username, - username - )?; - let shell = prompt!( - user.shell, - "/bin/ion".to_string(), - "{}: shell [/bin/ion]: ", - username - )?; + let name = user.name.unwrap_or(username.clone()); + let home = user.home.unwrap_or(format!("/home/{}", username)); + let shell = user.shell.unwrap_or("/bin/ion".into()); println!("Adding user {username}:"); - println!("\tPassword: {password}"); + if password.is_empty() { + println!("\tPassword: unset"); + } else { + println!("\tPassword: set"); + } println!("\tUID: {uid}"); println!("\tGID: {gid}"); println!("\tName: {name}"); @@ -852,8 +824,7 @@ fn install_inner(config: Config, output: &Path) -> Result<()> { } /// Install RedoxFS into a new disk file, or a sysroot directory. -/// This function assumes all interactive prompts resolved by the caller, -/// so "prompt" option is ignored from this function onward. +/// This function assumes all interactive prompts resolved by the caller. pub fn install(config: Config, output: impl AsRef) -> Result<()> { install_inner(config, output.as_ref()) }