diff --git a/src/lib/shell/job.rs b/src/lib/shell/job.rs
index 1a7fe26540163ff63b9bafbd79c962200c66dec7..e609af43b10467c11a2dc00cb0ecde47d567a701 100644
--- a/src/lib/shell/job.rs
+++ b/src/lib/shell/job.rs
@@ -71,43 +71,36 @@ fn expand_arg(arg: &str, shell: &Shell) -> types::Array {
 
 /// This represents a job that has been processed and expanded to be run
 /// as part of some pipeline
-pub(crate) enum RefinedJob {
+pub struct RefinedJob {
+    pub stdin:  Option<File>,
+    pub stdout: Option<File>,
+    pub stderr: Option<File>,
+    pub var:    JobVariant
+}
+
+pub enum JobVariant {
     /// An external program that is executed by this shell
     External {
-        name:   types::Str,
-        args:   types::Array,
-        stdin:  Option<File>,
-        stdout: Option<File>,
-        stderr: Option<File>,
+        name: types::Str,
+        args: types::Array
     },
     /// A procedure embedded into Ion
     Builtin {
-        main:   BuiltinFunction,
-        args:   types::Array,
-        stdin:  Option<File>,
-        stdout: Option<File>,
-        stderr: Option<File>,
+        main: BuiltinFunction,
+        args: types::Array,
     },
     /// Functions can act as commands too!
     Function {
-        name:   types::Str,
-        args:   types::Array,
-        stdin:  Option<File>,
-        stdout: Option<File>,
-        stderr: Option<File>,
+       name: types::Str,
+       args: types::Array,
     },
     /// Represents redirection into stdin from more than one source
     Cat {
         sources: Vec<File>,
-        stdin:   Option<File>,
-        stdout:  Option<File>,
     },
     Tee {
         /// 0 for stdout, 1 for stderr
         items: (Option<TeeItem>, Option<TeeItem>),
-        stdin: Option<File>,
-        stdout: Option<File>,
-        stderr: Option<File>,
     },
 }
 
@@ -177,138 +170,113 @@ impl TeeItem {
     }
 }
 
-macro_rules! set_field {
-    ($self:expr, $field:ident, $arg:expr) => {
-        match *$self {
-            RefinedJob::External { ref mut $field, .. }
-            | RefinedJob::Builtin { ref mut $field, .. }
-            | RefinedJob::Function { ref mut $field, .. }
-            | RefinedJob::Tee { ref mut $field, .. } => {
-                *$field = Some($arg);
-            }
-            // Do nothing for Cat
-            _ => {}
-        }
-    };
-}
-
 impl RefinedJob {
     /// Returns a long description of this job: the commands and arguments
     pub(crate) fn long(&self) -> String {
-        match *self {
-            RefinedJob::External { ref args, .. }
-            | RefinedJob::Builtin { ref args, .. }
-            | RefinedJob::Function { ref args, .. } => args.join(" ").to_owned(),
+        match self.var {
+            JobVariant::External { ref args, .. }
+            | JobVariant::Builtin { ref args, .. }
+            | JobVariant::Function { ref args, .. } => args.join(" ").to_owned(),
             // TODO: Figure out real printing
-            RefinedJob::Cat { .. } | RefinedJob::Tee { .. } => "".into(),
+            JobVariant::Cat { .. } | JobVariant::Tee { .. } => "".into(),
         }
     }
 
     /// Returns a short description of this job: often just the command
     /// or builtin name
     pub(crate) fn short(&self) -> String {
-        match *self {
-            RefinedJob::Builtin { .. } => String::from("Shell Builtin"),
-            RefinedJob::Function { ref name, .. } | RefinedJob::External { ref name, .. } => {
+        match self.var {
+            JobVariant::Builtin { .. } => String::from("Shell Builtin"),
+            JobVariant::Function { ref name, .. } | JobVariant::External { ref name, .. } => {
                 name.to_string()
             }
             // TODO: Print for real
-            RefinedJob::Cat { .. } => "multi-input".into(),
-            RefinedJob::Tee { .. } => "multi-output".into(),
+            JobVariant::Cat { .. } => "multi-input".into(),
+            JobVariant::Tee { .. } => "multi-output".into(),
         }
     }
 
     pub(crate) fn exec<S: PipelineExecution>(&self, shell: &mut S) -> i32 {
-        match *self {
-            RefinedJob::External {
+        let stdin = &self.stdin;
+        let stdout = &self.stdout;
+        let stderr = &self.stderr;
+        match self.var {
+            JobVariant::External {
                 ref name,
                 ref args,
-                ref stdin,
-                ref stdout,
-                ref stderr,
             } => shell.exec_external(&name, &args[1..], stdin, stdout, stderr),
-            RefinedJob::Builtin {
+            JobVariant::Builtin {
                 main,
                 ref args,
-                ref stdin,
-                ref stdout,
-                ref stderr,
             } => shell.exec_builtin(main, &**args, stdout, stderr, stdin),
-            RefinedJob::Function {
+            JobVariant::Function {
                 ref name,
                 ref args,
-                ref stdin,
-                ref stdout,
-                ref stderr,
             } => shell.exec_function(name, args, stdout, stderr, stdin),
             _ => panic!("exec job should not be able to be called on Cat or Tee jobs"),
         }
     }
 
     pub(crate) fn stderr(&mut self, file: File) {
-        set_field!(self, stderr, file);
+        if let JobVariant::Cat { .. } = self.var {
+            return;
+        }
+
+        self.stderr = Some(file);
     }
 
     pub(crate) fn stdout(&mut self, file: File) {
-        if let RefinedJob::Cat { ref mut stdout, .. } = *self {
-            *stdout = Some(file);
-        } else {
-            set_field!(self, stdout, file);
-        }
+        self.stdout = Some(file);
     }
 
     pub(crate) fn stdin(&mut self, file: File) {
-        if let &mut RefinedJob::Cat { ref mut stdin, .. } = self {
-            *stdin = Some(file);
-        } else {
-            set_field!(self, stdin, file);
-        }
+        self.stdin = Some(file);
     }
 
     pub(crate) fn tee(tee_out: Option<TeeItem>, tee_err: Option<TeeItem>) -> Self {
-        RefinedJob::Tee {
-            items:  (tee_out, tee_err),
+        RefinedJob {
             stdin:  None,
             stdout: None,
             stderr: None,
+            var: JobVariant::Tee {
+                items:  (tee_out, tee_err),
+            }
         }
     }
 
     pub(crate) fn cat(sources: Vec<File>) -> Self {
-        RefinedJob::Cat {
-            sources,
-            stdin: None,
+        RefinedJob {
+            stdin:  None,
             stdout: None,
+            stderr: None,
+            var: JobVariant::Cat { sources }
         }
     }
 
     pub(crate) fn function(name: types::Str, args: types::Array) -> Self {
-        RefinedJob::Function {
-            name,
-            args,
-            stdin: None,
+        RefinedJob {
+            stdin:  None,
             stdout: None,
             stderr: None,
+            var: JobVariant::Function { name, args }
         }
     }
 
     pub(crate) fn builtin(main: BuiltinFunction, args: types::Array) -> Self {
-        RefinedJob::Builtin {
-            main,
-            args,
-            stdin: None,
+        RefinedJob {
+            stdin:  None,
             stdout: None,
             stderr: None,
+            var: JobVariant::Builtin { main, args }
         }
     }
 
     pub(crate) fn external(name: types::Str, args: types::Array) -> Self {
-        RefinedJob::External {
-            name,
-            args,
-            stdin: None,
+        RefinedJob {
+            stdin:  None,
             stdout: None,
             stderr: None,
+            var: JobVariant::External { name, args }
         }
     }
 }
diff --git a/src/lib/shell/pipe_exec/mod.rs b/src/lib/shell/pipe_exec/mod.rs
index 1229519a006725267fed6afa2d0180e79201101e..d5d9dd3f23dc60ec492695d04d6f8ab64e74bdaf 100644
--- a/src/lib/shell/pipe_exec/mod.rs
+++ b/src/lib/shell/pipe_exec/mod.rs
@@ -9,6 +9,7 @@ pub mod foreground;
 mod fork;
 pub mod job_control;
 pub mod streams;
+mod pipes;
 
 use self::{
     fork::fork_pipe,
@@ -19,7 +20,7 @@ use super::{
     flags::*,
     flow_control::{Function, FunctionError},
     fork_function::command_not_found,
-    job::{RefinedJob, TeeItem},
+    job::{JobVariant, RefinedJob, TeeItem},
     signals::{self, SignalHandler},
     status::*,
     JobKind, Shell,
@@ -37,6 +38,7 @@ use std::{
     process::{self, exit},
 };
 use sys;
+use self::pipes::TeePipe;
 
 type RefinedItem = (RefinedJob, JobKind, Vec<Redirection>, Vec<Input>);
 
@@ -757,7 +759,7 @@ pub(crate) fn pipe(
 ) -> i32 {
     let mut previous_status = SUCCESS;
     let mut commands = commands.into_iter().peekable();
-    let mut possible_external_stdio_pipes: Option<Vec<File>> = None;
+    let mut ext_stdio_pipes: Option<Vec<File>> = None;
 
     loop {
         if let Some((mut parent, mut kind)) = commands.next() {
@@ -774,7 +776,7 @@ pub(crate) fn pipe(
                         // 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 JobVariant::External { .. } = parent.var {
                             true
                         } else {
                             false
@@ -783,59 +785,27 @@ pub(crate) fn pipe(
                         // TODO: Refactor this part
                         // If we need to tee both stdout and stderr, we directly connect pipes to
                         // the relevant sources in both of them.
-                        if let RefinedJob::Tee {
+                        if let JobVariant::Tee {
                             items: (Some(ref mut tee_out), Some(ref mut tee_err)),
                             ..
-                        } = child
-                        {
-                            match sys::pipe2(sys::O_CLOEXEC) {
-                                Err(e) => eprintln!("ion: failed to create pipe: {:?}", e),
-                                Ok((out_reader, out_writer)) => {
-                                    (*tee_out).source =
-                                        Some(unsafe { File::from_raw_fd(out_reader) });
-                                    parent.stdout(unsafe { File::from_raw_fd(out_writer) });
-                                    if is_external {
-                                        possible_external_stdio_pipes
-                                            .get_or_insert(vec![])
-                                            .push(unsafe { File::from_raw_fd(out_writer) });
-                                    }
-                                }
-                            }
-                            match sys::pipe2(sys::O_CLOEXEC) {
-                                Err(e) => eprintln!("ion: failed to create pipe: {:?}", e),
-                                Ok((err_reader, err_writer)) => {
-                                    (*tee_err).source =
-                                        Some(unsafe { File::from_raw_fd(err_reader) });
-                                    parent.stderr(unsafe { File::from_raw_fd(err_writer) });
-                                    if is_external {
-                                        possible_external_stdio_pipes
-                                            .get_or_insert(vec![])
-                                            .push(unsafe { File::from_raw_fd(err_writer) });
-                                    }
-                                }
-                            }
+                        } = child.var {
+                            TeePipe::new(&mut parent, &mut ext_stdio_pipes, is_external)
+                                .connect(tee_out, tee_err);
                         } else {
+                            // Pipe the previous command's stdin to this commands stdout/stderr.
                             match sys::pipe2(sys::O_CLOEXEC) {
-                                Err(e) => {
-                                    eprintln!("ion: failed to create pipe: {:?}", e);
-                                }
+                                Err(e) => pipe_fail(e),
                                 Ok((reader, writer)) => {
                                     if is_external {
-                                        possible_external_stdio_pipes
-                                            .get_or_insert(vec![])
-                                            .push(unsafe { File::from_raw_fd(writer) });
+                                        append_external_stdio_pipe(&mut ext_stdio_pipes, writer);
                                     }
                                     child.stdin(unsafe { File::from_raw_fd(reader) });
+                                    let writer = unsafe { File::from_raw_fd(writer) };
                                     match mode {
-                                        RedirectFrom::Stderr => {
-                                            parent.stderr(unsafe { File::from_raw_fd(writer) });
-                                        }
-                                        RedirectFrom::Stdout => {
-                                            parent.stdout(unsafe { File::from_raw_fd(writer) });
-                                        }
+                                        RedirectFrom::Stderr => parent.stderr(writer),
+                                        RedirectFrom::Stdout => parent.stdout(writer),
                                         RedirectFrom::Both => {
-                                            let temp = unsafe { File::from_raw_fd(writer) };
-                                            match temp.try_clone() {
+                                            match writer.try_clone() {
                                                 Err(e) => {
                                                     eprintln!(
                                                         "ion: failed to redirect stdout and \
@@ -844,7 +814,7 @@ pub(crate) fn pipe(
                                                     );
                                                 }
                                                 Ok(duped) => {
-                                                    parent.stderr(temp);
+                                                    parent.stderr(writer);
                                                     parent.stdout(duped);
                                                 }
                                             }
@@ -867,7 +837,7 @@ pub(crate) fn pipe(
                             error_code => return error_code,
                         }
 
-                        possible_external_stdio_pipes = None;
+                        ext_stdio_pipes = None;
 
                         if set_process_group(&mut pgid, current_pid)
                             && foreground
@@ -882,6 +852,8 @@ pub(crate) fn pipe(
                             parent = child;
                             mode = m;
                         } else {
+
+
                             kind = ckind;
                             block_child = false;
                             match spawn_proc(
@@ -905,8 +877,6 @@ pub(crate) fn pipe(
                     set_process_group(&mut pgid, current_pid);
 
                     previous_status = shell.wait(pgid, remember);
-                    let _ = io::stdout().flush();
-                    let _ = io::stderr().flush();
                     if previous_status == TERMINATED {
                         if let Err(why) = sys::killpg(pgid, sys::SIGTERM) {
                             eprintln!("ion: failed to terminate foreground jobs: {}", why);
@@ -916,14 +886,16 @@ pub(crate) fn pipe(
                 }
                 _ => {
                     previous_status = shell.exec_job(&mut parent, foreground);
-                    let _ = io::stdout().flush();
-                    let _ = io::stderr().flush();
                 }
             }
         } else {
             break;
         }
     }
+
+    let _ = io::stdout().flush();
+    let _ = io::stderr().flush();
+
     previous_status
 }
 
@@ -936,34 +908,18 @@ fn spawn_proc(
     current_pid: &mut u32,
     pgid: u32,
 ) -> i32 {
-    let short = cmd.short();
-    match cmd {
-        RefinedJob::External {
-            ref name,
-            ref args,
-            ref stdout,
-            ref stderr,
-            ref stdin,
-        } => {
+    let stdin = &mut cmd.stdin;
+    let stdout = &mut cmd.stdout;
+    let stderr = &mut cmd.stderr;
+    match cmd.var {
+        JobVariant::External { ref mut name, ref mut args } => {
             let args: Vec<&str> = args.iter().skip(1).map(|x| x as &str).collect();
-            let result = sys::fork_and_exec(
+            let mut result = sys::fork_and_exec(
                 name,
                 &args,
-                if let Some(ref f) = *stdin {
-                    Some(f.as_raw_fd())
-                } else {
-                    None
-                },
-                if let Some(ref f) = *stdout {
-                    Some(f.as_raw_fd())
-                } else {
-                    None
-                },
-                if let Some(ref f) = *stderr {
-                    Some(f.as_raw_fd())
-                } else {
-                    None
-                },
+                stdin.as_mut().map(|f| f.as_raw_fd()),
+                stdout.as_mut().map(|f| f.as_raw_fd()),
+                stderr.as_mut().map(|f| f.as_raw_fd()),
                 false,
                 || prepare_child(block_child, pgid),
             );
@@ -973,123 +929,97 @@ fn spawn_proc(
                     *last_pid = *current_pid;
                     *current_pid = pid;
                 }
-                Err(ref err) if err.kind() == io::ErrorKind::NotFound => {
+                Err(ref mut err) if err.kind() == io::ErrorKind::NotFound => {
                     if !command_not_found(shell, &name) {
                         eprintln!("ion: command not found: {}", name);
                     }
                 }
-                Err(ref err) => {
+                Err(ref mut err) => {
                     eprintln!("ion: command exec error: {}", err);
                 }
             }
         }
-        RefinedJob::Builtin {
-            main,
-            ref args,
-            ref stdout,
-            ref stderr,
-            ref stdin,
-        } => match unsafe { sys::fork() } {
-            Ok(0) => {
-                prepare_child(block_child, pgid);
-                let ret = shell.exec_builtin(main, args, stdout, stderr, stdin);
-                close(stdout);
-                close(stderr);
-                close(stdin);
-                exit(ret)
-            }
-            Ok(pid) => {
-                close(stdin);
-                close(stdout);
-                close(stderr);
-                *last_pid = *current_pid;
-                *current_pid = pid;
-            }
-            Err(e) => {
-                eprintln!("ion: failed to fork {}: {}", short, e);
-            }
+        JobVariant::Builtin { main, ref mut args } => {
+            fork_exec_internal(
+                stdout,
+                stderr,
+                stdin,
+                block_child,
+                last_pid,
+                current_pid,
+                pgid,
+                |stdout, stderr, stdin| shell.exec_builtin(main, args, stdout, stderr, stdin)
+            );
         },
-        RefinedJob::Function {
-            ref name,
-            ref args,
-            ref stdout,
-            ref stderr,
-            ref stdin,
-        } => match unsafe { sys::fork() } {
-            Ok(0) => {
-                prepare_child(block_child, pgid);
-                let ret = shell.exec_function(name, &args, stdout, stderr, stdin);
-                close(stdout);
-                close(stderr);
-                close(stdin);
-                exit(ret)
-            }
-            Ok(pid) => {
-                close(stdin);
-                close(stdout);
-                close(stderr);
-                *last_pid = *current_pid;
-                *current_pid = pid;
-            }
-            Err(e) => {
-                eprintln!("ion: failed to fork {}: {}", short, e);
-            }
+        JobVariant::Function { ref mut name, ref mut args } => {
+            fork_exec_internal(
+                stdout,
+                stderr,
+                stdin,
+                block_child,
+                last_pid,
+                current_pid,
+                pgid,
+                |stdout, stderr, stdin| shell.exec_function(name, &args, stdout, stderr, stdin)
+            );
         },
-        RefinedJob::Cat {
-            ref mut sources,
-            ref stdout,
-            ref mut stdin,
-        } => match unsafe { sys::fork() } {
-            Ok(0) => {
-                prepare_child(block_child, pgid);
-
-                let ret = shell.exec_multi_in(sources, stdout, stdin);
-                close(stdout);
-                close(stdin);
-                exit(ret);
-            }
-            Ok(pid) => {
-                close(stdin);
-                close(stdout);
-                *last_pid = *current_pid;
-                *current_pid = pid;
-            }
-            Err(e) => eprintln!("ion: failed to fork {}: {}", short, e),
+        JobVariant::Cat { ref mut sources } => {
+            fork_exec_internal(
+                stdout,
+                &mut None,
+                stdin,
+                block_child,
+                last_pid,
+                current_pid,
+                pgid,
+                |stdout, _, stdin| shell.exec_multi_in(sources, stdout, stdin)
+            );
         },
-        RefinedJob::Tee {
-            ref mut items,
-            ref stdout,
-            ref stderr,
-            ref stdin,
-        } => match unsafe { sys::fork() } {
-            Ok(0) => {
-                prepare_child(block_child, pgid);
-
-                let ret = shell.exec_multi_out(items, stdout, stderr, stdin, kind);
-                close(stdout);
-                close(stderr);
-                close(stdin);
-                exit(ret);
-            }
-            Ok(pid) => {
-                close(stdin);
-                close(stdout);
-                close(stderr);
-                *last_pid = *current_pid;
-                *current_pid = pid;
-            }
-            Err(e) => eprintln!("ion: failed to fork {}: {}", short, e),
+        JobVariant::Tee { ref mut items } => {
+            fork_exec_internal(
+                stdout,
+                stderr,
+                stdin,
+                block_child,
+                last_pid,
+                current_pid,
+                pgid,
+                |stdout, stderr, stdin| shell.exec_multi_out(items, stdout, stderr, stdin, kind)
+            );
         },
     }
     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);
+// TODO: Integrate this better within the RefinedJob type.
+fn fork_exec_internal<F>(
+    stdout: &mut Option<File>,
+    stderr: &mut Option<File>,
+    stdin: &mut Option<File>,
+    block_child: bool,
+    last_pid: &mut u32,
+    current_pid: &mut u32,
+    pgid: u32,
+    mut exec_action: F,
+) where F: FnMut(&mut Option<File>, &mut Option<File>, &mut Option<File>) -> i32 {
+    match unsafe { sys::fork() } {
+        Ok(0) => {
+            prepare_child(block_child, pgid);
+
+            let exit_status = exec_action(stdout, stderr, stdin);
+            stdout.take();
+            stderr.take();
+            stdin.take();
+            exit(exit_status)
+        }
+        Ok(pid) => {
+            stdin.take();
+            stdout.take();
+            stderr.take();
+            *last_pid = *current_pid;
+            *current_pid = pid;
         }
+        Err(e) => pipe_fail(e)
     }
 }
 
@@ -1139,3 +1069,11 @@ pub fn wait_for_interrupt(pid: u32) -> io::Result<()> {
         }
     }
 }
+
+pub fn pipe_fail(why: io::Error) {
+    eprintln!("ion: failed to create pipe: {:?}", why);
+}
+
+pub fn append_external_stdio_pipe(pipes: &mut Option<Vec<File>>, file: RawFd) {
+    pipes.get_or_insert_with(|| Vec::with_capacity(4)).push(unsafe { File::from_raw_fd(file) });
+}
diff --git a/src/lib/shell/pipe_exec/pipes.rs b/src/lib/shell/pipe_exec/pipes.rs
new file mode 100644
index 0000000000000000000000000000000000000000..59e22fa6c040dc44926d7abbfaf09fda467a4a8b
--- /dev/null
+++ b/src/lib/shell/pipe_exec/pipes.rs
@@ -0,0 +1,49 @@
+
+use super::{
+    append_external_stdio_pipe,
+    pipe_fail,
+};
+use super::super::job::{RefinedJob, TeeItem};
+
+use std::{
+    fs::File,
+    io,
+    os::unix::io::FromRawFd,
+};
+use sys;
+
+pub(crate) struct TeePipe<'a> {
+    parent:          &'a mut RefinedJob,
+    ext_stdio_pipes: &'a mut Option<Vec<File>>,
+    is_external:     bool
+}
+
+impl<'a> TeePipe<'a> {
+    pub(crate) fn new(
+        parent:          &'a mut RefinedJob,
+        ext_stdio_pipes: &'a mut Option<Vec<File>>,
+        is_external:     bool
+    ) -> TeePipe<'a> {
+        TeePipe { parent, ext_stdio_pipes, is_external }
+    }
+
+    fn inner_connect<F>(&mut self, tee: &mut TeeItem, mut action: F)
+        where F: FnMut(&mut RefinedJob, File)
+    {
+        match sys::pipe2(sys::O_CLOEXEC) {
+            Err(e) => pipe_fail(e),
+            Ok((reader, writer)) => {
+                (*tee).source = Some(unsafe { File::from_raw_fd(reader) });
+                action(self.parent, unsafe { File::from_raw_fd(writer) });
+                if self.is_external {
+                    append_external_stdio_pipe(self.ext_stdio_pipes, writer);
+                }
+            }
+        }
+    }
+
+    pub(crate) fn connect(&mut self, out: &mut TeeItem, err: &mut TeeItem) {
+        self.inner_connect(out, |parent, writer| parent.stdout(writer));
+        self.inner_connect(err, |parent, writer| parent.stderr(writer));
+    }
+}