Function get_input

Source
pub fn get_input(
    prompt: &str,
    default_value: Option<&str>,
    echo: bool,
    verify: bool,
) -> Option<String>
Expand description

A utility function that will prompt the user for input via the console/tty.

prompt is the text to show to the user. default_value can be used to pre-set the answer, allowing the user to simply press enter.

echo, if true, means to show the user’s answer on the screen as they type it. If false, means to conceal it.

verify, if true, will ask the user for their input twice in order to confirm that they provided the same text both times. This is useful when creating a password and echo == false.

Examples found in repository?
examples/whoami.rs (line 38)
37fn prompt(prompt: &str, echo: bool) -> SshResult<String> {
38    get_input(prompt, None, echo, false).ok_or_else(|| Error::Fatal("reading password".to_string()))
39}
40
41fn prompt_stdin(prompt: &str) -> SshResult<String> {
42    eprintln!("{}", prompt);
43    let mut input = String::new();
44    let _ = std::io::stdin().read_line(&mut input)?;
45    Ok(input.trim().to_string())
46}
47
48fn authenticate(sess: &Session, user_name: Option<&str>) -> SshResult<()> {
49    match sess.userauth_none(user_name)? {
50        AuthStatus::Success => return Ok(()),
51        _ => {}
52    }
53
54    loop {
55        let auth_methods = sess.userauth_list(user_name)?;
56
57        if auth_methods.contains(AuthMethods::PUBLIC_KEY) {
58            match sess.userauth_public_key_auto(None, None)? {
59                AuthStatus::Success => return Ok(()),
60                _ => {}
61            }
62        }
63
64        if auth_methods.contains(AuthMethods::INTERACTIVE) {
65            loop {
66                match sess.userauth_keyboard_interactive(None, None)? {
67                    AuthStatus::Success => return Ok(()),
68                    AuthStatus::Info => {
69                        let info = sess.userauth_keyboard_interactive_info()?;
70                        if !info.instruction.is_empty() {
71                            eprintln!("{}", info.instruction);
72                        }
73                        let mut answers = vec![];
74                        for p in &info.prompts {
75                            answers.push(prompt(&p.prompt, p.echo)?);
76                        }
77                        sess.userauth_keyboard_interactive_set_answers(&answers)?;
78
79                        continue;
80                    }
81                    AuthStatus::Denied => {
82                        break;
83                    }
84                    status => {
85                        return Err(Error::Fatal(format!(
86                            "interactive auth status: {:?}",
87                            status
88                        )))
89                    }
90                }
91            }
92        }
93
94        if auth_methods.contains(AuthMethods::PASSWORD) {
95            let pw = prompt("Password: ", false)?;
96
97            match sess.userauth_password(user_name, Some(&pw))? {
98                AuthStatus::Success => return Ok(()),
99                status => return Err(Error::Fatal(format!("password auth status: {:?}", status))),
100            }
101        }
102
103        return Err(Error::Fatal("unhandled auth case".to_string()));
104    }
105}
106
107fn main() -> SshResult<()> {
108    let sess = Session::new()?;
109    sess.set_auth_callback(|prompt, echo, verify, identity| {
110        let prompt = match identity {
111            Some(ident) => format!("{} ({}): ", prompt, ident),
112            None => prompt.to_string(),
113        };
114        get_input(&prompt, None, echo, verify)
115            .ok_or_else(|| Error::Fatal("reading password".to_string()))
116    });
117
118    sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119    // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120    sess.options_parse_config(None)?;
121    sess.connect()?;
122    eprintln!(
123        "using {} as user name for authentication",
124        sess.get_user_name()?
125    );
126    verify_known_hosts(&sess)?;
127
128    authenticate(&sess, None)?;
129
130    let channel = sess.new_channel()?;
131    channel.open_session()?;
132    channel.request_exec("whoami")?;
133    channel.send_eof()?;
134
135    let mut stdout = String::new();
136    channel.stdout().read_to_string(&mut stdout)?;
137
138    eprintln!("whoami -> {}", stdout);
139
140    let res = channel.get_exit_status();
141    eprintln!("exit status: {:?}", res);
142
143    Ok(())
144}