Better password input

This commit is contained in:
Ticki 2016-03-08 08:51:34 +01:00
parent a19d2e245d
commit 10f6654005
3 changed files with 16 additions and 19 deletions

View File

@ -6,14 +6,15 @@ use std::io::{Write, stdout, stdin};
fn main() { fn main() {
let stdout = stdout(); let stdout = stdout();
let mut stdout = stdout.lock(); let mut stdout = stdout.lock();
let mut stdin = stdin(); let stdin = stdin();
let mut stdin = stdin.lock();
stdout.write(b"password: ").unwrap(); stdout.write(b"password: ").unwrap();
stdout.flush().unwrap(); stdout.flush().unwrap();
let pass = stdin.read_passwd(&mut stdout); let pass = stdin.read_passwd(&mut stdout);
if let Some(pass) = pass { if let Ok(Some(pass)) = pass {
stdout.write(pass.as_bytes()).unwrap(); stdout.write(pass.as_bytes()).unwrap();
stdout.write(b"\n").unwrap(); stdout.write(b"\n").unwrap();
} else { } else {

View File

@ -12,6 +12,8 @@ pub enum TerminalError {
TermSizeError, TermSizeError,
/// Failed to write to stdout. /// Failed to write to stdout.
StdoutError, StdoutError,
/// Failed to read from stdin.
StdinError,
} }
impl TerminalError { impl TerminalError {
@ -21,6 +23,7 @@ impl TerminalError {
TerminalError::SetAttrError => "Failed to set Terminal attribute.", TerminalError::SetAttrError => "Failed to set Terminal attribute.",
TerminalError::TermSizeError => "Failed to get terminal size.", TerminalError::TermSizeError => "Failed to get terminal size.",
TerminalError::StdoutError => "Failed to write to stdout.", TerminalError::StdoutError => "Failed to write to stdout.",
TerminalError::StdinError => "Failed to read from stdin.",
} }
} }
} }

View File

@ -1,33 +1,26 @@
use std::io::{Read, Write}; use std::io::{Read, Write};
use IntoRawMode; use {IntoRawMode, TerminalError};
/// Extension to `Read` trait. /// Extension to `Read` trait.
pub trait ReadExt { pub trait ReadExt {
/// Read a password. /// Read a password.
fn read_passwd<W: Write>(&mut self, writer: &mut W) -> Option<String>; fn read_passwd<W: Write>(&mut self, writer: &mut W) -> Result<Option<String>, TerminalError>;
} }
impl<R: Read> ReadExt for R { impl<R: Read> ReadExt for R {
fn read_passwd<W: Write>(&mut self, writer: &mut W) -> Option<String> { fn read_passwd<W: Write>(&mut self, writer: &mut W) -> Result<Option<String>, TerminalError> {
let _raw = if let Ok(x) = writer.into_raw_mode() { let _raw = try!(writer.into_raw_mode());
x
} else {
return None;
};
let mut string = String::with_capacity(30); let mut string = String::with_capacity(30);
for c in self.chars() { for c in self.chars() {
match if let Ok(c) = c { match c {
c Err(_) => return Err(TerminalError::StdinError),
} else { Ok('\0') | Ok('\x03') | Ok('\x04') => return Ok(None),
return None; Ok('\n') | Ok('\r') => return Ok(Some(string)),
} { Ok(c) => string.push(c),
'\x00' | '\x03' | '\x04' => return None,
'\r' => return Some(string),
b => string.push(b),
} }
} }
Some(string) Ok(Some(string))
} }
} }