zrpass/src/prompt.rs
mateoferon 9b560174c1 init
2023-02-16 17:16:28 +01:00

108 lines
2.8 KiB
Rust

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<u8>,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<String> {
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<String> {
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<String> {
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
}
}