diff --git a/src/builtin/alias.rs b/src/builtin/alias.rs index de3bf96..d0414b2 100644 --- a/src/builtin/alias.rs +++ b/src/builtin/alias.rs @@ -25,6 +25,16 @@ pub fn alias(node: Node, io_stack: &mut IoStack, job: &mut JobBldr) -> ShResult< write(stdout, alias_output.as_bytes())?; // Write it } else { for (arg,span) in argv { + if arg == "command" || arg == "builtin" { + return Err( + ShErr::full( + ShErrKind::ExecFail, + format!("alias: Cannot assign alias to reserved name '{arg}'"), + span + ) + ) + } + let Some((name,body)) = arg.split_once('=') else { return Err( ShErr::full( diff --git a/src/builtin/mod.rs b/src/builtin/mod.rs index b2e34d2..d90d16a 100644 --- a/src/builtin/mod.rs +++ b/src/builtin/mod.rs @@ -14,7 +14,7 @@ pub mod flowctl; pub mod zoltraak; pub mod shopt; -pub const BUILTINS: [&str;17] = [ +pub const BUILTINS: [&str;19] = [ "echo", "cd", "export", @@ -31,7 +31,9 @@ pub const BUILTINS: [&str;17] = [ "continue", "exit", "zoltraak", - "shopt" + "shopt", + "builtin", + "command" ]; /// Sets up a builtin command diff --git a/src/parse/execute.rs b/src/parse/execute.rs index e0efb62..2a702e6 100644 --- a/src/parse/execute.rs +++ b/src/parse/execute.rs @@ -345,9 +345,9 @@ impl Dispatcher { write_vars(|v| v.set_var(&var.to_string(), &val.to_string(), false)); } - self.io_stack.push(body_frame.clone()); for node in body.clone() { + self.io_stack.push(body_frame.clone()); if let Err(e) = self.dispatch_node(node) { match e.kind() { ShErrKind::LoopBreak(code) => { @@ -433,14 +433,22 @@ impl Dispatcher { Ok(()) } fn exec_builtin(&mut self, mut cmd: Node) -> ShResult<()> { - let NdRule::Command { ref mut assignments, argv: _ } = &mut cmd.class else { + let NdRule::Command { ref mut assignments, ref mut argv } = &mut cmd.class else { unreachable!() }; let env_vars_to_unset = self.set_assignments(mem::take(assignments), AssignBehavior::Export); - let cmd_raw = cmd.get_command().unwrap(); + let cmd_raw = argv.first().unwrap(); let curr_job_mut = self.job_stack.curr_job_mut().unwrap(); let io_stack_mut = &mut self.io_stack; + if cmd_raw.as_str() == "builtin" || cmd_raw.as_str() == "command" { + *argv = argv.iter_mut() + .skip(1) + .map(|tk| tk.clone()) + .collect::>(); + return self.dispatch_cmd(cmd) + } + flog!(TRACE, "doing builtin"); let result = match cmd_raw.span.as_str() { "echo" => echo(cmd, io_stack_mut, curr_job_mut),