diff options
| -rw-r--r-- | src/run/mod.rs | 91 |
1 files changed, 35 insertions, 56 deletions
diff --git a/src/run/mod.rs b/src/run/mod.rs index 6484e30..e97c377 100644 --- a/src/run/mod.rs +++ b/src/run/mod.rs @@ -1,6 +1,4 @@ use std::collections::HashMap; -use std::fs; -use std::os::unix::fs::PermissionsExt; use std::path::PathBuf; use crate::parse::Ast; @@ -42,14 +40,7 @@ pub fn run(se: &mut Session, cmd: Vec<u8>) { (None, None) }; - let Some(dc) = se.dispatch.get(&cmd.cmd[..]) else { - println!( - "unknown command {}", - String::from_utf8_lossy(cmd.cmd.as_slice()) - ); - spawn_error = true; - break; - }; + let dc = se.dispatch.get(&cmd.cmd[..]); match dc { CommandKind::Path(path) => { @@ -66,10 +57,30 @@ pub fn run(se: &mut Session, cmd: Vec<u8>) { command.stdout(Stdio::from(w)); } - let Ok(child) = command.spawn() else { - println!("failed to spawn {path:?}"); - spawn_error = true; - break; + let child = match command.spawn() { + Ok(c) => c, + Err(e) => { + let cmd = path.to_string_lossy(); + let msg = match e.kind() { + io::ErrorKind::NotFound => format!("{cmd} not found"), + io::ErrorKind::PermissionDenied => format!("{cmd} is not executable"), + io::ErrorKind::FileTooLarge => format!("{cmd} is too massive"), + io::ErrorKind::ResourceBusy | io::ErrorKind::ExecutableFileBusy => { + format!("{cmd} is busy") + } + io::ErrorKind::TooManyLinks => format!("{cmd} could not be resolved"), + io::ErrorKind::InvalidFilename => { + format!("{cmd} is not a valid file name") + } + io::ErrorKind::ArgumentListTooLong => format!("too many arguments"), + io::ErrorKind::Interrupted => format!("got interrupted"), + io::ErrorKind::Unsupported => format!("{cmd} is not supported"), + e => format!("I am surprised you can get this error here: {e:?}"), + }; + println!("pish: {msg}"); + spawn_error = true; + break; + } }; children.push(child); @@ -88,9 +99,8 @@ pub fn run(se: &mut Session, cmd: Vec<u8>) { None => Box::new(io::stdout()), }; - let handle = std::thread::spawn(move || { - builtin.io(&cmd.args, &mut input, &mut output) - }); + let handle = + std::thread::spawn(move || builtin.io(&cmd.args, &mut input, &mut output)); threads.push(handle); } @@ -107,7 +117,7 @@ pub fn run(se: &mut Session, cmd: Vec<u8>) { println!("failed to kill child - {e:?}"); } } - status_string = "ERR".into(); + status_string = "".into(); } else { let mut code = 0; for jh in threads { @@ -178,40 +188,6 @@ impl CommandDispatch { pub fn new() -> Self { let mut map = HashMap::new(); - // all the commands from PATH - let path = std::env::var_os("PATH").unwrap(); - for p in path.as_bytes().split(|x| *x == b':').rev() { - let p = PathBuf::from(OsStr::from_bytes(p)); - let Ok(entries) = fs::read_dir(p) else { - continue; - }; - - for entry in entries { - let Ok(entry) = entry else { continue }; - let Ok(meta) = entry.metadata() else { - continue; - }; - - if !meta.is_file() { - continue; - } - - let perms = meta.permissions(); - let mode = perms.mode(); - - // Check if any execute bit is set (owner/group/other) - if mode & 0o111 == 0 { - continue; - } - - // insert into our command map, mind the .rev() on the iterator above s.t. correct precedence is had - map.insert( - entry.file_name().as_bytes().to_vec(), - CommandKind::Path(entry.path()), - ); - } - } - // builtins for &b in BUILTINS { map.insert(b.name().as_bytes().to_vec(), CommandKind::Builtin(b)); @@ -220,11 +196,14 @@ impl CommandDispatch { Self { map } } - fn get(&self, cmd: &bstr) -> Option<CommandKind> { - if cmd.starts_with(b"/") || cmd.starts_with(b"./") { - Some(CommandKind::Path(PathBuf::from(OsStr::from_bytes(cmd)))) + fn get(&self, cmd: &bstr) -> CommandKind { + let path_cmd = CommandKind::Path(PathBuf::from(OsStr::from_bytes(cmd))); + if cmd.contains(&b'/') { + path_cmd + } else if let Some(cmd) = self.map.get(cmd) { + cmd.clone() } else { - self.map.get(cmd).cloned() + path_cmd } } } |
