1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
extern crate libc;
extern crate rand;
extern crate seckey;
extern crate termion;
extern crate sha3;
pub mod readtty;
pub mod colorhash;
use std::io::{ self, Read, Write };
use std::iter::repeat;
use rand::random;
use seckey::{ SecKey, TempKey };
use termion::clear;
use termion::get_tty;
use termion::event::Key;
use termion::color::{ Fg, Reset, AnsiValue };
use colorhash::{ hash_as_ansi, hash_chars_as_ansi };
use readtty::{ RawTTY, read_from_tty };
#[inline]
pub fn askpass<F, T>(prompt: &str, f: F)
-> io::Result<T>
where F: FnOnce(&str) -> io::Result<T>
{
raw_askpass(&mut RawTTY::new()?, &mut get_tty()?, prompt, '*')
.and_then(|(buf, pos)| {
let mut buf = buf.read().iter().take(pos).collect::<String>();
let buf = TempKey::from(&mut buf as &mut str);
f(&buf)
})
}
pub fn raw_askpass(input: &mut Read, output: &mut Write, prompt: &str, star: char)
-> io::Result<(SecKey<[char; 256]>, usize)>
{
let mut pos = 0;
let mut buf = SecKey::new([char::default(); 256])
.map_err(|_| io::Error::new(io::ErrorKind::Other, "SecKey malloc fail"))?;
read_from_tty(input, |key| {
let mut buf = buf.write();
match key {
Key::Char('\n') => return Ok(true),
Key::Char(c) => if pos < buf.len() {
buf[pos] = c;
pos += 1;
},
Key::Backspace | Key::Delete if pos >= 1 => pos -= 1,
Key::Ctrl('c') => return Err(io::Error::new(io::ErrorKind::Interrupted, "Ctrl-c")),
Key::Null => (),
_ => return Ok(false)
}
let colors = match pos {
0 => [AnsiValue(30); 8],
1...7 => hash_as_ansi(&[random(), random(), random(), random()]),
p => hash_chars_as_ansi(&buf[..p])
};
write!(
output,
"\r{} {}{}",
prompt,
repeat(star)
.take(4)
.zip(&colors[..4])
.map(|(star, &color)| format!("{}{}{}", Fg(color), star, star))
.collect::<String>(),
Fg(Reset)
)?;
Ok(false)
})?;
write!(output, "{}\r", clear::CurrentLine)?;
Ok((buf, pos))
}