use std::io; use std::io::{Read,Write,Error}; use std::process::{Stdio,Command,ExitStatus}; use std::env; use which::which; use crate::config::Config; fn cmd_output_status(cmd: &mut Command) -> Result<(Vec,ExitStatus), Error> { let mut proc = cmd.stdout(Stdio::piped()).spawn().ok().expect("Execution failure"); let outstream = proc.stdout.as_mut() .expect("Pipe failue"); // Drain it into a &mut [u8]. let mut output = Vec::new(); outstream.read_to_end(&mut output) .expect("Pipe failue"); match proc.wait() { Ok(v) => Ok((output, v)), Err(e) => Err(e), } } fn hidden_cli(message: &str) -> Option { Command::new("stty").args(["-echo"]).status().expect("Execution failure"); eprint!("{}: ", message); io::stdout().flush().unwrap(); let mut val = String::new(); io::stdin().read_line(&mut val) .expect("Error reading input"); eprintln!(""); if &val[val.len()-1..] == "\n" { val.pop(); } Command::new("stty").args(["echo"]).status().expect("Execution failure"); Some(val) } fn is_graphical(config: &Config) -> bool { match env::var("DISPLAY") { Ok(v) => { v.len() > 0 && ! ( config.prioritize_cli && unsafe {libc::isatty(0)} != 0 ) }, _ => false, } } pub fn hidden(config: &Config, message: &str) -> Option { if is_graphical(config) { let mut cmd = ""; let mut args = Vec::new(); if which("kdialog").is_ok() { cmd = "kdialog"; args = Vec::from(["--title", "zpass", "--password", message]); } else if which("zenity").is_ok() { cmd = "zenity"; args = Vec::from(["--title", "zpass", "--password"]); } if cmd.len() > 0 { let r = cmd_output_status( Command::new(cmd).args(&args[..]) ); match r { Ok(v) => if v.1.success() { let mut val = unsafe { String::from_utf8_unchecked(v.0) }; if &val[val.len()-1..] == "\n" { val.pop(); } Some( val ) } else { None } _ => None, } } else { hidden_cli(message) } } else { hidden_cli(message) } } pub fn hidden_confirm(config: &Config, message1: &str, message2: &str, errmsg: &str) -> Option { let p1 = hidden(config, message1); if p1.is_none() { return None; } let p2 = hidden(config, message2); if p2.is_none() { return None; } if p1.as_ref().unwrap() != p2.as_ref().unwrap() { eprintln!("{}", errmsg); None } else { p1 } }