1
0
This commit is contained in:
2026-02-27 11:54:39 +09:00
commit fc35ccc271
10 changed files with 862 additions and 0 deletions

80
src/executor.rs Normal file
View File

@@ -0,0 +1,80 @@
use std::env;
use std::path::PathBuf;
use std::process::Command;
/// Execute a shell command line and print output directly to stdout/stderr.
/// Returns the exit code.
pub fn execute(input: &str) -> i32 {
let trimmed = input.trim();
// Handle cd specially - it must affect our process
if trimmed == "cd" || trimmed.starts_with("cd ") {
return handle_cd(trimmed);
}
// Run everything else through sh -c for full shell semantics
// (pipes, redirects, globs, etc.)
let status = Command::new("sh")
.arg("-c")
.arg(trimmed)
.status();
match status {
Ok(s) => s.code().unwrap_or(1),
Err(e) => {
eprintln!("aishell: {}", e);
127
}
}
}
fn handle_cd(input: &str) -> i32 {
let target = input.strip_prefix("cd").unwrap().trim();
let dir: PathBuf = if target.is_empty() {
// cd with no args → home directory
match env::var("HOME") {
Ok(home) => PathBuf::from(home),
Err(_) => {
eprintln!("aishell: cd: HOME not set");
return 1;
}
}
} else if target.starts_with('~') {
// Expand ~ to HOME
match env::var("HOME") {
Ok(home) => PathBuf::from(target.replacen('~', &home, 1)),
Err(_) => {
eprintln!("aishell: cd: HOME not set");
return 1;
}
}
} else if target == "-" {
// cd - → previous directory
match env::var("OLDPWD") {
Ok(old) => {
println!("{}", old);
PathBuf::from(old)
}
Err(_) => {
eprintln!("aishell: cd: OLDPWD not set");
return 1;
}
}
} else {
PathBuf::from(target)
};
// Save current dir as OLDPWD
if let Ok(cwd) = env::current_dir() {
env::set_var("OLDPWD", cwd);
}
match env::set_current_dir(&dir) {
Ok(_) => 0,
Err(e) => {
eprintln!("aishell: cd: {}: {}", dir.display(), e);
1
}
}
}