1pub use crate::repl::ReplWrapper;
2pub use expectrl::{spawn, Session};
3use futures_lite::{AsyncRead, AsyncWrite};
4use tracing::trace;
5
6pub mod repl;
7pub mod runner;
8
9#[derive(Debug, thiserror::Error)]
10pub enum Error {
11 #[error("{0}")]
12 ExpectrlError(#[from] expectrl::Error),
13 #[error("{0}")]
14 IoError(#[from] std::io::Error),
15}
16
17pub async fn linux_oneshot<
19 P,
20 S: AsyncRead + AsyncWrite + Unpin,
21 SS: AsRef<str> + Clone + std::fmt::Debug,
22>(
23 session: expectrl::Session<P, S>,
24 username: &str,
25 password: &str,
26 prompt: Option<String>,
27 cmd: SS,
28) -> core::result::Result<(Vec<u8>, ReplWrapper<P, S>), Error> {
29 let quit = "exit";
30 let prompt = match prompt {
31 Some(prompt) => prompt,
32 None => r".*]# |.*@.*:.*# ".to_string(),
33 };
34 let prompt = regex::Regex::new(&prompt).unwrap();
35
36 let session = runner::LinuxLoginRunner::builder()
37 .build()
38 .login(session, username, password, Some(&prompt))
39 .await?;
40 trace!("successfully logged in");
41 let mut session = ReplWrapper::new(session, prompt);
42 trace!("expect prompt...");
43 session.expect_prompt().await?;
44 trace!("run_command: {:?}", cmd);
45 let recv = session.run_command(cmd).await;
46
47 trace!("send quit command: {}", quit);
48 session.send_line(quit).await?;
49
50 Ok(recv.map(|recv| (recv, session))?)
51}