You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
use crossbeam_channel::{select, Receiver};
use std::io::ErrorKind;
use std::process::{Command, ExitStatus};
use std::{io, thread};
use crate::builtins::{execute_builtin, is_builtin, BuiltinConfig};
use crate::error::ShellError;
use crate::parse::parse_line;
pub fn interpret(
line: String,
config: &mut BuiltinConfig,
ctrlc_recv: Receiver<()>,
) -> Result<(), ShellError> {
if line.is_empty() {
return Err(ShellError::EmptyLine);
}
let (keyword, args) = parse_line(&line)?;
if is_builtin(keyword) {
execute_builtin(keyword, config, args)?;
} else {
let mut command = Command::new(keyword);
command.args(args);
execute(command, ctrlc_recv)?;
}
Ok(())
}
fn execute(mut command: Command, ctrlc_recv: Receiver<()>) -> Result<(), ShellError> {
match command.spawn() {
Ok(mut child) => {
let (cmd_send, cmd_recv) = crossbeam_channel::unbounded::<io::Result<ExitStatus>>();
thread::spawn(move || cmd_send.send(child.wait()));
select! {
recv(ctrlc_recv) -> _ => Err(ShellError::Interrupt),
recv(cmd_recv) -> result => {
if let Err(err) = result.unwrap() {
Err(ShellError::ExecuteFailure(err.to_string()))
} else {
Ok(())
}
}
}
}
Err(err) => match err.kind() {
ErrorKind::NotFound => Err(ShellError::NotFound(command)),
ErrorKind::Interrupted => Err(ShellError::Interrupt),
_ => Err(ShellError::ExecuteFailure(err.to_string())),
},
}
}
|