diff options
Diffstat (limited to 'src/parser/command.rs')
-rw-r--r-- | src/parser/command.rs | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/parser/command.rs b/src/parser/command.rs new file mode 100644 index 0000000..496614f --- /dev/null +++ b/src/parser/command.rs @@ -0,0 +1,91 @@ +use std::io::{Error, ErrorKind}; +use std::path::{Path, PathBuf}; + +#[derive(Debug)] +pub enum Redirect { + Std, + FileOverwrite(String), + FileAppend(String), +} + +#[derive(Debug, PartialEq)] +pub enum RunOn { + Always, + ExitSuccess, + ExitFailure, +} + +pub enum RunResult { + Command(std::process::ExitStatus), + Builtin, +} + +#[derive(Debug)] +pub struct CommandInfo { + pub args: Vec<String>, + pub stdout: Redirect, + pub when: RunOn, +} + +impl CommandInfo { + pub fn new() -> CommandInfo { + CommandInfo { + args: Vec::new(), + stdout: Redirect::Std, + when: RunOn::Always, + } + } + + pub fn run( + &self, + home: &PathBuf, + cwd: &mut PathBuf, + status: &Option<std::process::ExitStatus>, + ) -> Result<RunResult, Error> { + match self.args[0].as_str() { + "!" => { + println!("{:?}", status); + Ok(RunResult::Builtin) + } + "cd" => match cd(&self.args[1..], home) { + Ok(p) => { + *cwd = p; + Ok(RunResult::Builtin) + } + Err(e) => Err(e), + }, + "exit" => { + std::process::exit(0); + } + _ => { + let mut child = std::process::Command::new(&self.args[0]) + .args(&self.args[1..]) + .spawn()?; + Ok(RunResult::Command(child.wait().unwrap())) + } + } + } +} + +fn cd(args: &[String], home: &PathBuf) -> Result<PathBuf, Error> { + if args.len() > 1 { + return Err(Error::new( + ErrorKind::InvalidInput, + "Too many arguments passed to cd", + )); + } + + if args.len() == 0 { + return Ok(home.to_path_buf()); + } + + let root = match std::fs::canonicalize(Path::new(args[0].as_str())) { + Ok(p) => p, + Err(_) => Path::new("/").to_path_buf(), + }; + + match std::env::set_current_dir(&root) { + Ok(_) => Ok(root.to_path_buf()), + Err(e) => Err(e), + } +} |