108 lines
2.8 KiB
Rust
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
|
|
}
|
|
}
|