shell pipe function prototype finished
This commit is contained in:
parent
9c0f88ec91
commit
e5f81ad604
2 changed files with 67 additions and 22 deletions
|
|
@ -172,48 +172,79 @@ Each one has their output redirected to the input of the next one.
|
|||
Example:
|
||||
(pipe
|
||||
(ls -la)
|
||||
(grep '*.rs')
|
||||
(grep '.rs')
|
||||
(tr -d '.rs'))";
|
||||
fn pipe_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Result<Ctr, String> {
|
||||
if ast.is_empty() {
|
||||
return Err("need at least one argument".to_string())
|
||||
}
|
||||
|
||||
let mut input = Stdio::inherit();
|
||||
let mut err: String = String::new();
|
||||
// posix layer will never control pid 0
|
||||
let mut lastpid = 0;
|
||||
if !ast.circuit(&mut |arg: &Ctr| -> bool {
|
||||
if let Ctr::Seg(command_form) = arg {
|
||||
let args = VecDeque::from(args_from_ast(ast, syms));
|
||||
let mut args = VecDeque::from(args_from_ast(command_form, syms));
|
||||
if args.is_empty() {
|
||||
return false
|
||||
}
|
||||
|
||||
if let Some(filepath) = run::find_on_path(args.pop_front().unwrap()) {
|
||||
let tmp = Stdio::piped();
|
||||
// TODO Youll just have to break open launch_command here
|
||||
// youll need seperate calls for .stdin and .stdout anyways
|
||||
// and also the move semantics are not working
|
||||
launch_command(
|
||||
filepath,
|
||||
&Vec::from(args.make_contiguous()),
|
||||
input,
|
||||
Stdio::inherit(),
|
||||
tmp,
|
||||
false,
|
||||
state,
|
||||
).unwrap();
|
||||
input = tmp;
|
||||
true
|
||||
let mut newchld = Command::new(filepath);
|
||||
newchld.args(Vec::from(args.make_contiguous()))
|
||||
.stderr(Stdio::inherit())
|
||||
.stdout(Stdio::piped());
|
||||
|
||||
if let Some(pos) = state.children
|
||||
.iter()
|
||||
.position(|x| x.id() == lastpid)
|
||||
{
|
||||
newchld.stdin(state.children.remove(pos).stdout.unwrap());
|
||||
}
|
||||
|
||||
let chld_spwn = newchld.spawn();
|
||||
if let Ok(child) = chld_spwn {
|
||||
let pid = child.id();
|
||||
lastpid = pid;
|
||||
state.children.push(child);
|
||||
true
|
||||
} else {
|
||||
err = format!("failed to spawn: {}", chld_spwn.err().unwrap());
|
||||
false
|
||||
}
|
||||
|
||||
} else {
|
||||
eprintln!("file not found");
|
||||
err = "file not found".to_string();
|
||||
false
|
||||
}
|
||||
} else {
|
||||
err = format!("{} not a shell command", arg);
|
||||
false
|
||||
}
|
||||
}) {
|
||||
Err("all arguments must be full shell commands".to_string())
|
||||
Err(err)
|
||||
} else {
|
||||
Ok(Ctr::None)
|
||||
if lastpid > 0 {
|
||||
if let Some(pos) = state.children
|
||||
.iter()
|
||||
.position(|x| x.id() == lastpid)
|
||||
{
|
||||
let chld = state.children.remove(pos);
|
||||
let exit = chld.wait_with_output()
|
||||
.expect("failed to wait on last child");
|
||||
state.last_exit_code = exit.status
|
||||
.code()
|
||||
.or_else(|| {Some(-1)})
|
||||
.unwrap();
|
||||
|
||||
println!("{}", String::from_utf8_lossy(&exit.stdout));
|
||||
Ok(Ctr::Integer(state.last_exit_code.into()))
|
||||
} else {
|
||||
Err(format!("lost last child (pid {})", lastpid))
|
||||
}
|
||||
} else {
|
||||
Err("impossible error state".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -458,6 +489,7 @@ pub fn load_posix_shell(syms: &mut SymTable, shell_state: Rc<RefCell<ShellState>
|
|||
let q_ss = shell_state.clone();
|
||||
let lw_ss = shell_state.clone();
|
||||
let lts_ss = shell_state.clone();
|
||||
let p_ss = shell_state.clone();
|
||||
|
||||
syms.insert(
|
||||
String::from("l"),
|
||||
|
|
@ -543,6 +575,20 @@ pub fn load_posix_shell(syms: &mut SymTable, shell_state: Rc<RefCell<ShellState>
|
|||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
String::from("pipe"),
|
||||
Symbol {
|
||||
name: String::from("pipe"),
|
||||
args: Args::Infinite,
|
||||
conditional_branches: true,
|
||||
docs: String::from(PIPE_DOCSTRING),
|
||||
value: ValueType::Internal(Rc::new(move |ast: &Seg, symtable: &mut SymTable| -> Result<Ctr, String> {
|
||||
pipe_callback(ast, symtable, &mut p_ss.clone().borrow_mut())
|
||||
})),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
if let Err(e) = ctrlc::set_handler(move || println!("POSIX layer caught SIG-something")) {
|
||||
eprintln!("WARNING: couldn't set sig handler: {}", e);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue