use std::path::PathBuf;
use nix::sys::wait::{waitpid, WaitStatus};
use nix::unistd::Pid;
#[allow(dead_code)]
pub fn find_in_path(cmd: &str, path_var: &str) -> Option<PathBuf> {
for dir in path_var.split(':') {
if dir.is_empty() {
continue;
}
let candidate = PathBuf::from(dir).join(cmd);
if candidate.is_file() {
use std::os::unix::fs::PermissionsExt;
if let Ok(meta) = std::fs::metadata(&candidate)
&& meta.permissions().mode() & 0o111 != 0
{
return Some(candidate);
}
}
}
None
}
pub fn wait_child(child: Pid) -> i32 {
match waitpid(child, None) {
Ok(WaitStatus::Exited(_, code)) => code,
Ok(WaitStatus::Signaled(_, sig, _)) => 128 + sig as i32,
Ok(_) => 0,
Err(e) => {
eprintln!("yosh: waitpid: {}", e);
1
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
#[test]
fn find_in_path_finds_sh() {
let path_var = env::var("PATH").unwrap_or_else(|_| "/bin:/usr/bin".to_string());
let result = find_in_path("sh", &path_var);
assert!(result.is_some(), "should find 'sh' in PATH");
}
#[test]
fn find_in_path_returns_none_for_nonexistent() {
let path_var = "/bin:/usr/bin";
let result = find_in_path("nonexistent_cmd_12345", path_var);
assert!(result.is_none());
}
}