103 lines
2.6 KiB
Rust
103 lines
2.6 KiB
Rust
use std::{
|
|
io::{self, Read, Write},
|
|
os::fd::AsRawFd,
|
|
path::PathBuf,
|
|
sync::Arc,
|
|
};
|
|
|
|
use sparse_05_common::messages::Capabilities;
|
|
use tokio::net::UdpSocket;
|
|
|
|
use super::{commands, Connection};
|
|
|
|
macro_rules! libc_try {
|
|
($expr:expr) => {
|
|
if unsafe { $expr } == -1 {
|
|
return Err(std::io::Error::last_os_error())?;
|
|
}
|
|
};
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
fn get_term_attrs<F: AsRawFd>(fd: &F) -> anyhow::Result<libc::termios> {
|
|
let mut termios = unsafe { std::mem::zeroed() };
|
|
libc_try!(libc::tcgetattr(fd.as_raw_fd(), &mut termios));
|
|
Ok(termios)
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
fn set_term_attrs<F: AsRawFd>(fd: &mut F, attrs: &libc::termios) -> anyhow::Result<()> {
|
|
libc_try!(libc::tcsetattr(fd.as_raw_fd(), 0, attrs));
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
fn convert_termios_raw(attrs: &mut libc::termios) -> anyhow::Result<()> {
|
|
unsafe { libc::cfmakeraw(attrs) };
|
|
Ok(())
|
|
}
|
|
|
|
pub(super) async fn shell(
|
|
connection: Arc<Connection>,
|
|
mut capabilities: Capabilities,
|
|
) -> anyhow::Result<()> {
|
|
println!("Type #help to view a list of sparse commands\n");
|
|
|
|
let mut stdin = io::stdin();
|
|
let mut stdout = io::stdout();
|
|
let backup_term_attrs = get_term_attrs(&stdin)?;
|
|
let mut raw_term_attrs = get_term_attrs(&stdin)?;
|
|
convert_termios_raw(&mut raw_term_attrs)?;
|
|
|
|
macro_rules! cmd_matcher {
|
|
($input:expr, $(($check:ident, $matcher:expr) => {$($body:tt)*}),+, _ => {$($ebody:tt)*}) => {
|
|
match &$input[..] {
|
|
$($check if $check.len() >= $matcher.len() && $check[..$matcher.len()] == $matcher[..] => {
|
|
let $check = &$check[$matcher.len()..];
|
|
$($body)*
|
|
}),+
|
|
_ => {
|
|
$($ebody)*
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let mut cwd = "/".to_string();
|
|
|
|
loop {
|
|
print!(
|
|
"{}@{}:{} {} ",
|
|
capabilities.userent.as_deref().unwrap_or("unknown user!"),
|
|
match &capabilities.hostname {
|
|
Some(n) => n.clone(),
|
|
None => format!("{}", connection.ip.ip()),
|
|
},
|
|
cwd,
|
|
if capabilities.root { "#" } else { "$" }
|
|
);
|
|
stdout.flush().unwrap();
|
|
|
|
let mut cmd = [0u8; 256];
|
|
let amount = stdin.read(&mut cmd)?;
|
|
|
|
if amount == 0 {
|
|
break;
|
|
}
|
|
|
|
cmd_matcher!(
|
|
cmd[..amount],
|
|
(_sysinfo, b"#sysinfo") => {
|
|
commands::sysinfo::print_capabilities(&capabilities)
|
|
},
|
|
(_help, b"#help") => {},
|
|
(_exit, b"#exit") => {
|
|
break;
|
|
},
|
|
_ => {}
|
|
);
|
|
}
|
|
|
|
Ok(())
|
|
}
|