diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs
index 6b7af6994c6686435cce0fa81b90b2ed230e0225..d36e13a0c92bc6f5238a591e99c600ed648bffdf 100644
--- a/src/header/stdlib/mod.rs
+++ b/src/header/stdlib/mod.rs
@@ -618,7 +618,7 @@ pub unsafe extern "C" fn realpath(pathname: *const c_char, resolved: *mut c_char
         resolved
     };
 
-    let mut out = slice::from_raw_parts_mut(ptr as *mut u8, limits::PATH_MAX);
+    let out = slice::from_raw_parts_mut(ptr as *mut u8, limits::PATH_MAX);
     {
         let file = match File::open(&CStr::from_ptr(pathname), O_PATH | O_CLOEXEC) {
             Ok(file) => file,
diff --git a/src/header/sys_ioctl/redox.rs b/src/header/sys_ioctl/redox.rs
index 0b389bb7c603787c8201c44590421258393fcb5f..b0f0d1dd8e76242b5647e321cd522a6ca8748882 100644
--- a/src/header/sys_ioctl/redox.rs
+++ b/src/header/sys_ioctl/redox.rs
@@ -9,109 +9,104 @@ use platform::types::*;
 
 use super::winsize;
 
+pub const TCGETS: c_ulong = 0x5401;
+pub const TCSETS: c_ulong = 0x5402;
+
+pub const TCFLSH: c_ulong = 0x540B;
+
+pub const TIOCGPGRP: c_ulong = 0x540F;
+pub const TIOCSPGRP: c_ulong = 0x5410;
+
+pub const TIOCGWINSZ: c_ulong = 0x5413;
+pub const TIOCSWINSZ: c_ulong = 0x5414;
+
+fn dup_read<T>(fd: c_int, name: &str, t: &mut T) -> syscall::Result<usize> {
+    let dup = syscall::dup(fd as usize, name.as_bytes())?;
+
+    let size = mem::size_of::<T>();
+
+    let res = syscall::read(dup, unsafe {
+        slice::from_raw_parts_mut(t as *mut T as *mut u8, size)
+    });
+
+    let _ = syscall::close(dup);
+
+    res.map(|bytes| bytes/size)
+}
+
+fn dup_write<T>(fd: c_int, name: &str, t: &T) -> syscall::Result<usize> {
+    let dup = syscall::dup(fd as usize, name.as_bytes())?;
+
+    let size = mem::size_of::<T>();
+
+    let res = syscall::write(dup, unsafe {
+        slice::from_raw_parts(t as *const T as *const u8, size)
+    });
+
+    let _ = syscall::close(dup);
+
+    res.map(|bytes| bytes/size)
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
     match request {
         TCGETS => {
-            let dup = e(syscall::dup(fd as usize, b"termios"));
-            if dup == !0 {
-                return -1;
-            }
-
-            let count = e(syscall::read(dup, unsafe {
-                slice::from_raw_parts_mut(out as *mut u8, mem::size_of::<termios::termios>())
-            }));
-            let _ = syscall::close(dup);
-
-            if count == !0 {
-                return -1;
+            let termios = &mut *(out as *mut termios::termios);
+            if e(dup_read(fd, "termios", termios)) == !0 {
+                -1
+            } else {
+                0
             }
-            0
         }
 
         TCSETS => {
-            let dup = e(syscall::dup(fd as usize, b"termios"));
-            if dup == !0 {
-                return -1;
+            let termios = &*(out as *const termios::termios);
+            if e(dup_write(fd, "termios", termios)) == !0 {
+                -1
+            } else {
+                0
             }
-
-            let count = e(syscall::write(dup, unsafe {
-                slice::from_raw_parts(out as *const u8, mem::size_of::<termios::termios>())
-            }));
-            let _ = syscall::close(dup);
-
-            if count == !0 {
-                return -1;
+        },
+        TCFLSH => {
+            let queue = out as c_int;
+            if e(dup_write(fd, "flush", &queue)) == !0 {
+                -1
+            } else {
+                0
             }
-            0
         },
         TIOCGPGRP => {
-            let dup = e(syscall::dup(fd as usize, b"pgrp"));
-            if dup == !0 {
-                return -1;
-            }
-
-            let count = e(syscall::read(
-                dup,
-                slice::from_raw_parts_mut(out as *mut u8, mem::size_of::<pid_t>())
-            ));
-            let _ = syscall::close(dup);
-
-            if count == !0 {
-                return -1;
+            let pgrp = &mut *(out as *mut pid_t);
+            if e(dup_read(fd, "pgrp", pgrp)) == !0 {
+                -1
+            } else {
+                0
             }
-            0
         },
         TIOCSPGRP => {
-            let dup = e(syscall::dup(fd as usize, b"pgrp"));
-            if dup == !0 {
-                return -1;
+            let pgrp = &*(out as *const pid_t);
+            if e(dup_write(fd, "pgrp", pgrp)) == !0 {
+                -1
+            } else {
+                0
             }
-
-            let count = e(syscall::write(
-                dup,
-                slice::from_raw_parts(out as *const u8, mem::size_of::<pid_t>())
-            ));
-            let _ = syscall::close(dup);
-
-            if count == !0 {
-                return -1;
-            }
-            0
         },
         TIOCGWINSZ => {
-            let dup = e(syscall::dup(fd as usize, b"winsize"));
-            if dup == !0 {
-                return -1;
-            }
-
-            let count = e(syscall::read(
-                dup,
-                slice::from_raw_parts_mut(out as *mut u8, mem::size_of::<winsize>())
-            ));
-            let _ = syscall::close(dup);
-
-            if count == !0 {
-                return -1;
+            let winsize = &mut *(out as *mut winsize);
+            if e(dup_read(fd, "winsize", winsize)) == !0 {
+                -1
+            } else {
+                0
             }
-            0
         },
         TIOCSWINSZ => {
-            let dup = e(syscall::dup(fd as usize, b"winsize"));
-            if dup == !0 {
-                return -1;
+            let winsize = &*(out as *const winsize);
+            if e(dup_write(fd, "winsize", winsize)) == !0 {
+                -1
+            } else {
+                0
             }
-
-            let count = e(syscall::write(
-                dup,
-                slice::from_raw_parts(out as *const u8, mem::size_of::<winsize>())
-            ));
-            let _ = syscall::close(dup);
-
-            if count == !0 {
-                return -1;
-            }
-            0
         },
         _ => {
             platform::errno = errno::EINVAL;
@@ -119,12 +114,3 @@ pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) ->
         }
     }
 }
-
-pub const TCGETS: c_ulong = 0x5401;
-pub const TCSETS: c_ulong = 0x5402;
-
-pub const TIOCGPGRP: c_ulong = 0x540F;
-pub const TIOCSPGRP: c_ulong = 0x5410;
-
-pub const TIOCGWINSZ: c_ulong = 0x5413;
-pub const TIOCSWINSZ: c_ulong = 0x5414;
diff --git a/src/header/termios/mod.rs b/src/header/termios/mod.rs
index eb8978b564e1e97f8736ff6e3f43e4d17c4e8779..3172646f2b9552e82697c352314b669a4a3df35a 100644
--- a/src/header/termios/mod.rs
+++ b/src/header/termios/mod.rs
@@ -11,72 +11,6 @@ pub type tcflag_t = u32;
 
 pub const NCCS: usize = 32;
 
-#[repr(C)]
-#[derive(Default)]
-pub struct termios {
-    c_iflag: tcflag_t,
-    c_oflag: tcflag_t,
-    c_cflag: tcflag_t,
-    c_lflag: tcflag_t,
-    c_line: cc_t,
-    c_cc: [cc_t; NCCS],
-    __c_ispeed: speed_t,
-    __c_ospeed: speed_t,
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn tcgetattr(fd: c_int, out: *mut termios) -> c_int {
-    sys_ioctl::ioctl(fd, sys_ioctl::TCGETS, out as *mut c_void)
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn tcsetattr(fd: c_int, act: c_int, value: *mut termios) -> c_int {
-    if act < 0 || act > 2 {
-        platform::errno = errno::EINVAL;
-        return -1;
-    }
-    // This is safe because ioctl shouldn't modify the value
-    sys_ioctl::ioctl(fd, sys_ioctl::TCSETS + act as c_ulong, value as *mut c_void)
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn cfgetispeed(termios_p: *const termios) -> speed_t {
-    (*termios_p).__c_ispeed
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn cfgetospeed(termios_p: *const termios) -> speed_t {
-    (*termios_p).__c_ospeed
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn cfsetispeed(termios_p: *mut termios, speed: speed_t) -> c_int {
-    match speed as usize {
-        B0..=B38400 | B57600..=B4000000 => {
-            (*termios_p).__c_ispeed = speed;
-            0
-        }
-        _ => {
-            platform::errno = errno::EINVAL;
-            -1
-        }
-    }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn cfsetospeed(termios_p: *mut termios, speed: speed_t) -> c_int {
-    match speed as usize {
-        B0..=B38400 | B57600..=B4000000 => {
-            (*termios_p).__c_ospeed = speed;
-            0
-        }
-        _ => {
-            platform::errno = errno::EINVAL;
-            -1
-        }
-    }
-}
-
 pub const VINTR: usize = 0;
 pub const VQUIT: usize = 1;
 pub const VERASE: usize = 2;
@@ -191,3 +125,74 @@ pub const TCIOFLUSH: usize = 2;
 pub const TCSANOW: usize = 0;
 pub const TCSADRAIN: usize = 1;
 pub const TCSAFLUSH: usize = 2;
+
+#[repr(C)]
+#[derive(Default)]
+pub struct termios {
+    c_iflag: tcflag_t,
+    c_oflag: tcflag_t,
+    c_cflag: tcflag_t,
+    c_lflag: tcflag_t,
+    c_line: cc_t,
+    c_cc: [cc_t; NCCS],
+    __c_ispeed: speed_t,
+    __c_ospeed: speed_t,
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn tcgetattr(fd: c_int, out: *mut termios) -> c_int {
+    sys_ioctl::ioctl(fd, sys_ioctl::TCGETS, out as *mut c_void)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn tcsetattr(fd: c_int, act: c_int, value: *mut termios) -> c_int {
+    if act < 0 || act > 2 {
+        platform::errno = errno::EINVAL;
+        return -1;
+    }
+    // This is safe because ioctl shouldn't modify the value
+    sys_ioctl::ioctl(fd, sys_ioctl::TCSETS + act as c_ulong, value as *mut c_void)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn cfgetispeed(termios_p: *const termios) -> speed_t {
+    (*termios_p).__c_ispeed
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn cfgetospeed(termios_p: *const termios) -> speed_t {
+    (*termios_p).__c_ospeed
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn cfsetispeed(termios_p: *mut termios, speed: speed_t) -> c_int {
+    match speed as usize {
+        B0..=B38400 | B57600..=B4000000 => {
+            (*termios_p).__c_ispeed = speed;
+            0
+        }
+        _ => {
+            platform::errno = errno::EINVAL;
+            -1
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn cfsetospeed(termios_p: *mut termios, speed: speed_t) -> c_int {
+    match speed as usize {
+        B0..=B38400 | B57600..=B4000000 => {
+            (*termios_p).__c_ospeed = speed;
+            0
+        }
+        _ => {
+            platform::errno = errno::EINVAL;
+            -1
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn tcflush(fd: c_int, queue: c_int) -> c_int {
+    sys_ioctl::ioctl(fd, sys_ioctl::TCFLSH, queue as *mut c_void)
+}