diff --git a/src/lib/shell/job.rs b/src/lib/shell/job.rs
index d905ce7605648af98eb434b2f174bba693ae4099..4ad46d3d7b5d9a48d2d76949cf76482cc906398b 100644
--- a/src/lib/shell/job.rs
+++ b/src/lib/shell/job.rs
@@ -5,7 +5,6 @@ use parser::pipelines::RedirectFrom;
 use smallstring::SmallString;
 use std::fmt;
 use std::fs::File;
-use std::process::{Command, Stdio};
 use std::str;
 use types::*;
 
@@ -79,31 +78,27 @@ fn expand_arg(arg: &str, shell: &Shell) -> Array {
 /// as part of some pipeline
 pub(crate) enum RefinedJob {
     /// An external program that is executed by this shell
-    External(Command),
+    External {
+        name: Identifier,
+        args: Array,
+        stdin: Option<File>,
+        stdout: Option<File>,
+        stderr: Option<File>,
+    },
     /// A procedure embedded into Ion
     Builtin {
-        /// Name of the procedure
         main: BuiltinFunction,
-        /// Arguments to pass in to the procedure
         args: Array,
-        /// A file corresponding to the standard input for this builtin
         stdin: Option<File>,
-        /// A file corresponding to the standard output for this builtin
         stdout: Option<File>,
-        /// A file corresponding to the standard error for this builtin
         stderr: Option<File>,
     },
     /// Functions can act as commands too!
     Function {
-        /// Name of the procedure
         name: Identifier,
-        /// Arguments to pass in to the procedure
         args: Array,
-        /// A file corresponding to the standard input for this builtin
         stdin: Option<File>,
-        /// A file corresponding to the standard output for this builtin
         stdout: Option<File>,
-        /// A file corresponding to the standard error for this builtin
         stderr: Option<File>,
     },
     /// Represents redirection into stdin from more than one source
@@ -187,10 +182,8 @@ impl TeeItem {
 macro_rules! set_field {
     ($self:expr, $field:ident, $arg:expr) => {
         match *$self {
-            RefinedJob::External(ref mut command) => {
-                command.$field(Stdio::from($arg));
-            }
-            RefinedJob::Builtin { ref mut $field,  .. } |
+            RefinedJob::External { ref mut $field, .. } |
+                RefinedJob::Builtin { ref mut $field,  .. } |
                 RefinedJob::Function { ref mut $field, .. } |
                 RefinedJob::Tee { ref mut $field, .. } => {
                 *$field = Some($arg);
@@ -202,6 +195,16 @@ macro_rules! set_field {
 }
 
 impl RefinedJob {
+    pub(crate) fn external(name: Identifier, args: Array) -> Self {
+        RefinedJob::External {
+            name,
+            args,
+            stdin: None,
+            stdout: None,
+            stderr: None,
+        }
+    }
+
     pub(crate) fn builtin(main: BuiltinFunction, args: Array) -> Self {
         RefinedJob::Builtin {
             main,
@@ -263,13 +266,9 @@ impl RefinedJob {
     /// or builtin name
     pub(crate) fn short(&self) -> String {
         match *self {
-            RefinedJob::External(ref cmd) => format!("{:?}", cmd)
-                .split('"')
-                .nth(1)
-                .unwrap_or("")
-                .to_string(),
             RefinedJob::Builtin { .. } => String::from("Shell Builtin"),
-            RefinedJob::Function { ref name, .. } => name.to_string(),
+            RefinedJob::Function { ref name, .. } |
+                RefinedJob::External { ref name, .. } => name.to_string(),
             // TODO: Print for real
             RefinedJob::Cat { .. } => "multi-input".into(),
             RefinedJob::Tee { .. } => "multi-output".into(),
@@ -279,24 +278,9 @@ impl RefinedJob {
     /// Returns a long description of this job: the commands and arguments
     pub(crate) fn long(&self) -> String {
         match *self {
-            RefinedJob::External(ref cmd) => {
-                let command = format!("{:?}", cmd);
-                let mut arg_iter = command.split_whitespace();
-                let command = arg_iter.next().unwrap();
-                let mut output = String::from(&command[1..command.len() - 1]);
-                for argument in arg_iter {
-                    output.push(' ');
-                    if argument.len() > 2 {
-                        output.push_str(&argument[1..argument.len() - 1]);
-                    } else {
-                        output.push_str(&argument);
-                    }
-                }
-                output
-            }
-            RefinedJob::Builtin { ref args, .. } | RefinedJob::Function { ref args, .. } => {
-                format!("{}", args.join(" "))
-            }
+            RefinedJob::External { ref args, .. } |
+                RefinedJob::Builtin { ref args, .. } |
+                RefinedJob::Function { ref args, .. } => format!("{}", args.join(" ")),
             // TODO: Figure out real printing
             RefinedJob::Cat { .. } | RefinedJob::Tee { .. } => "".into(),
         }
diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs
index 7e56ca6fc77e18df352f577f9f5fa407095c4d78..1ca66d6da52d0a9d965d4e4aa2435cbd506577ed 100644
--- a/src/lib/shell/mod.rs
+++ b/src/lib/shell/mod.rs
@@ -126,6 +126,12 @@ impl ShellBuilder {
         let _ = sys::signal(sys::SIGINT, handler);
         let _ = sys::signal(sys::SIGTERM, handler);
 
+        extern "C" fn sigpipe_handler(signal: i32) {
+            sys::fork_exit(127 + signal);
+        }
+
+        let _ = sys::signal(sys::SIGPIPE, sigpipe_handler);
+
         self
     }
 
@@ -328,6 +334,7 @@ impl<'a> Shell {
             self.set_var("?", &code.to_string());
             self.previous_status = code;
         }
+
         exit_status
     }
 
diff --git a/src/lib/shell/pipe_exec/job_control.rs b/src/lib/shell/pipe_exec/job_control.rs
index e5fe69eb2bec35821a1561165c3102bc0bc66953..854fd97a1c15fd046996fde25cf88ec7007adc8c 100644
--- a/src/lib/shell/pipe_exec/job_control.rs
+++ b/src/lib/shell/pipe_exec/job_control.rs
@@ -33,16 +33,7 @@ pub(crate) trait JobControl {
     fn handle_signal(&self, signal: i32) -> bool;
     fn foreground_send(&self, signal: i32);
     fn background_send(&self, signal: i32);
-    fn watch_foreground<F, D>(
-        &mut self,
-        pid: u32,
-        last_pid: u32,
-        get_command: F,
-        drop_command: D,
-    ) -> i32
-    where
-        F: FnOnce() -> String,
-        D: FnMut(i32);
+    fn watch_foreground(&mut self, pid: i32, command: &str) -> i32;
     fn send_to_background(&mut self, child: u32, state: ProcessState, command: String);
 }
 
@@ -157,18 +148,8 @@ impl JobControl for Shell {
         self.exit(sigcode);
     }
 
-    fn watch_foreground<F, D>(
-        &mut self,
-        pid: u32,
-        last_pid: u32,
-        get_command: F,
-        drop_command: D,
-    ) -> i32
-    where
-        F: FnOnce() -> String,
-        D: FnMut(i32),
-    {
-        self_sys::watch_foreground(self, pid, last_pid, get_command, drop_command)
+    fn watch_foreground(&mut self, pid: i32, command: &str) -> i32 {
+        self_sys::watch_foreground(self, pid, command)
     }
 
     /// Send a kill signal to all running foreground tasks.
diff --git a/src/lib/shell/pipe_exec/mod.rs b/src/lib/shell/pipe_exec/mod.rs
index 8fb20e9f9cc25e736ea1392d23c252a470c9ebfd..639f70cd9c9151a3598087cdb6c9b519ff0c26df 100644
--- a/src/lib/shell/pipe_exec/mod.rs
+++ b/src/lib/shell/pipe_exec/mod.rs
@@ -11,8 +11,9 @@ mod fork;
 pub mod job_control;
 mod streams;
 
+// TODO: Reintegrate this
 use self::command_not_found::command_not_found;
-use self::fork::{create_process_group, fork_pipe};
+use self::fork::fork_pipe;
 use self::job_control::{JobControl, ProcessState};
 use self::streams::{duplicate_streams, redir, redirect_streams};
 use super::{JobKind, Shell};
@@ -27,9 +28,8 @@ use std::fs::{File, OpenOptions};
 use std::io::{self, Error, Write};
 use std::iter;
 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
-use std::os::unix::process::CommandExt;
 use std::path::Path;
-use std::process::{self, exit, Command};
+use std::process::{self, exit};
 use sys;
 
 type RefinedItem = (RefinedJob, JobKind, Vec<Redirection>, Vec<Input>);
@@ -348,9 +348,9 @@ pub(crate) trait PipelineExecution {
     /// associated will be marked as an `&&`, `||`, `|`, or final job.
     fn generate_commands(&self, pipeline: &mut Pipeline) -> Result<Vec<RefinedItem>, i32>;
 
-    /// Waits for all of the children within a pipe to finish exuecting, returning the
+    /// Waits for all of the children of the assigned pgid to finish executing, returning the
     /// exit status of the last process in the queue.
-    fn wait(&mut self, children: Vec<u32>, commands: Vec<RefinedJob>) -> i32;
+    fn wait(&mut self, pgid: u32, commands: Vec<RefinedJob>) -> i32;
 
     /// Executes a `RefinedJob` that was created in the `generate_commands` method.
     ///
@@ -375,6 +375,15 @@ pub(crate) trait PipelineExecution {
         stdin: &Option<File>,
     ) -> i32;
 
+    fn exec_external(
+        &mut self,
+        name: &str,
+        args: &[&str],
+        stdout: &Option<File>,
+        stderr: &Option<File>,
+        stdin: &Option<File>,
+    ) -> i32;
+
     fn exec_function(
         &mut self,
         name: &str,
@@ -474,19 +483,16 @@ impl PipelineExecution for Shell {
                 } else if let Some(builtin) = job.builtin {
                     RefinedJob::builtin(builtin, job.args.drain().collect())
                 } else {
-                    let mut command = Command::new(job.args[0].clone());
-                    for arg in job.args.drain().skip(1) {
-                        command.arg(arg);
-                    }
-                    RefinedJob::External(command)
+                    RefinedJob::external(job.args[0].clone().into(), job.args.drain().collect())
                 }
             };
             results.push((refined, job.kind, outputs, inputs));
         }
+
         Ok(results)
     }
 
-    fn wait(&mut self, mut children: Vec<u32>, mut commands: Vec<RefinedJob>) -> i32 {
+    fn wait(&mut self, pgid: u32, commands: Vec<RefinedJob>) -> i32 {
         // TODO: Find a way to only do this when absolutely necessary.
         let as_string = commands
             .iter()
@@ -494,55 +500,24 @@ impl PipelineExecution for Shell {
             .collect::<Vec<String>>()
             .join(" | ");
 
-        // Each process in the pipe has the same PGID, which is the first process's PID.
-        let pgid = children[0];
-
-        // If the last process exits, we know that all processes should exit.
-        let last_pid = children[children.len() - 1];
-
         // Watch the foreground group, dropping all commands that exit as they exit.
-        self.watch_foreground(
-            pgid,
-            last_pid,
-            move || as_string,
-            move |pid| {
-                if let Some(id) = children.iter().position(|&x| x as i32 == pid) {
-                    commands.remove(id);
-                    children.remove(id);
-                }
-            },
-        )
+        self.watch_foreground(-(pgid as i32), &as_string)
     }
 
-    fn exec_job(&mut self, job: &mut RefinedJob, foreground: bool) -> i32 {
+    fn exec_job(&mut self, job: &mut RefinedJob, _foreground: bool) -> i32 {
         let short = job.short();
         let long = job.long();
         match *job {
-            RefinedJob::External(ref mut command) => match {
-                command
-                    .before_exec(move || {
-                        signals::unblock();
-                        create_process_group(0);
-                        Ok(())
-                    })
-                    .spawn()
-            } {
-                Ok(child) => {
-                    if foreground && !self.is_library {
-                        let _ = sys::tcsetpgrp(0, child.id());
-                    }
-                    self.watch_foreground(child.id(), child.id(), move || long, |_| ())
-                }
-                Err(e) => if e.kind() == io::ErrorKind::NotFound {
-                    if !command_not_found(self, &short) {
-                        eprintln!("ion: command not found: {}", short);
-                    }
-                    NO_SUCH_COMMAND
-                } else {
-                    eprintln!("ion: error spawning process: {}", e);
-                    COULD_NOT_EXEC
-                },
-            },
+            RefinedJob::External {
+                ref name,
+                ref args,
+                ref stdin,
+                ref stdout,
+                ref stderr,
+            } => {
+                let args: Vec<&str> = args.iter().skip(1).map(|x| x as &str).collect();
+                return self.exec_external(&name, &args, stdin, stdout, stderr);
+            }
             RefinedJob::Builtin {
                 main,
                 ref args,
@@ -727,29 +702,67 @@ impl PipelineExecution for Shell {
             SUCCESS
         }
     }
+
+    fn exec_external(
+        &mut self,
+        name: &str,
+        args: &[&str],
+        stdin: &Option<File>,
+        stdout: &Option<File>,
+        stderr: &Option<File>,
+    ) -> i32 {
+        return match unsafe { sys::fork() } {
+            Ok(0) => {
+                if let Some(ref file) = *stdin {
+                    redir(file.as_raw_fd(), sys::STDIN_FILENO);
+                    let _ = sys::close(file.as_raw_fd());
+                }
+
+                if let Some(ref file) = *stdout {
+                    redir(file.as_raw_fd(), sys::STDOUT_FILENO);
+                    let _ = sys::close(file.as_raw_fd());
+                }
+
+                if let Some(ref file) = *stderr {
+                    redir(file.as_raw_fd(), sys::STDERR_FILENO);
+                    let _ = sys::close(file.as_raw_fd());
+                }
+
+                prepare_child(false);
+                if let Err(_why) = sys::execve(name, &args, false) {
+                    command_not_found(self, name);
+                    sys::fork_exit(NO_SUCH_COMMAND);
+                }
+                unreachable!()
+            },
+            Ok(pid) => {
+                close(stdin);
+                close(stdout);
+                close(stderr);
+                // TODO: get long string
+                self.watch_foreground(pid as i32, "")
+            }
+            Err(why) => {
+                eprintln!("ion: failed to fork: {}", why);
+                COULD_NOT_EXEC
+            }
+        }
+    }
 }
 
+/// Executes a piped job `job1 | job2 | job3`
+///
 /// This function will panic if called with an empty slice
 pub(crate) fn pipe(
     shell: &mut Shell,
     commands: Vec<(RefinedJob, JobKind)>,
     foreground: bool,
 ) -> i32 {
-    fn close(file: &Option<File>) {
-        if let &Some(ref file) = file {
-            if let Err(e) = sys::close(file.as_raw_fd()) {
-                eprintln!("ion: failed to close file '{:?}': {}", file, e);
-            }
-        }
-    }
-
     let mut previous_status = SUCCESS;
     let mut previous_kind = JobKind::And;
-    let mut commands = commands.into_iter();
-    // A vector to hold possible external command stdout/stderr pipes.
-    // If it is Some, then we close the various file descriptors after
-    // spawning a child job.
-    let mut ext_stdio: Option<Vec<RawFd>> = None;
+    let mut commands = commands.into_iter().peekable();
+    let mut possible_external_stdio_pipes: Option<Vec<File>> = None;
+
     loop {
         if let Some((mut parent, mut kind)) = commands.next() {
             // When an `&&` or `||` operator is utilized, execute commands based on the
@@ -774,219 +787,21 @@ pub(crate) fn pipe(
                 JobKind::Pipe(mut mode) => {
                     // We need to remember the commands as they own the file
                     // descriptors that are created by sys::pipe.
-                    // We purposfully drop the pipes that are owned by a given
-                    // command in `wait` in order to close those pipes, sending
-                    // EOF to the next command
                     let mut remember = Vec::new();
-                    // A list of the PIDs in the piped command
-                    let mut children: Vec<u32> = Vec::new();
-                    // The process group by which all of the PIDs belong to.
-                    let mut pgid = 0; // 0 means the PGID is not set yet.
-
-                    macro_rules! spawn_proc {
-                        ($cmd:expr) => {
-                            let short = $cmd.short();
-                            match $cmd {
-                                RefinedJob::External(ref mut command) => {
-                                    match {
-                                        command.before_exec(move || {
-                                            signals::unblock();
-                                            create_process_group(pgid);
-                                            Ok(())
-                                        }).spawn()
-                                    } {
-                                        Ok(child) => {
-                                            if pgid == 0 {
-                                                pgid = child.id();
-                                                if foreground && !shell.is_library {
-                                                    let _ = sys::tcsetpgrp(0, pgid);
-                                                }
-                                            }
-                                            shell.foreground.push(child.id());
-                                            children.push(child.id());
-                                        },
-                                        Err(e) => {
-                                            return if e.kind() == io::ErrorKind::NotFound {
-                                                if !command_not_found(shell, &short) {
-                                                    eprintln!("ion: command not found: {}", short);
-                                                }
-                                                NO_SUCH_COMMAND
-                                            } else {
-                                                eprintln!("ion: error spawning process: {}", e);
-                                                COULD_NOT_EXEC
-                                            }
-                                        }
-                                    }
-                                }
-                                RefinedJob::Builtin { main,
-                                                      ref args,
-                                                      ref stdout,
-                                                      ref stderr,
-                                                      ref stdin, } =>
-                                {
-                                    match unsafe { sys::fork() } {
-                                        Ok(0) => {
-                                            signals::unblock();
-                                            let _ = sys::reset_signal(sys::SIGINT);
-                                            let _ = sys::reset_signal(sys::SIGHUP);
-                                            let _ = sys::reset_signal(sys::SIGTERM);
-                                            create_process_group(pgid);
-                                            let args: Vec<&str> = args
-                                                .iter()
-                                                .map(|x| x as &str).collect();
-                                            let ret = shell.exec_builtin(main,
-                                                              &args,
-                                                              stdout,
-                                                              stderr,
-                                                              stdin);
-                                            close(stdout);
-                                            close(stderr);
-                                            close(stdin);
-                                            exit(ret)
-                                        },
-                                        Ok(pid) => {
-                                            close(stdout);
-                                            close(stderr);
-                                            if pgid == 0 {
-                                                pgid = pid;
-                                                if foreground && !shell.is_library {
-                                                    let _ = sys::tcsetpgrp(0, pgid);
-                                                }
-                                            }
-                                            shell.foreground.push(pid);
-                                            children.push(pid);
-                                        },
-                                        Err(e) => {
-                                            eprintln!("ion: failed to fork {}: {}",
-                                                      short,
-                                                      e);
-                                        }
-                                    }
-                                }
-                                RefinedJob::Function { ref name,
-                                                      ref args,
-                                                      ref stdout,
-                                                      ref stderr,
-                                                      ref stdin, } =>
-                                {
-                                    match unsafe { sys::fork() } {
-                                        Ok(0) => {
-                                            // signals::unblock();
-                                            let _ = sys::reset_signal(sys::SIGINT);
-                                            let _ = sys::reset_signal(sys::SIGHUP);
-                                            let _ = sys::reset_signal(sys::SIGTERM);
-                                            create_process_group(pgid);
-                                            let args: Vec<&str> = args
-                                                .iter()
-                                                .map(|x| x as &str).collect();
-                                            let ret = shell.exec_function(name,
-                                                              &args,
-                                                              stdout,
-                                                              stderr,
-                                                              stdin);
-                                            close(stdout);
-                                            close(stderr);
-                                            close(stdin);
-                                            exit(ret)
-                                        },
-                                        Ok(pid) => {
-                                            close(stdout);
-                                            close(stderr);
-                                            if pgid == 0 {
-                                                pgid = pid;
-                                                if foreground && !shell.is_library {
-                                                    let _ = sys::tcsetpgrp(0, pgid);
-                                                }
-                                            }
-                                            shell.foreground.push(pid);
-                                            children.push(pid);
-                                        },
-                                        Err(e) => {
-                                            eprintln!("ion: failed to fork {}: {}",
-                                                      short,
-                                                      e);
-                                        }
-                                    }
-                                }
-                                RefinedJob::Cat { ref mut sources,
-                                                  ref stdout,
-                                                  ref mut stdin } => {
-                                    match unsafe { sys::fork() } {
-                                        Ok(0) => {
-                                            let _ = sys::reset_signal(sys::SIGINT);
-                                            let _ = sys::reset_signal(sys::SIGHUP);
-                                            let _ = sys::reset_signal(sys::SIGTERM);
-                                            create_process_group(pgid);
-                                            let ret = shell.exec_multi_in(
-                                                sources,
-                                                stdout,
-                                                stdin,
-                                            );
-                                            close(stdout);
-                                            close(stdin);
-                                            exit(ret);
-                                        }
-                                        Ok(pid) => {
-                                            close(stdout);
-                                            if pgid == 0 {
-                                                pgid = pid;
-                                                if foreground && !shell.is_library {
-                                                    let _ = sys::tcsetpgrp(0, pgid);
-                                                }
-                                            }
-                                            shell.foreground.push(pid);
-                                            children.push(pid);
-                                        }
-                                        Err(e) => eprintln!("ion: failed to fork {}: {}", short, e),
-                                    }
-                                },
-                                RefinedJob::Tee { ref mut items,
-                                                  ref stdout,
-                                                  ref stderr,
-                                                  ref stdin } => {
-                                    match unsafe { sys::fork() } {
-                                        Ok(0) => {
-                                            let _ = sys::reset_signal(sys::SIGINT);
-                                            let _ = sys::reset_signal(sys::SIGHUP);
-                                            let _ = sys::reset_signal(sys::SIGTERM);
-                                            create_process_group(pgid);
-                                            let ret = shell.exec_multi_out(
-                                                items,
-                                                stdout,
-                                                stderr,
-                                                stdin,
-                                                kind,
-                                            );
-                                            close(stdout);
-                                            close(stderr);
-                                            close(stdin);
-                                            exit(ret);
-                                        },
-                                        Ok(pid) => {
-                                            close(stdout);
-                                            close(stderr);
-                                            if pgid == 0 {
-                                                pgid = pid;
-                                                if foreground && !shell.is_library {
-                                                    let _ = sys::tcsetpgrp(0, pgid);
-                                                }
-                                            }
-                                            shell.foreground.push(pid);
-                                            children.push(pid);
-                                        }
-                                        Err(e) => eprintln!("ion: failed to fork {}: {}", short, e),
-                                    }
-                                }
-                            }
-                        };
-                    }
 
-                    // Append other jobs until all piped jobs are running
+                    let mut pgid = 0;
+                    let mut last_pid = 0;
+                    let mut current_pid = 0;
+
+                    // When set to true, this command will be SIGSTOP'd  before it executes.
+                    let mut child_blocked;
+
+                    // Append jobs until all piped jobs are running
                     while let Some((mut child, ckind)) = commands.next() {
                         // If parent is a RefindJob::External, then we need to keep track of the
                         // output pipes, so we can properly close them after the job has been
                         // spawned.
-                        let is_external = if let RefinedJob::External(..) = parent {
+                        let is_external = if let RefinedJob::External { .. } = parent {
                             true
                         } else {
                             false
@@ -1006,7 +821,7 @@ pub(crate) fn pipe(
                                         Some(unsafe { File::from_raw_fd(out_reader) });
                                     parent.stdout(unsafe { File::from_raw_fd(out_writer) });
                                     if is_external {
-                                        ext_stdio.get_or_insert(vec![]).push(out_writer);
+                                        possible_external_stdio_pipes.get_or_insert(vec![]).push(unsafe { File::from_raw_fd(out_writer) });
                                     }
                                 }
                             }
@@ -1017,7 +832,7 @@ pub(crate) fn pipe(
                                         Some(unsafe { File::from_raw_fd(err_reader) });
                                     parent.stderr(unsafe { File::from_raw_fd(err_writer) });
                                     if is_external {
-                                        ext_stdio.get_or_insert(vec![]).push(err_writer);
+                                        possible_external_stdio_pipes.get_or_insert(vec![]).push(unsafe { File::from_raw_fd(err_writer) });
                                     }
                                 }
                             }
@@ -1028,7 +843,7 @@ pub(crate) fn pipe(
                                 }
                                 Ok((reader, writer)) => {
                                     if is_external {
-                                        ext_stdio.get_or_insert(vec![]).push(writer);
+                                        possible_external_stdio_pipes.get_or_insert(vec![]).push(unsafe { File::from_raw_fd(writer) });
                                     }
                                     child.stdin(unsafe { File::from_raw_fd(reader) });
                                     match mode {
@@ -1062,15 +877,26 @@ pub(crate) fn pipe(
                                 }
                             }
                         }
-                        spawn_proc!(parent);
-                        remember.push(parent);
-                        if let Some(fds) = ext_stdio.take() {
-                            for fd in fds {
-                                if let Err(e) = sys::close(fd) {
-                                    eprintln!("ion: failed to close file '{:?}': {}", fd, e);
-                                }
-                            }
+
+                        child_blocked = match ckind {
+                            JobKind::Pipe(_) | JobKind::Last => true,
+                            _ => false
+                        };
+
+                        match spawn_proc(shell, parent, kind, child_blocked, &mut last_pid, &mut current_pid) {
+                            SUCCESS => (),
+                            error_code => return error_code
+                        }
+
+                        // remember.push(parent);
+                        possible_external_stdio_pipes = None;
+
+                        if set_process_group(&mut pgid, current_pid) && foreground && !shell.is_library {
+                            let _ = sys::tcsetpgrp(0, pgid);
                         }
+
+                        resume_prior_process(&mut last_pid, current_pid, child_blocked);
+
                         if let JobKind::Pipe(m) = ckind {
                             parent = child;
                             mode = m;
@@ -1081,15 +907,32 @@ pub(crate) fn pipe(
                             // previous kind set to `And` after processing the
                             // initial pipeline
                             kind = ckind;
-                            spawn_proc!(child);
-                            remember.push(child);
+
+                            child_blocked = match commands.peek() {
+                                Some(&(_, JobKind::Pipe(_))) => true,
+                                Some(&(_, JobKind::Last)) => true,
+                                _ => false
+                            };
+
+                            match spawn_proc(shell, child, kind, child_blocked, &mut last_pid, &mut current_pid) {
+                                SUCCESS => (),
+                                error_code => return error_code
+                            }
+
+                            set_process_group(&mut pgid, current_pid) && foreground && !shell.is_library;
+
+                            // remember.push(child);
+                            resume_prior_process(&mut last_pid, current_pid, child_blocked);
+
                             break;
                         }
                     }
                     previous_kind = kind;
-                    previous_status = shell.wait(children, remember);
+                    previous_status = shell.wait(pgid, remember);
                     if previous_status == TERMINATED {
-                        shell.foreground_send(sys::SIGTERM);
+                        if let Err(why) = sys::killpg(pgid, sys::SIGTERM) {
+                            eprintln!("ion: failed to terminate foreground jobs: {}", why);
+                        }
                         return previous_status;
                     }
                 }
@@ -1104,3 +947,182 @@ pub(crate) fn pipe(
     }
     previous_status
 }
+
+fn spawn_proc(
+    shell: &mut Shell,
+    mut cmd: RefinedJob,
+    kind: JobKind,
+    child_blocked: bool,
+    last_pid: &mut u32,
+    current_pid: &mut u32
+) -> i32 {
+    let short = cmd.short();
+    match cmd {
+        RefinedJob::External { ref name, ref args, ref stdout, ref stderr, ref stdin} => {
+            let args: Vec<&str> = args.iter().skip(1).map(|x| x as &str).collect();
+            match unsafe { sys::fork() } {
+                Ok(0) => {
+                    if let Some(ref file) = *stdin {
+                        redir(file.as_raw_fd(), sys::STDIN_FILENO);
+                        let _ = sys::close(file.as_raw_fd());
+                    }
+                    if let Some(ref file) = *stdout {
+                        redir(file.as_raw_fd(), sys::STDOUT_FILENO);
+                        let _ = sys::close(file.as_raw_fd());
+                    }
+                    if let Some(ref file) = *stderr {
+                        redir(file.as_raw_fd(), sys::STDERR_FILENO);
+                        let _ = sys::close(file.as_raw_fd());
+                    }
+
+                    prepare_child(child_blocked);
+                    if let Err(_why) = sys::execve(&name, &args, false) {
+                        command_not_found(shell, name);
+                        sys::fork_exit(NO_SUCH_COMMAND);
+                    }
+                },
+                Ok(pid) => {
+                    close(stdin);
+                    close(stdout);
+                    close(stderr);
+                    shell.foreground.push(pid);
+                    *last_pid = *current_pid;
+                    *current_pid = pid;
+                },
+                Err(e) => {
+                    eprintln!("ion: failed to fork {}: {}", short, e);
+                }
+            }
+        }
+        RefinedJob::Builtin { main, ref args, ref stdout, ref stderr, ref stdin } => {
+            let args: Vec<&str> = args.iter().map(|x| x as &str).collect();
+            match unsafe { sys::fork() } {
+                Ok(0) => {
+                    prepare_child(child_blocked);
+                    let ret = shell.exec_builtin(main, &args, stdout, stderr, stdin);
+                    close(stdout);
+                    close(stderr);
+                    close(stdin);
+                    exit(ret)
+                },
+                Ok(pid) => {
+                    close(stdout);
+                    close(stderr);
+                    shell.foreground.push(pid);
+                    *last_pid = *current_pid;
+                    *current_pid = pid;
+                },
+                Err(e) => {
+                    eprintln!("ion: failed to fork {}: {}", short, e);
+                }
+            }
+        }
+        RefinedJob::Function { ref name, ref args, ref stdout, ref stderr, ref stdin, } => {
+            let args: Vec<&str> = args.iter().map(|x| x as &str).collect();
+            match unsafe { sys::fork() } {
+                Ok(0) => {
+                    prepare_child(child_blocked);
+                    let ret = shell.exec_function(name, &args, stdout, stderr, stdin);
+                    close(stdout);
+                    close(stderr);
+                    close(stdin);
+                    exit(ret)
+                },
+                Ok(pid) => {
+                    close(stdout);
+                    close(stderr);
+                    shell.foreground.push(pid);
+                    *last_pid = *current_pid;
+                    *current_pid = pid;
+                },
+                Err(e) => {
+                    eprintln!("ion: failed to fork {}: {}", short, e);
+                }
+            }
+        }
+        RefinedJob::Cat { ref mut sources, ref stdout, ref mut stdin } => {
+            match unsafe { sys::fork() } {
+                Ok(0) => {
+                    prepare_child(child_blocked);
+
+                    let ret = shell.exec_multi_in(sources, stdout, stdin);
+                    close(stdout);
+                    close(stdin);
+                    exit(ret);
+                }
+                Ok(pid) => {
+                    close(stdout);
+                    shell.foreground.push(pid);
+                    *last_pid = *current_pid;
+                    *current_pid = pid;
+                }
+                Err(e) => eprintln!("ion: failed to fork {}: {}", short, e),
+            }
+        },
+        RefinedJob::Tee { ref mut items, ref stdout, ref stderr, ref stdin } => {
+            match unsafe { sys::fork() } {
+                Ok(0) => {
+                    prepare_child(child_blocked);
+
+                    let ret = shell.exec_multi_out(items, stdout, stderr, stdin, kind);
+                    close(stdout);
+                    close(stderr);
+                    close(stdin);
+                    exit(ret);
+                },
+                Ok(pid) => {
+                    close(stdout);
+                    close(stderr);
+                    shell.foreground.push(pid);
+                    *last_pid = *current_pid;
+                    *current_pid = pid;
+                }
+                Err(e) => eprintln!("ion: failed to fork {}: {}", short, e),
+            }
+        }
+    }
+    SUCCESS
+}
+
+// TODO: Don't require this.
+fn close(file: &Option<File>) {
+    if let &Some(ref file) = file {
+        if let Err(e) = sys::close(file.as_raw_fd()) {
+            eprintln!("ion: failed to close file '{:?}': {}", file, e);
+        }
+    }
+}
+
+fn prepare_child(child_blocked: bool) {
+    signals::unblock();
+    let _ = sys::reset_signal(sys::SIGINT);
+    let _ = sys::reset_signal(sys::SIGHUP);
+    let _ = sys::reset_signal(sys::SIGTERM);
+
+    if child_blocked {
+        let _ = sys::kill(process::id(), sys::SIGSTOP);
+    } else {
+    }
+}
+
+fn resume_prior_process(last_pid: &mut u32, current_pid: u32, child_blocked: bool) {
+    if child_blocked {
+        // Ensure that the process is stopped before continuing.
+        if let Err(why) = sys::wait_for_interrupt(current_pid) {
+            eprintln!("ion: error waiting for sigstop: {}", why);
+        }
+    }
+
+    if *last_pid != 0 {
+        let _ = sys::kill(*last_pid, sys::SIGCONT);
+    }
+
+    *last_pid = current_pid;
+}
+
+fn set_process_group(pgid: &mut u32, pid: u32) -> bool {
+    let pgid_set = *pgid == 0;
+    if pgid_set { *pgid = pid; }
+    let _ = sys::setpgid(pid, *pgid);
+    pgid_set
+}
\ No newline at end of file
diff --git a/src/lib/shell/plugins/library_iter/mod.rs b/src/lib/shell/plugins/library_iter/mod.rs
index 286d5815aedba6635c57f138c25635754fa83cdc..2c5a0f74d3e884913d0250e0c67399ad9e3c0317 100644
--- a/src/lib/shell/plugins/library_iter/mod.rs
+++ b/src/lib/shell/plugins/library_iter/mod.rs
@@ -1,7 +1,7 @@
 #[cfg(target_os = "redox")]
 mod redox;
-#[cfg(target_os = "redox")]
-pub(crate) use self::redox::*;
+// #[cfg(target_os = "redox")]
+// pub(crate) use self::redox::*;
 
 #[cfg(all(unix, not(target_os = "redox")))]
 mod unix;
diff --git a/src/lib/shell/plugins/mod.rs b/src/lib/shell/plugins/mod.rs
index 527d0f44d6e3b954b24ba1505f9935b87cb04ddf..d792595cd5d4caa4cb2a52dd2dcc4ab5c4fdb155 100644
--- a/src/lib/shell/plugins/mod.rs
+++ b/src/lib/shell/plugins/mod.rs
@@ -3,6 +3,7 @@ pub mod namespaces;
 mod library_iter;
 mod string;
 
+#[cfg(not(target_os = "redox"))]
 pub(crate) use self::library_iter::*;
 pub(crate) use self::string::StringError;
 
diff --git a/src/lib/sys/redox.rs b/src/lib/sys/redox.rs
index d39c574c9bd7959dcc27919aaa63d55ef2f1a398..1b19fd5ace7a561e22768f88468cf5cb013a68e8 100644
--- a/src/lib/sys/redox.rs
+++ b/src/lib/sys/redox.rs
@@ -5,9 +5,9 @@ use std::env;
 use std::os::unix::ffi::OsStrExt;
 use std::os::unix::io::RawFd;
 use std::path::PathBuf;
-use std::process::exit;
-
-use syscall::SigAction;
+use std::process::{exit, ExitStatus};
+use std::os::unix::process::ExitStatusExt;
+use syscall::{EINTR, SigAction, waitpid};
 
 pub(crate) const PATH_SEPARATOR: &str = ";";
 pub(crate) const NULL_PATH: &str = "null:";
@@ -19,6 +19,7 @@ pub(crate) const SIGTERM: i32 = syscall::SIGTERM as i32;
 pub(crate) const SIGCONT: i32 = syscall::SIGCONT as i32;
 pub(crate) const SIGSTOP: i32 = syscall::SIGSTOP as i32;
 pub(crate) const SIGTSTP: i32 = syscall::SIGTSTP as i32;
+pub(crate) const SIGPIPE: i32 = syscall::SIGPIPE as i32;
 
 pub(crate) const STDIN_FILENO: RawFd = 0;
 pub(crate) const STDOUT_FILENO: RawFd = 1;
@@ -34,21 +35,33 @@ pub unsafe fn fork() -> io::Result<u32> { cvt(syscall::clone(0)).map(|pid| pid a
 
 pub fn fork_exit(status: i32) -> ! { exit(status) }
 
+pub fn wait_for_interrupt(pid: u32) -> io::Result<()> {
+    let mut status = 0;
+
+    loop {
+        match waitpid(pid as usize, &mut status, 0) {
+            Err(ref error) if error.errno == EINTR => continue,
+            Err(ref error) => break Err(io::Error::from_raw_os_error(error.errno)),
+            Ok(_) => break Ok(()),
+        }
+    }
+}
+
 pub fn wait_for_child(pid: u32) -> io::Result<u8> {
     let mut status;
     use syscall::{waitpid, ECHILD};
 
     loop {
         status = 0;
-        match unsafe { waitpid(pid as usize, &mut status, 0) } {
+        match waitpid(pid as usize, &mut status, 0) {
             Err(ref error) if error.errno == ECHILD => break,
             Err(error) => return Err(io::Error::from_raw_os_error(error.errno)),
             _ => ()
         }
     }
 
-    // Ok(WEXITSTATUS(status) as u8)
-    Ok(0)
+    let status = ExitStatus::from_raw(status as i32);
+    Ok(status.code().unwrap_or(0) as u8)
 }
 
 pub(crate) fn getpid() -> io::Result<u32> { cvt(syscall::getpid()).map(|pid| pid as u32) }
@@ -192,11 +205,12 @@ pub mod job_control {
 
     use shell::Shell;
     use shell::foreground::ForegroundSignals;
-    use shell::status::{FAILURE, TERMINATED};
+    use shell::status::FAILURE;
     use std::os::unix::process::ExitStatusExt;
     use std::process::ExitStatus;
     use std::sync::{Arc, Mutex};
-    use syscall;
+    use syscall::{ECHILD, waitpid};
+    use super::{SIGINT, SIGPIPE};
 
     pub(crate) fn watch_background(
         _fg: Arc<ForegroundSignals>,
@@ -207,54 +221,62 @@ pub mod job_control {
         // TODO: Implement this using syscall::call::waitpid
     }
 
-    pub(crate) fn watch_foreground<F, D>(
-        shell: &mut Shell,
-        _pid: u32,
-        last_pid: u32,
-        _get_command: F,
-        mut drop_command: D,
-    ) -> i32
-    where
-        F: FnOnce() -> String,
-        D: FnMut(i32),
-    {
+    pub(crate) fn watch_foreground(shell: &mut Shell, pid: i32, command: &str ) -> i32 {
+        let mut signaled = 0;
         let mut exit_status = 0;
+        let mut status;
+
+        fn get_pid_value(pid: i32) -> usize {
+            if pid < 0 {
+                !(pid.abs() as usize)
+            } else {
+                pid as usize
+            }
+        }
+
         loop {
-            let mut status_raw = 0;
-            match syscall::waitpid(0, &mut status_raw, 0) {
+            status = 0;
+            let result = waitpid(get_pid_value(pid), &mut status, 0);
+            match result {
+                Err(error) => {
+                    match error.errno {
+                        ECHILD if signaled == 0 => break exit_status,
+                        ECHILD => break signaled,
+                        _ => {
+                            eprintln!("ion: waitpid error: {}", error);
+                            break FAILURE;
+                        }
+                    }
+                }
+                Ok(0) => (),
                 Ok(pid) => {
-                    let status = ExitStatus::from_raw(status_raw as i32);
-                    if let Some(code) = status.code() {
-                        if pid == (last_pid as usize) {
-                            break code;
-                        } else {
-                            drop_command(pid as i32);
-                            exit_status = code;
+                    let es = ExitStatus::from_raw(status as i32);
+                    match es.signal() {
+                        Some(SIGPIPE) => continue,
+                        Some(signal) => {
+                            eprintln!("ion: process ended by signal {}", signal);
+                            match signal {
+                                SIGINT => {
+                                    shell.foreground_send(signal as i32);
+                                    shell.break_flow = true;
+                                }
+                                _ => {
+                                    shell.handle_signal(signal);
+                                }
+                            }
+                            signaled = 128 + signal as i32;
                         }
-                    } else if let Some(signal) = status.signal() {
-                        eprintln!("ion: process ended by signal: {}", signal);
-                        if signal == syscall::SIGTERM as i32 {
-                            shell.handle_signal(signal);
-                            shell.exit(TERMINATED);
-                        } else if signal == syscall::SIGHUP as i32 {
-                            shell.handle_signal(signal);
-                            shell.exit(TERMINATED);
-                        } else if signal == syscall::SIGINT as i32 {
-                            shell.foreground_send(signal);
-                            shell.break_flow = true;
+                        None => {
+                            exit_status = es.code().unwrap();
                         }
-                        break TERMINATED;
-                    } else {
-                        eprintln!("ion: process ended with unknown status: {}", status);
-                        break TERMINATED;
                     }
                 }
-                Err(err) => if err.errno == syscall::ECHILD {
-                    break exit_status;
-                } else {
-                    eprintln!("ion: process doesn't exist: {}", err);
-                    break FAILURE;
-                },
+                // TODO: Background job control for Redox
+                // _pid if WIFSTOPPED(status) => {
+                //     shell.send_to_background(pid as u32, ProcessState::Stopped, command.into());
+                //     shell.break_flow = true;
+                //     break 128 + signal as i32;
+                // }
             }
         }
     }
diff --git a/src/lib/sys/unix/job_control.rs b/src/lib/sys/unix/job_control.rs
index 4e1c5995d9e7b35dec1e7435513597afad8d5205..fee78255e074f5ec1e6f32c1af70a85ceb7448bc 100644
--- a/src/lib/sys/unix/job_control.rs
+++ b/src/lib/sys/unix/job_control.rs
@@ -78,58 +78,34 @@ pub(crate) fn watch_background(
     }
 }
 
-const FIRST: u8 = 1;
-const LAST: u8 = 2;
-
-pub(crate) fn watch_foreground<F, D>(
-    shell: &mut Shell,
-    first_pid: u32,
-    last_pid: u32,
-    get_command: F,
-    mut drop_command: D,
-) -> i32
-where
-    F: FnOnce() -> String,
-    D: FnMut(i32),
-{
+pub(crate) fn watch_foreground(shell: &mut Shell, pid: i32, command: &str) -> i32 {
+    let mut signaled = 0;
     let mut exit_status = 0;
-    let mut found = 0;
+    let mut status;
+
     loop {
         unsafe {
-            let mut status = 0;
-            let pid = waitpid(-1, &mut status, WUNTRACED);
-            match pid {
+            status = 0;
+            match waitpid(pid, &mut status, WUNTRACED) {
                 -1 => {
                     let error = errno();
                     match error.0 {
-                        ECHILD => break exit_status,
+                        ECHILD if signaled == 0 => break exit_status,
+                        ECHILD => break signaled,
                         _ => {
-                            eprintln!("ion: {}", error);
+                            eprintln!("ion: waitpid error: {}", error);
                             break FAILURE;
                         }
                     }
                 }
                 0 => (),
-                _ if WIFEXITED(status) => {
-                    let status = WEXITSTATUS(status) as i32;
-                    if pid == (last_pid as i32) {
-                        found |= LAST;
-                    }
-
-                    if pid == (first_pid as i32) {
-                        found |= FIRST;
-                    }
-
-                    if found == FIRST + LAST {
-                        break status;
-                    } else {
-                        drop_command(pid);
-                        exit_status = status;
-                    }
+                _pid if WIFEXITED(status) => {
+                    exit_status = WEXITSTATUS(status) as i32;
                 }
-                _ if WIFSIGNALED(status) => {
-                    eprintln!("ion: process ended by signal");
+                _pid if WIFSIGNALED(status) => {
                     let signal = WTERMSIG(status);
+                    if signal == SIGPIPE { continue }
+                    eprintln!("ion: process ended by signal {}", signal);
                     match signal {
                         SIGINT => {
                             shell.foreground_send(signal as i32);
@@ -137,15 +113,15 @@ where
                         }
                         _ => {
                             shell.handle_signal(signal);
-                            shell.exit(TERMINATED);
                         }
                     }
-                    break TERMINATED;
+                    signaled = 128 + signal as i32;
                 }
-                _ if WIFSTOPPED(status) => {
-                    shell.send_to_background(pid as u32, ProcessState::Stopped, get_command());
+                _pid if WIFSTOPPED(status) => {
+                    // TODO: Rework background control
+                    shell.send_to_background(pid as u32, ProcessState::Stopped, command.into());
                     shell.break_flow = true;
-                    break TERMINATED;
+                    break 128 + signal as i32;
                 }
                 _ => (),
             }
diff --git a/src/lib/sys/unix/mod.rs b/src/lib/sys/unix/mod.rs
index 2d191fa88c6bb945b48b7abcbdcec97545b1c7bf..073abbc38b2b9fe538c644b947fa582f396dfcbf 100644
--- a/src/lib/sys/unix/mod.rs
+++ b/src/lib/sys/unix/mod.rs
@@ -3,7 +3,7 @@ extern crate libc;
 pub mod job_control;
 pub mod signals;
 
-use libc::{c_char, c_int, pid_t, sighandler_t};
+use libc::{c_char, c_int, pid_t, sighandler_t, waitpid, ECHILD, EINTR, WEXITSTATUS, WUNTRACED};
 use std::{io, ptr};
 use std::env;
 use std::ffi::CString;
@@ -19,6 +19,7 @@ pub(crate) const SIGTERM: i32 = libc::SIGTERM;
 pub(crate) const SIGCONT: i32 = libc::SIGCONT;
 pub(crate) const SIGSTOP: i32 = libc::SIGSTOP;
 pub(crate) const SIGTSTP: i32 = libc::SIGTSTP;
+pub(crate) const SIGPIPE: i32 = libc::SIGPIPE;
 
 pub(crate) const STDOUT_FILENO: i32 = libc::STDOUT_FILENO;
 pub(crate) const STDERR_FILENO: i32 = libc::STDERR_FILENO;
@@ -34,20 +35,35 @@ pub(crate) fn is_root() -> bool { unsafe { libc::geteuid() == 0 } }
 
 pub unsafe fn fork() -> io::Result<u32> { cvt(libc::fork()).map(|pid| pid as u32) }
 
+pub fn wait_for_interrupt(pid: u32) -> io::Result<()> {
+    let mut status = 0;
+    let mut result;
+
+    loop {
+        result = unsafe { waitpid(pid as i32, &mut status, WUNTRACED) };
+        if result == -1 {
+            if errno() == EINTR { continue }
+            break Err(io::Error::from_raw_os_error(errno()));
+        }
+        break Ok(());
+    }
+}
+
 pub fn wait_for_child(pid: u32) -> io::Result<u8> {
     let mut status;
-    use libc::{waitpid, ECHILD, WEXITSTATUS};
+    let mut result;
 
     loop {
         status = 0;
-        match unsafe { waitpid(pid as i32, &mut status, 0) } {
-            -1 if errno() == ECHILD => break,
-            -1 => return Err(io::Error::from_raw_os_error(errno())),
-            _ => ()
+        result = unsafe { waitpid(pid as i32, &mut status, WUNTRACED) };
+        if result == -1 {
+            break if errno() == ECHILD {
+                Ok(unsafe { WEXITSTATUS(status) as u8 })
+            } else {
+                Err(io::Error::from_raw_os_error(errno()))
+            };
         }
     }
-
-    Ok(unsafe { WEXITSTATUS(status) as u8 })
 }
 
 pub fn fork_exit(exit_status: i32) -> ! { unsafe { libc::_exit(exit_status) } }