2023-09-04 01:11:55 -04:00

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(())
}