From 9d5bd561419e1145aea81ee820bc3e8405c4fd57 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Tue, 13 Oct 2020 21:46:42 +0200 Subject: rust: Server and account command-line arguments --- rust/src/getpass.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 rust/src/getpass.rs (limited to 'rust/src/getpass.rs') diff --git a/rust/src/getpass.rs b/rust/src/getpass.rs new file mode 100644 index 0000000..f40da0e --- /dev/null +++ b/rust/src/getpass.rs @@ -0,0 +1,65 @@ +extern crate libc; + +use std::io::{self, Write}; +use std::mem; +use std::str; + +fn error_checker(ret: i32) -> io::Result<()> { + if ret == 0 { + Ok(()) + } else { + Err(io::Error::last_os_error()) + } +} + +fn tcgetattr(fd: i32) -> io::Result { + unsafe { + let mut tios: libc::termios = mem::zeroed(); + error_checker(libc::tcgetattr(fd, &mut tios))?; + Ok(tios) + } +} + +fn tcsetattr(fd: i32, other_options: i32, tios: &libc::termios) -> io::Result<()> { + unsafe { + error_checker(libc::tcsetattr(fd, other_options, tios))?; + Ok(()) + } +} + +fn without_echo io::Result>(f: F) -> io::Result { + let tios_old = tcgetattr(0)?; + + let mut tios_new = tios_old; + tios_new.c_lflag &= !libc::ECHO; + tios_new.c_lflag |= libc::ECHONL; + + match tcsetattr(0, libc::TCSANOW, &tios_new) { + Ok(()) => {}, + Err(e) => { + // Just blindly try to reset the terminal, in case something changed + let _ = tcsetattr(0, libc::TCSANOW, &tios_old); + return Err(e); + } + } + + let ret = f()?; + + tcsetattr(0, libc::TCSANOW, &tios_old)?; + + Ok(ret) +} + +pub fn get_pass(prompt: &str) -> io::Result { + print!("{}", prompt); + io::stdout().flush()?; + + without_echo(|| { + let mut line = String::new(); + io::stdin().read_line(&mut line)?; + if line.ends_with('\n') { + line.pop(); + } + Ok(line) + }) +} -- cgit v1.2.3-70-g09d2