Commit c6bdc75c authored by jD91mZM2's avatar jD91mZM2 Committed by Michael Aaron Murphy
Browse files

Disown using &! (#635)

* Disown using &!

* Maybe did something hopefully?
parent 4baf9d50
......@@ -281,6 +281,10 @@ impl<'a> Collector<'a> {
bytes.next();
try_add_item!(JobKind::And);
}
Some(&(_, b'!')) => {
bytes.next();
try_add_item!(JobKind::Disown);
}
Some(_) | None => {
try_add_item!(JobKind::Background);
}
......@@ -643,6 +647,16 @@ mod tests {
}
}
#[test]
fn disown_job() {
if let Statement::Pipeline(pipeline) = parse("echo hello world&!") {
let items = pipeline.items;
assert_eq!(JobKind::Disown, items[0].job.kind);
} else {
assert!(false);
}
}
#[test]
fn and_job() {
if let Statement::Pipeline(pipeline) = parse("echo one && echo two") {
......
......@@ -84,6 +84,7 @@ impl Pipeline {
self.items.len() > 1 || self.items.iter().any(|it| it.outputs.len() > 0)
|| self.items.iter().any(|it| it.inputs.len() > 0)
|| self.items.last().unwrap().job.kind == JobKind::Background
|| self.items.last().unwrap().job.kind == JobKind::Disown
}
}
......@@ -127,6 +128,7 @@ impl fmt::Display for Pipeline {
JobKind::And => tokens.push("&&".into()),
JobKind::Or => tokens.push("||".into()),
JobKind::Background => tokens.push("&".into()),
JobKind::Disown => tokens.push("&!".into()),
JobKind::Pipe(RedirectFrom::Stdout) => tokens.push("|".into()),
JobKind::Pipe(RedirectFrom::Stderr) => tokens.push("^|".into()),
JobKind::Pipe(RedirectFrom::Both) => tokens.push("&|".into()),
......
......@@ -13,6 +13,7 @@ use types::*;
pub(crate) enum JobKind {
And,
Background,
Disown,
Last,
Or,
Pipe(RedirectFrom),
......
......@@ -18,6 +18,7 @@ pub(crate) fn fork_pipe(
shell: &mut Shell,
commands: Vec<(RefinedJob, JobKind)>,
command_name: String,
state: ProcessState
) -> i32 {
match unsafe { sys::fork() } {
Ok(0) => {
......@@ -38,8 +39,10 @@ pub(crate) fn fork_pipe(
exit(pipe(shell, commands, false));
}
Ok(pid) => {
// The parent process should add the child fork's PID to the background.
shell.send_to_background(pid, ProcessState::Running, command_name);
if state != ProcessState::Empty {
// The parent process should add the child fork's PID to the background.
shell.send_to_background(pid, state, command_name);
}
SUCCESS
}
Err(why) => {
......
......@@ -13,7 +13,7 @@ mod streams;
use self::command_not_found::command_not_found;
use self::fork::{create_process_group, fork_pipe};
use self::job_control::JobControl;
use self::job_control::{JobControl, ProcessState};
use self::streams::{duplicate_streams, redir, redirect_streams};
use super::{JobKind, Shell};
use super::flags::*;
......@@ -54,13 +54,14 @@ pub unsafe fn stdin_of<T: AsRef<[u8]>>(input: T) -> Result<RawFd, Error> {
/// 1. If the result is `Some`, then we will fork the pipeline executing into the background.
/// 2. The value stored within `Some` will be that background job's command name.
/// 3. If `set -x` was set, print the command.
fn gen_background_string(pipeline: &Pipeline, print_comm: bool) -> Option<String> {
if pipeline.items[pipeline.items.len() - 1].job.kind == JobKind::Background {
fn gen_background_string(pipeline: &Pipeline, print_comm: bool) -> Option<(String, bool)> {
let last = &pipeline.items[pipeline.items.len() - 1];
if last.job.kind == JobKind::Background || last.job.kind == JobKind::Disown {
let command = pipeline.to_string();
if print_comm {
eprintln!("> {}", command);
}
Some(command)
Some((command, last.job.kind == JobKind::Disown))
} else if print_comm {
eprintln!("> {}", pipeline.to_string());
None
......@@ -409,7 +410,7 @@ impl PipelineExecution for Shell {
// Remove any leftover foreground tasks from the last execution.
self.foreground.clear();
// If the supplied pipeline is a background, a string representing the command
// will be stored here.
// and a boolean representing whether it should be disowned is stored here.
let possible_background_name =
gen_background_string(&pipeline, self.flags & PRINT_COMMS != 0);
// Generates commands for execution, differentiating between external and
......@@ -431,8 +432,12 @@ impl PipelineExecution for Shell {
};
// If the given pipeline is a background task, fork the shell.
if let Some(command_name) = possible_background_name {
fork_pipe(self, piped_commands, command_name)
if let Some((command_name, disown)) = possible_background_name {
fork_pipe(self, piped_commands, command_name, if disown {
ProcessState::Empty
} else {
ProcessState::Running
})
} else {
// While active, the SIGTTOU signal will be ignored.
let _sig_ignore = SignalHandler::new();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment