diff --git a/src/shell/job.rs b/src/shell/job.rs index cc638c72b3fe111d3433cfe18c44b0ba6e076efa..bbc97fe2a3d788ff1c9cf073eaddd2c71429e2cb 100644 --- a/src/shell/job.rs +++ b/src/shell/job.rs @@ -48,10 +48,39 @@ impl Job { } pub fn build_command(&mut self) -> Command { - let mut command = Command::new(&self.command); - for arg in self.args.drain(..).skip(1) { - command.arg(arg); + match CommandType::from(self.command.as_str()) { + CommandType::Builtin => { + use std::env; + let process = env::current_exe().unwrap(); + let mut command = Command::new(process); + command.arg("-c"); + command.arg(&self.command); + for arg in self.args.drain(..).skip(1) { + command.arg(arg); + } + command + }, + CommandType::External => { + let mut command = Command::new(&self.command); + for arg in self.args.drain(..).skip(1) { + command.arg(arg); + } + command + } + } + } +} + +enum CommandType { + Builtin, + External +} + +impl<'a> From<&'a str> for CommandType { + fn from(command: &'a str) -> CommandType { + match command { + "help" | "history" => CommandType::Builtin, + _ => CommandType::External } - command } } diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 0a93de622b67292973351f030220e0e236d2834d..22398e98b62b21336bf120f8502b73b7ff77ce6a 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -297,8 +297,6 @@ impl<'a> Shell<'a> { /// To avoid infinite recursion when using aliases, the noalias boolean will be set the true /// if an alias branch was executed. fn run_pipeline(&mut self, pipeline: &mut Pipeline, noalias: bool) -> Option<i32> { - pipeline.expand(&self.variables, &self.directory_stack); - let command_start_time = SystemTime::now(); let mut exit_status = None; @@ -329,36 +327,48 @@ impl<'a> Shell<'a> { } if !branched { + pipeline.expand(&self.variables, &self.directory_stack); // Branch if -> input == shell command i.e. echo exit_status = if let Some(command) = builtins.get(pipeline.jobs[0].command.as_str()) { // Run the 'main' of the command and set exit_status - Some((*command.main)(pipeline.jobs[0].args.as_slice(), self)) + if pipeline.jobs.len() == 1 { + Some((*command.main)(pipeline.jobs[0].args.as_slice(), self)) + } else { + Some(execute_pipeline(pipeline)) + } // Branch else if -> input == shell function and set the exit_status } else if let Some(function) = self.functions.get(pipeline.jobs[0].command.as_str()).cloned() { - if pipeline.jobs[0].args.len() - 1 == function.args.len() { - let mut variables_backup: FnvHashMap<&str, Option<String>> = FnvHashMap::with_capacity_and_hasher ( - 64, Default::default() - ); - for (name, value) in function.args.iter().zip(pipeline.jobs[0].args.iter().skip(1)) { - variables_backup.insert(name, self.variables.get_var(name)); - self.variables.set_var(name, value); - } + if pipeline.jobs.len() == 1 { + if pipeline.jobs[0].args.len() - 1 == function.args.len() { + let mut variables_backup: FnvHashMap<&str, Option<String>> = FnvHashMap::with_capacity_and_hasher ( + 64, Default::default() + ); + for (name, value) in function.args.iter().zip(pipeline.jobs[0].args.iter().skip(1)) { + variables_backup.insert(name, self.variables.get_var(name)); + self.variables.set_var(name, value); + } - self.execute_statements(function.statements); + self.execute_statements(function.statements); - for (name, value_option) in &variables_backup { - match *value_option { - Some(ref value) => self.variables.set_var(name, value), - None => {self.variables.unset_var(name);}, + for (name, value_option) in &variables_backup { + match *value_option { + Some(ref value) => self.variables.set_var(name, value), + None => {self.variables.unset_var(name);}, + } } + None + } else { + let stderr = io::stderr(); + let mut stderr = stderr.lock(); + let _ = writeln!(stderr, "This function takes {} arguments, but you provided {}", + function.args.len(), pipeline.jobs[0].args.len()-1); + Some(NO_SUCH_COMMAND) // not sure if this is the right error code } - None } else { let stderr = io::stderr(); let mut stderr = stderr.lock(); - let _ = writeln!(stderr, "This function takes {} arguments, but you provided {}", - function.args.len(), pipeline.jobs[0].args.len()-1); - Some(NO_SUCH_COMMAND) // not sure if this is the right error code + let _ = writeln!(stderr, "Function pipelining is not implemented yet"); + Some(FAILURE) } // If not a shell command or a shell function execute the pipeline and set the exit_status } else {