diff --git a/src/lib/shell/job.rs b/src/lib/shell/job.rs
index a08d86ad1c0bc781b5b05db633aa2d2e010f1ec7..a822004fdcb8183cfb46c0c9e4c5a7a38e07b1f8 100644
--- a/src/lib/shell/job.rs
+++ b/src/lib/shell/job.rs
@@ -67,16 +67,17 @@ pub struct RefinedJob<'a> {
     pub stdin:  Option<File>,
     pub stdout: Option<File>,
     pub stderr: Option<File>,
+    pub args:   types::Args,
     pub var:    JobVariant<'a>,
 }
 
 pub enum JobVariant<'a> {
     /// An external program that is executed by this shell
-    External { args: types::Args },
+    External,
     /// A procedure embedded into Ion
-    Builtin { main: BuiltinFunction<'a>, args: types::Args },
+    Builtin { main: BuiltinFunction<'a> },
     /// Functions can act as commands too!
-    Function { args: types::Args },
+    Function,
     /// Represents redirection into stdin from more than one source
     Cat { sources: Vec<File> },
     Tee {
@@ -151,15 +152,11 @@ impl TeeItem {
 
 impl<'a> RefinedJob<'a> {
     /// Returns a long description of this job: the commands and arguments
-    pub fn long(&self) -> String {
-        match self.var {
-            JobVariant::External { ref args, .. }
-            | JobVariant::Builtin { ref args, .. }
-            | JobVariant::Function { ref args, .. } => args.join(" ").to_owned(),
-            // TODO: Figure out real printing
-            JobVariant::Cat { .. } | JobVariant::Tee { .. } => "".into(),
-        }
-    }
+    pub fn long(&self) -> String { self.args.join(" ") }
+
+    pub fn command(&self) -> &types::Str { &self.args[0] }
+
+    pub fn args(&self) -> &types::Args { &self.args }
 
     pub fn stderr(&mut self, file: File) {
         if let JobVariant::Cat { .. } = self.var {
@@ -169,6 +166,13 @@ impl<'a> RefinedJob<'a> {
         self.stderr = Some(file);
     }
 
+    pub fn needs_forking(&self) -> bool {
+        match self.var {
+            JobVariant::Function | JobVariant::Builtin { .. } => false,
+            _ => true,
+        }
+    }
+
     pub fn stdout(&mut self, file: File) { self.stdout = Some(file); }
 
     pub fn stdin(&mut self, file: File) { self.stdin = Some(file); }
@@ -178,38 +182,36 @@ impl<'a> RefinedJob<'a> {
             stdin:  None,
             stdout: None,
             stderr: None,
+            args:   types::Args::new(),
             var:    JobVariant::Tee { items: (tee_out, tee_err) },
         }
     }
 
     pub fn cat(sources: Vec<File>) -> Self {
-        RefinedJob { stdin: None, stdout: None, stderr: None, var: JobVariant::Cat { sources } }
-    }
-
-    pub fn function(args: types::Args) -> Self {
         RefinedJob {
             stdin:  None,
             stdout: None,
             stderr: None,
-            var:    JobVariant::Function { args },
+            args:   types::Args::new(),
+            var:    JobVariant::Cat { sources },
         }
     }
 
+    pub fn function(args: types::Args) -> Self {
+        RefinedJob { stdin: None, stdout: None, stderr: None, args, var: JobVariant::Function }
+    }
+
     pub fn builtin(main: BuiltinFunction<'a>, args: types::Args) -> Self {
         RefinedJob {
-            stdin:  None,
+            stdin: None,
             stdout: None,
             stderr: None,
-            var:    JobVariant::Builtin { main, args },
+            args,
+            var: JobVariant::Builtin { main },
         }
     }
 
     pub fn external(args: types::Args) -> Self {
-        RefinedJob {
-            stdin:  None,
-            stdout: None,
-            stderr: None,
-            var:    JobVariant::External { args },
-        }
+        RefinedJob { stdin: None, stdout: None, stderr: None, args, var: JobVariant::External }
     }
 }
diff --git a/src/lib/shell/pipe_exec/mod.rs b/src/lib/shell/pipe_exec/mod.rs
index 8fc371116becd19316691c1ded9b1c5dba8884a8..b70f1f4b4577c8087b72256f40fc4e76ab14cd2e 100644
--- a/src/lib/shell/pipe_exec/mod.rs
+++ b/src/lib/shell/pipe_exec/mod.rs
@@ -180,40 +180,6 @@ fn prepare<'a, 'b>(
 }
 
 impl<'b> Shell<'b> {
-    fn exec_external<'a, S: AsRef<str>>(
-        &mut self,
-        name: &'a str,
-        args: &'a [S],
-        stdin: &Option<File>,
-        stdout: &Option<File>,
-        stderr: &Option<File>,
-    ) -> Status {
-        let result = sys::fork_and_exec(
-            name,
-            args,
-            stdin.as_ref().map(File::as_raw_fd),
-            stdout.as_ref().map(File::as_raw_fd),
-            stderr.as_ref().map(File::as_raw_fd),
-            false,
-            || prepare_child(true, 0),
-        );
-
-        match result {
-            Ok(pid) => {
-                let _ = sys::setpgid(pid, pid);
-                let _ = sys::tcsetpgrp(0, pid);
-                let _ = wait_for_interrupt(pid);
-                let _ = sys::kill(pid, sys::SIGCONT);
-                self.watch_foreground(pid)
-            }
-            Err(ref err) if err.kind() == io::ErrorKind::NotFound => {
-                self.command_not_found(name);
-                Status::NO_SUCH_COMMAND
-            }
-            Err(ref err) => Status::error(format!("ion: command exec error: {}", err)),
-        }
-    }
-
     /// For tee jobs
     fn exec_multi_out(
         &mut self,
@@ -295,11 +261,8 @@ impl<'b> Shell<'b> {
         if let Ok((stdin_bk, stdout_bk, stderr_bk)) = duplicate_streams() {
             redirect_streams(&job.stdin, &job.stdout, &job.stderr);
             let code = match job.var {
-                JobVariant::External { ref args } => {
-                    self.exec_external(&args[0], &args[1..], &job.stdin, &job.stdout, &job.stderr)
-                }
-                JobVariant::Builtin { ref main, ref args } => self.exec_builtin(main, &**args),
-                JobVariant::Function { ref args } => self.exec_function(&args[0], args),
+                JobVariant::Builtin { ref main } => self.exec_builtin(main, job.args()),
+                JobVariant::Function => self.exec_function(job.command(), job.args()),
                 _ => panic!("exec job should not be able to be called on Cat or Tee jobs"),
             };
             redirect_streams(&stdin_bk, &Some(stdout_bk), &Some(stderr_bk));
@@ -390,7 +353,14 @@ impl<'b> Shell<'b> {
         };
 
         if let Some((mut parent, mut kind)) = commands.next() {
-            if kind != RedirectFrom::None {
+            if kind == RedirectFrom::None && !parent.needs_forking() {
+                let status = self.exec_job(&parent);
+
+                let _ = io::stdout().flush();
+                let _ = io::stderr().flush();
+
+                status
+            } else {
                 let (mut pgid, mut last_pid, mut current_pid) = (0, 0, 0);
 
                 // Append jobs until all piped jobs are running
@@ -472,13 +442,6 @@ impl<'b> Shell<'b> {
                     let _ = io::stdout().flush();
                     let _ = io::stderr().flush();
                 }
-                status
-            } else {
-                let status = self.exec_job(&parent);
-
-                let _ = io::stdout().flush();
-                let _ = io::stderr().flush();
-
                 status
             }
         } else {
@@ -489,23 +452,19 @@ impl<'b> Shell<'b> {
 
 fn spawn_proc(
     shell: &mut Shell,
-    mut cmd: RefinedJob,
+    cmd: RefinedJob,
     redirection: RedirectFrom,
     block_child: bool,
     last_pid: &mut u32,
     current_pid: &mut u32,
     pgid: u32,
 ) {
-    let stdin = cmd.stdin;
-    let stdout = cmd.stdout;
-    let stderr = cmd.stderr;
-    match cmd.var {
-        JobVariant::External { ref args } => {
-            let name = &args[0];
-            let args: Vec<&str> = args.iter().skip(1).map(|x| x as &str).collect();
+    let RefinedJob { mut var, args, stdin, stdout, stderr } = cmd;
+    match var {
+        JobVariant::External => {
             let mut result = sys::fork_and_exec(
-                name,
-                &args,
+                &args[0],
+                &args[1..],
                 stdin.as_ref().map(AsRawFd::as_raw_fd),
                 stdout.as_ref().map(AsRawFd::as_raw_fd),
                 stderr.as_ref().map(AsRawFd::as_raw_fd),
@@ -519,14 +478,14 @@ fn spawn_proc(
                     *current_pid = pid;
                 }
                 Err(ref mut err) if err.kind() == io::ErrorKind::NotFound => {
-                    shell.command_not_found(name)
+                    shell.command_not_found(&args[0])
                 }
                 Err(ref mut err) => {
                     eprintln!("ion: command exec error: {}", err);
                 }
             }
         }
-        JobVariant::Builtin { main, ref mut args } => {
+        JobVariant::Builtin { main } => {
             fork_exec_internal(
                 stdout,
                 stderr,
@@ -535,10 +494,10 @@ fn spawn_proc(
                 last_pid,
                 current_pid,
                 pgid,
-                |_, _, _| shell.exec_builtin(main, args),
+                |_, _, _| main(&args, shell),
             );
         }
-        JobVariant::Function { ref mut args } => {
+        JobVariant::Function => {
             fork_exec_internal(
                 stdout,
                 stderr,