commit c5f5b2a8688324cc7ed488c4e4bd9a1ee446ee6f Author: William Brawner Date: Sat Jul 23 22:14:31 2022 -0600 Initial commit This is still experimental, though for now I've been able to implement a few commands: - cd: changes the current working directory of the agent - ls: lists the directories and files in the current working directory - ping: responds with "pong" - pwd: prints the current working directory - shell: executes an arbitrary command on the host diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e71169f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "gsm-agent" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..bff75c2 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "gsm-agent" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/.main.rs.swp b/src/.main.rs.swp new file mode 100644 index 0000000..b9728cb Binary files /dev/null and b/src/.main.rs.swp differ diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d4a9100 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,78 @@ +use std::cmp::Ordering; +use std::env; +use std::fs; +use std::fs::DirEntry; +use std::io::Read; +use std::io::Write; +use std::net::TcpListener; +use std::net::TcpStream; +use std::path::Path; +use std::process::Command; + +fn main() { + let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); + for stream in listener.incoming() { + let stream = stream.unwrap(); + handle_connection(stream); + } +} + +fn cwd() -> String { + env::current_dir().unwrap().to_string_lossy().to_string() +} + +fn handle_connection(mut stream: TcpStream) { + let mut buffer = [0; 1024]; + stream.read(&mut buffer).unwrap(); + let mut request: &str = &String::from_utf8(buffer.to_vec()).unwrap(); + request = request.trim(); + let trim_chars = [' ', '\n', '\0']; + request = request.trim_matches(&trim_chars[..]); + let mut command_iter = request.split_whitespace(); + let command = command_iter.next().unwrap(); + let response: String = match command { + "cd" => { + let path = Path::new(command_iter.next().unwrap()); + env::set_current_dir(path).unwrap(); + cwd() + } + "ls" => { + let mut files: Vec = Vec::new(); + let mut paths: Vec = + fs::read_dir(cwd()).unwrap().map(|r| r.unwrap()).collect(); + paths.sort_by(|a, b| { + let a_is_dir = a.file_type().unwrap().is_dir(); + let b_is_dir = b.file_type().unwrap().is_dir(); + if a_is_dir && !b_is_dir { + Ordering::Less + } else if !a_is_dir && b_is_dir { + Ordering::Greater + } else { + a.file_name().cmp(&b.file_name()) + } + }); + for file in paths { + files.push(file.file_name().into_string().unwrap()); + } + files.join("\n") + } + "ping" => String::from("pong"), + "pwd" => cwd(), + "shell" => String::from_utf8( + Command::new(command_iter.next().unwrap()) + .args(command_iter) + .output() + .unwrap() + .stdout, + ) + .unwrap(), + _ => { + format!( + "unknown command: {:?}", + request.split_whitespace().next().unwrap_or("") + ) + } + }; + stream.write(format!("{}\n", response).as_bytes()).unwrap(); + stream.flush().unwrap(); +}