47 lines
1.1 KiB
Rust
47 lines
1.1 KiB
Rust
use nix::{errno::Errno, unistd::execvpe};
|
|
|
|
use crate::{
|
|
builtin::setup_builtin,
|
|
jobs::JobBldr,
|
|
libsh::error::{ShErr, ShErrKind, ShResult},
|
|
parse::{execute::ExecArgs, NdRule, Node},
|
|
procio::IoStack,
|
|
state,
|
|
};
|
|
|
|
pub fn exec_builtin(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult<()> {
|
|
let NdRule::Command {
|
|
assignments: _,
|
|
argv,
|
|
} = node.class
|
|
else {
|
|
unreachable!()
|
|
};
|
|
|
|
let (expanded_argv, guard) = setup_builtin(argv, job, Some((io_stack, node.redirs)))?;
|
|
if let Some(g) = guard {
|
|
// Persist redirections so they affect the entire shell,
|
|
// not just this command call
|
|
g.persist()
|
|
}
|
|
|
|
if expanded_argv.is_empty() {
|
|
state::set_status(0);
|
|
return Ok(());
|
|
}
|
|
|
|
let args = ExecArgs::from_expanded(expanded_argv)?;
|
|
|
|
let cmd = &args.cmd.0;
|
|
let span = args.cmd.1;
|
|
|
|
let Err(e) = execvpe(cmd, &args.argv, &args.envp);
|
|
|
|
// execvpe only returns on error
|
|
let cmd_str = cmd.to_str().unwrap().to_string();
|
|
match e {
|
|
Errno::ENOENT => Err(ShErr::full(ShErrKind::CmdNotFound(cmd_str), "", span)),
|
|
_ => Err(ShErr::full(ShErrKind::Errno(e), format!("{e}"), span)),
|
|
}
|
|
}
|