diff --git a/src/lib/builtins/man_pages.rs b/src/lib/builtins/man_pages.rs
index 135d598f22007fd7c2b81c27c6b3814171e6050f..82e1da209fe79cd2c011502cc44791f454c759e5 100644
--- a/src/lib/builtins/man_pages.rs
+++ b/src/lib/builtins/man_pages.rs
@@ -78,6 +78,16 @@ OPTIONS
         returns 0 if the two arguments are not equal.
 "#;
 
+pub(crate) const MAN_ISATTY: &'static str = r#"
+    isatty - Checks if argument is a file descriptor
+
+SYNOPSIS
+    isatty [FD]
+
+DESCRIPTION
+    Returns 0 exit status if the supplied file descriptor is a tty.
+"#;
+
 pub(crate) const MAN_DIRS: &'static str = r#"NAME
     dirs - prints the directory stack
 
diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs
index 3d1415009f189b71981dd4bdf132fb6629552480..5a2338b8a582192a5c53c0498d872b90585e1451 100644
--- a/src/lib/builtins/mod.rs
+++ b/src/lib/builtins/mod.rs
@@ -64,7 +64,7 @@ macro_rules! map {
 
 /// If you are implementing a builtin add it to the table below, create a well named manpage in
 /// man_pages and check for help flags by adding to the start of your builtin the following
-/// if check_help(args, MAN_CD) {
+/// if check_help(args, MAN_BUILTIN_NAME) {
 ///     return SUCCESS
 /// }
 
@@ -93,6 +93,7 @@ pub const BUILTINS: &'static BuiltinMap = &map!(
     "history" => builtin_history : "Display a log of all commands previously executed",
     "ion-docs" => ion_docs : "Opens the Ion manual",
     "is" => builtin_is : "Simple alternative to == and !=",
+    "isatty" => builtin_isatty : "Returns 0 exit status if the supplied FD is a tty",
     "jobs" => builtin_jobs : "Displays all jobs that are attached to the background",
     "matches" => builtin_matches : "Checks if a string matches a given regex",
     "not" => builtin_not : "Reverses the exit status value of the given command.",
@@ -637,3 +638,50 @@ fn builtin_which(args: &[&str], shell: &mut Shell) -> i32 {
     }
     result
 }
+
+/// There are two different `builtin_isatty()` functions because 
+/// `sys::isatty()` when built for redox expects a usize while otherwise expecting a i32.
+/// This could probably be done more elegantly.
+#[cfg(target_os = "redox")]
+fn builtin_isatty(args: &[&str], _: &mut Shell) -> i32 {
+    if check_help(args, MAN_ISATTY) {
+        return SUCCESS
+    }
+
+    let stderr = io::stderr();
+    let mut stderr = stderr.lock();
+    if args.len() > 1 {
+        match args[1].parse::<usize>() {
+            Ok(r) => if sys::isatty(r) {
+                return SUCCESS
+            },
+            Err(_) => { let _ = stderr.write_all("ion: isatty given bad number".as_bytes()); }
+        }
+    } else {
+        return SUCCESS
+    }
+
+    FAILURE
+}
+
+#[cfg(not(target_os = "redox"))]
+fn builtin_isatty(args: &[&str], _: &mut Shell) -> i32 {
+    if check_help(args, MAN_ISATTY) {
+        return SUCCESS
+    }
+
+    let stderr = io::stderr();
+    let mut stderr = stderr.lock();
+    if args.len() > 1 {
+        match args[1].parse::<i32>() {
+            Ok(r) => if sys::isatty(r) {
+                return SUCCESS
+            },
+            Err(_) => { let _ = stderr.write_all("ion: isatty given bad number".as_bytes()); }
+        }
+    } else {
+        return SUCCESS
+    }
+
+    FAILURE
+}
\ No newline at end of file
diff --git a/src/lib/sys/redox.rs b/src/lib/sys/redox.rs
index 58e1cd478f39a244a0d73b5797fa865a972a2b02..62bb6409c72303d2a0d30fad61cabd6a0f7ebe04 100644
--- a/src/lib/sys/redox.rs
+++ b/src/lib/sys/redox.rs
@@ -93,91 +93,46 @@ pub(crate) fn fork_and_exec<F: Fn()>(
     clear_env: bool,
     before_exec: F
 ) -> io::Result<u32> {
-    // Construct a valid set of arguments to pass to execve. Ensure
-    // that the program is the first argument.
-    let mut cvt_args: Vec<[usize; 2]> = Vec::new();
-    cvt_args.push([prog.as_ptr() as usize, prog.len()]);
-    for arg in args {
-        cvt_args.push([arg.as_ptr() as usize, arg.len()]);
-    }
-
-    // Get the PathBuf of the program if it exists.
-    let prog = if prog.contains(':') || prog.contains('/') {
-        // This is a fully specified scheme or path to an
-        // executable.
-        Some(PathBuf::from(prog))
-    } else if let Ok(paths) = env::var("PATH") {
-        // This is not a fully specified scheme or path.
-        // Iterate through the possible paths in the
-        // env var PATH that this executable may be found
-        // in and return the first one found.
-        env::split_paths(&paths)
-            .filter_map(|mut path| {
-                path.push(prog);
-                if path.exists() {
-                    Some(path)
-                } else {
-                    None
+    unsafe {
+        match fork()? {
+            0 => {
+                if let Some(stdin) = stdin {
+                    let _ = dup2(stdin, STDIN_FILENO);
+                    let _ = close(stdin);
                 }
-            })
-            .next()
-    } else {
-        None
-    };
-
-    // If clear_env set, clear the env.
-    if clear_env {
-        for (key, _) in env::vars() {
-            env::remove_var(key);
-        }
-    }
-
-    if let Some(prog) = prog {
-        unsafe {
-            match fork()? {
-                0 => {
-                    if let Some(stdin) = stdin {
-                        let _ = dup2(stdin, STDIN_FILENO);
-                        let _ = close(stdin);
-                    }
 
-                    if let Some(stdout) = stdout {
-                        let _ = dup2(stdout, STDOUT_FILENO);
-                        let _ = close(stdout);
-                    }
+                if let Some(stdout) = stdout {
+                    let _ = dup2(stdout, STDOUT_FILENO);
+                    let _ = close(stdout);
+                }
 
-                    if let Some(stderr) = stderr {
-                        let _ = dup2(stderr, STDERR_FILENO);
-                        let _ = close(stderr);
-                    }
+                if let Some(stderr) = stderr {
+                    let _ = dup2(stderr, STDERR_FILENO);
+                    let _ = close(stderr);
+                }
 
-                    before_exec();
+                before_exec();
 
-                    let error = syscall::execve(prog.as_os_str().as_bytes(), &cvt_args);
-                    let error = io::Error::from_raw_os_error(error.err().unwrap().errno);
-                    eprintln!("ion: command exec: {}", error);
-                    fork_exit(1);
+                let error = execve(prog, args, clear_env);
+                eprintln!("ion: command exec: {}", error);
+                fork_exit(1);
+            }
+            pid => {
+                if let Some(stdin) = stdin {
+                    let _ = close(stdin);
                 }
-                pid => {
-                    if let Some(stdin) = stdin {
-                        let _ = close(stdin);
-                    }
 
-                    if let Some(stdout) = stdout {
-                        let _ = close(stdout);
-                    }
-
-                    if let Some(stderr) = stderr {
-                        let _ = close(stderr);
-                    }
+                if let Some(stdout) = stdout {
+                    let _ = close(stdout);
+                }
 
-                    Ok(pid)
+                if let Some(stderr) = stderr {
+                    let _ = close(stderr);
                 }
+
+                Ok(pid)
             }
         }
-    } else {
-        // The binary was not found.
-        Err(io::Error::from_raw_os_error(syscall::ENOENT))
     }
 }