diff --git a/Cargo.lock b/Cargo.lock
index 2ba1307728bc1433d6d0130ebd647f3313e59000..5f39557e6ae1fadc6cf2f205fe156e8b0ed00f6b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6,30 +6,19 @@ dependencies = [
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "arpainet"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "errno 0.1.0",
- "netinet 0.1.0",
- "platform 0.1.0",
- "sys_socket 0.1.0",
-]
-
 [[package]]
 name = "atty"
-version = "0.2.10"
+version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "bitflags"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -38,9 +27,9 @@ version = "0.5.2"
 dependencies = [
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "standalone-syn 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -48,12 +37,12 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.18"
+version = "1.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "cfg-if"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -62,8 +51,8 @@ version = "2.32.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -73,80 +62,13 @@ dependencies = [
 [[package]]
 name = "compiler_builtins"
 version = "0.1.0"
-source = "git+https://github.com/rust-lang-nursery/compiler-builtins.git#5d370bb352c915225981d89b80227afa4836cb93"
+source = "git+https://github.com/rust-lang-nursery/compiler-builtins.git#3caed3c80207fa43ba2963949c5f104a63c4264e"
 
 [[package]]
 name = "crt0"
 version = "0.1.0"
 dependencies = [
- "platform 0.1.0",
- "stdio 0.1.0",
-]
-
-[[package]]
-name = "ctype"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "dirent"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "errno 0.1.0",
- "fcntl 0.1.0",
- "platform 0.1.0",
- "stdio 0.1.0",
- "unistd 0.1.0",
-]
-
-[[package]]
-name = "dtoa"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "errno"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "fcntl"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "fenv"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "float"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "fenv 0.1.0",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "fnmatch"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
+ "relibc 0.1.0",
 ]
 
 [[package]]
@@ -154,7 +76,7 @@ name = "fuchsia-zircon"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -163,34 +85,6 @@ name = "fuchsia-zircon-sys"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "grp"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "in_h"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
- "sys_socket 0.1.0",
-]
-
-[[package]]
-name = "inttypes"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "ctype 0.1.0",
- "errno 0.1.0",
- "platform 0.1.0",
- "stdlib 0.1.0",
-]
-
 [[package]]
 name = "itoa"
 version = "0.4.2"
@@ -198,56 +92,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lazy_static"
-version = "1.0.2"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "libc"
-version = "0.2.42"
+version = "0.2.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "locale"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
 [[package]]
 name = "log"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "log"
-version = "0.4.3"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "netinet"
-version = "0.1.0"
-dependencies = [
- "in_h 0.1.0",
-]
-
-[[package]]
-name = "platform"
-version = "0.1.0"
-dependencies = [
- "ralloc 1.0.0",
- "redox_syscall 0.1.40 (git+https://gitlab.redox-os.org/redox-os/syscall.git?branch=relibc)",
- "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -258,16 +128,6 @@ dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "pwd"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "errno 0.1.0",
- "fcntl 0.1.0",
- "platform 0.1.0",
-]
-
 [[package]]
 name = "quote"
 version = "0.3.15"
@@ -291,17 +151,17 @@ dependencies = [
 
 [[package]]
 name = "rand"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rand"
-version = "0.5.4"
+version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -334,46 +194,15 @@ dependencies = [
 name = "relibc"
 version = "0.1.0"
 dependencies = [
- "arpainet 0.1.0",
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins.git)",
- "ctype 0.1.0",
- "dirent 0.1.0",
- "errno 0.1.0",
- "fcntl 0.1.0",
- "fenv 0.1.0",
- "float 0.1.0",
- "fnmatch 0.1.0",
- "grp 0.1.0",
- "inttypes 0.1.0",
- "locale 0.1.0",
- "netinet 0.1.0",
- "platform 0.1.0",
- "pwd 0.1.0",
- "semaphore 0.1.0",
- "setjmp 0.1.0",
- "signal 0.1.0",
- "stdio 0.1.0",
- "stdlib 0.1.0",
- "string 0.1.0",
- "strings 0.1.0",
- "sys_ioctl 0.1.0",
- "sys_mman 0.1.0",
- "sys_resource 0.1.0",
- "sys_select 0.1.0",
- "sys_socket 0.1.0",
- "sys_stat 0.1.0",
- "sys_time 0.1.0",
- "sys_times 0.1.0",
- "sys_un 0.1.0",
- "sys_utsname 0.1.0",
- "sys_wait 0.1.0",
- "termios 0.1.0",
- "time 0.1.0",
- "unistd 0.1.0",
- "utime 0.1.0",
- "wchar 0.1.0",
- "wctype 0.1.0",
+ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ralloc 1.0.0",
+ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.40 (git+https://gitlab.redox-os.org/redox-os/syscall.git?branch=relibc)",
+ "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "va_list 0.1.0",
 ]
 
 [[package]]
@@ -385,21 +214,18 @@ dependencies = [
 ]
 
 [[package]]
-name = "sc"
-version = "0.2.2"
+name = "ryu"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
-name = "semaphore"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
+name = "sc"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "1.0.70"
+version = "1.0.75"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -426,30 +252,17 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.24"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "setjmp"
-version = "0.1.0"
-
-[[package]]
-name = "signal"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "errno 0.1.0",
- "platform 0.1.0",
+ "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "spin"
-version = "0.4.8"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -470,53 +283,6 @@ dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "stdio"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "errno 0.1.0",
- "fcntl 0.1.0",
- "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "platform 0.1.0",
- "string 0.1.0",
- "va_list 0.1.0",
-]
-
-[[package]]
-name = "stdlib"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "ctype 0.1.0",
- "errno 0.1.0",
- "fcntl 0.1.0",
- "platform 0.1.0",
- "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "string 0.1.0",
- "time 0.1.0",
- "unistd 0.1.0",
- "wchar 0.1.0",
-]
-
-[[package]]
-name = "string"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "errno 0.1.0",
- "platform 0.1.0",
- "signal 0.1.0",
-]
-
-[[package]]
-name = "strings"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
 [[package]]
 name = "strsim"
 version = "0.7.0"
@@ -540,103 +306,12 @@ dependencies = [
  "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "sys_ioctl"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "sys_mman"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "sys_resource"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
- "sys_time 0.1.0",
-]
-
-[[package]]
-name = "sys_select"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "sys_socket"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "sys_stat"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "sys_time"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "sys_times"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "sys_un"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
- "sys_socket 0.1.0",
-]
-
-[[package]]
-name = "sys_utsname"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
-[[package]]
-name = "sys_wait"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
- "sys_resource 0.1.0",
-]
-
 [[package]]
 name = "tempdir"
 version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -645,19 +320,11 @@ name = "termion"
 version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "termios"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
 [[package]]
 name = "textwrap"
 version = "0.10.0"
@@ -666,21 +333,12 @@ dependencies = [
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "time"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "errno 0.1.0",
- "platform 0.1.0",
-]
-
 [[package]]
 name = "toml"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -703,26 +361,6 @@ name = "unicode-xid"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "unistd"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "errno 0.1.0",
- "platform 0.1.0",
- "stdio 0.1.0",
- "string 0.1.0",
- "sys_time 0.1.0",
-]
-
-[[package]]
-name = "utime"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
-
 [[package]]
 name = "va_list"
 version = "0.1.0"
@@ -734,7 +372,7 @@ dependencies = [
 name = "va_list-helper"
 version = "0.0.2"
 dependencies = [
- "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -743,24 +381,9 @@ version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
-name = "wchar"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "errno 0.1.0",
- "platform 0.1.0",
- "stdio 0.1.0",
- "time 0.1.0",
- "va_list 0.1.0",
-]
-
-[[package]]
-name = "wctype"
-version = "0.1.0"
-dependencies = [
- "cbindgen 0.5.2",
- "platform 0.1.0",
-]
+name = "version_check"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "winapi"
@@ -783,35 +406,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
-"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1"
-"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
-"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275"
-"checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e"
+"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
+"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
+"checksum cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4a6007c146fdd28d4512a794b07ffe9d8e89e6bf86e2e0c4ddff2e1fb54a0007"
+"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
 "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
 "checksum compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins.git)" = "<none>"
-"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd"
 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
 "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 "checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606"
-"checksum lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fb497c35d362b6a331cfd94956a07fc2c78a4604cdbee844a81170386b996dd3"
-"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1"
+"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
+"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
-"checksum log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61bd98ae7f7b754bc53dca7d44b604f733c6bba044ea6f41bc8d89272d8161d2"
+"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2"
 "checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
-"checksum rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "12397506224b2f93e6664ffc4f664b29be8208e5157d3d90b44f09b5fae470ea"
+"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
+"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
 "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2"
 "checksum redox_syscall 0.1.40 (git+https://gitlab.redox-os.org/redox-os/syscall.git?branch=relibc)" = "<none>"
 "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
+"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7"
 "checksum sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4ebbb026ba4a707c25caec2db5ef59ad8b41f7ad77cad06257e06229c891f376"
-"checksum serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3adf19c07af6d186d91dae8927b83b0553d07ca56cbf7f2f32560455c91920"
+"checksum serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "22d340507cea0b7e6632900a176101fea959c7065d93ba555072da90aaaafc87"
 "checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788"
 "checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab"
-"checksum serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c6908c7b925cd6c590358a4034de93dbddb20c45e1d021931459fd419bf0e2"
-"checksum spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14db77c5b914df6d6173dda9a3b3f5937bd802934fa5edaf934df06a3491e56f"
+"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
+"checksum spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "37b5646825922b96b5d7d676b5bb3458a54498e96ed7b0ce09dc43a07038fea4"
 "checksum standalone-quote 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dcedac1d6d98e7e9d1d6e628f5635af9566688ae5f6cea70a3976f495ae8d839"
 "checksum standalone-syn 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "115808f5187c07c23cb93eee49d542fae54c6e8285d3a24c6ff683fcde9243db"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
@@ -826,6 +449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
+"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051"
 "checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
index 41e6711aec88baf615834d3d8b830f9b227453be..0736e52eebe21fe45c4dccf7ec6cda3183de6fe4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,56 +8,33 @@ name = "c"
 crate-type = ["staticlib"]
 
 [workspace]
-members = ["src/crt0"]
+members = ["src/crt0", "cbindgen"]
 
 [build-dependencies]
 cc = "1.0.17"
 
 [dependencies]
-arpainet = { path = "src/arpainet" }
-ctype = { path = "src/ctype" }
-dirent = { path = "src/dirent" }
-errno = { path = "src/errno" }
-fcntl = { path = "src/fcntl" }
-fenv = { path = "src/fenv" }
-float = { path = "src/float" }
-fnmatch = { path = "src/fnmatch" }
-grp = { path = "src/grp" }
-inttypes = { path = "src/inttypes" }
-locale = { path = "src/locale" }
-netinet = { path = "src/netinet" }
-platform = { path = "src/platform" }
-pwd = { path = "src/pwd" }
-semaphore = { path = "src/semaphore" }
-setjmp = { path = "src/setjmp" }
-signal = { path = "src/signal" }
-stdio = { path = "src/stdio" }
-stdlib = { path = "src/stdlib" }
-string = { path = "src/string" }
-strings = { path = "src/strings" }
-sys_ioctl = { path = "src/sys_ioctl" }
-sys_mman = { path = "src/sys_mman" }
-sys_resource = { path = "src/sys_resource" }
-sys_select = { path = "src/sys_select" }
-sys_socket = { path = "src/sys_socket" }
-sys_stat = { path = "src/sys_stat" }
-sys_time = { path = "src/sys_time" }
-sys_times = { path = "src/sys_times" }
-sys_un = { path = "src/sys_un" }
-sys_utsname = { path = "src/sys_utsname" }
-sys_wait = { path = "src/sys_wait" }
-termios = { path = "src/termios" }
-time = { path = "src/time" }
-unistd = { path = "src/unistd" }
-utime = { path = "src/utime" }
-wchar = { path = "src/wchar" }
-wctype = { path = "src/wctype" }
+lazy_static = { version = "*", features = ["nightly", "spin_no_std"] }
+rand = { version = "0.5.2", default-features = false }
+va_list = { path = "va_list", features = ["no_std"] }
 
 [dependencies.compiler_builtins]
 git = "https://github.com/rust-lang-nursery/compiler-builtins.git"
 default-features = false
 features = ["no-lang-items", "mangled-names"]
 
+[dependencies.ralloc]
+path = "ralloc"
+default-features = false
+optional = true
+
+[target.'cfg(target_os = "linux")'.dependencies]
+sc = "0.2"
+
+[target.'cfg(target_os = "redox")'.dependencies]
+redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git", branch = "relibc" }
+spin = "0.4"
+
 [profile.dev]
 panic = "abort"
 
diff --git a/Makefile b/Makefile
index cf37919e0a320fb0b60b9b3f91425e247f5f9799..ee536cc62117fee1b9f6fdb62e9e0b161a2d7d12 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ SRC=\
 	src/*/*/* \
 	src/*/*/*/*
 
-.PHONY: all clean fmt install libc libm test
+.PHONY: all clean fmt include install libc libm test
 
 all: | libc libm
 
@@ -28,6 +28,9 @@ clean:
 	cargo clean
 	make -C tests clean
 
+check:
+	cargo check
+
 fmt:
 	./fmt.sh
 
@@ -35,14 +38,14 @@ install: all
 	mkdir -pv "$(DESTDIR)/lib"
 	mkdir -pv "$(DESTDIR)/include"
 	cp -rv "include"/* "$(DESTDIR)/include"
-	cp -rv "target/include"/* "$(DESTDIR)/include"
+	cp -rv "$(BUILD)/include"/* "$(DESTDIR)/include"
 	cp -v "$(BUILD)/release/libc.a" "$(DESTDIR)/lib"
 	cp -v "$(BUILD)/release/crt0.o" "$(DESTDIR)/lib"
 	cp -rv "openlibm/include"/* "$(DESTDIR)/include"
 	cp -rv "openlibm/src"/*.h "$(DESTDIR)/include"
 	cp -v "$(BUILD)/openlibm/libopenlibm.a" "$(DESTDIR)/lib/libm.a"
 
-libc: $(BUILD)/release/libc.a $(BUILD)/release/crt0.o
+libc: $(BUILD)/release/libc.a $(BUILD)/release/crt0.o $(BUILD)/include
 
 libm: $(BUILD)/openlibm/libopenlibm.a
 
@@ -65,6 +68,12 @@ $(BUILD)/release/crt0.o: $(SRC)
 	CARGO_INCREMENTAL=0 cargo rustc --release --manifest-path src/crt0/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@
 	touch $@
 
+$(BUILD)/include: $(SRC)
+	rm -rf $@ $@.partial
+	mkdir -p $@.partial
+	./include.sh $@.partial
+	mv $@.partial $@
+
 $(BUILD)/openlibm: openlibm
 	rm -rf $@ $@.partial
 	mkdir -p $(BUILD)
@@ -72,5 +81,5 @@ $(BUILD)/openlibm: openlibm
 	mv $@.partial $@
 	touch $@
 
-$(BUILD)/openlibm/libopenlibm.a: $(BUILD)/openlibm
-	make CC=$(CC) CPPFLAGS="-fno-stack-protector -I$(shell pwd)/include -I $(shell pwd)/target/include" -C $< libopenlibm.a
+$(BUILD)/openlibm/libopenlibm.a: $(BUILD)/openlibm $(BUILD)/include
+	make CC=$(CC) CPPFLAGS="-fno-stack-protector -I$(shell pwd)/include -I $(shell pwd)/$(BUILD)/include" -C $< libopenlibm.a
diff --git a/build.rs b/build.rs
index 8f61a6d4b2d0979afa5bc4629eb7454bef6427a6..4ee52afdf9f18ed803004123be841a4cb6c8e08c 100644
--- a/build.rs
+++ b/build.rs
@@ -11,6 +11,7 @@ fn main() {
         .flag("-I")
         .flag(&format!("{}/include", crate_dir))
         .flag("-fno-stack-protector")
+        .flag("-Wno-expansion-to-defined")
         .file("src/c/dlmalloc.c")
         .file("src/c/fcntl.c")
         .file("src/c/stack_chk.c")
diff --git a/fmt.sh b/fmt.sh
index cb5a928a33df8657a51debf0a0eb73b84cc3d5c7..be8636e2ab16a4bc43a86d252a7bd77193b6ad4a 100755
--- a/fmt.sh
+++ b/fmt.sh
@@ -1,9 +1,3 @@
 #!/usr/bin/env bash
-ARGS=()
 
-for crate in relibc $(find src -name Cargo.toml | cut -d '/' -f2 | grep -v template)
-do
-    ARGS+=("--package" "$crate")
-done
-
-cargo fmt "${ARGS[@]}" "$@"
+cargo fmt --package relibc --package crt0 "$@"
diff --git a/include.sh b/include.sh
new file mode 100755
index 0000000000000000000000000000000000000000..82f7f8a523ce93947aa92841fc8504972360164f
--- /dev/null
+++ b/include.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -ex
+
+include="$(realpath "$1")"
+cbindgen="$(realpath cbindgen)"
+
+for config in src/header/*/cbindgen.toml
+do
+    dir="$(dirname "$config")"
+    name="$(basename "$dir")"
+    if [ "${name:0:1}" != "_" ]
+    then
+        header="$include/${name/_/\/}.h"
+        pushd "$dir"
+        cargo run --release --manifest-path "$cbindgen/Cargo.toml" -- \
+            -c cbindgen.toml -o "$header" mod.rs
+        popd
+    fi
+done
diff --git a/src/arpainet/Cargo.toml b/src/arpainet/Cargo.toml
deleted file mode 100644
index 5a015567516ce115e84e172e2c033b9855dac5d7..0000000000000000000000000000000000000000
--- a/src/arpainet/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "arpainet"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
-errno = { path = "../errno" }
-sys_socket = { path = "../sys_socket" }
-netinet = { path = "../netinet" }
diff --git a/src/arpainet/build.rs b/src/arpainet/build.rs
deleted file mode 100644
index ad73b43495a11529f63c5466a2c230ca29df8349..0000000000000000000000000000000000000000
--- a/src/arpainet/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/arpa/inet.h");
-}
diff --git a/src/c_str.rs b/src/c_str.rs
new file mode 100644
index 0000000000000000000000000000000000000000..cb37b8959363ef9bd8d6c6ad55bebbc3ff6a5c1b
--- /dev/null
+++ b/src/c_str.rs
@@ -0,0 +1,1255 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use alloc::arc::Arc;
+use alloc::borrow::{Borrow, Cow, ToOwned};
+use alloc::boxed::Box;
+use alloc::rc::Rc;
+use alloc::string::String;
+use alloc::vec::Vec;
+use core::ascii;
+use core::cmp::Ordering;
+use core::fmt::{self, Write};
+use core::mem;
+use core::ops;
+use core::ptr;
+use core::slice;
+use core::str::{self, Utf8Error};
+
+use header::string::strlen;
+use platform::types::*;
+
+pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
+    use header::string;
+
+    let p = unsafe {
+        string::memchr(
+            haystack.as_ptr() as *const c_void,
+            needle as c_int,
+            haystack.len(),
+        )
+    };
+    if p.is_null() {
+        None
+    } else {
+        Some(p as usize - (haystack.as_ptr() as usize))
+    }
+}
+
+/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
+/// middle.
+///
+/// This type serves the purpose of being able to safely generate a
+/// C-compatible string from a Rust byte slice or vector. An instance of this
+/// type is a static guarantee that the underlying bytes contain no interior 0
+/// bytes ("nul characters") and that the final byte is 0 ("nul terminator").
+///
+/// `CString` is to [`CStr`] as [`String`] is to [`&str`]: the former
+/// in each pair are owned strings; the latter are borrowed
+/// references.
+///
+/// # Creating a `CString`
+///
+/// A `CString` is created from either a byte slice or a byte vector,
+/// or anything that implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>` (for
+/// example, you can build a `CString` straight out of a [`String`] or
+/// a [`&str`], since both implement that trait).
+///
+/// The [`new`] method will actually check that the provided `&[u8]`
+/// does not have 0 bytes in the middle, and return an error if it
+/// finds one.
+///
+/// # Extracting a raw pointer to the whole C string
+///
+/// `CString` implements a [`as_ptr`] method through the [`Deref`]
+/// trait. This method will give you a `*const c_char` which you can
+/// feed directly to extern functions that expect a nul-terminated
+/// string, like C's `strdup()`.
+///
+/// # Extracting a slice of the whole C string
+///
+/// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a
+/// `CString` with the [`as_bytes`] method. Slices produced in this
+/// way do *not* contain the trailing nul terminator. This is useful
+/// when you will be calling an extern function that takes a `*const
+/// u8` argument which is not necessarily nul-terminated, plus another
+/// argument with the length of the string — like C's `strndup()`.
+/// You can of course get the slice's length with its
+/// [`len`][slice.len] method.
+///
+/// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you
+/// can use [`as_bytes_with_nul`] instead.
+///
+/// Once you have the kind of slice you need (with or without a nul
+/// terminator), you can call the slice's own
+/// [`as_ptr`][slice.as_ptr] method to get a raw pointer to pass to
+/// extern functions. See the documentation for that function for a
+/// discussion on ensuring the lifetime of the raw pointer.
+///
+/// [`Into`]: ../convert/trait.Into.html
+/// [`Vec`]: ../vec/struct.Vec.html
+/// [`String`]: ../string/struct.String.html
+/// [`&str`]: ../primitive.str.html
+/// [`u8`]: ../primitive.u8.html
+/// [`new`]: #method.new
+/// [`as_bytes`]: #method.as_bytes
+/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
+/// [`as_ptr`]: #method.as_ptr
+/// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr
+/// [slice.len]: ../primitive.slice.html#method.len
+/// [`Deref`]: ../ops/trait.Deref.html
+/// [`CStr`]: struct.CStr.html
+///
+/// # Examples
+///
+/// ```ignore (extern-declaration)
+/// # fn main() {
+/// use std::ffi::CString;
+/// use std::os::raw::c_char;
+///
+/// extern {
+///     fn my_printer(s: *const c_char);
+/// }
+///
+/// // We are certain that our string doesn't have 0 bytes in the middle,
+/// // so we can .unwrap()
+/// let c_to_print = CString::new("Hello, world!").unwrap();
+/// unsafe {
+///     my_printer(c_to_print.as_ptr());
+/// }
+/// # }
+/// ```
+///
+/// # Safety
+///
+/// `CString` is intended for working with traditional C-style strings
+/// (a sequence of non-nul bytes terminated by a single nul byte); the
+/// primary use case for these kinds of strings is interoperating with C-like
+/// code. Often you will need to transfer ownership to/from that external
+/// code. It is strongly recommended that you thoroughly read through the
+/// documentation of `CString` before use, as improper ownership management
+/// of `CString` instances can lead to invalid memory accesses, memory leaks,
+/// and other memory errors.
+
+#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
+pub struct CString {
+    // Invariant 1: the slice ends with a zero byte and has a length of at least one.
+    // Invariant 2: the slice contains only one zero byte.
+    // Improper usage of unsafe function can break Invariant 2, but not Invariant 1.
+    inner: Box<[u8]>,
+}
+
+/// Representation of a borrowed C string.
+///
+/// This type represents a borrowed reference to a nul-terminated
+/// array of bytes. It can be constructed safely from a `&[`[`u8`]`]`
+/// slice, or unsafely from a raw `*const c_char`. It can then be
+/// converted to a Rust [`&str`] by performing UTF-8 validation, or
+/// into an owned [`CString`].
+///
+/// `CStr` is to [`CString`] as [`&str`] is to [`String`]: the former
+/// in each pair are borrowed references; the latter are owned
+/// strings.
+///
+/// Note that this structure is **not** `repr(C)` and is not recommended to be
+/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
+/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
+/// interface to other consumers.
+///
+/// # Examples
+///
+/// Inspecting a foreign C string:
+///
+/// ```ignore (extern-declaration)
+/// use std::ffi::CStr;
+/// use std::os::raw::c_char;
+///
+/// extern { fn my_string() -> *const c_char; }
+///
+/// unsafe {
+///     let slice = CStr::from_ptr(my_string());
+///     println!("string buffer size without nul terminator: {}", slice.to_bytes().len());
+/// }
+/// ```
+///
+/// Passing a Rust-originating C string:
+///
+/// ```ignore (extern-declaration)
+/// use std::ffi::{CString, CStr};
+/// use std::os::raw::c_char;
+///
+/// fn work(data: &CStr) {
+///     extern { fn work_with(data: *const c_char); }
+///
+///     unsafe { work_with(data.as_ptr()) }
+/// }
+///
+/// let s = CString::new("data data data data").unwrap();
+/// work(&s);
+/// ```
+///
+/// Converting a foreign C string into a Rust [`String`]:
+///
+/// ```ignore (extern-declaration)
+/// use std::ffi::CStr;
+/// use std::os::raw::c_char;
+///
+/// extern { fn my_string() -> *const c_char; }
+///
+/// fn my_string_safe() -> String {
+///     unsafe {
+///         CStr::from_ptr(my_string()).to_string_lossy().into_owned()
+///     }
+/// }
+///
+/// println!("string: {}", my_string_safe());
+/// ```
+///
+/// [`u8`]: ../primitive.u8.html
+/// [`&str`]: ../primitive.str.html
+/// [`String`]: ../string/struct.String.html
+/// [`CString`]: struct.CString.html
+/// [`from_ptr`]: #method.from_ptr
+#[derive(Hash)]
+pub struct CStr {
+    // FIXME: this should not be represented with a DST slice but rather with
+    //        just a raw `c_char` along with some form of marker to make
+    //        this an unsized type. Essentially `sizeof(&CStr)` should be the
+    //        same as `sizeof(&c_char)` but `CStr` should be an unsized type.
+    inner: [c_char],
+}
+
+/// An error indicating that an interior nul byte was found.
+///
+/// While Rust strings may contain nul bytes in the middle, C strings
+/// can't, as that byte would effectively truncate the string.
+///
+/// This error is created by the [`new`][`CString::new`] method on
+/// [`CString`]. See its documentation for more.
+///
+/// [`CString`]: struct.CString.html
+/// [`CString::new`]: struct.CString.html#method.new
+///
+/// # Examples
+///
+/// ```
+/// use std::ffi::{CString, NulError};
+///
+/// let _: NulError = CString::new(b"f\0oo".to_vec()).unwrap_err();
+/// ```
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct NulError(usize, Vec<u8>);
+
+/// An error indicating that a nul byte was not in the expected position.
+///
+/// The slice used to create a [`CStr`] must have one and only one nul
+/// byte at the end of the slice.
+///
+/// This error is created by the
+/// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on
+/// [`CStr`]. See its documentation for more.
+///
+/// [`CStr`]: struct.CStr.html
+/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
+///
+/// # Examples
+///
+/// ```
+/// use std::ffi::{CStr, FromBytesWithNulError};
+///
+/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err();
+/// ```
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FromBytesWithNulError {
+    kind: FromBytesWithNulErrorKind,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+enum FromBytesWithNulErrorKind {
+    InteriorNul(usize),
+    NotNulTerminated,
+}
+
+impl FromBytesWithNulError {
+    fn interior_nul(pos: usize) -> FromBytesWithNulError {
+        FromBytesWithNulError {
+            kind: FromBytesWithNulErrorKind::InteriorNul(pos),
+        }
+    }
+    fn not_nul_terminated() -> FromBytesWithNulError {
+        FromBytesWithNulError {
+            kind: FromBytesWithNulErrorKind::NotNulTerminated,
+        }
+    }
+
+    fn description(&self) -> &str {
+        match self.kind {
+            FromBytesWithNulErrorKind::InteriorNul(..) => {
+                "data provided contains an interior nul byte"
+            }
+            FromBytesWithNulErrorKind::NotNulTerminated => "data provided is not nul terminated",
+        }
+    }
+}
+
+/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
+///
+/// `CString` is just a wrapper over a buffer of bytes with a nul
+/// terminator; [`into_string`][`CString::into_string`] performs UTF-8
+/// validation on those bytes and may return this error.
+///
+/// This `struct` is created by the
+/// [`into_string`][`CString::into_string`] method on [`CString`]. See
+/// its documentation for more.
+///
+/// [`String`]: ../string/struct.String.html
+/// [`CString`]: struct.CString.html
+/// [`CString::into_string`]: struct.CString.html#method.into_string
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct IntoStringError {
+    inner: CString,
+    error: Utf8Error,
+}
+
+impl CString {
+    /// Creates a new C-compatible string from a container of bytes.
+    ///
+    /// This function will consume the provided data and use the
+    /// underlying bytes to construct a new string, ensuring that
+    /// there is a trailing 0 byte. This trailing 0 byte will be
+    /// appended by this function; the provided data should *not*
+    /// contain any 0 bytes in it.
+    ///
+    /// # Examples
+    ///
+    /// ```ignore (extern-declaration)
+    /// use std::ffi::CString;
+    /// use std::os::raw::c_char;
+    ///
+    /// extern { fn puts(s: *const c_char); }
+    ///
+    /// let to_print = CString::new("Hello!").unwrap();
+    /// unsafe {
+    ///     puts(to_print.as_ptr());
+    /// }
+    /// ```
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if the supplied bytes contain an
+    /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as
+    /// the position of the nul byte.
+    ///
+    /// [`NulError`]: struct.NulError.html
+    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
+        Self::_new(t.into())
+    }
+
+    fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
+        match memchr(0, &bytes) {
+            Some(i) => Err(NulError(i, bytes)),
+            None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
+        }
+    }
+
+    /// Creates a C-compatible string by consuming a byte vector,
+    /// without checking for interior 0 bytes.
+    ///
+    /// This method is equivalent to [`new`] except that no runtime assertion
+    /// is made that `v` contains no 0 bytes, and it requires an actual
+    /// byte vector, not anything that can be converted to one with Into.
+    ///
+    /// [`new`]: #method.new
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let raw = b"foo".to_vec();
+    /// unsafe {
+    ///     let c_string = CString::from_vec_unchecked(raw);
+    /// }
+    /// ```
+    pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
+        v.reserve_exact(1);
+        v.push(0);
+        CString {
+            inner: v.into_boxed_slice(),
+        }
+    }
+
+    /// Retakes ownership of a `CString` that was transferred to C via [`into_raw`].
+    ///
+    /// Additionally, the length of the string will be recalculated from the pointer.
+    ///
+    /// # Safety
+    ///
+    /// This should only ever be called with a pointer that was earlier
+    /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g. trying to take
+    /// ownership of a string that was allocated by foreign code) is likely to lead
+    /// to undefined behavior or allocator corruption.
+    ///
+    /// > **Note:** If you need to borrow a string that was allocated by
+    /// > foreign code, use [`CStr`]. If you need to take ownership of
+    /// > a string that was allocated by foreign code, you will need to
+    /// > make your own provisions for freeing it appropriately, likely
+    /// > with the foreign code's API to do that.
+    ///
+    /// [`into_raw`]: #method.into_raw
+    /// [`CStr`]: struct.CStr.html
+    ///
+    /// # Examples
+    ///
+    /// Create a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
+    /// ownership with `from_raw`:
+    ///
+    /// ```ignore (extern-declaration)
+    /// use std::ffi::CString;
+    /// use std::os::raw::c_char;
+    ///
+    /// extern {
+    ///     fn some_extern_function(s: *mut c_char);
+    /// }
+    ///
+    /// let c_string = CString::new("Hello!").unwrap();
+    /// let raw = c_string.into_raw();
+    /// unsafe {
+    ///     some_extern_function(raw);
+    ///     let c_string = CString::from_raw(raw);
+    /// }
+    /// ```
+    pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
+        let len = strlen(ptr) + 1; // Including the NUL byte
+        let slice = slice::from_raw_parts_mut(ptr, len as usize);
+        CString {
+            inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]),
+        }
+    }
+
+    /// Consumes the `CString` and transfers ownership of the string to a C caller.
+    ///
+    /// The pointer which this function returns must be returned to Rust and reconstituted using
+    /// [`from_raw`] to be properly deallocated. Specifically, one
+    /// should *not* use the standard C `free()` function to deallocate
+    /// this string.
+    ///
+    /// Failure to call [`from_raw`] will lead to a memory leak.
+    ///
+    /// [`from_raw`]: #method.from_raw
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let c_string = CString::new("foo").unwrap();
+    ///
+    /// let ptr = c_string.into_raw();
+    ///
+    /// unsafe {
+    ///     assert_eq!(b'f', *ptr as u8);
+    ///     assert_eq!(b'o', *ptr.offset(1) as u8);
+    ///     assert_eq!(b'o', *ptr.offset(2) as u8);
+    ///     assert_eq!(b'\0', *ptr.offset(3) as u8);
+    ///
+    ///     // retake pointer to free memory
+    ///     let _ = CString::from_raw(ptr);
+    /// }
+    /// ```
+    #[inline]
+    pub fn into_raw(self) -> *mut c_char {
+        Box::into_raw(self.into_inner()) as *mut c_char
+    }
+
+    /// Converts the `CString` into a [`String`] if it contains valid UTF-8 data.
+    ///
+    /// On failure, ownership of the original `CString` is returned.
+    ///
+    /// [`String`]: ../string/struct.String.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let valid_utf8 = vec![b'f', b'o', b'o'];
+    /// let cstring = CString::new(valid_utf8).unwrap();
+    /// assert_eq!(cstring.into_string().unwrap(), "foo");
+    ///
+    /// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o'];
+    /// let cstring = CString::new(invalid_utf8).unwrap();
+    /// let err = cstring.into_string().err().unwrap();
+    /// assert_eq!(err.utf8_error().valid_up_to(), 1);
+    /// ```
+
+    pub fn into_string(self) -> Result<String, IntoStringError> {
+        String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError {
+            error: e.utf8_error(),
+            inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) },
+        })
+    }
+
+    /// Consumes the `CString` and returns the underlying byte buffer.
+    ///
+    /// The returned buffer does **not** contain the trailing nul
+    /// terminator, and it is guaranteed to not have any interior nul
+    /// bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let c_string = CString::new("foo").unwrap();
+    /// let bytes = c_string.into_bytes();
+    /// assert_eq!(bytes, vec![b'f', b'o', b'o']);
+    /// ```
+    pub fn into_bytes(self) -> Vec<u8> {
+        let mut vec = self.into_inner().into_vec();
+        let _nul = vec.pop();
+        debug_assert_eq!(_nul, Some(0u8));
+        vec
+    }
+
+    /// Equivalent to the [`into_bytes`] function except that the returned vector
+    /// includes the trailing nul terminator.
+    ///
+    /// [`into_bytes`]: #method.into_bytes
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let c_string = CString::new("foo").unwrap();
+    /// let bytes = c_string.into_bytes_with_nul();
+    /// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);
+    /// ```
+    pub fn into_bytes_with_nul(self) -> Vec<u8> {
+        self.into_inner().into_vec()
+    }
+
+    /// Returns the contents of this `CString` as a slice of bytes.
+    ///
+    /// The returned slice does **not** contain the trailing nul
+    /// terminator, and it is guaranteed to not have any interior nul
+    /// bytes. If you need the nul terminator, use
+    /// [`as_bytes_with_nul`] instead.
+    ///
+    /// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let c_string = CString::new("foo").unwrap();
+    /// let bytes = c_string.as_bytes();
+    /// assert_eq!(bytes, &[b'f', b'o', b'o']);
+    /// ```
+    #[inline]
+    pub fn as_bytes(&self) -> &[u8] {
+        &self.inner[..self.inner.len() - 1]
+    }
+
+    /// Equivalent to the [`as_bytes`] function except that the returned slice
+    /// includes the trailing nul terminator.
+    ///
+    /// [`as_bytes`]: #method.as_bytes
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let c_string = CString::new("foo").unwrap();
+    /// let bytes = c_string.as_bytes_with_nul();
+    /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);
+    /// ```
+    #[inline]
+    pub fn as_bytes_with_nul(&self) -> &[u8] {
+        &self.inner
+    }
+
+    /// Extracts a [`CStr`] slice containing the entire string.
+    ///
+    /// [`CStr`]: struct.CStr.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::{CString, CStr};
+    ///
+    /// let c_string = CString::new(b"foo".to_vec()).unwrap();
+    /// let c_str = c_string.as_c_str();
+    /// assert_eq!(c_str, CStr::from_bytes_with_nul(b"foo\0").unwrap());
+    /// ```
+    #[inline]
+    pub fn as_c_str(&self) -> &CStr {
+        &*self
+    }
+
+    /// Converts this `CString` into a boxed [`CStr`].
+    ///
+    /// [`CStr`]: struct.CStr.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::{CString, CStr};
+    ///
+    /// let c_string = CString::new(b"foo".to_vec()).unwrap();
+    /// let boxed = c_string.into_boxed_c_str();
+    /// assert_eq!(&*boxed, CStr::from_bytes_with_nul(b"foo\0").unwrap());
+    /// ```
+    pub fn into_boxed_c_str(self) -> Box<CStr> {
+        unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) }
+    }
+
+    // Bypass "move out of struct which implements [`Drop`] trait" restriction.
+    ///
+    /// [`Drop`]: ../ops/trait.Drop.html
+    fn into_inner(self) -> Box<[u8]> {
+        unsafe {
+            let result = ptr::read(&self.inner);
+            mem::forget(self);
+            result
+        }
+    }
+}
+
+// Turns this `CString` into an empty string to prevent
+// memory unsafe code from working by accident. Inline
+// to prevent LLVM from optimizing it away in debug builds.
+impl Drop for CString {
+    #[inline]
+    fn drop(&mut self) {
+        unsafe {
+            *self.inner.get_unchecked_mut(0) = 0;
+        }
+    }
+}
+
+impl ops::Deref for CString {
+    type Target = CStr;
+
+    #[inline]
+    fn deref(&self) -> &CStr {
+        unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) }
+    }
+}
+
+impl fmt::Debug for CString {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&**self, f)
+    }
+}
+
+impl From<CString> for Vec<u8> {
+    /// Converts a [`CString`] into a [`Vec`]`<u8>`.
+    ///
+    /// The conversion consumes the [`CString`], and removes the terminating NUL byte.
+    ///
+    /// [`Vec`]: ../vec/struct.Vec.html
+    /// [`CString`]: ../ffi/struct.CString.html
+    #[inline]
+    fn from(s: CString) -> Vec<u8> {
+        s.into_bytes()
+    }
+}
+
+impl fmt::Debug for CStr {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "\"")?;
+        for byte in self
+            .to_bytes()
+            .iter()
+            .flat_map(|&b| ascii::escape_default(b))
+        {
+            f.write_char(byte as char)?;
+        }
+        write!(f, "\"")
+    }
+}
+
+impl<'a> Default for &'a CStr {
+    fn default() -> &'a CStr {
+        const SLICE: &'static [c_char] = &[0];
+        unsafe { CStr::from_ptr(SLICE.as_ptr()) }
+    }
+}
+
+impl Default for CString {
+    /// Creates an empty `CString`.
+    fn default() -> CString {
+        let a: &CStr = Default::default();
+        a.to_owned()
+    }
+}
+
+impl Borrow<CStr> for CString {
+    #[inline]
+    fn borrow(&self) -> &CStr {
+        self
+    }
+}
+
+impl<'a> From<Cow<'a, CStr>> for CString {
+    #[inline]
+    fn from(s: Cow<'a, CStr>) -> Self {
+        s.into_owned()
+    }
+}
+
+impl<'a> From<&'a CStr> for Box<CStr> {
+    fn from(s: &'a CStr) -> Box<CStr> {
+        let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul());
+        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
+    }
+}
+
+impl From<Box<CStr>> for CString {
+    /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`CString`]: ../ffi/struct.CString.html
+    #[inline]
+    fn from(s: Box<CStr>) -> CString {
+        s.into_c_string()
+    }
+}
+
+impl Clone for Box<CStr> {
+    #[inline]
+    fn clone(&self) -> Self {
+        (**self).into()
+    }
+}
+
+impl From<CString> for Box<CStr> {
+    /// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Box`]: ../boxed/struct.Box.html
+    #[inline]
+    fn from(s: CString) -> Box<CStr> {
+        s.into_boxed_c_str()
+    }
+}
+
+impl<'a> From<CString> for Cow<'a, CStr> {
+    #[inline]
+    fn from(s: CString) -> Cow<'a, CStr> {
+        Cow::Owned(s)
+    }
+}
+
+impl<'a> From<&'a CStr> for Cow<'a, CStr> {
+    #[inline]
+    fn from(s: &'a CStr) -> Cow<'a, CStr> {
+        Cow::Borrowed(s)
+    }
+}
+
+impl<'a> From<&'a CString> for Cow<'a, CStr> {
+    #[inline]
+    fn from(s: &'a CString) -> Cow<'a, CStr> {
+        Cow::Borrowed(s.as_c_str())
+    }
+}
+
+impl From<CString> for Arc<CStr> {
+    /// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Arc`]: ../sync/struct.Arc.html
+    #[inline]
+    fn from(s: CString) -> Arc<CStr> {
+        let arc: Arc<[u8]> = Arc::from(s.into_inner());
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
+    }
+}
+
+impl<'a> From<&'a CStr> for Arc<CStr> {
+    #[inline]
+    fn from(s: &CStr) -> Arc<CStr> {
+        let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul());
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) }
+    }
+}
+
+impl From<CString> for Rc<CStr> {
+    /// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
+    ///
+    /// [`CString`]: ../ffi/struct.CString.html
+    /// [`Rc`]: ../rc/struct.Rc.html
+    #[inline]
+    fn from(s: CString) -> Rc<CStr> {
+        let rc: Rc<[u8]> = Rc::from(s.into_inner());
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
+    }
+}
+
+impl<'a> From<&'a CStr> for Rc<CStr> {
+    #[inline]
+    fn from(s: &CStr) -> Rc<CStr> {
+        let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul());
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) }
+    }
+}
+
+impl Default for Box<CStr> {
+    fn default() -> Box<CStr> {
+        let boxed: Box<[u8]> = Box::from([0]);
+        unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
+    }
+}
+
+impl NulError {
+    /// Returns the position of the nul byte in the slice that caused
+    /// [`CString::new`] to fail.
+    ///
+    /// [`CString::new`]: struct.CString.html#method.new
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let nul_error = CString::new("foo\0bar").unwrap_err();
+    /// assert_eq!(nul_error.nul_position(), 3);
+    ///
+    /// let nul_error = CString::new("foo bar\0").unwrap_err();
+    /// assert_eq!(nul_error.nul_position(), 7);
+    /// ```
+    pub fn nul_position(&self) -> usize {
+        self.0
+    }
+
+    /// Consumes this error, returning the underlying vector of bytes which
+    /// generated the error in the first place.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let nul_error = CString::new("foo\0bar").unwrap_err();
+    /// assert_eq!(nul_error.into_vec(), b"foo\0bar");
+    /// ```
+    pub fn into_vec(self) -> Vec<u8> {
+        self.1
+    }
+}
+
+impl fmt::Display for NulError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "nul byte found in provided data at position: {}", self.0)
+    }
+}
+
+impl fmt::Display for FromBytesWithNulError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(self.description())?;
+        if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind {
+            write!(f, " at byte pos {}", pos)?;
+        }
+        Ok(())
+    }
+}
+
+impl IntoStringError {
+    /// Consumes this error, returning original [`CString`] which generated the
+    /// error.
+    ///
+    /// [`CString`]: struct.CString.html
+    pub fn into_cstring(self) -> CString {
+        self.inner
+    }
+
+    /// Access the underlying UTF-8 error that was the cause of this error.
+    pub fn utf8_error(&self) -> Utf8Error {
+        self.error
+    }
+
+    fn description(&self) -> &str {
+        "C string contained non-utf8 bytes"
+    }
+}
+
+impl fmt::Display for IntoStringError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.description().fmt(f)
+    }
+}
+
+impl CStr {
+    /// Wraps a raw C string with a safe C string wrapper.
+    ///
+    /// This function will wrap the provided `ptr` with a `CStr` wrapper, which
+    /// allows inspection and interoperation of non-owned C strings. This method
+    /// is unsafe for a number of reasons:
+    ///
+    /// * There is no guarantee to the validity of `ptr`.
+    /// * The returned lifetime is not guaranteed to be the actual lifetime of
+    ///   `ptr`.
+    /// * There is no guarantee that the memory pointed to by `ptr` contains a
+    ///   valid nul terminator byte at the end of the string.
+    /// * It is not guaranteed that the memory pointed by `ptr` won't change
+    ///   before the `CStr` has been destroyed.
+    ///
+    /// > **Note**: This operation is intended to be a 0-cost cast but it is
+    /// > currently implemented with an up-front calculation of the length of
+    /// > the string. This is not guaranteed to always be the case.
+    ///
+    /// # Examples
+    ///
+    /// ```ignore (extern-declaration)
+    /// # fn main() {
+    /// use std::ffi::CStr;
+    /// use std::os::raw::c_char;
+    ///
+    /// extern {
+    ///     fn my_string() -> *const c_char;
+    /// }
+    ///
+    /// unsafe {
+    ///     let slice = CStr::from_ptr(my_string());
+    ///     println!("string returned: {}", slice.to_str().unwrap());
+    /// }
+    /// # }
+    /// ```
+    pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
+        let len = strlen(ptr);
+        let ptr = ptr as *const u8;
+        CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
+    }
+
+    /// Creates a C string wrapper from a byte slice.
+    ///
+    /// This function will cast the provided `bytes` to a `CStr`
+    /// wrapper after ensuring that the byte slice is nul-terminated
+    /// and does not contain any interior nul bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CStr;
+    ///
+    /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
+    /// assert!(cstr.is_ok());
+    /// ```
+    ///
+    /// Creating a `CStr` without a trailing nul terminator is an error:
+    ///
+    /// ```
+    /// use std::ffi::CStr;
+    ///
+    /// let c_str = CStr::from_bytes_with_nul(b"hello");
+    /// assert!(c_str.is_err());
+    /// ```
+    ///
+    /// Creating a `CStr` with an interior nul byte is an error:
+    ///
+    /// ```
+    /// use std::ffi::CStr;
+    ///
+    /// let c_str = CStr::from_bytes_with_nul(b"he\0llo\0");
+    /// assert!(c_str.is_err());
+    /// ```
+    pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> {
+        let nul_pos = memchr(0, bytes);
+        if let Some(nul_pos) = nul_pos {
+            if nul_pos + 1 != bytes.len() {
+                return Err(FromBytesWithNulError::interior_nul(nul_pos));
+            }
+            Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) })
+        } else {
+            Err(FromBytesWithNulError::not_nul_terminated())
+        }
+    }
+
+    /// Unsafely creates a C string wrapper from a byte slice.
+    ///
+    /// This function will cast the provided `bytes` to a `CStr` wrapper without
+    /// performing any sanity checks. The provided slice **must** be nul-terminated
+    /// and not contain any interior nul bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::{CStr, CString};
+    ///
+    /// unsafe {
+    ///     let cstring = CString::new("hello").unwrap();
+    ///     let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
+    ///     assert_eq!(cstr, &*cstring);
+    /// }
+    /// ```
+    #[inline]
+    pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
+        &*(bytes as *const [u8] as *const CStr)
+    }
+
+    /// Returns the inner pointer to this C string.
+    ///
+    /// The returned pointer will be valid for as long as `self` is, and points
+    /// to a contiguous region of memory terminated with a 0 byte to represent
+    /// the end of the string.
+    ///
+    /// **WARNING**
+    ///
+    /// It is your responsibility to make sure that the underlying memory is not
+    /// freed too early. For example, the following code will cause undefined
+    /// behavior when `ptr` is used inside the `unsafe` block:
+    ///
+    /// ```no_run
+    /// # #![allow(unused_must_use)]
+    /// use std::ffi::{CString};
+    ///
+    /// let ptr = CString::new("Hello").unwrap().as_ptr();
+    /// unsafe {
+    ///     // `ptr` is dangling
+    ///     *ptr;
+    /// }
+    /// ```
+    ///
+    /// This happens because the pointer returned by `as_ptr` does not carry any
+    /// lifetime information and the [`CString`] is deallocated immediately after
+    /// the `CString::new("Hello").unwrap().as_ptr()` expression is evaluated.
+    /// To fix the problem, bind the `CString` to a local variable:
+    ///
+    /// ```no_run
+    /// # #![allow(unused_must_use)]
+    /// use std::ffi::{CString};
+    ///
+    /// let hello = CString::new("Hello").unwrap();
+    /// let ptr = hello.as_ptr();
+    /// unsafe {
+    ///     // `ptr` is valid because `hello` is in scope
+    ///     *ptr;
+    /// }
+    /// ```
+    ///
+    /// This way, the lifetime of the `CString` in `hello` encompasses
+    /// the lifetime of `ptr` and the `unsafe` block.
+    ///
+    /// [`CString`]: struct.CString.html
+    #[inline]
+    pub fn as_ptr(&self) -> *const c_char {
+        self.inner.as_ptr()
+    }
+
+    /// Converts this C string to a byte slice.
+    ///
+    /// The returned slice will **not** contain the trailing nul terminator that this C
+    /// string has.
+    ///
+    /// > **Note**: This method is currently implemented as a constant-time
+    /// > cast, but it is planned to alter its definition in the future to
+    /// > perform the length calculation whenever this method is called.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CStr;
+    ///
+    /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
+    /// assert_eq!(c_str.to_bytes(), b"foo");
+    /// ```
+    #[inline]
+    pub fn to_bytes(&self) -> &[u8] {
+        let bytes = self.to_bytes_with_nul();
+        &bytes[..bytes.len() - 1]
+    }
+
+    /// Converts this C string to a byte slice containing the trailing 0 byte.
+    ///
+    /// This function is the equivalent of [`to_bytes`] except that it will retain
+    /// the trailing nul terminator instead of chopping it off.
+    ///
+    /// > **Note**: This method is currently implemented as a 0-cost cast, but
+    /// > it is planned to alter its definition in the future to perform the
+    /// > length calculation whenever this method is called.
+    ///
+    /// [`to_bytes`]: #method.to_bytes
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CStr;
+    ///
+    /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
+    /// assert_eq!(c_str.to_bytes_with_nul(), b"foo\0");
+    /// ```
+    #[inline]
+    pub fn to_bytes_with_nul(&self) -> &[u8] {
+        unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
+    }
+
+    /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
+    ///
+    /// If the contents of the `CStr` are valid UTF-8 data, this
+    /// function will return the corresponding [`&str`] slice. Otherwise,
+    /// it will return an error with details of where UTF-8 validation failed.
+    ///
+    /// > **Note**: This method is currently implemented to check for validity
+    /// > after a constant-time cast, but it is planned to alter its definition
+    /// > in the future to perform the length calculation in addition to the
+    /// > UTF-8 check whenever this method is called.
+    ///
+    /// [`&str`]: ../primitive.str.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CStr;
+    ///
+    /// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
+    /// assert_eq!(c_str.to_str(), Ok("foo"));
+    /// ```
+    pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
+        // NB: When CStr is changed to perform the length check in .to_bytes()
+        // instead of in from_ptr(), it may be worth considering if this should
+        // be rewritten to do the UTF-8 check inline with the length calculation
+        // instead of doing it afterwards.
+        str::from_utf8(self.to_bytes())
+    }
+
+    /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`.
+    ///
+    /// If the contents of the `CStr` are valid UTF-8 data, this
+    /// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)`
+    /// with the the corresponding [`&str`] slice. Otherwise, it will
+    /// replace any invalid UTF-8 sequences with
+    /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
+    /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
+    ///
+    /// > **Note**: This method is currently implemented to check for validity
+    /// > after a constant-time cast, but it is planned to alter its definition
+    /// > in the future to perform the length calculation in addition to the
+    /// > UTF-8 check whenever this method is called.
+    ///
+    /// [`Cow`]: ../borrow/enum.Cow.html
+    /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
+    /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned
+    /// [`str`]: ../primitive.str.html
+    /// [`String`]: ../string/struct.String.html
+    /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html
+    ///
+    /// # Examples
+    ///
+    /// Calling `to_string_lossy` on a `CStr` containing valid UTF-8:
+    ///
+    /// ```
+    /// use std::borrow::Cow;
+    /// use std::ffi::CStr;
+    ///
+    /// let c_str = CStr::from_bytes_with_nul(b"Hello World\0").unwrap();
+    /// assert_eq!(c_str.to_string_lossy(), Cow::Borrowed("Hello World"));
+    /// ```
+    ///
+    /// Calling `to_string_lossy` on a `CStr` containing invalid UTF-8:
+    ///
+    /// ```
+    /// use std::borrow::Cow;
+    /// use std::ffi::CStr;
+    ///
+    /// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0").unwrap();
+    /// assert_eq!(
+    ///     c_str.to_string_lossy(),
+    ///     Cow::Owned(String::from("Hello �World")) as Cow<str>
+    /// );
+    /// ```
+    pub fn to_string_lossy(&self) -> Cow<str> {
+        String::from_utf8_lossy(self.to_bytes())
+    }
+
+    /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
+    ///
+    /// [`Box`]: ../boxed/struct.Box.html
+    /// [`CString`]: struct.CString.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ffi::CString;
+    ///
+    /// let c_string = CString::new(b"foo".to_vec()).unwrap();
+    /// let boxed = c_string.into_boxed_c_str();
+    /// assert_eq!(boxed.into_c_string(), CString::new("foo").unwrap());
+    /// ```
+    pub fn into_c_string(self: Box<CStr>) -> CString {
+        let raw = Box::into_raw(self) as *mut [u8];
+        CString {
+            inner: unsafe { Box::from_raw(raw) },
+        }
+    }
+}
+
+impl PartialEq for CStr {
+    fn eq(&self, other: &CStr) -> bool {
+        self.to_bytes().eq(other.to_bytes())
+    }
+}
+
+impl Eq for CStr {}
+
+impl PartialOrd for CStr {
+    fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
+        self.to_bytes().partial_cmp(&other.to_bytes())
+    }
+}
+
+impl Ord for CStr {
+    fn cmp(&self, other: &CStr) -> Ordering {
+        self.to_bytes().cmp(&other.to_bytes())
+    }
+}
+
+impl ToOwned for CStr {
+    type Owned = CString;
+
+    fn to_owned(&self) -> CString {
+        CString {
+            inner: self.to_bytes_with_nul().into(),
+        }
+    }
+}
+
+impl<'a> From<&'a CStr> for CString {
+    fn from(s: &'a CStr) -> CString {
+        s.to_owned()
+    }
+}
+
+impl ops::Index<ops::RangeFull> for CString {
+    type Output = CStr;
+
+    #[inline]
+    fn index(&self, _index: ops::RangeFull) -> &CStr {
+        self
+    }
+}
+
+impl AsRef<CStr> for CStr {
+    #[inline]
+    fn as_ref(&self) -> &CStr {
+        self
+    }
+}
+
+impl AsRef<CStr> for CString {
+    #[inline]
+    fn as_ref(&self) -> &CStr {
+        self
+    }
+}
diff --git a/src/crt0/Cargo.toml b/src/crt0/Cargo.toml
index 9133360068f67e4df8a953d5bb00bb2f87f22622..9b6c91a2bf4afecf46976043e5f2d2b43535ff19 100644
--- a/src/crt0/Cargo.toml
+++ b/src/crt0/Cargo.toml
@@ -8,5 +8,4 @@ name = "crt0"
 crate-type = ["staticlib"]
 
 [dependencies]
-platform = { path = "../platform" }
-stdio = { path = "../stdio" }
+relibc = { path = "../.." }
diff --git a/src/crt0/src/lib.rs b/src/crt0/src/lib.rs
index e790ec60d0d8f69b173a7782306b389f20beab07..ca2c2ff2e23620fcb730d8b569f192ff68b18e33 100644
--- a/src/crt0/src/lib.rs
+++ b/src/crt0/src/lib.rs
@@ -1,20 +1,11 @@
 //! crt0
 
 #![no_std]
-#![feature(alloc)]
 #![feature(asm)]
+#![feature(lang_items)]
 #![feature(linkage)]
 #![feature(naked_functions)]
 #![feature(panic_implementation)]
-#![feature(lang_items)]
-
-extern crate alloc;
-extern crate platform;
-extern crate stdio;
-
-use alloc::Vec;
-use core::ptr;
-use platform::types::*;
 
 #[no_mangle]
 #[naked]
@@ -22,7 +13,7 @@ pub unsafe extern "C" fn _start() {
     #[cfg(target_arch = "x86_64")]
     asm!("mov rdi, rsp
         and rsp, 0xFFFFFFFFFFFFFFF0
-        call _start_rust"
+        call relibc_start"
         :
         :
         :
@@ -30,7 +21,7 @@ pub unsafe extern "C" fn _start() {
     );
     #[cfg(target_arch = "aarch64")]
     asm!("mov x0, sp
-        bl _start_rust"
+        bl relibc_start"
         :
         :
         :
@@ -38,96 +29,13 @@ pub unsafe extern "C" fn _start() {
     );
 }
 
-#[repr(C)]
-pub struct Stack {
-    argc: isize,
-    argv0: *const c_char,
-}
-
-impl Stack {
-    fn argc(&self) -> isize {
-        self.argc
-    }
-
-    fn argv(&self) -> *const *const c_char {
-        &self.argv0 as *const _
-    }
-
-    fn envp(&self) -> *const *const c_char {
-        unsafe { self.argv().offset(self.argc() + 1) }
-    }
-}
-
-#[inline(never)]
-#[no_mangle]
-pub unsafe extern "C" fn _start_rust(sp: &'static Stack) -> ! {
-    extern "C" {
-        fn main(argc: isize, argv: *const *const c_char, envp: *const *const c_char) -> c_int;
-    }
-
-    let argc = sp.argc();
-    let argv = sp.argv();
-
-    let envp = sp.envp();
-    let mut len = 0;
-    while *envp.offset(len) != ptr::null() {
-        len += 1;
-    }
-    platform::inner_environ = Vec::with_capacity(len as usize + 1);
-    for i in 0..len {
-        let mut item = *envp.offset(i);
-        let mut len = 0;
-        while *item.offset(len) != 0 {
-            len += 1;
-        }
-
-        let buf = platform::alloc(len as usize + 1) as *mut c_char;
-        for i in 0..=len {
-            *buf.offset(i) = *item.offset(i);
-        }
-        platform::inner_environ.push(buf);
-    }
-    platform::inner_environ.push(ptr::null_mut());
-    platform::environ = platform::inner_environ.as_mut_ptr();
-
-    // Initialize stdin/stdout/stderr, see https://github.com/rust-lang/rust/issues/51718
-    stdio::stdin = stdio::default_stdin.get();
-    stdio::stdout = stdio::default_stdout.get();
-    stdio::stderr = stdio::default_stderr.get();
-
-    platform::exit(main(
-        argc,
-        argv,
-        // not envp, because programs like bash try to modify this *const*
-        // pointer :|
-        platform::environ as *const *const c_char
-    ));
-}
-
 #[panic_implementation]
 #[linkage = "weak"]
 #[no_mangle]
-pub extern "C" fn rust_begin_unwind(pi: &::core::panic::PanicInfo) -> ! {
-    use core::fmt::Write;
-
-    let mut w = platform::FileWriter(2);
-    let _ = w.write_fmt(format_args!("RELIBC CRT0 PANIC: {}\n", pi));
-
-    platform::exit(1);
-}
-
-#[lang = "oom"]
-#[linkage = "weak"]
-#[no_mangle]
-pub extern "C" fn rust_oom(layout: ::core::alloc::Layout) -> ! {
-    use core::fmt::Write;
-
-    let mut w = platform::FileWriter(2);
-    let _ = w.write_fmt(format_args!(
-        "RELIBC OOM: {} bytes aligned to {} bytes\n",
-        layout.size(),
-        layout.align()
-    ));
+pub extern "C" fn rust_begin_unwind(_pi: &::core::panic::PanicInfo) -> ! {
+    extern "C" {
+        fn exit(status: i32) -> !;
+    }
 
-    platform::exit(1);
+    unsafe { exit(1) }
 }
diff --git a/src/ctype/Cargo.toml b/src/ctype/Cargo.toml
deleted file mode 100644
index f8f98d92956a3d29c6433363e2e6f12aa7fa7b4f..0000000000000000000000000000000000000000
--- a/src/ctype/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "ctype"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/ctype/build.rs b/src/ctype/build.rs
deleted file mode 100644
index 9b1ee3aecbc76216eea19fc7dfa6be44097a5f78..0000000000000000000000000000000000000000
--- a/src/ctype/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/ctype.h");
-}
diff --git a/src/dirent/Cargo.toml b/src/dirent/Cargo.toml
deleted file mode 100644
index fb799207a871b9a48d37b50f77bf6db561f75b02..0000000000000000000000000000000000000000
--- a/src/dirent/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "dirent"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-errno = { path = "../errno" }
-fcntl = { path = "../fcntl" }
-platform = { path = "../platform" }
-stdio = { path = "../stdio" }
-unistd = { path = "../unistd" }
diff --git a/src/dirent/build.rs b/src/dirent/build.rs
deleted file mode 100644
index 252c1648cb77d26a760a81eee0ba29cc1be1cbe6..0000000000000000000000000000000000000000
--- a/src/dirent/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/dirent.h");
-}
diff --git a/src/errno/Cargo.toml b/src/errno/Cargo.toml
deleted file mode 100644
index cfaaad846516b32966aeee42efc7b2399cfcc070..0000000000000000000000000000000000000000
--- a/src/errno/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "errno"
-version = "0.1.0"
-authors = ["Alex Lyon <arcterus@mail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/errno/build.rs b/src/errno/build.rs
deleted file mode 100644
index 5de392d433998a6e0f7412671017b5bd5659eec0..0000000000000000000000000000000000000000
--- a/src/errno/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/errno.h");
-}
diff --git a/src/fcntl/Cargo.toml b/src/fcntl/Cargo.toml
deleted file mode 100644
index c2b0198c38151910437d388ef3dc4f071568d93d..0000000000000000000000000000000000000000
--- a/src/fcntl/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "fcntl"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/fcntl/build.rs b/src/fcntl/build.rs
deleted file mode 100644
index fb1647837e07bdee25a395f6bd12c5631238b463..0000000000000000000000000000000000000000
--- a/src/fcntl/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/fcntl.h");
-}
diff --git a/src/fcntl/src/linux.rs b/src/fcntl/src/linux.rs
deleted file mode 100644
index 05948a6da50d482a5f6879dccffd6285c588b48c..0000000000000000000000000000000000000000
--- a/src/fcntl/src/linux.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-use platform::types::*;
-
-pub const O_RDONLY: c_int = 0x0000;
-pub const O_WRONLY: c_int = 0x0001;
-pub const O_RDWR: c_int = 0x0002;
-pub const O_CREAT: c_int = 0x0040;
-pub const O_TRUNC: c_int = 0x0200;
-pub const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
-pub const O_APPEND: c_int = 0o2000;
-pub const O_CLOEXEC: c_int = 0o2_000_000;
-pub const O_DIRECTORY: c_int = 0o200_000;
-pub const O_EXCL: c_int = 0o200;
-pub const O_NONBLOCK: c_int = 0o4000;
diff --git a/src/fenv/Cargo.toml b/src/fenv/Cargo.toml
deleted file mode 100644
index ed3b2142f1ef12b8633facefa01f928e44dd88cc..0000000000000000000000000000000000000000
--- a/src/fenv/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-name = "fenv"
-version = "0.1.0"
-authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/fenv/build.rs b/src/fenv/build.rs
deleted file mode 100644
index a79287ee765847e4e356072d1d6e23645dd809d3..0000000000000000000000000000000000000000
--- a/src/fenv/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/fenv.h");
-}
diff --git a/src/float/Cargo.toml b/src/float/Cargo.toml
deleted file mode 100644
index 3ae7acb3fe4310522973543c42183a26d597b0b7..0000000000000000000000000000000000000000
--- a/src/float/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "float"
-version = "0.1.0"
-authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
-fenv = { path = "../fenv" }
diff --git a/src/float/build.rs b/src/float/build.rs
deleted file mode 100644
index e9b224fd13a684c9821fc850fab69b5781da650b..0000000000000000000000000000000000000000
--- a/src/float/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/float.h");
-}
diff --git a/src/fnmatch/Cargo.toml b/src/fnmatch/Cargo.toml
deleted file mode 100644
index 9d9a891de3089fe4318672740400615468e2d0a0..0000000000000000000000000000000000000000
--- a/src/fnmatch/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-name = "fnmatch"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/fnmatch/build.rs b/src/fnmatch/build.rs
deleted file mode 100644
index 2b6e70c118cf3f73c86f607731aaa878de9f4b24..0000000000000000000000000000000000000000
--- a/src/fnmatch/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-      .expect("failed to generate bindings")
-      .write_to_file("../../target/include/fnmatch.h");
-}
diff --git a/src/grp/Cargo.toml b/src/grp/Cargo.toml
deleted file mode 100644
index d9eb91db9e0c85754f878946316bb343346560e9..0000000000000000000000000000000000000000
--- a/src/grp/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "grp"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/grp/build.rs b/src/grp/build.rs
deleted file mode 100644
index 196206d6c4b3e921d8cebb8fff9a7674a487f1f9..0000000000000000000000000000000000000000
--- a/src/grp/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/grp.h");
-}
diff --git a/src/todo/oldlib/dns/answer.rs b/src/header/_oldlib/dns/answer.rs
similarity index 100%
rename from src/todo/oldlib/dns/answer.rs
rename to src/header/_oldlib/dns/answer.rs
diff --git a/src/todo/oldlib/dns/mod.rs b/src/header/_oldlib/dns/mod.rs
similarity index 100%
rename from src/todo/oldlib/dns/mod.rs
rename to src/header/_oldlib/dns/mod.rs
diff --git a/src/todo/oldlib/dns/query.rs b/src/header/_oldlib/dns/query.rs
similarity index 100%
rename from src/todo/oldlib/dns/query.rs
rename to src/header/_oldlib/dns/query.rs
diff --git a/src/todo/oldlib/event.rs b/src/header/_oldlib/event.rs
similarity index 100%
rename from src/todo/oldlib/event.rs
rename to src/header/_oldlib/event.rs
diff --git a/src/todo/oldlib/file.rs b/src/header/_oldlib/file.rs
similarity index 100%
rename from src/todo/oldlib/file.rs
rename to src/header/_oldlib/file.rs
diff --git a/src/todo/oldlib/folder.rs b/src/header/_oldlib/folder.rs
similarity index 100%
rename from src/todo/oldlib/folder.rs
rename to src/header/_oldlib/folder.rs
diff --git a/src/todo/oldlib/hostname.rs b/src/header/_oldlib/hostname.rs
similarity index 100%
rename from src/todo/oldlib/hostname.rs
rename to src/header/_oldlib/hostname.rs
diff --git a/src/todo/oldlib/lib.rs b/src/header/_oldlib/lib.rs
similarity index 100%
rename from src/todo/oldlib/lib.rs
rename to src/header/_oldlib/lib.rs
diff --git a/src/todo/oldlib/macros.rs b/src/header/_oldlib/macros.rs
similarity index 100%
rename from src/todo/oldlib/macros.rs
rename to src/header/_oldlib/macros.rs
diff --git a/src/todo/oldlib/mallocnull.rs b/src/header/_oldlib/mallocnull.rs
similarity index 100%
rename from src/todo/oldlib/mallocnull.rs
rename to src/header/_oldlib/mallocnull.rs
diff --git a/src/todo/oldlib/netdb.rs b/src/header/_oldlib/netdb.rs
similarity index 100%
rename from src/todo/oldlib/netdb.rs
rename to src/header/_oldlib/netdb.rs
diff --git a/src/todo/oldlib/process.rs b/src/header/_oldlib/process.rs
similarity index 100%
rename from src/todo/oldlib/process.rs
rename to src/header/_oldlib/process.rs
diff --git a/src/todo/oldlib/rawfile.rs b/src/header/_oldlib/rawfile.rs
similarity index 100%
rename from src/todo/oldlib/rawfile.rs
rename to src/header/_oldlib/rawfile.rs
diff --git a/src/todo/oldlib/redox.rs b/src/header/_oldlib/redox.rs
similarity index 100%
rename from src/todo/oldlib/redox.rs
rename to src/header/_oldlib/redox.rs
diff --git a/src/todo/oldlib/socket.rs b/src/header/_oldlib/socket.rs
similarity index 100%
rename from src/todo/oldlib/socket.rs
rename to src/header/_oldlib/socket.rs
diff --git a/src/todo/oldlib/termios.rs b/src/header/_oldlib/termios.rs
similarity index 100%
rename from src/todo/oldlib/termios.rs
rename to src/header/_oldlib/termios.rs
diff --git a/src/todo/oldlib/time.rs b/src/header/_oldlib/time.rs
similarity index 100%
rename from src/todo/oldlib/time.rs
rename to src/header/_oldlib/time.rs
diff --git a/src/todo/oldlib/types.rs b/src/header/_oldlib/types.rs
similarity index 100%
rename from src/todo/oldlib/types.rs
rename to src/header/_oldlib/types.rs
diff --git a/src/todo/oldlib/unimpl.rs b/src/header/_oldlib/unimpl.rs
similarity index 100%
rename from src/todo/oldlib/unimpl.rs
rename to src/header/_oldlib/unimpl.rs
diff --git a/src/todo/oldlib/user.rs b/src/header/_oldlib/user.rs
similarity index 100%
rename from src/todo/oldlib/user.rs
rename to src/header/_oldlib/user.rs
diff --git a/src/header/_pthread/cbindgen.toml b/src/header/_pthread/cbindgen.toml
new file mode 100644
index 0000000000000000000000000000000000000000..a1ea51c3f35fbfdecd72eca0eac08231f534d976
--- /dev/null
+++ b/src/header/_pthread/cbindgen.toml
@@ -0,0 +1,7 @@
+sys_includes = []
+include_guard = "_PTHREAD_H"
+language = "C"
+style = "Tag"
+
+[enum]
+prefix_with_name = true
diff --git a/src/todo/pthread/lib.rs b/src/header/_pthread/mod.rs
similarity index 69%
rename from src/todo/pthread/lib.rs
rename to src/header/_pthread/mod.rs
index 661c9cdf2813b3367e82e887865f86809169bd0e..b02f301a5177c01f5f50d5a78cd01086b4d136af 100644
--- a/src/todo/pthread/lib.rs
+++ b/src/header/_pthread/mod.rs
@@ -1,13 +1,26 @@
+use platform::types::*;
+
+#[repr(C)]
+#[derive(Debug, Copy)]
+pub struct sched_param {
+    pub _address: u8,
+}
+impl Clone for sched_param {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
 // #[no_mangle]
-pub extern "C" fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> libc::c_int {
+pub extern "C" fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_getdetachstate(
     attr: *const pthread_attr_t,
-    detachstate: *mut libc::c_int,
-) -> libc::c_int {
+    detachstate: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
@@ -15,15 +28,15 @@ pub extern "C" fn pthread_attr_getdetachstate(
 pub extern "C" fn pthread_attr_getguardsize(
     attr: *const pthread_attr_t,
     guardsize: *mut usize,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_getinheritsched(
     attr: *const pthread_attr_t,
-    inheritsched: *mut libc::c_int,
-) -> libc::c_int {
+    inheritsched: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
@@ -31,31 +44,31 @@ pub extern "C" fn pthread_attr_getinheritsched(
 pub extern "C" fn pthread_attr_getschedparam(
     attr: *const pthread_attr_t,
     param: *mut sched_param,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_getschedpolicy(
     attr: *const pthread_attr_t,
-    policy: *mut libc::c_int,
-) -> libc::c_int {
+    policy: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_getscope(
     attr: *const pthread_attr_t,
-    contentionscope: *mut libc::c_int,
-) -> libc::c_int {
+    contentionscope: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_getstackaddr(
     attr: *const pthread_attr_t,
-    stackaddr: *mut *mut libc::c_void,
-) -> libc::c_int {
+    stackaddr: *mut *mut c_void,
+) -> c_int {
     unimplemented!();
 }
 
@@ -63,33 +76,33 @@ pub extern "C" fn pthread_attr_getstackaddr(
 pub extern "C" fn pthread_attr_getstacksize(
     attr: *const pthread_attr_t,
     stacksize: *mut usize,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_attr_init(arg1: *mut pthread_attr_t) -> libc::c_int {
+pub extern "C" fn pthread_attr_init(arg1: *mut pthread_attr_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_setdetachstate(
     attr: *mut pthread_attr_t,
-    detachstate: libc::c_int,
-) -> libc::c_int {
+    detachstate: c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_attr_setguardsize(arg1: *mut pthread_attr_t, arg2: usize) -> libc::c_int {
+pub extern "C" fn pthread_attr_setguardsize(arg1: *mut pthread_attr_t, arg2: usize) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_setinheritsched(
     attr: *mut pthread_attr_t,
-    inheritsched: libc::c_int,
-) -> libc::c_int {
+    inheritsched: c_int,
+) -> c_int {
     unimplemented!();
 }
 
@@ -97,61 +110,61 @@ pub extern "C" fn pthread_attr_setinheritsched(
 pub extern "C" fn pthread_attr_setschedparam(
     attr: *mut pthread_attr_t,
     param: *mut sched_param,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_setschedpolicy(
     attr: *mut pthread_attr_t,
-    policy: libc::c_int,
-) -> libc::c_int {
+    policy: c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_setscope(
     attr: *mut pthread_attr_t,
-    contentionscope: libc::c_int,
-) -> libc::c_int {
+    contentionscope: c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_attr_setstackaddr(
     attr: *mut pthread_attr_t,
-    stackaddr: *mut libc::c_void,
-) -> libc::c_int {
+    stackaddr: *mut c_void,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, stacksize: usize) -> libc::c_int {
+pub extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, stacksize: usize) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_cancel(thread: pthread_t) -> libc::c_int {
+pub extern "C" fn pthread_cancel(thread: pthread_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_cleanup_push(routine: *mut libc::c_void, arg: *mut libc::c_void) {
+pub extern "C" fn pthread_cleanup_push(routine: *mut c_void, arg: *mut c_void) {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_cleanup_pop(execute: libc::c_int) {
+pub extern "C" fn pthread_cleanup_pop(execute: c_int) {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> libc::c_int {
+pub extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> libc::c_int {
+pub extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int {
     unimplemented!();
 }
 
@@ -159,12 +172,12 @@ pub extern "C" fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> libc::c_int
 pub extern "C" fn pthread_cond_init(
     cond: *mut pthread_cond_t,
     attr: *const pthread_condattr_t,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> libc::c_int {
+pub extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
     unimplemented!();
 }
 
@@ -173,7 +186,7 @@ pub extern "C" fn pthread_cond_timedwait(
     cond: *mut pthread_cond_t,
     mutex: *mut pthread_mutex_t,
     abstime: *const timespec,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
@@ -181,33 +194,33 @@ pub extern "C" fn pthread_cond_timedwait(
 pub extern "C" fn pthread_cond_wait(
     cond: *mut pthread_cond_t,
     mutex: *mut pthread_mutex_t,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> libc::c_int {
+pub extern "C" fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_condattr_getpshared(
     attr: *const pthread_condattr_t,
-    pshared: *mut libc::c_int,
-) -> libc::c_int {
+    pshared: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> libc::c_int {
+pub extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_condattr_setpshared(
     attr: *mut pthread_condattr_t,
-    pshared: libc::c_int,
-) -> libc::c_int {
+    pshared: c_int,
+) -> c_int {
     unimplemented!();
 }
 
@@ -215,74 +228,74 @@ pub extern "C" fn pthread_condattr_setpshared(
 pub extern "C" fn pthread_create(
     thread: *mut pthread_t,
     attr: *const pthread_attr_t,
-    start_routine: Option<unsafe extern "C" fn(arg1: *mut libc::c_void) -> *mut libc::c_void>,
-    arg: *mut libc::c_void,
-) -> libc::c_int {
+    start_routine: Option<unsafe extern "C" fn(arg1: *mut c_void) -> *mut c_void>,
+    arg: *mut c_void,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_detach(thread: pthread_t) -> libc::c_int {
+pub extern "C" fn pthread_detach(thread: pthread_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_equal(t1: pthread_t, t2: pthread_t) -> libc::c_int {
+pub extern "C" fn pthread_equal(t1: pthread_t, t2: pthread_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_exit(value_ptr: *mut libc::c_void) {
+pub extern "C" fn pthread_exit(value_ptr: *mut c_void) {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_getconcurrency() -> libc::c_int {
+pub extern "C" fn pthread_getconcurrency() -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_getschedparam(
     thread: pthread_t,
-    policy: *mut libc::c_int,
+    policy: *mut c_int,
     param: *mut sched_param,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut libc::c_void {
+pub extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_join(thread: pthread_t, value_ptr: *mut *mut libc::c_void) -> libc::c_int {
+pub extern "C" fn pthread_join(thread: pthread_t, value_ptr: *mut *mut c_void) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_key_create(
     key: *mut pthread_key_t,
-    destructor: Option<unsafe extern "C" fn(arg1: *mut libc::c_void)>,
-) -> libc::c_int {
+    destructor: Option<unsafe extern "C" fn(arg1: *mut c_void)>,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_key_delete(key: pthread_key_t) -> libc::c_int {
+pub extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> libc::c_int {
+pub extern "C" fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutex_getprioceiling(
     mutex: *const pthread_mutex_t,
-    prioceiling: *mut libc::c_int,
-) -> libc::c_int {
+    prioceiling: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
@@ -290,105 +303,105 @@ pub extern "C" fn pthread_mutex_getprioceiling(
 pub extern "C" fn pthread_mutex_init(
     mutex: *mut pthread_mutex_t,
     attr: *const pthread_mutexattr_t,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> libc::c_int {
+pub extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutex_setprioceiling(
     mutex: *mut pthread_mutex_t,
-    prioceiling: libc::c_int,
-    old_ceiling: *mut libc::c_int,
-) -> libc::c_int {
+    prioceiling: c_int,
+    old_ceiling: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> libc::c_int {
+pub extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> libc::c_int {
+pub extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> libc::c_int {
+pub extern "C" fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutexattr_getprioceiling(
     attr: *const pthread_mutexattr_t,
-    prioceiling: *mut libc::c_int,
-) -> libc::c_int {
+    prioceiling: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutexattr_getprotocol(
     attr: *const pthread_mutexattr_t,
-    protocol: *mut libc::c_int,
-) -> libc::c_int {
+    protocol: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutexattr_getpshared(
     attr: *const pthread_mutexattr_t,
-    pshared: *mut libc::c_int,
-) -> libc::c_int {
+    pshared: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutexattr_gettype(
     attr: *const pthread_mutexattr_t,
-    type_: *mut libc::c_int,
-) -> libc::c_int {
+    type_: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> libc::c_int {
+pub extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutexattr_setprioceiling(
     attr: *mut pthread_mutexattr_t,
-    prioceiling: libc::c_int,
-) -> libc::c_int {
+    prioceiling: c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutexattr_setprotocol(
     attr: *mut pthread_mutexattr_t,
-    protocol: libc::c_int,
-) -> libc::c_int {
+    protocol: c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutexattr_setpshared(
     attr: *mut pthread_mutexattr_t,
-    pshared: libc::c_int,
-) -> libc::c_int {
+    pshared: c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_mutexattr_settype(
     attr: *mut pthread_mutexattr_t,
-    type_: libc::c_int,
-) -> libc::c_int {
+    type_: c_int,
+) -> c_int {
     unimplemented!();
 }
 
@@ -396,12 +409,12 @@ pub extern "C" fn pthread_mutexattr_settype(
 pub extern "C" fn pthread_once(
     once_control: *mut pthread_once_t,
     init_routine: Option<unsafe extern "C" fn()>,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_rwlock_destroy(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
+pub extern "C" fn pthread_rwlock_destroy(rwlock: *mut pthread_rwlock_t) -> c_int {
     unimplemented!();
 }
 
@@ -409,58 +422,58 @@ pub extern "C" fn pthread_rwlock_destroy(rwlock: *mut pthread_rwlock_t) -> libc:
 pub extern "C" fn pthread_rwlock_init(
     rwlock: *mut pthread_rwlock_t,
     attr: *const pthread_rwlockattr_t,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_rwlock_rdlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
+pub extern "C" fn pthread_rwlock_rdlock(rwlock: *mut pthread_rwlock_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_rwlock_tryrdlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
+pub extern "C" fn pthread_rwlock_tryrdlock(rwlock: *mut pthread_rwlock_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_rwlock_trywrlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
+pub extern "C" fn pthread_rwlock_trywrlock(rwlock: *mut pthread_rwlock_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_rwlock_unlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
+pub extern "C" fn pthread_rwlock_unlock(rwlock: *mut pthread_rwlock_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_rwlock_wrlock(rwlock: *mut pthread_rwlock_t) -> libc::c_int {
+pub extern "C" fn pthread_rwlock_wrlock(rwlock: *mut pthread_rwlock_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_rwlockattr_destroy(rwlock: *mut pthread_rwlockattr_t) -> libc::c_int {
+pub extern "C" fn pthread_rwlockattr_destroy(rwlock: *mut pthread_rwlockattr_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_rwlockattr_getpshared(
     rwlock: *const pthread_rwlockattr_t,
-    pshared: *mut libc::c_int,
-) -> libc::c_int {
+    pshared: *mut c_int,
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_rwlockattr_init(rwlock: *mut pthread_rwlockattr_t) -> libc::c_int {
+pub extern "C" fn pthread_rwlockattr_init(rwlock: *mut pthread_rwlockattr_t) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_rwlockattr_setpshared(
     rwlock: *mut pthread_rwlockattr_t,
-    pshared: libc::c_int,
-) -> libc::c_int {
+    pshared: c_int,
+) -> c_int {
     unimplemented!();
 }
 
@@ -470,34 +483,34 @@ pub extern "C" fn pthread_self() -> pthread_t {
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_setcancelstate(state: libc::c_int, oldstate: *mut libc::c_int) -> libc::c_int {
+pub extern "C" fn pthread_setcancelstate(state: c_int, oldstate: *mut c_int) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_setcanceltype(type_: libc::c_int, oldtype: *mut libc::c_int) -> libc::c_int {
+pub extern "C" fn pthread_setcanceltype(type_: c_int, oldtype: *mut c_int) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn pthread_setconcurrency(new_level: libc::c_int) -> libc::c_int {
+pub extern "C" fn pthread_setconcurrency(new_level: c_int) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_setschedparam(
     thread: pthread_t,
-    policy: libc::c_int,
+    policy: c_int,
     param: *mut sched_param,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn pthread_setspecific(
     key: pthread_key_t,
-    value: *const libc::c_void,
-) -> libc::c_int {
+    value: *const c_void,
+) -> c_int {
     unimplemented!();
 }
 
@@ -505,44 +518,3 @@ pub extern "C" fn pthread_setspecific(
 pub extern "C" fn pthread_testcancel() {
     unimplemented!();
 }
-
-#[repr(C)]
-#[derive(Debug, Copy)]
-pub struct sched_param {
-    pub _address: u8,
-}
-impl Clone for sched_param {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
-#[repr(C)]
-#[derive(Debug, Copy)]
-pub struct sched_param {
-    pub _address: u8,
-}
-impl Clone for sched_param {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
-#[repr(C)]
-#[derive(Debug, Copy)]
-pub struct sched_param {
-    pub _address: u8,
-}
-impl Clone for sched_param {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
-#[repr(C)]
-#[derive(Debug, Copy)]
-pub struct sched_param {
-    pub _address: u8,
-}
-impl Clone for sched_param {
-    fn clone(&self) -> Self {
-        *self
-    }
-}
diff --git a/src/template/cbindgen.toml b/src/header/_template/cbindgen.toml
similarity index 100%
rename from src/template/cbindgen.toml
rename to src/header/_template/cbindgen.toml
diff --git a/src/template/src/lib.rs b/src/header/_template/mod.rs
similarity index 86%
rename from src/template/src/lib.rs
rename to src/header/_template/mod.rs
index e0c83c7cef6b09ba428d036c27b923657416048b..ed73313a1d0ff4698d071a339f46677437deecb1 100644
--- a/src/template/src/lib.rs
+++ b/src/header/_template/mod.rs
@@ -1,9 +1,5 @@
 //! template implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/template.h.html
 
-#![no_std]
-
-extern crate platform;
-
 use platform::types::*;
 
 /*
diff --git a/src/header/aio/cbindgen.toml b/src/header/aio/cbindgen.toml
new file mode 100644
index 0000000000000000000000000000000000000000..007f687f949f86fd27d7d6fa2e0aaa8542ca70b3
--- /dev/null
+++ b/src/header/aio/cbindgen.toml
@@ -0,0 +1,7 @@
+sys_includes = []
+include_guard = "_AIO_H"
+language = "C"
+style = "Tag"
+
+[enum]
+prefix_with_name = true
diff --git a/src/todo/aio/lib.rs b/src/header/aio/mod.rs
similarity index 51%
rename from src/todo/aio/lib.rs
rename to src/header/aio/mod.rs
index 40002aa5117180768e5ac85aaed6212a011a57a5..d1d9ef49f5bfe25a6e4366189fa7c80927665234 100644
--- a/src/todo/aio/lib.rs
+++ b/src/header/aio/mod.rs
@@ -1,34 +1,37 @@
+use header::time::sigevent;
+use platform::types::*;
+
 pub struct aiocb {
-    pub aio_fildes: libc::c_int,
-    pub aio_lio_opcode: libc::c_int,
-    pub aio_reqprio: libc::c_int,
-    pub aio_buf: *mut libc::c_void,
+    pub aio_fildes: c_int,
+    pub aio_lio_opcode: c_int,
+    pub aio_reqprio: c_int,
+    pub aio_buf: *mut c_void,
     pub aio_nbytes: usize,
     pub aio_sigevent: sigevent,
 }
 
 // #[no_mangle]
-pub extern "C" fn aio_read(aiocbp: *mut aiocb) -> libc::c_int {
+pub extern "C" fn aio_read(aiocbp: *mut aiocb) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn aio_write(aiocbp: *mut aiocb) -> libc::c_int {
+pub extern "C" fn aio_write(aiocbp: *mut aiocb) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn lio_listio(
-    mode: libc::c_int,
+    mode: c_int,
     list: *const *const aiocb,
-    nent: libc::c_int,
+    nent: c_int,
     sig: *mut sigevent,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn aio_error(aiocbp: *const aiocb) -> libc::c_int {
+pub extern "C" fn aio_error(aiocbp: *const aiocb) -> c_int {
     unimplemented!();
 }
 
@@ -38,20 +41,20 @@ pub extern "C" fn aio_return(aiocbp: *mut aiocb) -> usize {
 }
 
 // #[no_mangle]
-pub extern "C" fn aio_cancel(fildes: libc::c_int, aiocbp: *mut aiocb) -> libc::c_int {
+pub extern "C" fn aio_cancel(fildes: c_int, aiocbp: *mut aiocb) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
 pub extern "C" fn aio_suspend(
     list: *const *const aiocb,
-    nent: libc::c_int,
+    nent: c_int,
     timeout: *const timespec,
-) -> libc::c_int {
+) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn aio_fsync(operation: libc::c_int, aiocbp: *mut aiocb) -> libc::c_int {
+pub extern "C" fn aio_fsync(operation: c_int, aiocbp: *mut aiocb) -> c_int {
     unimplemented!();
 }
diff --git a/src/arpainet/cbindgen.toml b/src/header/arpa_inet/cbindgen.toml
similarity index 79%
rename from src/arpainet/cbindgen.toml
rename to src/header/arpa_inet/cbindgen.toml
index 661140fa0bae879d4ab88b71858b9754351b512a..4e00706ff5608869db49a112bed5c9e402029937 100644
--- a/src/arpainet/cbindgen.toml
+++ b/src/header/arpa_inet/cbindgen.toml
@@ -1,5 +1,5 @@
 sys_includes = ["stddef.h", "sys/socket.h", "netinet/in.h"]
-include_guard = "_ARPAINET_H"
+include_guard = "_ARPA_INET_H"
 language = "C"
 style = "Tag"
 
diff --git a/src/arpainet/src/lib.rs b/src/header/arpa_inet/mod.rs
similarity index 83%
rename from src/arpainet/src/lib.rs
rename to src/header/arpa_inet/mod.rs
index 632cb396672d51248582509694ed601642a48530..cca48be4b98b1f7444254464c140d4e1e5b21e8d 100644
--- a/src/arpainet/src/lib.rs
+++ b/src/header/arpa_inet/mod.rs
@@ -1,20 +1,11 @@
-//! arpainet implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/arpainet.h.html
-
-#![no_std]
-#![feature(alloc)]
-
-#[macro_use]
-extern crate alloc;
-
-extern crate errno;
-extern crate netinet;
-extern crate platform;
-extern crate sys_socket;
+//! arpa/inet implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/arpainet.h.html
 
 use core::str::FromStr;
-use core::{mem, ptr, slice, str};
-use errno::*;
-use netinet::in_h::in_addr;
+use core::{ptr, slice, str};
+
+use header::errno::*;
+use header::netinet_in::in_addr;
+use platform;
 use platform::c_str;
 use platform::types::*;
 
@@ -38,8 +29,6 @@ pub extern "C" fn ntohs(netshort: u16) -> u16 {
     u16::from_be(netshort)
 }
 
-static mut NTOA_ADDR: [c_char; 16] = [0; 16];
-
 #[no_mangle]
 pub unsafe extern "C" fn inet_aton(cp: *const c_char, inp: *mut in_addr) -> c_int {
     // TODO: octal/hex
@@ -48,6 +37,8 @@ pub unsafe extern "C" fn inet_aton(cp: *const c_char, inp: *mut in_addr) -> c_in
 
 #[no_mangle]
 pub unsafe extern "C" fn inet_ntoa(addr: in_addr) -> *const c_char {
+    static mut NTOA_ADDR: [c_char; 16] = [0; 16];
+
     inet_ntop(
         AF_INET,
         &addr as *const in_addr as *const c_void,
@@ -62,7 +53,7 @@ pub unsafe extern "C" fn inet_pton(domain: c_int, src: *const c_char, dest: *mut
         platform::errno = EAFNOSUPPORT;
         -1
     } else {
-        let mut s_addr = slice::from_raw_parts_mut(
+        let s_addr = slice::from_raw_parts_mut(
             &mut (*(dest as *mut in_addr)).s_addr as *mut _ as *mut u8,
             4,
         );
@@ -106,27 +97,27 @@ pub unsafe extern "C" fn inet_ntop(
     }
 }
 
-#[no_mangle]
+//#[no_mangle]
 pub extern "C" fn inet_addr(cp: *const c_char) -> in_addr_t {
     unimplemented!();
 }
 
-#[no_mangle]
+//#[no_mangle]
 pub extern "C" fn inet_lnaof(_in: in_addr) -> in_addr_t {
     unimplemented!();
 }
 
-#[no_mangle]
+//#[no_mangle]
 pub extern "C" fn inet_makeaddr(net: in_addr_t, lna: in_addr_t) -> in_addr {
     unimplemented!();
 }
 
-#[no_mangle]
+//#[no_mangle]
 pub extern "C" fn inet_netof(_in: in_addr) -> in_addr_t {
     unimplemented!();
 }
 
-#[no_mangle]
+//#[no_mangle]
 pub extern "C" fn inet_network(cp: *const c_char) -> in_addr_t {
     unimplemented!();
 }
diff --git a/src/ctype/cbindgen.toml b/src/header/ctype/cbindgen.toml
similarity index 100%
rename from src/ctype/cbindgen.toml
rename to src/header/ctype/cbindgen.toml
diff --git a/src/ctype/src/lib.rs b/src/header/ctype/mod.rs
similarity index 98%
rename from src/ctype/src/lib.rs
rename to src/header/ctype/mod.rs
index a9f602043f72cca1304b1deb900a143339eeef43..8506f84257bcdc8f21dd843a7a9283e17b99b50c 100644
--- a/src/ctype/src/lib.rs
+++ b/src/header/ctype/mod.rs
@@ -1,9 +1,5 @@
 //! ctype implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/ctype.h.html
 
-#![no_std]
-
-extern crate platform;
-
 use platform::types::*;
 
 #[no_mangle]
diff --git a/src/dirent/cbindgen.toml b/src/header/dirent/cbindgen.toml
similarity index 100%
rename from src/dirent/cbindgen.toml
rename to src/header/dirent/cbindgen.toml
diff --git a/src/dirent/src/lib.rs b/src/header/dirent/mod.rs
similarity index 91%
rename from src/dirent/src/lib.rs
rename to src/header/dirent/mod.rs
index 62edcf9a399f0079434d991fd7410f9d8fbc6134..478e902461cf300c5e6cd7bd7a22c6b03d05fc9f 100644
--- a/src/dirent/src/lib.rs
+++ b/src/header/dirent/mod.rs
@@ -1,18 +1,13 @@
 //! dirent implementation following http://pubs.opengroup.org/onlinepubs/009695399/basedefs/dirent.h.html
 
-#![no_std]
-#![feature(alloc)]
-
-extern crate alloc;
-extern crate errno;
-extern crate fcntl;
-extern crate platform;
-extern crate stdio;
-extern crate unistd;
-
 use alloc::boxed::Box;
 use core::{mem, ptr};
+
+use c_str::CStr;
+use header::{errno, fcntl, unistd};
+use platform;
 use platform::types::*;
+use platform::{Pal, Sys};
 
 const DIR_BUF_SIZE: usize = mem::size_of::<dirent>() * 3;
 
@@ -41,7 +36,8 @@ pub struct dirent {
 
 #[no_mangle]
 pub extern "C" fn opendir(path: *const c_char) -> *mut DIR {
-    let fd = platform::open(
+    let path = unsafe { CStr::from_ptr(path) };
+    let fd = Sys::open(
         path,
         fcntl::O_RDONLY | fcntl::O_DIRECTORY | fcntl::O_CLOEXEC,
         0,
@@ -62,7 +58,7 @@ pub extern "C" fn opendir(path: *const c_char) -> *mut DIR {
 
 #[no_mangle]
 pub unsafe extern "C" fn closedir(dir: *mut DIR) -> c_int {
-    let ret = platform::close((*dir).fd);
+    let ret = Sys::close((*dir).fd);
     Box::from_raw(dir);
     ret
 }
@@ -70,7 +66,7 @@ pub unsafe extern "C" fn closedir(dir: *mut DIR) -> c_int {
 #[no_mangle]
 pub unsafe extern "C" fn readdir(dir: *mut DIR) -> *mut dirent {
     if (*dir).index >= (*dir).len {
-        let read = platform::getdents(
+        let read = Sys::getdents(
             (*dir).fd,
             (*dir).buf.as_mut_ptr() as *mut platform::types::dirent,
             (*dir).buf.len(),
diff --git a/src/errno/cbindgen.toml b/src/header/errno/cbindgen.toml
similarity index 100%
rename from src/errno/cbindgen.toml
rename to src/header/errno/cbindgen.toml
diff --git a/src/errno/src/lib.rs b/src/header/errno/mod.rs
similarity index 99%
rename from src/errno/src/lib.rs
rename to src/header/errno/mod.rs
index b96105963486cf5eb36baf7488411634bd45624d..e39fb205e555990f4be38832bc8c0174bf341476 100644
--- a/src/errno/src/lib.rs
+++ b/src/header/errno/mod.rs
@@ -1,9 +1,6 @@
 //! errno implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/errno.h.html
 
-#![no_std]
-
-extern crate platform;
-
+use platform;
 use platform::types::*;
 
 #[no_mangle]
diff --git a/src/fcntl/cbindgen.toml b/src/header/fcntl/cbindgen.toml
similarity index 100%
rename from src/fcntl/cbindgen.toml
rename to src/header/fcntl/cbindgen.toml
diff --git a/src/header/fcntl/linux.rs b/src/header/fcntl/linux.rs
new file mode 100644
index 0000000000000000000000000000000000000000..7b0af1982fe495c8d766cf9724f2357fe01e204d
--- /dev/null
+++ b/src/header/fcntl/linux.rs
@@ -0,0 +1,15 @@
+use platform::types::*;
+
+pub const O_RDONLY: c_int = 0x0000;
+pub const O_WRONLY: c_int = 0x0001;
+pub const O_RDWR: c_int = 0x0002;
+pub const O_CREAT: c_int = 0x0040;
+pub const O_EXCL: c_int = 0x0080;
+pub const O_TRUNC: c_int = 0x0200;
+pub const O_APPEND: c_int = 0x0400;
+pub const O_NONBLOCK: c_int = 0x0800;
+pub const O_DIRECTORY: c_int = 0x1_0000;
+pub const O_NOFOLLOW: c_int = 0x2_0000;
+pub const O_CLOEXEC: c_int = 0x8_0000;
+pub const O_PATH: c_int = 0x20_0000;
+pub const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
diff --git a/src/fcntl/src/lib.rs b/src/header/fcntl/mod.rs
similarity index 82%
rename from src/fcntl/src/lib.rs
rename to src/header/fcntl/mod.rs
index 0c0fa43ce2e5f667bd9b4c3baa89fe8a037a9638..07a88647c5f4378b05e3f09169aef10ca070db73 100644
--- a/src/fcntl/src/lib.rs
+++ b/src/header/fcntl/mod.rs
@@ -1,12 +1,10 @@
 //! fcntl implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/fcntl.h.html
 
-#![no_std]
-
-extern crate platform;
-
+use c_str::CStr;
 use platform::types::*;
+use platform::{Pal, Sys};
 
-pub use sys::*;
+pub use self::sys::*;
 
 #[cfg(target_os = "linux")]
 #[path = "linux.rs"]
@@ -38,17 +36,11 @@ pub extern "C" fn creat(path: *const c_char, mode: mode_t) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn sys_fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
-    platform::fcntl(fildes, cmd, arg)
+    Sys::fcntl(fildes, cmd, arg)
 }
 
 #[no_mangle]
 pub extern "C" fn sys_open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int {
-    platform::open(path, oflag, mode)
-}
-
-/*
-#[no_mangle]
-pub extern "C" fn func(args) -> c_int {
-    unimplemented!();
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::open(path, oflag, mode)
 }
-*/
diff --git a/src/fcntl/src/redox.rs b/src/header/fcntl/redox.rs
similarity index 95%
rename from src/fcntl/src/redox.rs
rename to src/header/fcntl/redox.rs
index 1ea3ca45de4191d7fda1467bff0fcc56f4084e61..95f2da5570ee2ba57af46e2b204c12c6d3e393cd 100644
--- a/src/fcntl/src/redox.rs
+++ b/src/header/fcntl/redox.rs
@@ -14,7 +14,7 @@ pub const O_CREAT: c_int = 0x0200_0000;
 pub const O_TRUNC: c_int = 0x0400_0000;
 pub const O_EXCL: c_int = 0x0800_0000;
 pub const O_DIRECTORY: c_int = 0x1000_0000;
-pub const O_STAT: c_int = 0x2000_0000;
+pub const O_PATH: c_int = 0x2000_0000;
 pub const O_SYMLINK: c_int = 0x4000_0000;
 pub const O_NOFOLLOW: c_int = 0x8000_0000;
 pub const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
diff --git a/src/fenv/cbindgen.toml b/src/header/fenv/cbindgen.toml
similarity index 100%
rename from src/fenv/cbindgen.toml
rename to src/header/fenv/cbindgen.toml
diff --git a/src/fenv/src/lib.rs b/src/header/fenv/mod.rs
similarity index 97%
rename from src/fenv/src/lib.rs
rename to src/header/fenv/mod.rs
index 116293c1c0485369a262792b80d585cdb69b860d..6aa92216f079f3901d8c1e183229da7761ee1fcc 100644
--- a/src/fenv/src/lib.rs
+++ b/src/header/fenv/mod.rs
@@ -1,10 +1,6 @@
 //! fenv.h implementation for Redox, following
 //! http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fenv.h.html
 
-#![no_std]
-
-extern crate platform;
-
 use platform::types::*;
 
 pub const FE_ALL_EXCEPT: c_int = 0;
diff --git a/src/float/cbindgen.toml b/src/header/float/cbindgen.toml
similarity index 100%
rename from src/float/cbindgen.toml
rename to src/header/float/cbindgen.toml
diff --git a/src/float/src/lib.rs b/src/header/float/mod.rs
similarity index 77%
rename from src/float/src/lib.rs
rename to src/header/float/mod.rs
index 4a355c0b786614675ee690fd2d971a16d6bdace3..dec7861c54bb458af1651fd46911487f0276d5f7 100644
--- a/src/float/src/lib.rs
+++ b/src/header/float/mod.rs
@@ -1,12 +1,7 @@
 //! float.h implementation for Redox, following
 //! http://pubs.opengroup.org/onlinepubs/7908799/xsh/float.h.html
 
-#![no_std]
-
-extern crate fenv;
-extern crate platform;
-
-use fenv::{fegetround, FE_TONEAREST};
+use header::fenv::{fegetround, FE_TONEAREST};
 use platform::types::*;
 
 pub const FLT_RADIX: c_int = 2;
diff --git a/src/fnmatch/cbindgen.toml b/src/header/fnmatch/cbindgen.toml
similarity index 100%
rename from src/fnmatch/cbindgen.toml
rename to src/header/fnmatch/cbindgen.toml
diff --git a/src/fnmatch/src/lib.rs b/src/header/fnmatch/mod.rs
similarity index 88%
rename from src/fnmatch/src/lib.rs
rename to src/header/fnmatch/mod.rs
index ff60a80fd37ecf719a98e9cdb4849ed87f24e864..899dbf7b7c797519e1158452a92adad5333ec586 100644
--- a/src/fnmatch/src/lib.rs
+++ b/src/header/fnmatch/mod.rs
@@ -1,18 +1,14 @@
 //! fnmatch implementation
-#![no_std]
-#![feature(alloc)]
-
-extern crate alloc;
-extern crate platform;
 
 use alloc::vec::Vec;
+
 use platform::types::*;
 
 pub const FNM_NOMATCH: c_int = 1;
 
 pub const FNM_NOESCAPE: c_int = 1;
 pub const FNM_PATHNAME: c_int = 2;
-pub const FNM_PERIOD:   c_int = 4;
+pub const FNM_PERIOD: c_int = 4;
 pub const FNM_CASEFOLD: c_int = 8;
 
 #[derive(Debug)]
@@ -43,7 +39,7 @@ unsafe fn next_token(pattern: &mut *const c_char, flags: c_int) -> Option<Token>
             }
             *pattern = pattern.offset(1);
             Token::Char(c)
-        },
+        }
         b'?' => Token::Any,
         b'*' => Token::Wildcard,
         b'[' => {
@@ -51,7 +47,9 @@ unsafe fn next_token(pattern: &mut *const c_char, flags: c_int) -> Option<Token>
             let invert = if **pattern as u8 == b'!' {
                 *pattern = pattern.offset(1);
                 true
-            } else { false };
+            } else {
+                false
+            };
 
             loop {
                 let mut c = **pattern as u8;
@@ -68,8 +66,8 @@ unsafe fn next_token(pattern: &mut *const c_char, flags: c_int) -> Option<Token>
                             // Trailing backslash. Maybe error?
                             break;
                         }
-                    },
-                    _ => ()
+                    }
+                    _ => (),
                 }
                 if matches.len() >= 2 && matches[matches.len() - 1] == b'-' {
                     let len = matches.len();
@@ -85,13 +83,17 @@ unsafe fn next_token(pattern: &mut *const c_char, flags: c_int) -> Option<Token>
             // Otherwise, there was no closing ]. Maybe error?
 
             Token::Match(invert, matches)
-        },
-        c => Token::Char(c)
+        }
+        c => Token::Char(c),
     })
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn fnmatch(mut pattern: *const c_char, mut input: *const c_char, flags: c_int) -> c_int {
+pub unsafe extern "C" fn fnmatch(
+    mut pattern: *const c_char,
+    mut input: *const c_char,
+    flags: c_int,
+) -> c_int {
     let pathname = flags & FNM_PATHNAME == FNM_PATHNAME;
     let casefold = flags & FNM_CASEFOLD == FNM_CASEFOLD;
 
@@ -113,7 +115,7 @@ pub unsafe extern "C" fn fnmatch(mut pattern: *const c_char, mut input: *const c
                     return FNM_NOMATCH;
                 }
                 input = input.offset(1);
-            },
+            }
             Some(Token::Char(c)) => {
                 let mut a = *input as u8;
                 if casefold && a >= b'a' && a <= b'z' {
@@ -130,14 +132,15 @@ pub unsafe extern "C" fn fnmatch(mut pattern: *const c_char, mut input: *const c
                     leading = true;
                 }
                 input = input.offset(1);
-            },
+            }
             Some(Token::Match(invert, matches)) => {
-                if (pathname && *input as u8 == b'/') || matches.contains(&(*input as u8)) == invert {
+                if (pathname && *input as u8 == b'/') || matches.contains(&(*input as u8)) == invert
+                {
                     // Found it, but it's inverted! Or vise versa.
                     return FNM_NOMATCH;
                 }
                 input = input.offset(1);
-            },
+            }
             Some(Token::Wildcard) => {
                 loop {
                     let c = *input as u8;
@@ -158,9 +161,8 @@ pub unsafe extern "C" fn fnmatch(mut pattern: *const c_char, mut input: *const c
                         return FNM_NOMATCH;
                     }
                 }
-                unreachable!("nothing should be able to break out of the loop");
-            },
-            None => return FNM_NOMATCH // Pattern ended but there's still some input
+            }
+            None => return FNM_NOMATCH, // Pattern ended but there's still some input
         }
     }
 }
diff --git a/src/grp/cbindgen.toml b/src/header/grp/cbindgen.toml
similarity index 100%
rename from src/grp/cbindgen.toml
rename to src/header/grp/cbindgen.toml
diff --git a/src/grp/src/lib.rs b/src/header/grp/mod.rs
similarity index 97%
rename from src/grp/src/lib.rs
rename to src/header/grp/mod.rs
index 1d93b1dbf401d1e01d1e1902a945ac330ca8e550..b0fcd33c48c0c370593a42091a505c3873703329 100644
--- a/src/grp/src/lib.rs
+++ b/src/header/grp/mod.rs
@@ -1,9 +1,5 @@
 //! grp implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/grp.h.html
 
-#![no_std]
-
-extern crate platform;
-
 use platform::types::*;
 
 #[repr(C)]
diff --git a/src/inttypes/cbindgen.toml b/src/header/inttypes/cbindgen.toml
similarity index 100%
rename from src/inttypes/cbindgen.toml
rename to src/header/inttypes/cbindgen.toml
diff --git a/src/inttypes/src/lib.rs b/src/header/inttypes/mod.rs
similarity index 88%
rename from src/inttypes/src/lib.rs
rename to src/header/inttypes/mod.rs
index c4d1ab545e9c14e6b87c083513c4496becd977fd..380450b987238a041a3fff13ac2cfbdc5665ddeb 100644
--- a/src/inttypes/src/lib.rs
+++ b/src/header/inttypes/mod.rs
@@ -1,12 +1,7 @@
-#![no_std]
-
-#[macro_use]
-extern crate stdlib;
-extern crate ctype;
-extern crate errno;
-extern crate platform;
-
-use errno::*;
+use header::ctype;
+use header::errno::*;
+use header::stdlib::*;
+use platform;
 use platform::types::*;
 
 #[no_mangle]
@@ -35,7 +30,6 @@ pub unsafe extern "C" fn strtoimax(
     endptr: *mut *mut c_char,
     base: c_int,
 ) -> intmax_t {
-    use stdlib::*;
     strto_impl!(
         intmax_t,
         false,
@@ -53,7 +47,6 @@ pub unsafe extern "C" fn strtoumax(
     endptr: *mut *mut c_char,
     base: c_int,
 ) -> uintmax_t {
-    use stdlib::*;
     strto_impl!(
         uintmax_t,
         false,
diff --git a/src/locale/cbindgen.toml b/src/header/locale/cbindgen.toml
similarity index 100%
rename from src/locale/cbindgen.toml
rename to src/header/locale/cbindgen.toml
diff --git a/src/locale/src/lib.rs b/src/header/locale/mod.rs
similarity index 97%
rename from src/locale/src/lib.rs
rename to src/header/locale/mod.rs
index a9bb89d11ae8d975bc74afebb39a38b4f6333485..d3a03c740bd17e73a7259701ed051178aa4b7a14 100644
--- a/src/locale/src/lib.rs
+++ b/src/header/locale/mod.rs
@@ -1,11 +1,7 @@
 //! locale implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/locale.h.html
 
-#![no_std]
-#![feature(alloc)]
-
-extern crate platform;
-
 use core::ptr;
+
 use platform::types::*;
 
 const EMPTY_PTR: *const c_char = "\0" as *const _ as *const c_char;
diff --git a/src/header/mod.rs b/src/header/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..0e1556201f2b3ce123582adcde6e1e8d753b310f
--- /dev/null
+++ b/src/header/mod.rs
@@ -0,0 +1,41 @@
+pub mod aio;
+pub mod arpa_inet;
+pub mod ctype;
+pub mod dirent;
+pub mod errno;
+pub mod fcntl;
+pub mod fenv;
+pub mod float;
+pub mod fnmatch;
+pub mod grp;
+pub mod inttypes;
+pub mod locale;
+pub mod netinet_in;
+//pub mod pthread;
+pub mod pwd;
+pub mod semaphore;
+pub mod setjmp;
+pub mod sgtty;
+pub mod signal;
+pub mod stdio;
+pub mod stdlib;
+pub mod string;
+pub mod strings;
+pub mod sys_file;
+pub mod sys_ioctl;
+pub mod sys_mman;
+pub mod sys_resource;
+pub mod sys_select;
+pub mod sys_socket;
+pub mod sys_stat;
+pub mod sys_time;
+pub mod sys_times;
+pub mod sys_un;
+pub mod sys_utsname;
+pub mod sys_wait;
+pub mod termios;
+pub mod time;
+pub mod unistd;
+pub mod utime;
+pub mod wchar;
+pub mod wctype;
diff --git a/src/netinet/Cargo.toml b/src/header/netinet_in/Cargo.toml
similarity index 100%
rename from src/netinet/Cargo.toml
rename to src/header/netinet_in/Cargo.toml
diff --git a/src/netinet/in/cbindgen.toml b/src/header/netinet_in/cbindgen.toml
similarity index 100%
rename from src/netinet/in/cbindgen.toml
rename to src/header/netinet_in/cbindgen.toml
diff --git a/src/netinet/in/src/lib.rs b/src/header/netinet_in/mod.rs
similarity index 87%
rename from src/netinet/in/src/lib.rs
rename to src/header/netinet_in/mod.rs
index 2f909a3d75c13dfb54f4c73be35456a539d794ea..db230c997bfefd5b99dc3e8050a8406c4695538e 100644
--- a/src/netinet/in/src/lib.rs
+++ b/src/header/netinet_in/mod.rs
@@ -1,12 +1,7 @@
-#![no_std]
-
 #![allow(non_camel_case_types)]
 
-extern crate platform;
-extern crate sys_socket;
-
+use header::sys_socket::sa_family_t;
 use platform::types::*;
-use sys_socket::{sa_family_t, sockaddr};
 
 pub type in_addr_t = u32;
 pub type in_port_t = u16;
@@ -14,19 +9,19 @@ pub type in_port_t = u16;
 #[repr(C)]
 #[derive(Debug, Clone, Copy)]
 pub struct in_addr {
-    pub s_addr: in_addr_t
+    pub s_addr: in_addr_t,
 }
 
 #[repr(C)]
 pub struct in6_addr {
-    pub s6_addr: [u8; 16]
+    pub s6_addr: [u8; 16],
 }
 
 #[repr(C)]
 pub struct sockaddr_in {
     pub sin_family: sa_family_t,
     pub sin_port: in_port_t,
-    pub sin_addr: in_addr
+    pub sin_addr: in_addr,
 }
 
 #[repr(C)]
@@ -35,7 +30,7 @@ pub struct sockaddr_in6 {
     pub sin6_port: in_port_t,
     pub sin6_flowinfo: u32,
     pub sin6_addr: in6_addr,
-    pub sin6_scope_id: u32
+    pub sin6_scope_id: u32,
 }
 
 #[repr(C)]
diff --git a/src/pwd/cbindgen.toml b/src/header/pwd/cbindgen.toml
similarity index 100%
rename from src/pwd/cbindgen.toml
rename to src/header/pwd/cbindgen.toml
diff --git a/src/pwd/src/lib.rs b/src/header/pwd/mod.rs
similarity index 97%
rename from src/pwd/src/lib.rs
rename to src/header/pwd/mod.rs
index 6d82a1f9dd3b420c7fe200851597b5cb00860ae0..97b912af9150dce37e0d9bbe735a55894730a8ec 100644
--- a/src/pwd/src/lib.rs
+++ b/src/header/pwd/mod.rs
@@ -1,17 +1,14 @@
 //! pwd implementation for relibc
 
-#![no_std]
-#![feature(alloc)]
-
-extern crate alloc;
-extern crate errno;
-extern crate fcntl;
-extern crate platform;
-
 use alloc::vec::Vec;
 use core::ptr;
+
+use c_str::CStr;
+use header::{errno, fcntl};
+use platform;
 use platform::types::*;
 use platform::RawFile;
+use platform::{Pal, Sys};
 
 #[repr(C)]
 pub struct passwd {
@@ -51,7 +48,7 @@ where
     F: FnMut(&[&[u8]]) -> bool,
 {
     let file = match RawFile::open(
-        "/etc/passwd\0".as_ptr() as *const c_char,
+        unsafe { CStr::from_bytes_with_nul_unchecked(b"/etc/passwd\0") },
         fcntl::O_RDONLY,
         0,
     ) {
@@ -90,7 +87,7 @@ where
                 buf.set_len(capacity);
             }
 
-            let read = platform::read(*file, &mut buf[len..]);
+            let read = Sys::read(*file, &mut buf[len..]);
 
             unsafe {
                 buf.set_len(len + read as usize);
diff --git a/src/semaphore/cbindgen.toml b/src/header/semaphore/cbindgen.toml
similarity index 100%
rename from src/semaphore/cbindgen.toml
rename to src/header/semaphore/cbindgen.toml
diff --git a/src/semaphore/src/lib.rs b/src/header/semaphore/mod.rs
similarity index 97%
rename from src/semaphore/src/lib.rs
rename to src/header/semaphore/mod.rs
index 0204358a37498c4cf7a4b4672fd4cfb90a1ec34e..f1331a43813025387b57f72adb398f96f1f12bcd 100644
--- a/src/semaphore/src/lib.rs
+++ b/src/header/semaphore/mod.rs
@@ -1,7 +1,3 @@
-#![no_std]
-
-extern crate platform;
-
 use platform::types::*;
 
 #[repr(C)]
diff --git a/src/setjmp/src/impl/README.md b/src/header/setjmp/impl/README.md
similarity index 100%
rename from src/setjmp/src/impl/README.md
rename to src/header/setjmp/impl/README.md
diff --git a/src/setjmp/src/impl/aarch64/longjmp.s b/src/header/setjmp/impl/aarch64/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/aarch64/longjmp.s
rename to src/header/setjmp/impl/aarch64/longjmp.s
diff --git a/src/setjmp/src/impl/aarch64/setjmp.s b/src/header/setjmp/impl/aarch64/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/aarch64/setjmp.s
rename to src/header/setjmp/impl/aarch64/setjmp.s
diff --git a/src/setjmp/src/impl/arm/longjmp.s b/src/header/setjmp/impl/arm/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/arm/longjmp.s
rename to src/header/setjmp/impl/arm/longjmp.s
diff --git a/src/setjmp/src/impl/arm/setjmp.s b/src/header/setjmp/impl/arm/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/arm/setjmp.s
rename to src/header/setjmp/impl/arm/setjmp.s
diff --git a/src/setjmp/src/impl/i386/longjmp.s b/src/header/setjmp/impl/i386/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/i386/longjmp.s
rename to src/header/setjmp/impl/i386/longjmp.s
diff --git a/src/setjmp/src/impl/i386/setjmp.s b/src/header/setjmp/impl/i386/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/i386/setjmp.s
rename to src/header/setjmp/impl/i386/setjmp.s
diff --git a/src/setjmp/src/impl/m68k/longjmp.s b/src/header/setjmp/impl/m68k/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/m68k/longjmp.s
rename to src/header/setjmp/impl/m68k/longjmp.s
diff --git a/src/setjmp/src/impl/m68k/setjmp.s b/src/header/setjmp/impl/m68k/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/m68k/setjmp.s
rename to src/header/setjmp/impl/m68k/setjmp.s
diff --git a/src/setjmp/src/impl/microblaze/longjmp.s b/src/header/setjmp/impl/microblaze/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/microblaze/longjmp.s
rename to src/header/setjmp/impl/microblaze/longjmp.s
diff --git a/src/setjmp/src/impl/microblaze/setjmp.s b/src/header/setjmp/impl/microblaze/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/microblaze/setjmp.s
rename to src/header/setjmp/impl/microblaze/setjmp.s
diff --git a/src/setjmp/src/impl/mips/longjmp.S b/src/header/setjmp/impl/mips/longjmp.S
similarity index 100%
rename from src/setjmp/src/impl/mips/longjmp.S
rename to src/header/setjmp/impl/mips/longjmp.S
diff --git a/src/setjmp/src/impl/mips/setjmp.S b/src/header/setjmp/impl/mips/setjmp.S
similarity index 100%
rename from src/setjmp/src/impl/mips/setjmp.S
rename to src/header/setjmp/impl/mips/setjmp.S
diff --git a/src/setjmp/src/impl/mips64/longjmp.S b/src/header/setjmp/impl/mips64/longjmp.S
similarity index 100%
rename from src/setjmp/src/impl/mips64/longjmp.S
rename to src/header/setjmp/impl/mips64/longjmp.S
diff --git a/src/setjmp/src/impl/mips64/setjmp.S b/src/header/setjmp/impl/mips64/setjmp.S
similarity index 100%
rename from src/setjmp/src/impl/mips64/setjmp.S
rename to src/header/setjmp/impl/mips64/setjmp.S
diff --git a/src/setjmp/src/impl/mipsn32/longjmp.S b/src/header/setjmp/impl/mipsn32/longjmp.S
similarity index 100%
rename from src/setjmp/src/impl/mipsn32/longjmp.S
rename to src/header/setjmp/impl/mipsn32/longjmp.S
diff --git a/src/setjmp/src/impl/mipsn32/setjmp.S b/src/header/setjmp/impl/mipsn32/setjmp.S
similarity index 100%
rename from src/setjmp/src/impl/mipsn32/setjmp.S
rename to src/header/setjmp/impl/mipsn32/setjmp.S
diff --git a/src/setjmp/src/impl/or1k/longjmp.s b/src/header/setjmp/impl/or1k/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/or1k/longjmp.s
rename to src/header/setjmp/impl/or1k/longjmp.s
diff --git a/src/setjmp/src/impl/or1k/setjmp.s b/src/header/setjmp/impl/or1k/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/or1k/setjmp.s
rename to src/header/setjmp/impl/or1k/setjmp.s
diff --git a/src/setjmp/src/impl/powerpc/longjmp.S b/src/header/setjmp/impl/powerpc/longjmp.S
similarity index 100%
rename from src/setjmp/src/impl/powerpc/longjmp.S
rename to src/header/setjmp/impl/powerpc/longjmp.S
diff --git a/src/setjmp/src/impl/powerpc/setjmp.S b/src/header/setjmp/impl/powerpc/setjmp.S
similarity index 100%
rename from src/setjmp/src/impl/powerpc/setjmp.S
rename to src/header/setjmp/impl/powerpc/setjmp.S
diff --git a/src/setjmp/src/impl/powerpc64/longjmp.s b/src/header/setjmp/impl/powerpc64/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/powerpc64/longjmp.s
rename to src/header/setjmp/impl/powerpc64/longjmp.s
diff --git a/src/setjmp/src/impl/powerpc64/setjmp.s b/src/header/setjmp/impl/powerpc64/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/powerpc64/setjmp.s
rename to src/header/setjmp/impl/powerpc64/setjmp.s
diff --git a/src/setjmp/src/impl/s390x/longjmp.s b/src/header/setjmp/impl/s390x/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/s390x/longjmp.s
rename to src/header/setjmp/impl/s390x/longjmp.s
diff --git a/src/setjmp/src/impl/s390x/setjmp.s b/src/header/setjmp/impl/s390x/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/s390x/setjmp.s
rename to src/header/setjmp/impl/s390x/setjmp.s
diff --git a/src/setjmp/src/impl/sh/longjmp.S b/src/header/setjmp/impl/sh/longjmp.S
similarity index 100%
rename from src/setjmp/src/impl/sh/longjmp.S
rename to src/header/setjmp/impl/sh/longjmp.S
diff --git a/src/setjmp/src/impl/sh/setjmp.S b/src/header/setjmp/impl/sh/setjmp.S
similarity index 100%
rename from src/setjmp/src/impl/sh/setjmp.S
rename to src/header/setjmp/impl/sh/setjmp.S
diff --git a/src/setjmp/src/impl/x32/longjmp.s b/src/header/setjmp/impl/x32/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/x32/longjmp.s
rename to src/header/setjmp/impl/x32/longjmp.s
diff --git a/src/setjmp/src/impl/x32/setjmp.s b/src/header/setjmp/impl/x32/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/x32/setjmp.s
rename to src/header/setjmp/impl/x32/setjmp.s
diff --git a/src/setjmp/src/impl/x86_64/longjmp.s b/src/header/setjmp/impl/x86_64/longjmp.s
similarity index 100%
rename from src/setjmp/src/impl/x86_64/longjmp.s
rename to src/header/setjmp/impl/x86_64/longjmp.s
diff --git a/src/setjmp/src/impl/x86_64/setjmp.s b/src/header/setjmp/impl/x86_64/setjmp.s
similarity index 100%
rename from src/setjmp/src/impl/x86_64/setjmp.s
rename to src/header/setjmp/impl/x86_64/setjmp.s
diff --git a/src/setjmp/src/lib.rs b/src/header/setjmp/mod.rs
similarity index 95%
rename from src/setjmp/src/lib.rs
rename to src/header/setjmp/mod.rs
index 0f6392dc9fcbdd8c446d89b267fce5518dc1c377..6371c9a58b4ab0f46f280a8bb938f2bb24d30bc5 100644
--- a/src/setjmp/src/lib.rs
+++ b/src/header/setjmp/mod.rs
@@ -1,8 +1,5 @@
 //! setjmp implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/setjmp.h.html
 
-#![no_std]
-#![feature(global_asm)]
-
 macro_rules! platform_specific {
     ($($arch:expr,$ext:expr;)+) => {
         $(
diff --git a/src/sgtty/cbindgen.toml b/src/header/sgtty/cbindgen.toml
similarity index 100%
rename from src/sgtty/cbindgen.toml
rename to src/header/sgtty/cbindgen.toml
diff --git a/src/sgtty/src/lib.rs b/src/header/sgtty/mod.rs
similarity index 80%
rename from src/sgtty/src/lib.rs
rename to src/header/sgtty/mod.rs
index eece192334f1f9af2a53221b157efa89c06c9066..b5f1a40900858138c3fe904328e32c8041c292d9 100644
--- a/src/sgtty/src/lib.rs
+++ b/src/header/sgtty/mod.rs
@@ -1,12 +1,10 @@
 //! sgtty implementation that won't work on redox because no ioctl
-#![no_std]
-
-extern crate platform;
-extern crate sys_ioctl;
 
 use core::fmt::Write;
+
+use header::sys_ioctl::*;
+use platform;
 use platform::types::*;
-use sys_ioctl::*;
 
 #[no_mangle]
 pub extern "C" fn gtty(fd: c_int, out: *mut sgttyb) -> c_int {
diff --git a/src/signal/cbindgen.toml b/src/header/signal/cbindgen.toml
similarity index 100%
rename from src/signal/cbindgen.toml
rename to src/header/signal/cbindgen.toml
diff --git a/src/signal/src/linux.rs b/src/header/signal/linux.rs
similarity index 100%
rename from src/signal/src/linux.rs
rename to src/header/signal/linux.rs
diff --git a/src/signal/src/lib.rs b/src/header/signal/mod.rs
similarity index 90%
rename from src/signal/src/lib.rs
rename to src/header/signal/mod.rs
index 1a463beeffc068689603baa1698eaa93bfc9c191..2aa9862a10c0ff8e2f1e89a26c7ae3c9086451b1 100644
--- a/src/signal/src/lib.rs
+++ b/src/header/signal/mod.rs
@@ -1,10 +1,13 @@
 //! signal implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/signal.h.html
 
-#![no_std]
-#![feature(asm, const_fn, core_intrinsics, global_asm)]
+use core::{mem, ptr};
+
+use header::errno;
+use platform;
+use platform::types::*;
+use platform::{PalSignal, Sys};
 
-extern crate errno;
-extern crate platform;
+pub use self::sys::*;
 
 #[cfg(target_os = "linux")]
 #[path = "linux.rs"]
@@ -14,11 +17,6 @@ pub mod sys;
 #[path = "redox.rs"]
 pub mod sys;
 
-pub use sys::*;
-
-use core::{mem, ptr};
-use platform::types::*;
-
 const SIG_ERR: usize = !0;
 
 pub const SIG_BLOCK: c_int = 0;
@@ -45,17 +43,17 @@ pub type sigset_t = c_ulong;
 
 #[no_mangle]
 pub extern "C" fn kill(pid: pid_t, sig: c_int) -> c_int {
-    platform::kill(pid, sig)
+    Sys::kill(pid, sig)
 }
 
 #[no_mangle]
 pub extern "C" fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
-    platform::killpg(pgrp, sig)
+    Sys::killpg(pgrp, sig)
 }
 
 #[no_mangle]
 pub extern "C" fn raise(sig: c_int) -> c_int {
-    platform::raise(sig)
+    Sys::raise(sig)
 }
 
 #[no_mangle]
@@ -72,11 +70,11 @@ pub unsafe extern "C" fn sigaction(
     } else {
         ptr::null_mut()
     };
-    platform::sigaction(sig, ptr, oact as *mut platform::types::sigaction)
+    Sys::sigaction(sig, ptr, oact as *mut platform::types::sigaction)
 }
 
 #[no_mangle]
-pub extern "C" fn sigaddset(set: *mut sigset_t, mut signo: c_int) -> c_int {
+pub extern "C" fn sigaddset(set: *mut sigset_t, signo: c_int) -> c_int {
     if signo <= 0 || signo as usize > NSIG {
         unsafe {
             platform::errno = errno::EINVAL;
@@ -149,7 +147,10 @@ extern "C" {
 }
 
 #[no_mangle]
-pub extern "C" fn signal(sig: c_int, func: Option<extern "C" fn(c_int)>) -> Option<extern "C" fn(c_int)> {
+pub extern "C" fn signal(
+    sig: c_int,
+    func: Option<extern "C" fn(c_int)>,
+) -> Option<extern "C" fn(c_int)> {
     let sa = sigaction {
         sa_handler: func,
         sa_flags: SA_RESTART as c_ulong,
@@ -176,7 +177,7 @@ pub extern "C" fn sigpending(set: *mut sigset_t) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
-    platform::sigprocmask(how, set, oset)
+    Sys::sigprocmask(how, set, oset)
 }
 
 // #[no_mangle]
@@ -231,5 +232,5 @@ pub const _signal_strings: [&'static str; 32] = [
     "Window changed\0",
     "I/O possible\0",
     "Power failure\0",
-    "Bad system call\0"
+    "Bad system call\0",
 ];
diff --git a/src/signal/src/redox.rs b/src/header/signal/redox.rs
similarity index 100%
rename from src/signal/src/redox.rs
rename to src/header/signal/redox.rs
diff --git a/src/stdio/cbindgen.toml b/src/header/stdio/cbindgen.toml
similarity index 100%
rename from src/stdio/cbindgen.toml
rename to src/header/stdio/cbindgen.toml
diff --git a/src/stdio/src/constants.rs b/src/header/stdio/constants.rs
similarity index 100%
rename from src/stdio/src/constants.rs
rename to src/header/stdio/constants.rs
diff --git a/src/stdio/src/default.rs b/src/header/stdio/default.rs
similarity index 100%
rename from src/stdio/src/default.rs
rename to src/header/stdio/default.rs
diff --git a/src/stdio/src/helpers.rs b/src/header/stdio/helpers.rs
similarity index 98%
rename from src/stdio/src/helpers.rs
rename to src/header/stdio/helpers.rs
index f888162728c72704bec122b5286925a213ab2a16..7f5bcad833a26d7e4d6f48d901a156578982dabb 100644
--- a/src/stdio/src/helpers.rs
+++ b/src/header/stdio/helpers.rs
@@ -1,15 +1,17 @@
-use super::constants::*;
-use super::{BUFSIZ, FILE, UNGET};
 use core::mem;
 use core::sync::atomic::AtomicBool;
-use errno;
-use fcntl::*;
+
+use header::errno;
+use header::fcntl::*;
+use header::string::strchr;
 use platform;
 use platform::types::*;
 
+use super::constants::*;
+use super::{BUFSIZ, FILE, UNGET};
+
 /// Parse mode flags as a string and output a mode flags integer
 pub unsafe fn parse_mode_flags(mode_str: *const c_char) -> i32 {
-    use string::strchr;
     let mut flags = if !strchr(mode_str, b'+' as i32).is_null() {
         O_RDWR
     } else if (*mode_str) == b'r' as i8 {
@@ -38,7 +40,6 @@ pub unsafe fn parse_mode_flags(mode_str: *const c_char) -> i32 {
 
 /// Open a file with the file descriptor `fd` in the mode `mode`
 pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> {
-    use string::strchr;
     if *mode != b'r' as i8 && *mode != b'w' as i8 && *mode != b'a' as i8 {
         platform::errno = errno::EINVAL;
         return None;
diff --git a/src/stdio/src/internal.rs b/src/header/stdio/internal.rs
similarity index 100%
rename from src/stdio/src/internal.rs
rename to src/header/stdio/internal.rs
diff --git a/src/stdio/src/lib.rs b/src/header/stdio/mod.rs
similarity index 95%
rename from src/stdio/src/lib.rs
rename to src/header/stdio/mod.rs
index 0b7700fc0e61755bbfe014453b405322b5dbceb0..e4e0e8d9ef2e2f1ec77feb76a1cc72a11686b801 100644
--- a/src/stdio/src/lib.rs
+++ b/src/header/stdio/mod.rs
@@ -1,39 +1,30 @@
 //! stdio implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdio.h.html
 
-#![no_std]
-// For Vec
-#![feature(alloc)]
-#![feature(const_fn)]
-
-#[macro_use]
-extern crate alloc;
-extern crate errno;
-extern crate fcntl;
-#[macro_use]
-extern crate lazy_static;
-extern crate platform;
-extern crate string;
-extern crate va_list as vl;
-
+use alloc::vec::Vec;
 use core::fmt::Write as WriteFmt;
 use core::fmt::{self, Error};
 use core::sync::atomic::{AtomicBool, Ordering};
 use core::{ptr, str};
-
-use alloc::vec::Vec;
-use errno::STR_ERROR;
+use va_list::VaList as va_list;
+
+use c_str::CStr;
+use header::errno::{self, STR_ERROR};
+use header::fcntl;
+use header::stdlib::mkstemp;
+use header::string::strlen;
+use platform;
 use platform::types::*;
 use platform::{c_str, errno, Read, Write};
-use vl::VaList as va_list;
+use platform::{Pal, Sys};
 
 mod printf;
 mod scanf;
 
+pub use self::default::*;
 mod default;
-pub use default::*;
 
+pub use self::constants::*;
 mod constants;
-pub use constants::*;
 
 mod helpers;
 
@@ -110,6 +101,7 @@ impl FILE {
         };
         return true;
     }
+
     pub fn write(&mut self, to_write: &[u8]) -> usize {
         if let Some((wbase, wpos, _)) = self.write {
             let len = wpos - wbase;
@@ -119,9 +111,9 @@ impl FILE {
             let mut rem = f_buf.len() + to_write.len();
             loop {
                 let mut count = if f_filled {
-                    platform::write(self.fd, &f_buf[advance..])
+                    Sys::write(self.fd, &f_buf[advance..])
                 } else {
-                    platform::write(self.fd, &f_buf[advance..]) + platform::write(self.fd, to_write)
+                    Sys::write(self.fd, &f_buf[advance..]) + Sys::write(self.fd, to_write)
                 };
                 if count == rem as isize {
                     self.write = if self.buf.len() == 0 {
@@ -152,13 +144,14 @@ impl FILE {
         //            -- Tommoa (20/6/2018)
         unreachable!()
     }
+
     pub fn read(&mut self, buf: &mut [u8]) -> usize {
         let adj = if self.buf.len() > 0 { 0 } else { 1 };
         let mut file_buf = &mut self.buf[self.unget..];
         let count = if buf.len() <= 1 - adj {
-            platform::read(self.fd, &mut file_buf)
+            Sys::read(self.fd, &mut file_buf)
         } else {
-            platform::read(self.fd, buf) + platform::read(self.fd, &mut file_buf)
+            Sys::read(self.fd, buf) + Sys::read(self.fd, &mut file_buf)
         };
         if count <= 0 {
             self.flags |= if count == 0 {
@@ -182,8 +175,9 @@ impl FILE {
         }
         buf.len()
     }
+
     pub fn seek(&self, off: off_t, whence: c_int) -> off_t {
-        platform::lseek(self.fd, off, whence)
+        Sys::lseek(self.fd, off, whence)
     }
 
     pub fn lock(&mut self) -> LockGuard {
@@ -229,7 +223,7 @@ impl<'a> Read for LockGuard<'a> {
         let mut buf = [0];
         match self.0.read(&mut buf) {
             0 => Ok(None),
-            _ => Ok(Some(buf[0]))
+            _ => Ok(Some(buf[0])),
         }
     }
 }
@@ -266,7 +260,7 @@ pub extern "C" fn cuserid(_s: *mut c_char) -> *mut c_char {
 #[no_mangle]
 pub extern "C" fn fclose(stream: &mut FILE) -> c_int {
     flockfile(stream);
-    let r = helpers::fflush_unlocked(stream) | platform::close(stream.fd);
+    let r = helpers::fflush_unlocked(stream) | Sys::close(stream.fd);
     if stream.flags & constants::F_PERM == 0 {
         // Not one of stdin, stdout or stderr
         unsafe {
@@ -444,7 +438,7 @@ pub extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FI
     if let Some(f) = unsafe { helpers::_fdopen(fd, mode) } {
         f
     } else {
-        platform::close(fd);
+        Sys::close(fd);
         ptr::null_mut()
     }
 }
@@ -461,9 +455,6 @@ pub extern "C" fn fputc(c: c_int, stream: &mut FILE) -> c_int {
 /// Insert a string into a stream
 #[no_mangle]
 pub extern "C" fn fputs(s: *const c_char, stream: &mut FILE) -> c_int {
-    extern "C" {
-        fn strlen(s: *const c_char) -> size_t;
-    }
     let len = unsafe { strlen(s) };
     (fwrite(s as *const c_void, 1, len, stream) == len) as c_int - 1
 }
@@ -555,7 +546,7 @@ pub extern "C" fn freopen(
         let new = unsafe { &mut *new }; // Should be safe, new is not null
         if new.fd == stream.fd {
             new.fd = -1;
-        } else if platform::dup2(new.fd, stream.fd) < 0
+        } else if Sys::dup2(new.fd, stream.fd) < 0
             || fcntl::sys_fcntl(stream.fd, fcntl::F_SETFL, flags & fcntl::O_CLOEXEC) < 0
         {
             fclose(new);
@@ -824,9 +815,10 @@ pub extern "C" fn putw(w: c_int, stream: &mut FILE) -> c_int {
 /// Delete file or directory `path`
 #[no_mangle]
 pub extern "C" fn remove(path: *const c_char) -> c_int {
-    let r = platform::unlink(path);
+    let path = unsafe { CStr::from_ptr(path) };
+    let r = Sys::unlink(path);
     if r == -errno::EISDIR {
-        platform::rmdir(path)
+        Sys::rmdir(path)
     } else {
         r
     }
@@ -834,7 +826,9 @@ pub extern "C" fn remove(path: *const c_char) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn rename(oldpath: *const c_char, newpath: *const c_char) -> c_int {
-    platform::rename(oldpath, newpath)
+    let oldpath = unsafe { CStr::from_ptr(oldpath) };
+    let newpath = unsafe { CStr::from_ptr(newpath) };
+    Sys::rename(oldpath, newpath)
 }
 
 /// Rewind `stream` back to the beginning of it
@@ -895,23 +889,22 @@ pub extern "C" fn tempnam(_dir: *const c_char, _pfx: *const c_char) -> *mut c_ch
 
 #[no_mangle]
 pub extern "C" fn tmpfile() -> *mut FILE {
-    extern "C" {
-        fn mkstemp(name: *mut c_char) -> c_int;
-    }
-
     let mut file_name = *b"/tmp/tmpfileXXXXXX";
     let file_name = file_name.as_mut_ptr() as *mut c_char;
-    let fd = unsafe { mkstemp(file_name) };
+    let fd = mkstemp(file_name);
 
     if fd < 0 {
         return ptr::null_mut();
     }
 
     let fp = fdopen(fd, b"w+".as_ptr() as *const i8);
-    platform::unlink(file_name);
+    {
+        let file_name = unsafe { CStr::from_ptr(file_name) };
+        Sys::unlink(file_name);
+    }
 
     if fp == ptr::null_mut() {
-        platform::close(fd);
+        Sys::close(fd);
     }
 
     fp
diff --git a/src/stdio/src/printf.rs b/src/header/stdio/printf.rs
similarity index 99%
rename from src/stdio/src/printf.rs
rename to src/header/stdio/printf.rs
index 71c0ca94fa766579461e6ee7d003efbb7692f02e..061fba7ef17f7f0b8b59440f6c005f05eef858b9 100644
--- a/src/stdio/src/printf.rs
+++ b/src/header/stdio/printf.rs
@@ -3,7 +3,7 @@ use core::{slice, str};
 
 use platform::types::*;
 use platform::{self, Write};
-use vl::VaList;
+use va_list::VaList;
 
 pub unsafe fn printf<W: Write>(w: W, format: *const c_char, mut ap: VaList) -> c_int {
     let mut w = platform::CountingWriter::new(w);
diff --git a/src/stdio/src/scanf.rs b/src/header/stdio/scanf.rs
similarity index 99%
rename from src/stdio/src/scanf.rs
rename to src/header/stdio/scanf.rs
index 2652c141b440f16256b83b145daf2b744045b97a..d9cd3e15eb69b13fd6dc03834801ac3cb93757a8 100644
--- a/src/stdio/src/scanf.rs
+++ b/src/header/stdio/scanf.rs
@@ -2,7 +2,7 @@ use alloc::String;
 use alloc::Vec;
 use platform::types::*;
 use platform::Read;
-use vl::VaList;
+use va_list::VaList;
 
 #[derive(PartialEq, Eq)]
 enum IntKind {
@@ -44,9 +44,9 @@ unsafe fn inner_scanf<R: Read>(
                     byte = b;
                     count += 1;
                     true
-                },
+                }
                 Ok(None) => false,
-                Err(()) => return Err(-1)
+                Err(()) => return Err(-1),
             }
         }};
     }
diff --git a/src/stdlib/cbindgen.toml b/src/header/stdlib/cbindgen.toml
similarity index 100%
rename from src/stdlib/cbindgen.toml
rename to src/header/stdlib/cbindgen.toml
diff --git a/src/stdlib/src/lib.rs b/src/header/stdlib/mod.rs
similarity index 84%
rename from src/stdlib/src/lib.rs
rename to src/header/stdlib/mod.rs
index b171747806c77c139347236a66fe62f45c460bff..9116eb7a4a4a19d68b7e583ffa6ff53ac4afd068 100644
--- a/src/stdlib/src/lib.rs
+++ b/src/header/stdlib/mod.rs
@@ -1,29 +1,21 @@
 //! stdlib implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdlib.h.html
 
-#![no_std]
-#![feature(core_intrinsics)]
-
-extern crate ctype;
-extern crate errno;
-extern crate fcntl;
-extern crate platform;
-extern crate rand;
-extern crate string;
-extern crate time;
-extern crate unistd;
-extern crate wchar;
-
-use core::{iter, mem, ptr, slice, str};
+use core::{intrinsics, iter, mem, ptr};
 use rand::distributions::Alphanumeric;
 use rand::prng::XorShiftRng;
 use rand::rngs::JitterRng;
 use rand::{Rng, SeedableRng};
-use string::*;
-use wchar::*;
 
-use errno::*;
-use fcntl::*;
+use c_str::CStr;
+use header::errno::*;
+use header::fcntl::*;
+use header::string::*;
+use header::time::constants::CLOCK_MONOTONIC;
+use header::wchar::*;
+use header::{ctype, errno, unistd};
+use platform;
 use platform::types::*;
+use platform::{Pal, Sys};
 
 mod sort;
 
@@ -68,8 +60,6 @@ pub unsafe extern "C" fn a64l(s: *const c_char) -> c_long {
 
 #[no_mangle]
 pub unsafe extern "C" fn abort() {
-    use core::intrinsics;
-
     intrinsics::abort();
 }
 
@@ -183,8 +173,6 @@ pub unsafe extern "C" fn bsearch(
 
 #[no_mangle]
 pub unsafe extern "C" fn calloc(nelem: size_t, elsize: size_t) -> *mut c_void {
-    use core::intrinsics;
-
     let size = nelem * elsize;
     let ptr = malloc(size);
     if !ptr.is_null() {
@@ -235,7 +223,7 @@ pub unsafe extern "C" fn exit(status: c_int) {
         }
     }
 
-    platform::exit(status);
+    Sys::exit(status);
 }
 
 // #[no_mangle]
@@ -403,7 +391,7 @@ fn inner_mktemp<T, F>(name: *mut c_char, suffix_len: c_int, mut attempt: F) -> O
 where
     F: FnMut() -> Option<T>,
 {
-    let len = unsafe { strlen(name) } as c_int;
+    let len = unsafe { strlen(name) as c_int };
 
     if len < 6 || suffix_len > len - 6 {
         unsafe { platform::errno = errno::EINVAL };
@@ -445,13 +433,12 @@ where
 #[no_mangle]
 pub extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
     if inner_mktemp(name, 0, || unsafe {
-        let mut st: stat = mem::uninitialized();
-        let ret = if platform::stat(name, &mut st) != 0 && platform::errno == ENOENT {
+        let name = unsafe { CStr::from_ptr(name) };
+        let ret = if Sys::access(name, 0) != 0 && platform::errno == ENOENT {
             Some(())
         } else {
             None
         };
-        mem::forget(st);
         ret
     }).is_none()
     {
@@ -463,10 +450,8 @@ pub extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
 }
 
 fn get_nstime() -> u64 {
-    use core::mem;
-    use time::constants::CLOCK_MONOTONIC;
     let mut ts: timespec = unsafe { mem::uninitialized() };
-    platform::clock_gettime(CLOCK_MONOTONIC, &mut ts);
+    Sys::clock_gettime(CLOCK_MONOTONIC, &mut ts);
     ts.tv_nsec as u64
 }
 
@@ -476,7 +461,8 @@ pub extern "C" fn mkostemps(name: *mut c_char, suffix_len: c_int, mut flags: c_i
     flags |= O_RDWR | O_CREAT | O_EXCL;
 
     inner_mktemp(name, suffix_len, || {
-        let fd = platform::open(name, flags, 0600);
+        let name = unsafe { CStr::from_ptr(name) };
+        let fd = Sys::open(name, flags, 0600);
 
         if fd >= 0 {
             Some(fd)
@@ -522,7 +508,11 @@ pub unsafe extern "C" fn putenv(insert: *mut c_char) -> c_int {
         platform::inner_environ[i] = insert;
     } else {
         let i = platform::inner_environ.len() - 1;
-        assert_eq!(platform::inner_environ[i], ptr::null_mut(), "environ did not end with null");
+        assert_eq!(
+            platform::inner_environ[i],
+            ptr::null_mut(),
+            "environ did not end with null"
+        );
         platform::inner_environ[i] = insert;
         platform::inner_environ.push(ptr::null_mut());
         platform::environ = platform::inner_environ.as_mut_ptr();
@@ -586,7 +576,11 @@ pub extern "C" fn seed48(seed16v: [c_ushort; 3]) -> c_ushort {
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn setenv(mut key: *const c_char, mut value: *const c_char, overwrite: c_int) -> c_int {
+pub unsafe extern "C" fn setenv(
+    mut key: *const c_char,
+    mut value: *const c_char,
+    overwrite: c_int,
+) -> c_int {
     let mut key_len = 0;
     while *key.offset(key_len) != 0 {
         key_len += 1;
@@ -617,7 +611,11 @@ pub unsafe extern "C" fn setenv(mut key: *const c_char, mut value: *const c_char
         }
     } else {
         let i = platform::inner_environ.len() - 1;
-        assert_eq!(platform::inner_environ[i], ptr::null_mut(), "environ did not end with null");
+        assert_eq!(
+            platform::inner_environ[i],
+            ptr::null_mut(),
+            "environ did not end with null"
+        );
         platform::inner_environ.push(ptr::null_mut());
         platform::environ = platform::inner_environ.as_mut_ptr();
         i
@@ -679,9 +677,15 @@ pub unsafe extern "C" fn strtod(mut s: *const c_char, endptr: *mut *mut c_char)
     let mut radix = 10;
 
     let negative = match *s as u8 {
-        b'-' => { s = s.offset(1); true },
-        b'+' => { s = s.offset(1); false },
-        _ => false
+        b'-' => {
+            s = s.offset(1);
+            true
+        }
+        b'+' => {
+            s = s.offset(1);
+            false
+        }
+        _ => false,
     };
 
     if *s as u8 == b'0' && *s.offset(1) as u8 == b'x' {
@@ -830,110 +834,6 @@ pub fn convert_integer(s: *const c_char, base: c_int) -> Option<(c_ulong, isize,
     }
 }
 
-#[macro_export]
-macro_rules! strto_impl {
-    (
-        $rettype:ty, $signed:expr, $maxval:expr, $minval:expr, $s:ident, $endptr:ident, $base:ident
-    ) => {{
-        // ensure these are constants
-        const CHECK_SIGN: bool = $signed;
-        const MAX_VAL: $rettype = $maxval;
-        const MIN_VAL: $rettype = $minval;
-
-        let set_endptr = |idx: isize| {
-            if !$endptr.is_null() {
-                // This is stupid, but apparently strto* functions want
-                // const input but mut output, yet the man page says
-                // "stores the address of the first invalid character in *endptr"
-                // so obviously it doesn't want us to clone it.
-                *$endptr = $s.offset(idx) as *mut _;
-            }
-        };
-
-        let invalid_input = || {
-            platform::errno = EINVAL;
-            set_endptr(0);
-        };
-
-        // only valid bases are 2 through 36
-        if $base != 0 && ($base < 2 || $base > 36) {
-            invalid_input();
-            return 0;
-        }
-
-        let mut idx = 0;
-
-        // skip any whitespace at the beginning of the string
-        while ctype::isspace(*$s.offset(idx) as c_int) != 0 {
-            idx += 1;
-        }
-
-        // check for +/-
-        let positive = match is_positive(*$s.offset(idx)) {
-            Some((pos, i)) => {
-                idx += i;
-                pos
-            }
-            None => {
-                invalid_input();
-                return 0;
-            }
-        };
-
-        // convert the string to a number
-        let num_str = $s.offset(idx);
-        let res = match $base {
-            0 => detect_base(num_str)
-                .and_then(|($base, i)| convert_integer(num_str.offset(i), $base)),
-            8 => convert_octal(num_str),
-            16 => convert_hex(num_str),
-            _ => convert_integer(num_str, $base),
-        };
-
-        // check for error parsing octal/hex prefix
-        // also check to ensure a number was indeed parsed
-        let (num, i, overflow) = match res {
-            Some(res) => res,
-            None => {
-                invalid_input();
-                return 0;
-            }
-        };
-        idx += i;
-
-        let overflow = if CHECK_SIGN {
-            overflow || (num as c_long).is_negative()
-        } else {
-            overflow
-        };
-        // account for the sign
-        let num = num as $rettype;
-        let num = if overflow {
-            platform::errno = ERANGE;
-            if CHECK_SIGN {
-                if positive {
-                    MAX_VAL
-                } else {
-                    MIN_VAL
-                }
-            } else {
-                MAX_VAL
-            }
-        } else {
-            if positive {
-                num
-            } else {
-                // not using -num to keep the compiler happy
-                num.overflowing_neg().0
-            }
-        };
-
-        set_endptr(idx);
-
-        num
-    }};
-}
-
 #[no_mangle]
 pub unsafe extern "C" fn strtoul(
     s: *const c_char,
@@ -974,7 +874,11 @@ pub unsafe extern "C" fn strtoull(
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn strtoll(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
+pub unsafe extern "C" fn strtoll(
+    s: *const c_char,
+    endptr: *mut *mut c_char,
+    base: c_int,
+) -> c_long {
     strtol(s, endptr, base)
 }
 
@@ -1004,7 +908,7 @@ pub unsafe extern "C" fn system(command: *const c_char) -> c_int {
         unreachable!();
     } else {
         let mut wstatus = 0;
-        if platform::waitpid(child_pid, &mut wstatus, 0) == !0 {
+        if Sys::waitpid(child_pid, &mut wstatus, 0) == !0 {
             return -1;
         }
 
diff --git a/src/stdlib/src/sort.rs b/src/header/stdlib/sort.rs
similarity index 100%
rename from src/stdlib/src/sort.rs
rename to src/header/stdlib/sort.rs
diff --git a/src/string/cbindgen.toml b/src/header/string/cbindgen.toml
similarity index 100%
rename from src/string/cbindgen.toml
rename to src/header/string/cbindgen.toml
diff --git a/src/string/src/lib.rs b/src/header/string/mod.rs
similarity index 96%
rename from src/string/src/lib.rs
rename to src/header/string/mod.rs
index 7960febbce5d49fb349247e9d3269b80959fcd25..cb48b8871bde8d9ee5c4926ed98d284036c1dcbb 100644
--- a/src/string/src/lib.rs
+++ b/src/header/string/mod.rs
@@ -1,15 +1,12 @@
 //! string implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html
-#![no_std]
 
-extern crate errno;
-extern crate platform;
-extern crate signal;
-
-use core::cmp;
 use core::mem;
 use core::ptr;
 use core::usize;
-use errno::*;
+
+use header::errno::*;
+use header::signal;
+use platform;
 use platform::types::*;
 
 #[no_mangle]
@@ -182,14 +179,15 @@ pub unsafe fn inner_strspn(s1: *const c_char, s2: *const c_char, cmp: bool) -> s
     let mut i = 0;
     while *s2.offset(i) != 0 {
         byteset[(*s2.offset(i) as usize) / BITSIZE] |=
-            1 << (*s2.offset(i) as usize & (BITSIZE-1));
+            1 << (*s2.offset(i) as usize & (BITSIZE - 1));
         i += 1;
     }
 
     i = 0; // reset
-    while *s1.offset(i) != 0 &&
-            (byteset[(*s1.offset(i) as usize) / BITSIZE] &
-            1 << (*s1.offset(i) as usize & (BITSIZE-1)) != 0) == cmp {
+    while *s1.offset(i) != 0
+        && (byteset[(*s1.offset(i) as usize) / BITSIZE]
+            & 1 << (*s1.offset(i) as usize & (BITSIZE - 1)) != 0) == cmp
+    {
         i += 1;
     }
     i as size_t
diff --git a/src/strings/cbindgen.toml b/src/header/strings/cbindgen.toml
similarity index 100%
rename from src/strings/cbindgen.toml
rename to src/header/strings/cbindgen.toml
diff --git a/src/strings/src/lib.rs b/src/header/strings/mod.rs
similarity index 94%
rename from src/strings/src/lib.rs
rename to src/header/strings/mod.rs
index 5737face2672b56f676866a52f58253287e0976a..d755295d76b128c9c5f3c21e617dce61a7bbcd35 100644
--- a/src/strings/src/lib.rs
+++ b/src/header/strings/mod.rs
@@ -1,20 +1,12 @@
 //! strings implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/strings.h.html
-#![no_std]
-#![feature(alloc)]
-
-extern crate alloc;
-extern crate platform;
 
 use alloc::Vec;
 use core::ptr;
+
 use platform::types::*;
 
 #[no_mangle]
-pub unsafe extern "C" fn bcmp(
-    mut first: *const c_void,
-    mut second: *const c_void,
-    n: size_t,
-) -> c_int {
+pub unsafe extern "C" fn bcmp(first: *const c_void, second: *const c_void, n: size_t) -> c_int {
     let first = first as *const c_char;
     let second = second as *const c_char;
 
diff --git a/src/sys_file/cbindgen.toml b/src/header/sys_file/cbindgen.toml
similarity index 100%
rename from src/sys_file/cbindgen.toml
rename to src/header/sys_file/cbindgen.toml
diff --git a/src/sys_file/src/lib.rs b/src/header/sys_file/mod.rs
similarity index 82%
rename from src/sys_file/src/lib.rs
rename to src/header/sys_file/mod.rs
index a12bcc2a0bee2b1a3b71c543389df10d0a3e1c7b..80a99855c40d74f3e54ece0b0b85c02f0d5a9b3e 100644
--- a/src/sys_file/src/lib.rs
+++ b/src/header/sys_file/mod.rs
@@ -1,10 +1,7 @@
 //! sys/file.h implementation
 
-#![no_std]
-
-extern crate platform;
-
 use platform::types::*;
+use platform::{Pal, Sys};
 
 pub const LOCK_SH: usize = 1;
 pub const LOCK_EX: usize = 2;
@@ -17,5 +14,5 @@ pub const L_XTND: usize = 2;
 
 #[no_mangle]
 pub extern "C" fn flock(fd: c_int, operation: c_int) -> c_int {
-    platform::flock(fd, operation)
+    Sys::flock(fd, operation)
 }
diff --git a/src/sys_ioctl/cbindgen.toml b/src/header/sys_ioctl/cbindgen.toml
similarity index 100%
rename from src/sys_ioctl/cbindgen.toml
rename to src/header/sys_ioctl/cbindgen.toml
diff --git a/src/sys_ioctl/src/lib.rs b/src/header/sys_ioctl/mod.rs
similarity index 98%
rename from src/sys_ioctl/src/lib.rs
rename to src/header/sys_ioctl/mod.rs
index 40b0427bfd58943df24faf2ccdff486d1aef1e65..adbdd7f3e27b44f4134f2ef1a893fcdfed91758e 100644
--- a/src/sys_ioctl/src/lib.rs
+++ b/src/header/sys_ioctl/mod.rs
@@ -1,9 +1,5 @@
 //! ioctl implementation for linux
 
-#![no_std]
-
-extern crate platform;
-
 use platform::types::*;
 
 // This is used from sgtty
@@ -18,7 +14,8 @@ pub struct sgttyb {
 
 #[cfg(target_os = "linux")]
 pub mod inner {
-    use *;
+    use platform::types::*;
+    use platform::{Pal, Sys};
 
     #[repr(C)]
     pub struct winsize {
@@ -31,7 +28,7 @@ pub mod inner {
     #[no_mangle]
     pub extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
         // TODO: Somehow support varargs to syscall??
-        platform::ioctl(fd, request, out)
+        Sys::ioctl(fd, request, out)
     }
 
     pub const TCGETS: c_ulong = 0x5401;
@@ -224,4 +221,4 @@ pub mod inner {
 }
 
 #[cfg(target_os = "linux")]
-pub use inner::*;
+pub use self::inner::*;
diff --git a/src/sys_mman/cbindgen.toml b/src/header/sys_mman/cbindgen.toml
similarity index 100%
rename from src/sys_mman/cbindgen.toml
rename to src/header/sys_mman/cbindgen.toml
diff --git a/src/sys_mman/src/linux.rs b/src/header/sys_mman/linux.rs
similarity index 100%
rename from src/sys_mman/src/linux.rs
rename to src/header/sys_mman/linux.rs
diff --git a/src/sys_mman/src/lib.rs b/src/header/sys_mman/mod.rs
similarity index 90%
rename from src/sys_mman/src/lib.rs
rename to src/header/sys_mman/mod.rs
index c2151e40368b85b25a09f5ca59a965cb30883fce..013050a053bd119c99c07f11fa1a37d3f5f4ba54 100644
--- a/src/sys_mman/src/lib.rs
+++ b/src/header/sys_mman/mod.rs
@@ -1,10 +1,7 @@
-#![no_std]
-
-extern crate platform;
-
 use platform::types::*;
+use platform::{Pal, Sys};
 
-pub use sys::*;
+pub use self::sys::*;
 
 #[cfg(target_os = "linux")]
 #[path = "linux.rs"]
@@ -33,7 +30,7 @@ pub unsafe extern "C" fn mmap(
     fildes: c_int,
     off: off_t,
 ) -> *mut c_void {
-    platform::mmap(addr, len, prot, flags, fildes, off)
+    Sys::mmap(addr, len, prot, flags, fildes, off)
 }
 
 // #[no_mangle]
@@ -58,7 +55,7 @@ pub extern "C" fn munlockall() -> c_int {
 
 #[no_mangle]
 pub unsafe extern "C" fn munmap(addr: *mut c_void, len: usize) -> c_int {
-    platform::munmap(addr, len)
+    Sys::munmap(addr, len)
 }
 
 // #[no_mangle]
diff --git a/src/sys_mman/src/redox.rs b/src/header/sys_mman/redox.rs
similarity index 100%
rename from src/sys_mman/src/redox.rs
rename to src/header/sys_mman/redox.rs
diff --git a/src/sys_resource/cbindgen.toml b/src/header/sys_resource/cbindgen.toml
similarity index 100%
rename from src/sys_resource/cbindgen.toml
rename to src/header/sys_resource/cbindgen.toml
diff --git a/src/sys_resource/src/lib.rs b/src/header/sys_resource/mod.rs
similarity index 82%
rename from src/sys_resource/src/lib.rs
rename to src/header/sys_resource/mod.rs
index 228f26fc7d1d09b0f00d77ae7cd1f3e28639c9d5..f4b7bc29a2503d3d632a1739b861715ede819d5b 100644
--- a/src/sys_resource/src/lib.rs
+++ b/src/header/sys_resource/mod.rs
@@ -1,19 +1,16 @@
 //! sys/resource.h implementation for Redox, following
 //! http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysresource.h.html
 
-#![no_std]
-
-extern crate platform;
-extern crate sys_time;
-
+use header::sys_time::timeval;
+use platform;
 use platform::types::*;
-use sys_time::timeval;
+use platform::{Pal, Sys};
 
 // Exported in bits file
-const RUSAGE_SELF: c_int = 0;
-const RUSAGE_CHILDREN: c_int = -1;
-const RUSAGE_BOTH: c_int = -2;
-const RUSAGE_THREAD: c_int = 1;
+// const RUSAGE_SELF: c_int = 0;
+// const RUSAGE_CHILDREN: c_int = -1;
+// const RUSAGE_BOTH: c_int = -2;
+// const RUSAGE_THREAD: c_int = 1;
 
 type rlim_t = u64;
 
@@ -55,7 +52,7 @@ pub unsafe extern "C" fn getrlimit(resource: c_int, rlp: *mut rlimit) -> c_int {
 
 #[no_mangle]
 pub unsafe extern "C" fn getrusage(who: c_int, r_usage: *mut rusage) -> c_int {
-    platform::getrusage(who, r_usage as *mut platform::types::rusage)
+    Sys::getrusage(who, r_usage as *mut platform::types::rusage)
 }
 
 // #[no_mangle]
diff --git a/src/sys_select/cbindgen.toml b/src/header/sys_select/cbindgen.toml
similarity index 100%
rename from src/sys_select/cbindgen.toml
rename to src/header/sys_select/cbindgen.toml
diff --git a/src/sys_select/src/lib.rs b/src/header/sys_select/mod.rs
similarity index 73%
rename from src/sys_select/src/lib.rs
rename to src/header/sys_select/mod.rs
index 8b63fe29f190d27f40588e7bf6ba523cfab4a784..dcb40b6af6ce572a9f50d33cd1e1141f3ec8c062 100644
--- a/src/sys_select/src/lib.rs
+++ b/src/header/sys_select/mod.rs
@@ -1,10 +1,7 @@
 //! sys/select.h implementation
-#![no_std]
 
-extern crate platform;
-
-use core::mem;
 use platform::types::*;
+use platform::{Pal, Sys};
 
 // fd_set is defined in C because cbindgen is incompatible with mem::size_of booo
 
@@ -16,5 +13,5 @@ pub extern "C" fn select(
     exceptfds: *mut fd_set,
     timeout: *mut timeval,
 ) -> c_int {
-    platform::select(nfds, readfds, writefds, exceptfds, timeout)
+    Sys::select(nfds, readfds, writefds, exceptfds, timeout)
 }
diff --git a/src/sys_socket/cbindgen.toml b/src/header/sys_socket/cbindgen.toml
similarity index 100%
rename from src/sys_socket/cbindgen.toml
rename to src/header/sys_socket/cbindgen.toml
diff --git a/src/sys_socket/src/constants.rs b/src/header/sys_socket/constants.rs
similarity index 100%
rename from src/sys_socket/src/constants.rs
rename to src/header/sys_socket/constants.rs
diff --git a/src/sys_socket/src/lib.rs b/src/header/sys_socket/mod.rs
similarity index 85%
rename from src/sys_socket/src/lib.rs
rename to src/header/sys_socket/mod.rs
index 7354e1b6e5721b69f3b6d02f83920db38d46fb22..877b9cae2cba6cf7741eb263c1f6c55def08f97f 100644
--- a/src/sys_socket/src/lib.rs
+++ b/src/header/sys_socket/mod.rs
@@ -1,15 +1,12 @@
 //! socket implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xns/syssocket.h.html
 
-#![no_std]
-#![allow(non_camel_case_types)]
-
-extern crate platform;
-
 use core::ptr;
+
+use platform;
 use platform::types::*;
+use platform::{PalSocket, Sys};
 
-mod constants;
-use constants::*;
+pub mod constants;
 
 pub type in_addr_t = [u8; 4];
 pub type in_port_t = u16;
@@ -28,7 +25,7 @@ pub unsafe extern "C" fn accept(
     address: *mut sockaddr,
     address_len: *mut socklen_t,
 ) -> c_int {
-    platform::accept(
+    Sys::accept(
         socket,
         address as *mut platform::types::sockaddr,
         address_len,
@@ -41,7 +38,7 @@ pub unsafe extern "C" fn bind(
     address: *const sockaddr,
     address_len: socklen_t,
 ) -> c_int {
-    platform::bind(
+    Sys::bind(
         socket,
         address as *const platform::types::sockaddr,
         address_len,
@@ -54,7 +51,7 @@ pub unsafe extern "C" fn connect(
     address: *const sockaddr,
     address_len: socklen_t,
 ) -> c_int {
-    platform::connect(
+    Sys::connect(
         socket,
         address as *const platform::types::sockaddr,
         address_len,
@@ -67,7 +64,7 @@ pub unsafe extern "C" fn getpeername(
     address: *mut sockaddr,
     address_len: *mut socklen_t,
 ) -> c_int {
-    platform::getpeername(
+    Sys::getpeername(
         socket,
         address as *mut platform::types::sockaddr,
         address_len,
@@ -80,7 +77,7 @@ pub unsafe extern "C" fn getsockname(
     address: *mut sockaddr,
     address_len: *mut socklen_t,
 ) -> c_int {
-    platform::getsockname(
+    Sys::getsockname(
         socket,
         address as *mut platform::types::sockaddr,
         address_len,
@@ -95,12 +92,12 @@ pub unsafe extern "C" fn getsockopt(
     option_value: *mut c_void,
     option_len: *mut socklen_t,
 ) -> c_int {
-    platform::getsockopt(socket, level, option_name, option_value, option_len)
+    Sys::getsockopt(socket, level, option_name, option_value, option_len)
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn listen(socket: c_int, backlog: c_int) -> c_int {
-    platform::listen(socket, backlog)
+    Sys::listen(socket, backlog)
 }
 
 #[no_mangle]
@@ -129,7 +126,7 @@ pub unsafe extern "C" fn recvfrom(
     address: *mut sockaddr,
     address_len: *mut socklen_t,
 ) -> ssize_t {
-    platform::recvfrom(
+    Sys::recvfrom(
         socket,
         buffer,
         length,
@@ -158,7 +155,7 @@ pub unsafe extern "C" fn sendto(
     dest_addr: *const sockaddr,
     dest_len: socklen_t,
 ) -> ssize_t {
-    platform::sendto(
+    Sys::sendto(
         socket,
         message,
         length,
@@ -176,17 +173,17 @@ pub unsafe extern "C" fn setsockopt(
     option_value: *const c_void,
     option_len: socklen_t,
 ) -> c_int {
-    platform::setsockopt(socket, level, option_name, option_value, option_len)
+    Sys::setsockopt(socket, level, option_name, option_value, option_len)
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn shutdown(socket: c_int, how: c_int) -> c_int {
-    platform::shutdown(socket, how)
+    Sys::shutdown(socket, how)
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
-    platform::socket(domain, kind, protocol)
+    Sys::socket(domain, kind, protocol)
 }
 
 #[no_mangle]
@@ -196,5 +193,5 @@ pub unsafe extern "C" fn socketpair(
     protocol: c_int,
     socket_vector: *mut c_int,
 ) -> c_int {
-    platform::socketpair(domain, kind, protocol, socket_vector)
+    Sys::socketpair(domain, kind, protocol, socket_vector)
 }
diff --git a/src/sys_stat/cbindgen.toml b/src/header/sys_stat/cbindgen.toml
similarity index 100%
rename from src/sys_stat/cbindgen.toml
rename to src/header/sys_stat/cbindgen.toml
diff --git a/src/sys_stat/src/lib.rs b/src/header/sys_stat/mod.rs
similarity index 75%
rename from src/sys_stat/src/lib.rs
rename to src/header/sys_stat/mod.rs
index 17c793e5e6292aadd9a0ea4b1d94b9d928ae0dc7..1bd6c005d117f38c90d4dca76011733a2546b499 100644
--- a/src/sys_stat/src/lib.rs
+++ b/src/header/sys_stat/mod.rs
@@ -1,10 +1,10 @@
 //! stat implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysstat.h.html
 
-#![no_std]
-
-extern crate platform;
-
+use c_str::CStr;
+use header::fcntl::{O_NOFOLLOW, O_PATH};
+use platform;
 use platform::types::*;
+use platform::{Pal, Sys};
 
 pub const S_IFMT: c_int = 0o0170000;
 
@@ -59,17 +59,18 @@ pub struct stat {
 
 #[no_mangle]
 pub extern "C" fn chmod(path: *const c_char, mode: mode_t) -> c_int {
-    platform::chmod(path, mode)
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::chmod(path, mode)
 }
 
 #[no_mangle]
 pub extern "C" fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
-    platform::fchmod(fildes, mode)
+    Sys::fchmod(fildes, mode)
 }
 
 #[no_mangle]
 pub extern "C" fn fstat(fildes: c_int, buf: *mut platform::types::stat) -> c_int {
-    platform::fstat(fildes, buf)
+    Sys::fstat(fildes, buf)
 }
 
 #[no_mangle]
@@ -79,22 +80,34 @@ pub extern "C" fn __fxstat(_ver: c_int, fildes: c_int, buf: *mut platform::types
 
 #[no_mangle]
 pub extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
-    platform::futimens(fd, times)
+    Sys::futimens(fd, times)
 }
 
 #[no_mangle]
 pub extern "C" fn lstat(path: *const c_char, buf: *mut platform::types::stat) -> c_int {
-    platform::lstat(path, buf)
+    let path = unsafe { CStr::from_ptr(path) };
+    let fd = Sys::open(path, O_PATH | O_NOFOLLOW, 0);
+    if fd < 0 {
+        return -1;
+    }
+
+    let res = Sys::fstat(fd, buf);
+
+    Sys::close(fd);
+
+    res
 }
 
 #[no_mangle]
 pub extern "C" fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
-    platform::mkdir(path, mode)
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::mkdir(path, mode)
 }
 
 #[no_mangle]
 pub extern "C" fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
-    platform::mkfifo(path, mode)
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::mkfifo(path, mode)
 }
 
 // #[no_mangle]
@@ -104,17 +117,20 @@ pub extern "C" fn mknod(path: *const c_char, mode: mode_t, dev: dev_t) -> c_int
 
 #[no_mangle]
 pub extern "C" fn stat(file: *const c_char, buf: *mut platform::types::stat) -> c_int {
-    platform::stat(file, buf)
-}
+    let file = unsafe { CStr::from_ptr(file) };
+    let fd = Sys::open(file, O_PATH, 0);
+    if fd < 0 {
+        return -1;
+    }
 
-#[no_mangle]
-pub extern "C" fn umask(mask: mode_t) -> mode_t {
-    platform::umask(mask)
+    let res = Sys::fstat(fd, buf);
+
+    Sys::close(fd);
+
+    res
 }
 
-/*
 #[no_mangle]
-pub extern "C" fn func(args) -> c_int {
-    unimplemented!();
+pub extern "C" fn umask(mask: mode_t) -> mode_t {
+    Sys::umask(mask)
 }
-*/
diff --git a/src/sys_time/cbindgen.toml b/src/header/sys_time/cbindgen.toml
similarity index 100%
rename from src/sys_time/cbindgen.toml
rename to src/header/sys_time/cbindgen.toml
diff --git a/src/sys_time/src/lib.rs b/src/header/sys_time/mod.rs
similarity index 88%
rename from src/sys_time/src/lib.rs
rename to src/header/sys_time/mod.rs
index fae8bfddc993b93051b7c828a3efce48b8f5cd5d..dc50a4ce80b47e771de6c9ff0b029ea1d5c80ddc 100644
--- a/src/sys_time/src/lib.rs
+++ b/src/header/sys_time/mod.rs
@@ -1,10 +1,9 @@
 //! sys/time implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/systime.h.html
 
-#![no_std]
-
-extern crate platform;
-
+use c_str::CStr;
+use platform;
 use platform::types::*;
+use platform::{Pal, Sys};
 
 pub const ITIMER_REAL: c_int = 0;
 pub const ITIMER_VIRTUAL: c_int = 1;
@@ -36,7 +35,7 @@ pub struct fd_set {
 
 #[no_mangle]
 pub extern "C" fn getitimer(which: c_int, value: *mut itimerval) -> c_int {
-    platform::getitimer(which, value as *mut platform::types::itimerval)
+    Sys::getitimer(which, value as *mut platform::types::itimerval)
 }
 
 #[no_mangle]
@@ -45,7 +44,7 @@ pub extern "C" fn setitimer(
     value: *const itimerval,
     ovalue: *mut itimerval,
 ) -> c_int {
-    platform::setitimer(
+    Sys::setitimer(
         which,
         value as *const platform::types::itimerval,
         ovalue as *mut platform::types::itimerval,
@@ -54,7 +53,7 @@ pub extern "C" fn setitimer(
 
 #[no_mangle]
 pub extern "C" fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
-    platform::gettimeofday(
+    Sys::gettimeofday(
         tp as *mut platform::types::timeval,
         tzp as *mut platform::types::timezone,
     )
@@ -73,6 +72,7 @@ pub extern "C" fn select(
 
 #[no_mangle]
 pub unsafe extern "C" fn utimes(path: *const c_char, times: *const timeval) -> c_int {
+    let path = CStr::from_ptr(path);
     let times_spec = [
         timespec {
             tv_sec: (*times.offset(0)).tv_sec,
@@ -83,7 +83,7 @@ pub unsafe extern "C" fn utimes(path: *const c_char, times: *const timeval) -> c
             tv_nsec: ((*times.offset(1)).tv_usec as i64) * 1000,
         },
     ];
-    platform::utimens(path, times_spec.as_ptr())
+    Sys::utimens(path, times_spec.as_ptr())
 }
 
 /*
diff --git a/src/sys_times/cbindgen.toml b/src/header/sys_times/cbindgen.toml
similarity index 100%
rename from src/sys_times/cbindgen.toml
rename to src/header/sys_times/cbindgen.toml
diff --git a/src/sys_times/src/lib.rs b/src/header/sys_times/mod.rs
similarity index 73%
rename from src/sys_times/src/lib.rs
rename to src/header/sys_times/mod.rs
index 3d8b7f89031bb4fb3ef16624d309533e09e6f285..72c0305a2fd5ef4a7fc694fa9f744c18d8c52ee9 100644
--- a/src/sys_times/src/lib.rs
+++ b/src/header/sys_times/mod.rs
@@ -1,10 +1,8 @@
 //! sys/times.h implementation
 
-#![no_std]
-
-extern crate platform;
-
+use platform;
 use platform::types::*;
+use platform::{Pal, Sys};
 
 #[repr(C)]
 pub struct tms {
@@ -16,5 +14,5 @@ pub struct tms {
 
 #[no_mangle]
 pub extern "C" fn times(out: *mut tms) -> clock_t {
-    platform::times(out as *mut platform::types::tms)
+    Sys::times(out as *mut platform::types::tms)
 }
diff --git a/src/sys_un/cbindgen.toml b/src/header/sys_un/cbindgen.toml
similarity index 100%
rename from src/sys_un/cbindgen.toml
rename to src/header/sys_un/cbindgen.toml
diff --git a/src/sys_un/src/lib.rs b/src/header/sys_un/mod.rs
similarity index 57%
rename from src/sys_un/src/lib.rs
rename to src/header/sys_un/mod.rs
index 19a75443a4a394861e8962bee162dfb947767d1a..41f55107be232a4868f510d987defd7eef06190d 100644
--- a/src/sys_un/src/lib.rs
+++ b/src/header/sys_un/mod.rs
@@ -1,10 +1,5 @@
-#![no_std]
-
-extern crate platform;
-extern crate sys_socket;
-
+use header::sys_socket::sa_family_t;
 use platform::types::*;
-use sys_socket::sa_family_t;
 
 #[repr(C)]
 pub struct sockaddr_un {
diff --git a/src/sys_utsname/cbindgen.toml b/src/header/sys_utsname/cbindgen.toml
similarity index 100%
rename from src/sys_utsname/cbindgen.toml
rename to src/header/sys_utsname/cbindgen.toml
diff --git a/src/sys_utsname/src/lib.rs b/src/header/sys_utsname/mod.rs
similarity index 79%
rename from src/sys_utsname/src/lib.rs
rename to src/header/sys_utsname/mod.rs
index 916ed56e0fa968043bb40578cfd1c2b4efa88783..fcd6c80728dfc0d79f50e3645af5c68d877d6206 100644
--- a/src/sys_utsname/src/lib.rs
+++ b/src/header/sys_utsname/mod.rs
@@ -1,12 +1,10 @@
 //! sys/utsname implementation for linux, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysutsname.h.html
 
-#![no_std]
-
 #[cfg(target_os = "linux")]
 mod inner {
-    extern crate platform;
-
-    use self::platform::types::*;
+    use platform;
+    use platform::types::*;
+    use platform::{Pal, Sys};
 
     const UTSLENGTH: usize = 65;
 
@@ -22,8 +20,8 @@ mod inner {
 
     #[no_mangle]
     pub unsafe extern "C" fn uname(uts: *mut utsname) -> c_int {
-        platform::uname(uts as *mut platform::types::utsname)
+        Sys::uname(uts as *mut platform::types::utsname)
     }
 }
 #[cfg(target_os = "linux")]
-pub use inner::*;
+pub use self::inner::*;
diff --git a/src/sys_wait/cbindgen.toml b/src/header/sys_wait/cbindgen.toml
similarity index 100%
rename from src/sys_wait/cbindgen.toml
rename to src/header/sys_wait/cbindgen.toml
diff --git a/src/sys_wait/src/lib.rs b/src/header/sys_wait/mod.rs
similarity index 89%
rename from src/sys_wait/src/lib.rs
rename to src/header/sys_wait/mod.rs
index 311678c138ce77c0476fa35ea82f274811578956..4259c48d1bc6b2e2c36233ba74fbf840ab06ee68 100644
--- a/src/sys_wait/src/lib.rs
+++ b/src/header/sys_wait/mod.rs
@@ -1,13 +1,9 @@
 //! sys/wait.h implementation for Redox, following
 //! http://pubs.opengroup.org/onlinepubs/7908799/xsh/syswait.h.html
 
-#![no_std]
-
-extern crate platform;
-extern crate sys_resource;
-
+use header::sys_resource::rusage;
 use platform::types::*;
-use sys_resource::rusage;
+use platform::{Pal, Sys};
 
 pub const WNOHANG: c_int = 1;
 pub const WUNTRACED: c_int = 2;
@@ -19,6 +15,7 @@ pub const WNOWAIT: c_int = 0x1000000;
 
 pub const __WNOTHREAD: c_int = 0x20000000;
 pub const __WALL: c_int = 0x40000000;
+#[allow(overflowing_literals)]
 pub const __WCLONE: c_int = 0x80000000;
 
 #[no_mangle]
@@ -51,5 +48,5 @@ pub unsafe extern "C" fn wait3(
 
 #[no_mangle]
 pub unsafe extern "C" fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
-    platform::waitpid(pid, stat_loc, options)
+    Sys::waitpid(pid, stat_loc, options)
 }
diff --git a/src/termios/cbindgen.toml b/src/header/termios/cbindgen.toml
similarity index 100%
rename from src/termios/cbindgen.toml
rename to src/header/termios/cbindgen.toml
diff --git a/src/termios/src/lib.rs b/src/header/termios/mod.rs
similarity index 95%
rename from src/termios/src/lib.rs
rename to src/header/termios/mod.rs
index e7306f76fc0189f3531ba1ed196463baa7a642b1..c9159ffdbabfaa22fd820349637d3ce9cd88be77 100644
--- a/src/termios/src/lib.rs
+++ b/src/header/termios/mod.rs
@@ -1,9 +1,8 @@
 //! termios implementation, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/termios.h.html
-#![no_std]
-
-extern crate platform;
 
+use platform;
 use platform::types::*;
+use platform::{Pal, Sys};
 
 pub type cc_t = u8;
 pub type speed_t = u32;
@@ -20,17 +19,17 @@ pub struct termios {
     c_line: cc_t,
     c_cc: [cc_t; NCCS],
     __c_ispeed: speed_t,
-    __c_ospeed: speed_t
+    __c_ospeed: speed_t,
 }
 
 #[no_mangle]
 pub extern "C" fn tcgetattr(fd: c_int, out: *mut termios) -> c_int {
-    platform::tcgetattr(fd, out as *mut platform::types::termios)
+    Sys::tcgetattr(fd, out as *mut platform::types::termios)
 }
 
 #[no_mangle]
 pub extern "C" fn tcsetattr(fd: c_int, act: c_int, value: *mut termios) -> c_int {
-    platform::tcsetattr(fd, act, value as *mut platform::types::termios)
+    Sys::tcsetattr(fd, act, value as *mut platform::types::termios)
 }
 
 pub const VINTR: usize = 0;
diff --git a/src/time/cbindgen.toml b/src/header/time/cbindgen.toml
similarity index 100%
rename from src/time/cbindgen.toml
rename to src/header/time/cbindgen.toml
diff --git a/src/time/src/constants.rs b/src/header/time/constants.rs
similarity index 96%
rename from src/time/src/constants.rs
rename to src/header/time/constants.rs
index d677f91b50f32eb5c7bc78de1ded1d3cbea9d185..15810f64c6c44ec284f708e33291c7a530aa781e 100644
--- a/src/time/src/constants.rs
+++ b/src/header/time/constants.rs
@@ -1,3 +1,7 @@
+use platform::types::*;
+
+pub use self::sys::*;
+
 #[cfg(target_os = "linux")]
 #[path = "linux.rs"]
 pub mod sys;
@@ -6,9 +10,6 @@ pub mod sys;
 #[path = "redox.rs"]
 pub mod sys;
 
-use platform::types::*;
-pub use sys::*;
-
 // Move epoch from 01.01.1970 to 01.03.0000 (yes, Year 0) - this is the first
 // day of a 400-year long "era", right after additional day of leap year.
 // This adjustment is required only for date calculation, so instead of
@@ -46,7 +47,6 @@ pub(crate) const MON_NAMES: [&str; 12] = [
 pub(crate) const CLOCK_REALTIME: clockid_t = 0;
 pub const CLOCK_MONOTONIC: clockid_t = 1;
 pub(crate) const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2;
-pub(crate) const CLOCK_THREAD_CPUTIME_ID: clockid_t = 3;
 
 // Can't be time_t because cbindgen UGH
 pub(crate) const CLOCKS_PER_SEC: c_long = 1_000_000;
diff --git a/src/time/src/helpers.rs b/src/header/time/helpers.rs
similarity index 98%
rename from src/time/src/helpers.rs
rename to src/header/time/helpers.rs
index 581c72eca1a5f15b2300e3d0fade8d46df982295..70ff5f3afe3e7dcb84e7d48edfe0b62cb6b4135f 100644
--- a/src/time/src/helpers.rs
+++ b/src/header/time/helpers.rs
@@ -1,6 +1,7 @@
-use constants::*;
 use platform::types::*;
 
+use super::constants::*;
+
 // compute year, month, day & day of year
 // for description of this algorithm see
 // http://howardhinnant.github.io/date_algorithms.html#civil_from_days
diff --git a/src/time/src/linux.rs b/src/header/time/linux.rs
similarity index 100%
rename from src/time/src/linux.rs
rename to src/header/time/linux.rs
diff --git a/src/time/src/lib.rs b/src/header/time/mod.rs
similarity index 96%
rename from src/time/src/lib.rs
rename to src/header/time/mod.rs
index 69ca7dcc9ba043e3efeeefa3c9ac97a27a81a211..1819601a09bf270ae6f13c46a15b8a6b55896c47 100644
--- a/src/time/src/lib.rs
+++ b/src/header/time/mod.rs
@@ -1,22 +1,19 @@
 //! time implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html
 
-#![no_std]
-#![feature(alloc, const_fn)]
+use core::mem::transmute;
+
+use header::errno::EIO;
+use platform;
+use platform::types::*;
+use platform::{Pal, Sys};
 
-extern crate alloc;
-extern crate errno;
-extern crate platform;
+use self::constants::*;
+use self::helpers::*;
 
 pub mod constants;
 mod helpers;
 mod strftime;
 
-use constants::*;
-use core::mem::transmute;
-use errno::EIO;
-use helpers::*;
-use platform::types::*;
-
 #[repr(C)]
 pub struct timespec {
     pub tv_sec: time_t,
@@ -121,7 +118,7 @@ pub extern "C" fn clock_getres(clock_id: clockid_t, res: *mut timespec) -> c_int
 
 #[no_mangle]
 pub extern "C" fn clock_gettime(clock_id: clockid_t, tp: *mut timespec) -> c_int {
-    platform::clock_gettime(clock_id, tp as *mut platform::types::timespec)
+    Sys::clock_gettime(clock_id, tp as *mut platform::types::timespec)
 }
 
 // #[no_mangle]
@@ -328,7 +325,7 @@ pub unsafe extern "C" fn mktime(t: *mut tm) -> time_t {
 
 #[no_mangle]
 pub extern "C" fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
-    platform::nanosleep(
+    Sys::nanosleep(
         rqtp as *const platform::types::timespec,
         rmtp as *mut platform::types::timespec,
     )
@@ -361,7 +358,7 @@ pub extern "C" fn strptime(buf: *const c_char, format: *const c_char, tm: *mut t
 #[no_mangle]
 pub extern "C" fn time(tloc: *mut time_t) -> time_t {
     let mut ts: platform::types::timespec = Default::default();
-    platform::clock_gettime(CLOCK_REALTIME, &mut ts);
+    Sys::clock_gettime(CLOCK_REALTIME, &mut ts);
     unsafe {
         if !tloc.is_null() {
             *tloc = ts.tv_sec
diff --git a/src/time/src/redox.rs b/src/header/time/redox.rs
similarity index 100%
rename from src/time/src/redox.rs
rename to src/header/time/redox.rs
diff --git a/src/time/src/strftime.rs b/src/header/time/strftime.rs
similarity index 95%
rename from src/time/src/strftime.rs
rename to src/header/time/strftime.rs
index aef702f684de1646d38f26dba4fdb301c67a6eb2..d2f6f91100b51ff3f8cdf0cbb3450a021b3ecff9 100644
--- a/src/time/src/strftime.rs
+++ b/src/header/time/strftime.rs
@@ -1,15 +1,13 @@
 use alloc::string::String;
+
 use platform::types::*;
 use platform::{self, Write};
-use tm;
 
-pub unsafe fn strftime<W: Write>(
-    w: &mut W,
-    format: *const c_char,
-    t: *const tm,
-) -> size_t {
+use super::tm;
+
+pub unsafe fn strftime<W: Write>(w: &mut W, format: *const c_char, t: *const tm) -> size_t {
     pub unsafe fn inner_strftime<W: Write>(
-        mut w: &mut W,
+        w: &mut W,
         mut format: *const c_char,
         t: *const tm,
     ) -> bool {
@@ -71,7 +69,7 @@ pub unsafe fn strftime<W: Write>(
 
         while *format != 0 {
             if *format as u8 != b'%' {
-                w!(byte *format as u8);
+                w!(byte * format as u8);
                 format = format.offset(1);
                 continue;
             }
@@ -115,7 +113,7 @@ pub unsafe fn strftime<W: Write>(
                 b'r' => w!(recurse "%I:%M:%S %p"),
                 b'R' => w!(recurse "%H:%M"),
                 // Nothing is modified in mktime, but the C standard of course requires a mutable pointer ._.
-                b's' => w!("{}", ::mktime(t as *mut tm)),
+                b's' => w!("{}", super::mktime(t as *mut tm)),
                 b'S' => w!("{:02}", (*t).tm_sec),
                 b'T' => w!(recurse "%H:%M:%S"),
                 b'u' => w!("{}", ((*t).tm_wday + 7 - 1) % 7 + 1),
diff --git a/src/unistd/src/brk.rs b/src/header/unistd/brk.rs
similarity index 80%
rename from src/unistd/src/brk.rs
rename to src/header/unistd/brk.rs
index bd186f8eba480e0f9c5019b5046940cbb6dee619..07466da39bd707fdad5894436b2431410666b69e 100644
--- a/src/unistd/src/brk.rs
+++ b/src/header/unistd/brk.rs
@@ -1,14 +1,15 @@
 use core::ptr;
 
-use errno::ENOMEM;
+use header::errno::ENOMEM;
 use platform;
 use platform::types::*;
+use platform::{Pal, Sys};
 
 static mut BRK: *mut c_void = ptr::null_mut();
 
 #[no_mangle]
 pub unsafe extern "C" fn brk(addr: *mut c_void) -> c_int {
-    BRK = platform::brk(addr);
+    BRK = Sys::brk(addr);
 
     if BRK < addr {
         platform::errno = ENOMEM;
@@ -21,7 +22,7 @@ pub unsafe extern "C" fn brk(addr: *mut c_void) -> c_int {
 #[no_mangle]
 pub unsafe extern "C" fn sbrk(incr: intptr_t) -> *mut c_void {
     if BRK == ptr::null_mut() {
-        BRK = platform::brk(ptr::null_mut());
+        BRK = Sys::brk(ptr::null_mut());
     }
 
     let old_brk = BRK;
@@ -29,7 +30,7 @@ pub unsafe extern "C" fn sbrk(incr: intptr_t) -> *mut c_void {
     if incr != 0 {
         let addr = old_brk.offset(incr);
 
-        BRK = platform::brk(addr);
+        BRK = Sys::brk(addr);
 
         if BRK < addr {
             platform::errno = ENOMEM;
diff --git a/src/unistd/cbindgen.toml b/src/header/unistd/cbindgen.toml
similarity index 100%
rename from src/unistd/cbindgen.toml
rename to src/header/unistd/cbindgen.toml
diff --git a/src/unistd/src/getopt.rs b/src/header/unistd/getopt.rs
similarity index 99%
rename from src/unistd/src/getopt.rs
rename to src/header/unistd/getopt.rs
index 29d77b4df65dd1286ffa495615f63442321b042a..1a4a66fd2fdae039bcd4aab4bda3604f87f0a311 100644
--- a/src/unistd/src/getopt.rs
+++ b/src/header/unistd/getopt.rs
@@ -2,9 +2,8 @@
 
 use core::ptr;
 
+use header::{stdio, string};
 use platform::types::*;
-use stdio;
-use string;
 
 #[allow(non_upper_case_globals)]
 #[no_mangle]
diff --git a/src/unistd/src/lib.rs b/src/header/unistd/mod.rs
similarity index 85%
rename from src/unistd/src/lib.rs
rename to src/header/unistd/mod.rs
index 944d9726694dd6d58cd301a86b15307d50f36c02..5a7e8b1cd3c627b76b189e3671577102dd6221ef 100644
--- a/src/unistd/src/lib.rs
+++ b/src/header/unistd/mod.rs
@@ -1,20 +1,16 @@
 //! unistd implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html
 
-#![no_std]
-
-extern crate errno;
-extern crate platform;
-extern crate stdio;
-extern crate string;
-extern crate sys_time;
-
 use core::{ptr, slice};
 
+use c_str::CStr;
+use header::sys_time;
+use platform;
 use platform::types::*;
+use platform::{Pal, Sys};
 
-pub use brk::*;
-pub use getopt::*;
-pub use pathconf::*;
+pub use self::brk::*;
+pub use self::getopt::*;
+pub use self::pathconf::*;
 
 mod brk;
 mod getopt;
@@ -42,12 +38,13 @@ const PATH_MAX: usize = 4096;
 
 #[no_mangle]
 pub extern "C" fn _exit(status: c_int) {
-    platform::exit(status)
+    Sys::exit(status)
 }
 
 #[no_mangle]
 pub extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
-    platform::access(path, mode)
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::access(path, mode)
 }
 
 #[no_mangle]
@@ -74,7 +71,8 @@ pub extern "C" fn alarm(seconds: c_uint) -> c_uint {
 
 #[no_mangle]
 pub extern "C" fn chdir(path: *const c_char) -> c_int {
-    platform::chdir(path)
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::chdir(path)
 }
 
 // #[no_mangle]
@@ -84,12 +82,13 @@ pub extern "C" fn chroot(path: *const c_char) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn chown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
-    platform::chown(path, owner, group)
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::chown(path, owner, group)
 }
 
 #[no_mangle]
 pub extern "C" fn close(fildes: c_int) -> c_int {
-    platform::close(fildes)
+    Sys::close(fildes)
 }
 
 // #[no_mangle]
@@ -104,12 +103,12 @@ pub extern "C" fn crypt(key: *const c_char, salt: *const c_char) -> *mut c_char
 
 #[no_mangle]
 pub extern "C" fn dup(fildes: c_int) -> c_int {
-    platform::dup(fildes)
+    Sys::dup(fildes)
 }
 
 #[no_mangle]
 pub extern "C" fn dup2(fildes: c_int, fildes2: c_int) -> c_int {
-    platform::dup2(fildes, fildes2)
+    Sys::dup2(fildes, fildes2)
 }
 
 // #[no_mangle]
@@ -147,7 +146,8 @@ pub unsafe extern "C" fn execve(
     argv: *const *mut c_char,
     envp: *const *mut c_char,
 ) -> c_int {
-    platform::execve(path, argv, envp)
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::execve(path, argv, envp)
 }
 
 // #[no_mangle]
@@ -157,12 +157,12 @@ pub extern "C" fn execvp(file: *const c_char, argv: *const *mut c_char) -> c_int
 
 #[no_mangle]
 pub extern "C" fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
-    platform::fchown(fildes, owner, group)
+    Sys::fchown(fildes, owner, group)
 }
 
 #[no_mangle]
 pub extern "C" fn fchdir(fildes: c_int) -> c_int {
-    platform::fchdir(fildes)
+    Sys::fchdir(fildes)
 }
 
 // #[no_mangle]
@@ -172,17 +172,17 @@ pub extern "C" fn fdatasync(fildes: c_int) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn fork() -> pid_t {
-    platform::fork()
+    Sys::fork()
 }
 
 #[no_mangle]
 pub extern "C" fn fsync(fildes: c_int) -> c_int {
-    platform::fsync(fildes)
+    Sys::fsync(fildes)
 }
 
 #[no_mangle]
 pub extern "C" fn ftruncate(fildes: c_int, length: off_t) -> c_int {
-    platform::ftruncate(fildes, length)
+    Sys::ftruncate(fildes, length)
 }
 
 #[no_mangle]
@@ -194,14 +194,17 @@ pub extern "C" fn getcwd(mut buf: *mut c_char, mut size: size_t) -> *mut c_char
         size = stack_buf.len();
     }
 
-    let ret = platform::getcwd(buf, size);
+    let ret = Sys::getcwd(buf, size);
     if ret == ptr::null_mut() {
         return ptr::null_mut();
     }
 
     if alloc {
-        let mut len = stack_buf.iter().position(|b| *b == 0).expect("no nul-byte in getcwd string") + 1;
-        let mut heap_buf = unsafe { platform::alloc(len) as *mut c_char };
+        let len = stack_buf
+            .iter()
+            .position(|b| *b == 0)
+            .expect("no nul-byte in getcwd string") + 1;
+        let heap_buf = unsafe { platform::alloc(len) as *mut c_char };
         for i in 0..len {
             unsafe {
                 *heap_buf.offset(i as isize) = stack_buf[i];
@@ -220,17 +223,17 @@ pub extern "C" fn getdtablesize() -> c_int {
 
 #[no_mangle]
 pub extern "C" fn getegid() -> gid_t {
-    platform::getegid()
+    Sys::getegid()
 }
 
 #[no_mangle]
 pub extern "C" fn geteuid() -> uid_t {
-    platform::geteuid()
+    Sys::geteuid()
 }
 
 #[no_mangle]
 pub extern "C" fn getgid() -> gid_t {
-    platform::getgid()
+    Sys::getgid()
 }
 
 // #[no_mangle]
@@ -245,7 +248,7 @@ pub extern "C" fn gethostid() -> c_long {
 
 #[no_mangle]
 pub unsafe extern "C" fn gethostname(name: *mut c_char, len: size_t) -> c_int {
-    platform::gethostname(name, len)
+    Sys::gethostname(name, len)
 }
 
 // #[no_mangle]
@@ -270,22 +273,22 @@ pub extern "C" fn getpass(prompt: *const c_char) -> *mut c_char {
 
 #[no_mangle]
 pub extern "C" fn getpgid(pid: pid_t) -> pid_t {
-    platform::getpgid(pid)
+    Sys::getpgid(pid)
 }
 
 #[no_mangle]
 pub extern "C" fn getpgrp() -> pid_t {
-    platform::getpgid(platform::getpid())
+    Sys::getpgid(Sys::getpid())
 }
 
 #[no_mangle]
 pub extern "C" fn getpid() -> pid_t {
-    platform::getpid()
+    Sys::getpid()
 }
 
 #[no_mangle]
 pub extern "C" fn getppid() -> pid_t {
-    platform::getppid()
+    Sys::getppid()
 }
 
 // #[no_mangle]
@@ -295,7 +298,7 @@ pub extern "C" fn getsid(pid: pid_t) -> pid_t {
 
 #[no_mangle]
 pub extern "C" fn getuid() -> uid_t {
-    platform::getuid()
+    Sys::getuid()
 }
 
 #[no_mangle]
@@ -305,7 +308,7 @@ pub extern "C" fn getwd(path_name: *mut c_char) -> *mut c_char {
 
 #[no_mangle]
 pub extern "C" fn isatty(fd: c_int) -> c_int {
-    platform::isatty(fd)
+    Sys::isatty(fd)
 }
 
 // #[no_mangle]
@@ -315,7 +318,9 @@ pub extern "C" fn lchown(path: *const c_char, owner: uid_t, group: gid_t) -> c_i
 
 #[no_mangle]
 pub extern "C" fn link(path1: *const c_char, path2: *const c_char) -> c_int {
-    platform::link(path1, path2)
+    let path1 = unsafe { CStr::from_ptr(path1) };
+    let path2 = unsafe { CStr::from_ptr(path2) };
+    Sys::link(path1, path2)
 }
 
 // #[no_mangle]
@@ -325,7 +330,7 @@ pub extern "C" fn lockf(fildes: c_int, function: c_int, size: off_t) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t {
-    platform::lseek(fildes, offset, whence)
+    Sys::lseek(fildes, offset, whence)
 }
 
 // #[no_mangle]
@@ -340,7 +345,7 @@ pub extern "C" fn pause() -> c_int {
 
 #[no_mangle]
 pub unsafe extern "C" fn pipe(fildes: *mut c_int) -> c_int {
-    platform::pipe(slice::from_raw_parts_mut(fildes, 2))
+    Sys::pipe(slice::from_raw_parts_mut(fildes, 2))
 }
 
 // #[no_mangle]
@@ -371,7 +376,7 @@ pub extern "C" fn pwrite(
 pub extern "C" fn read(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t {
     use core::slice;
     let buf = unsafe { slice::from_raw_parts_mut(buf as *mut u8, nbyte as usize) };
-    platform::read(fildes, buf)
+    Sys::read(fildes, buf)
 }
 
 // #[no_mangle]
@@ -381,17 +386,18 @@ pub extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsize: size_
 
 #[no_mangle]
 pub extern "C" fn rmdir(path: *const c_char) -> c_int {
-    platform::rmdir(path)
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::rmdir(path)
 }
 
 #[no_mangle]
 pub extern "C" fn setgid(gid: gid_t) -> c_int {
-    platform::setregid(gid, gid)
+    Sys::setregid(gid, gid)
 }
 
 #[no_mangle]
 pub extern "C" fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
-    platform::setpgid(pid, pgid)
+    Sys::setpgid(pid, pgid)
 }
 
 // #[no_mangle]
@@ -401,12 +407,12 @@ pub extern "C" fn setpgrp() -> pid_t {
 
 #[no_mangle]
 pub extern "C" fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
-    platform::setregid(rgid, egid)
+    Sys::setregid(rgid, egid)
 }
 
 #[no_mangle]
 pub extern "C" fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
-    platform::setreuid(ruid, euid)
+    Sys::setreuid(ruid, euid)
 }
 
 // #[no_mangle]
@@ -416,7 +422,7 @@ pub extern "C" fn setsid() -> pid_t {
 
 #[no_mangle]
 pub extern "C" fn setuid(uid: uid_t) -> c_int {
-    platform::setreuid(uid, uid)
+    Sys::setreuid(uid, uid)
 }
 
 #[no_mangle]
@@ -426,7 +432,7 @@ pub extern "C" fn sleep(seconds: c_uint) -> c_uint {
         tv_nsec: 0,
     };
     let rmtp = ptr::null_mut();
-    platform::nanosleep(&rqtp, rmtp);
+    Sys::nanosleep(&rqtp, rmtp);
     0
 }
 
@@ -502,7 +508,8 @@ pub extern "C" fn ualarm(value: useconds_t, interval: useconds_t) -> useconds_t
 
 #[no_mangle]
 pub extern "C" fn unlink(path: *const c_char) -> c_int {
-    platform::unlink(path)
+    let path = unsafe { CStr::from_ptr(path) };
+    Sys::unlink(path)
 }
 
 #[no_mangle]
@@ -512,7 +519,7 @@ pub extern "C" fn usleep(useconds: useconds_t) -> c_int {
         tv_nsec: ((useconds % 1000) * 1000) as i64,
     };
     let rmtp = ptr::null_mut();
-    platform::nanosleep(&rqtp, rmtp)
+    Sys::nanosleep(&rqtp, rmtp)
 }
 
 // #[no_mangle]
@@ -525,7 +532,7 @@ pub extern "C" fn write(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssi
     use core::slice;
 
     let buf = unsafe { slice::from_raw_parts(buf as *const u8, nbyte as usize) };
-    platform::write(fildes, buf)
+    Sys::write(fildes, buf)
 }
 
 /*
diff --git a/src/unistd/src/pathconf.rs b/src/header/unistd/pathconf.rs
similarity index 100%
rename from src/unistd/src/pathconf.rs
rename to src/header/unistd/pathconf.rs
diff --git a/src/utime/cbindgen.toml b/src/header/utime/cbindgen.toml
similarity index 100%
rename from src/utime/cbindgen.toml
rename to src/header/utime/cbindgen.toml
diff --git a/src/utime/src/lib.rs b/src/header/utime/mod.rs
similarity index 80%
rename from src/utime/src/lib.rs
rename to src/header/utime/mod.rs
index cea8b06f8d0a6644b7fe79c52b7f03a1fb11abac..8007744a32363475ae1873cae40c2a5eeb43f474 100644
--- a/src/utime/src/lib.rs
+++ b/src/header/utime/mod.rs
@@ -1,10 +1,8 @@
 //! utime implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/utime.h.html
 
-#![no_std]
-
-extern crate platform;
-
+use c_str::CStr;
 use platform::types::*;
+use platform::{Pal, Sys};
 
 #[repr(C)]
 #[derive(Clone)]
@@ -15,6 +13,7 @@ pub struct utimbuf {
 
 #[no_mangle]
 pub unsafe extern "C" fn utime(filename: *const c_char, times: *const utimbuf) -> c_int {
+    let filename = CStr::from_ptr(filename);
     let times_spec = [
         timespec {
             tv_sec: (*times).actime,
@@ -25,5 +24,5 @@ pub unsafe extern "C" fn utime(filename: *const c_char, times: *const utimbuf) -
             tv_nsec: 0,
         },
     ];
-    platform::utimens(filename, times_spec.as_ptr())
+    Sys::utimens(filename, times_spec.as_ptr())
 }
diff --git a/src/wchar/cbindgen.toml b/src/header/wchar/cbindgen.toml
similarity index 100%
rename from src/wchar/cbindgen.toml
rename to src/header/wchar/cbindgen.toml
diff --git a/src/wchar/src/lib.rs b/src/header/wchar/mod.rs
similarity index 94%
rename from src/wchar/src/lib.rs
rename to src/header/wchar/mod.rs
index fdeb25becf2cf2ea04225931205aadb0048da213..b60232e7d5f6a720b1e3268acae5af0ed3e7b8f1 100644
--- a/src/wchar/src/lib.rs
+++ b/src/header/wchar/mod.rs
@@ -1,29 +1,18 @@
 //! wchar implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/wchar.h.html
 
-#![no_std]
-#![feature(str_internals)]
-
-extern crate errno;
-extern crate platform;
-extern crate stdio;
-extern crate time;
-extern crate va_list as vl;
-
 use core::ptr;
+use va_list::VaList as va_list;
+
+use header::stdio::*;
+use header::stdlib::MB_CUR_MAX;
+use header::time::*;
+use platform;
 use platform::types::*;
-use stdio::*;
-use time::*;
-use vl::VaList as va_list;
 
 mod utf8;
 
 const WEOF: wint_t = 0xFFFFFFFFu32;
 
-//Maximum number of bytes in a multibyte character for the current locale
-const MB_CUR_MAX: c_int = 4;
-//Maximum number of bytes in a multibyte characters for any locale
-const MB_LEN_MAX: c_int = 4;
-
 #[repr(C)]
 #[derive(Clone, Copy)]
 pub struct mbstate_t;
@@ -211,13 +200,13 @@ pub extern "C" fn swprintf(
     s: *mut wchar_t,
     n: size_t,
     format: *const wchar_t,
-    mut ap: va_list,
+    ap: va_list,
 ) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn swscanf(s: *const wchar_t, format: *const wchar_t, mut ap: va_list) -> c_int {
+pub extern "C" fn swscanf(s: *const wchar_t, format: *const wchar_t, ap: va_list) -> c_int {
     unimplemented!();
 }
 
@@ -436,11 +425,11 @@ pub extern "C" fn wmemset(ws1: *mut wchar_t, ws2: wchar_t, n: size_t) -> *mut wc
 }
 
 // #[no_mangle]
-pub extern "C" fn wprintf(format: *const wchar_t, mut ap: va_list) -> c_int {
+pub extern "C" fn wprintf(format: *const wchar_t, ap: va_list) -> c_int {
     unimplemented!();
 }
 
 // #[no_mangle]
-pub extern "C" fn wscanf(format: *const wchar_t, mut ap: va_list) -> c_int {
+pub extern "C" fn wscanf(format: *const wchar_t, ap: va_list) -> c_int {
     unimplemented!();
 }
diff --git a/src/wchar/src/utf8.rs b/src/header/wchar/utf8.rs
similarity index 87%
rename from src/wchar/src/utf8.rs
rename to src/header/wchar/utf8.rs
index d9a23380ff2b50a6ea3408a5eb333fc83397c887..fded8d1d86681e0e0f1d9cfabf8d7ca3c01b613f 100644
--- a/src/wchar/src/utf8.rs
+++ b/src/header/wchar/utf8.rs
@@ -1,16 +1,17 @@
 //UTF implementation parts for wchar.h.
 //Partially ported from the Sortix libc
 
-extern crate errno;
-extern crate platform;
-
 use core::{char, slice, str, usize};
-use mbstate_t;
+
+use header::errno;
+use platform;
 use platform::types::*;
 
+use super::mbstate_t;
+
 //It's guaranteed that we don't have any nullpointers here
 pub unsafe fn mbrtowc(pwc: *mut wchar_t, s: *const c_char, n: usize, ps: *mut mbstate_t) -> usize {
-    let mut size = str::utf8_char_width(*s as u8);
+    let size = str::utf8_char_width(*s as u8);
     if size > n {
         platform::errno = errno::EILSEQ;
         return -2isize as usize;
@@ -49,7 +50,7 @@ pub unsafe fn wcrtomb(s: *mut c_char, wc: wchar_t, ps: *mut mbstate_t) -> usize
 
     let c = dc.unwrap();
     let size = c.len_utf8();
-    let mut slice = slice::from_raw_parts_mut(s as *mut u8, size);
+    let slice = slice::from_raw_parts_mut(s as *mut u8, size);
 
     c.encode_utf8(slice);
 
diff --git a/src/wctype/cbindgen.toml b/src/header/wctype/cbindgen.toml
similarity index 100%
rename from src/wctype/cbindgen.toml
rename to src/header/wctype/cbindgen.toml
diff --git a/src/wctype/src/lib.rs b/src/header/wctype/mod.rs
similarity index 97%
rename from src/wctype/src/lib.rs
rename to src/header/wctype/mod.rs
index fc6e4b9cb094d3430b24598fa071d9a4b32ef955..ab8205497a5f80b9edcdf38a61eaffde7e55edc4 100644
--- a/src/wctype/src/lib.rs
+++ b/src/header/wctype/mod.rs
@@ -1,9 +1,5 @@
 //! wctype implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/wctype.h.html
 
-#![no_std]
-
-extern crate platform;
-
 use platform::types::*;
 
 // #[no_mangle]
diff --git a/src/inttypes/Cargo.toml b/src/inttypes/Cargo.toml
deleted file mode 100644
index 68a991073e22c8b56c8c34eab782948f417e29a7..0000000000000000000000000000000000000000
--- a/src/inttypes/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "inttypes"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-ctype = { path = "../ctype" }
-errno = { path = "../errno" }
-platform = { path = "../platform" }
-stdlib = { path = "../stdlib" }
diff --git a/src/inttypes/build.rs b/src/inttypes/build.rs
deleted file mode 100644
index 483201ff825a87b968eef670d73133323a6a6e60..0000000000000000000000000000000000000000
--- a/src/inttypes/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/inttypes.h");
-}
diff --git a/src/lib.rs b/src/lib.rs
index 0cffd0abeb7199b71d9b9bd1184eaa2e4627342a..90f2507fcdc3210ec04adad8a7f74322a647c52a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,47 +1,48 @@
 #![no_std]
+#![allow(non_camel_case_types)]
+#![allow(non_upper_case_globals)]
+#![allow(unused_variables)]
+#![feature(alloc)]
+#![feature(allocator_api)]
+#![feature(const_fn)]
+#![feature(const_vec_new)]
+#![feature(core_intrinsics)]
+#![feature(extern_prelude)]
+#![feature(global_asm)]
 #![feature(lang_items)]
 #![feature(linkage)]
 #![feature(panic_implementation)]
+#![feature(str_internals)]
+#![feature(thread_local)]
 
-//extern crate compiler_builtins;
-extern crate platform;
-
-pub extern crate arpainet;
-pub extern crate ctype;
-pub extern crate dirent;
-pub extern crate errno;
-pub extern crate fcntl;
-pub extern crate fenv;
-pub extern crate float;
-pub extern crate fnmatch;
-pub extern crate grp;
-pub extern crate locale;
-pub extern crate netinet;
-pub extern crate pwd;
-pub extern crate semaphore;
-pub extern crate setjmp;
-pub extern crate signal;
-pub extern crate stdio;
-pub extern crate stdlib;
-pub extern crate string;
-pub extern crate strings;
-pub extern crate sys_ioctl;
-pub extern crate sys_mman;
-pub extern crate sys_resource;
-pub extern crate sys_select;
-pub extern crate sys_socket;
-pub extern crate sys_stat;
-pub extern crate sys_time;
-pub extern crate sys_times;
-pub extern crate sys_un;
-pub extern crate sys_utsname;
-pub extern crate sys_wait;
-pub extern crate termios;
-pub extern crate time;
-pub extern crate unistd;
-pub extern crate utime;
-pub extern crate wchar;
-pub extern crate wctype;
+#[macro_use]
+extern crate alloc;
+#[macro_use]
+extern crate lazy_static;
+extern crate rand;
+extern crate va_list;
+
+#[cfg(target_os = "linux")]
+#[macro_use]
+extern crate sc;
+
+#[cfg(target_os = "redox")]
+extern crate syscall;
+
+#[cfg(target_os = "redox")]
+extern crate spin;
+
+#[macro_use]
+mod macros;
+pub mod c_str;
+pub mod header;
+pub mod platform;
+pub mod start;
+
+use platform::{Allocator, Pal, Sys};
+
+#[global_allocator]
+static ALLOCATOR: Allocator = Allocator;
 
 #[cfg(not(test))]
 #[panic_implementation]
@@ -53,7 +54,7 @@ pub extern "C" fn rust_begin_unwind(pi: &::core::panic::PanicInfo) -> ! {
     let mut w = platform::FileWriter(2);
     let _ = w.write_fmt(format_args!("RELIBC PANIC: {}\n", pi));
 
-    platform::exit(1);
+    Sys::exit(1);
 }
 
 #[cfg(not(test))]
@@ -76,7 +77,7 @@ pub extern "C" fn rust_oom(layout: ::core::alloc::Layout) -> ! {
         layout.align()
     ));
 
-    platform::exit(1);
+    Sys::exit(1);
 }
 
 #[cfg(not(test))]
@@ -89,5 +90,5 @@ pub extern "C" fn _Unwind_Resume() -> ! {
     let mut w = platform::FileWriter(2);
     let _ = w.write_str("_Unwind_Resume\n");
 
-    platform::exit(1);
+    Sys::exit(1);
 }
diff --git a/src/locale/Cargo.toml b/src/locale/Cargo.toml
deleted file mode 100644
index 1840ba8f90555289ef8db8aaf5416b8c0f4d48aa..0000000000000000000000000000000000000000
--- a/src/locale/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "locale"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/locale/build.rs b/src/locale/build.rs
deleted file mode 100644
index 60404ed885663b630b4947bf861986b7231959ca..0000000000000000000000000000000000000000
--- a/src/locale/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/locale.h");
-}
diff --git a/src/macros.rs b/src/macros.rs
new file mode 100644
index 0000000000000000000000000000000000000000..bdccf675b3696821a3029b2fa5bf5e11d1b0bc10
--- /dev/null
+++ b/src/macros.rs
@@ -0,0 +1,103 @@
+#[macro_export]
+macro_rules! strto_impl {
+    (
+        $rettype:ty, $signed:expr, $maxval:expr, $minval:expr, $s:ident, $endptr:ident, $base:ident
+    ) => {{
+        // ensure these are constants
+        const CHECK_SIGN: bool = $signed;
+        const MAX_VAL: $rettype = $maxval;
+        const MIN_VAL: $rettype = $minval;
+
+        let set_endptr = |idx: isize| {
+            if !$endptr.is_null() {
+                // This is stupid, but apparently strto* functions want
+                // const input but mut output, yet the man page says
+                // "stores the address of the first invalid character in *endptr"
+                // so obviously it doesn't want us to clone it.
+                *$endptr = $s.offset(idx) as *mut _;
+            }
+        };
+
+        let invalid_input = || {
+            platform::errno = EINVAL;
+            set_endptr(0);
+        };
+
+        // only valid bases are 2 through 36
+        if $base != 0 && ($base < 2 || $base > 36) {
+            invalid_input();
+            return 0;
+        }
+
+        let mut idx = 0;
+
+        // skip any whitespace at the beginning of the string
+        while ctype::isspace(*$s.offset(idx) as c_int) != 0 {
+            idx += 1;
+        }
+
+        // check for +/-
+        let positive = match is_positive(*$s.offset(idx)) {
+            Some((pos, i)) => {
+                idx += i;
+                pos
+            }
+            None => {
+                invalid_input();
+                return 0;
+            }
+        };
+
+        // convert the string to a number
+        let num_str = $s.offset(idx);
+        let res = match $base {
+            0 => detect_base(num_str)
+                .and_then(|($base, i)| convert_integer(num_str.offset(i), $base)),
+            8 => convert_octal(num_str),
+            16 => convert_hex(num_str),
+            _ => convert_integer(num_str, $base),
+        };
+
+        // check for error parsing octal/hex prefix
+        // also check to ensure a number was indeed parsed
+        let (num, i, overflow) = match res {
+            Some(res) => res,
+            None => {
+                invalid_input();
+                return 0;
+            }
+        };
+        idx += i;
+
+        let overflow = if CHECK_SIGN {
+            overflow || (num as c_long).is_negative()
+        } else {
+            overflow
+        };
+        // account for the sign
+        let num = num as $rettype;
+        let num = if overflow {
+            platform::errno = ERANGE;
+            if CHECK_SIGN {
+                if positive {
+                    MAX_VAL
+                } else {
+                    MIN_VAL
+                }
+            } else {
+                MAX_VAL
+            }
+        } else {
+            if positive {
+                num
+            } else {
+                // not using -num to keep the compiler happy
+                num.overflowing_neg().0
+            }
+        };
+
+        set_endptr(idx);
+
+        num
+    }};
+}
diff --git a/src/netinet/in/Cargo.toml b/src/netinet/in/Cargo.toml
deleted file mode 100644
index b6f5356c0bc9fd09cfe8cdf9ad1fe09e1b2d1ca0..0000000000000000000000000000000000000000
--- a/src/netinet/in/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "in_h"
-version = "0.1.0"
-authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../../cbindgen" }
-
-[dependencies]
-platform = { path = "../../platform" }
-sys_socket = { path = "../../sys_socket" }
diff --git a/src/netinet/in/build.rs b/src/netinet/in/build.rs
deleted file mode 100644
index f9df3f1a781856bd52f511d854dc728929e80483..0000000000000000000000000000000000000000
--- a/src/netinet/in/build.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../../target/include").expect("failed to create include directory");
-    fs::create_dir_all("../../../target/include/netinet").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../../target/include/netinet/in.h");
-}
diff --git a/src/netinet/src/lib.rs b/src/netinet/src/lib.rs
deleted file mode 100644
index 86a0d5a0811b8c2c4f90d1a356f1306ef6a7d502..0000000000000000000000000000000000000000
--- a/src/netinet/src/lib.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#![no_std]
-
-pub extern crate in_h;
diff --git a/src/platform/Cargo.toml b/src/platform/Cargo.toml
deleted file mode 100644
index 7a313fea47f2ea7e455d783b3c5a88ec36d51a08..0000000000000000000000000000000000000000
--- a/src/platform/Cargo.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-[package]
-name = "platform"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-
-[dependencies.ralloc]
-path = "../../ralloc"
-default-features = false
-optional = true
-
-[target.'cfg(target_os = "linux")'.dependencies]
-sc = "0.2"
-
-[target.'cfg(target_os = "redox")'.dependencies]
-redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git", branch = "relibc" }
-spin = "0.4"
diff --git a/src/platform/src/allocator/dlmalloc.rs b/src/platform/allocator/dlmalloc.rs
similarity index 97%
rename from src/platform/src/allocator/dlmalloc.rs
rename to src/platform/allocator/dlmalloc.rs
index ad02e7539de35b42291fe3b86b8d624c99ff9fe7..a57748c7e00dbbdb06cc2f9b2bdf4a542ba59f1a 100644
--- a/src/platform/src/allocator/dlmalloc.rs
+++ b/src/platform/allocator/dlmalloc.rs
@@ -1,6 +1,6 @@
 use core::alloc::{GlobalAlloc, Layout};
 
-use types::*;
+use super::types::*;
 
 extern "C" {
     fn dlmalloc(bytes: size_t) -> *mut c_void;
diff --git a/src/platform/src/allocator/ralloc.rs b/src/platform/allocator/ralloc.rs
similarity index 100%
rename from src/platform/src/allocator/ralloc.rs
rename to src/platform/allocator/ralloc.rs
diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..7bd671f821435de5d9a5bf68eee82d54c249d1b5
--- /dev/null
+++ b/src/platform/linux/mod.rs
@@ -0,0 +1,364 @@
+use core::fmt::Write;
+use core::{mem, ptr};
+
+use super::types::*;
+use super::{errno, FileWriter, Pal};
+use c_str::CStr;
+
+mod signal;
+mod socket;
+
+const EINVAL: c_int = 22;
+const ENOSYS: c_int = 38;
+
+const SIGCHLD: usize = 17;
+
+const TCGETS: c_ulong = 0x5401;
+const TCSETS: c_ulong = 0x5402;
+const TIOCGWINSZ: c_ulong = 0x5413;
+
+const AT_FDCWD: c_int = -100;
+const AT_EMPTY_PATH: c_int = 0x1000;
+const AT_REMOVEDIR: c_int = 0x200;
+
+fn e(sys: usize) -> usize {
+    if (sys as isize) < 0 && (sys as isize) >= -256 {
+        unsafe {
+            errno = -(sys as isize) as c_int;
+        }
+        !0
+    } else {
+        sys
+    }
+}
+
+pub struct Sys;
+
+impl Pal for Sys {
+    fn no_pal(name: &str) -> c_int {
+        let _ = writeln!(FileWriter(2), "relibc: no_pal: {}", name);
+        unsafe {
+            errno = ENOSYS;
+        }
+        -1
+    }
+
+    fn access(path: &CStr, mode: c_int) -> c_int {
+        e(unsafe { syscall!(ACCESS, path.as_ptr(), mode) }) as c_int
+    }
+
+    fn brk(addr: *mut c_void) -> *mut c_void {
+        unsafe { syscall!(BRK, addr) as *mut c_void }
+    }
+
+    fn chdir(path: &CStr) -> c_int {
+        e(unsafe { syscall!(CHDIR, path.as_ptr()) }) as c_int
+    }
+
+    fn chmod(path: &CStr, mode: mode_t) -> c_int {
+        e(unsafe { syscall!(FCHMODAT, AT_FDCWD, path.as_ptr(), mode, 0) }) as c_int
+    }
+
+    fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
+        e(unsafe {
+            syscall!(
+                FCHOWNAT,
+                AT_FDCWD,
+                path.as_ptr(),
+                owner as u32,
+                group as u32
+            )
+        }) as c_int
+    }
+
+    fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
+        e(unsafe { syscall!(CLOCK_GETTIME, clk_id, tp) }) as c_int
+    }
+
+    fn close(fildes: c_int) -> c_int {
+        e(unsafe { syscall!(CLOSE, fildes) }) as c_int
+    }
+
+    fn dup(fildes: c_int) -> c_int {
+        e(unsafe { syscall!(DUP, fildes) }) as c_int
+    }
+
+    fn dup2(fildes: c_int, fildes2: c_int) -> c_int {
+        e(unsafe { syscall!(DUP3, fildes, fildes2, 0) }) as c_int
+    }
+
+    unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
+        e(syscall!(EXECVE, path.as_ptr(), argv, envp)) as c_int
+    }
+
+    fn exit(status: c_int) -> ! {
+        unsafe {
+            syscall!(EXIT, status);
+        }
+        loop {}
+    }
+
+    fn fchdir(fildes: c_int) -> c_int {
+        e(unsafe { syscall!(FCHDIR, fildes) }) as c_int
+    }
+
+    fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
+        e(unsafe { syscall!(FCHMOD, fildes, mode) }) as c_int
+    }
+
+    fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
+        e(unsafe { syscall!(FCHOWN, fildes, owner, group) }) as c_int
+    }
+
+    fn flock(fd: c_int, operation: c_int) -> c_int {
+        e(unsafe { syscall!(FLOCK, fd, operation) }) as c_int
+    }
+
+    fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
+        let empty_cstr: *const c_char = unsafe { super::cstr_from_bytes_with_nul_unchecked(b"\0") };
+        e(unsafe { syscall!(NEWFSTATAT, fildes, empty_cstr, buf, AT_EMPTY_PATH) }) as c_int
+    }
+
+    fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
+        e(unsafe { syscall!(FCNTL, fildes, cmd, arg) }) as c_int
+    }
+
+    fn fork() -> pid_t {
+        e(unsafe { syscall!(CLONE, SIGCHLD, 0) }) as pid_t
+    }
+
+    fn fsync(fildes: c_int) -> c_int {
+        e(unsafe { syscall!(FSYNC, fildes) }) as c_int
+    }
+
+    fn ftruncate(fildes: c_int, length: off_t) -> c_int {
+        e(unsafe { syscall!(FTRUNCATE, fildes, length) }) as c_int
+    }
+
+    fn futimens(fd: c_int, times: *const timespec) -> c_int {
+        e(unsafe { syscall!(UTIMENSAT, fd, ptr::null::<c_char>(), times, 0) }) as c_int
+    }
+
+    fn utimens(path: &CStr, times: *const timespec) -> c_int {
+        e(unsafe { syscall!(UTIMENSAT, AT_FDCWD, path.as_ptr(), times, 0) }) as c_int
+    }
+
+    fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
+        if e(unsafe { syscall!(GETCWD, buf, size) }) == !0 {
+            ptr::null_mut()
+        } else {
+            buf
+        }
+    }
+
+    fn getdents(fd: c_int, dirents: *mut dirent, bytes: usize) -> c_int {
+        unsafe { syscall!(GETDENTS64, fd, dirents, bytes) as c_int }
+    }
+
+    fn getegid() -> gid_t {
+        e(unsafe { syscall!(GETEGID) }) as gid_t
+    }
+
+    fn geteuid() -> uid_t {
+        e(unsafe { syscall!(GETEUID) }) as uid_t
+    }
+
+    fn getgid() -> gid_t {
+        e(unsafe { syscall!(GETGID) }) as gid_t
+    }
+
+    fn getrusage(who: c_int, r_usage: *mut rusage) -> c_int {
+        e(unsafe { syscall!(GETRUSAGE, who, r_usage) }) as c_int
+    }
+
+    unsafe fn gethostname(mut name: *mut c_char, len: size_t) -> c_int {
+        // len only needs to be mutable on linux
+        let mut len = len;
+
+        let mut uts = mem::uninitialized();
+        let err = Sys::uname(&mut uts);
+        if err < 0 {
+            mem::forget(uts);
+            return err;
+        }
+        for c in uts.nodename.iter() {
+            if len == 0 {
+                break;
+            }
+            len -= 1;
+
+            *name = *c;
+
+            if *name == 0 {
+                // We do want to copy the zero also, so we check this after the copying.
+                break;
+            }
+
+            name = name.offset(1);
+        }
+        0
+    }
+
+    fn getitimer(which: c_int, out: *mut itimerval) -> c_int {
+        e(unsafe { syscall!(GETITIMER, which, out) }) as c_int
+    }
+
+    fn getpgid(pid: pid_t) -> pid_t {
+        e(unsafe { syscall!(GETPGID, pid) }) as pid_t
+    }
+
+    fn getpid() -> pid_t {
+        e(unsafe { syscall!(GETPID) }) as pid_t
+    }
+
+    fn getppid() -> pid_t {
+        e(unsafe { syscall!(GETPPID) }) as pid_t
+    }
+
+    fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
+        e(unsafe { syscall!(GETTIMEOFDAY, tp, tzp) }) as c_int
+    }
+
+    fn getuid() -> uid_t {
+        e(unsafe { syscall!(GETUID) }) as uid_t
+    }
+
+    fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
+        // TODO: Somehow support varargs to syscall??
+        e(unsafe { syscall!(IOCTL, fd, request, out) }) as c_int
+    }
+
+    fn isatty(fd: c_int) -> c_int {
+        let mut winsize = winsize::default();
+        (Self::ioctl(fd, TIOCGWINSZ, &mut winsize as *mut _ as *mut c_void) == 0) as c_int
+    }
+
+    fn link(path1: &CStr, path2: &CStr) -> c_int {
+        e(unsafe {
+            syscall!(
+                LINKAT,
+                AT_FDCWD,
+                path1.as_ptr(),
+                AT_FDCWD,
+                path2.as_ptr(),
+                0
+            )
+        }) as c_int
+    }
+
+    fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t {
+        e(unsafe { syscall!(LSEEK, fildes, offset, whence) }) as off_t
+    }
+
+    fn mkdir(path: &CStr, mode: mode_t) -> c_int {
+        e(unsafe { syscall!(MKDIRAT, AT_FDCWD, path.as_ptr(), mode) }) as c_int
+    }
+
+    fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
+        e(unsafe { syscall!(MKNODAT, AT_FDCWD, path.as_ptr(), mode, 0) }) as c_int
+    }
+
+    unsafe fn mmap(
+        addr: *mut c_void,
+        len: usize,
+        prot: c_int,
+        flags: c_int,
+        fildes: c_int,
+        off: off_t,
+    ) -> *mut c_void {
+        e(syscall!(MMAP, addr, len, prot, flags, fildes, off)) as *mut c_void
+    }
+
+    unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
+        e(syscall!(MUNMAP, addr, len)) as c_int
+    }
+
+    fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
+        e(unsafe { syscall!(NANOSLEEP, rqtp, rmtp) }) as c_int
+    }
+
+    fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
+        e(unsafe { syscall!(OPENAT, AT_FDCWD, path.as_ptr(), oflag, mode) }) as c_int
+    }
+
+    fn pipe(fildes: &mut [c_int]) -> c_int {
+        e(unsafe { syscall!(PIPE2, fildes.as_mut_ptr(), 0) }) as c_int
+    }
+
+    fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t {
+        e(unsafe { syscall!(READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t
+    }
+
+    fn rename(old: &CStr, new: &CStr) -> c_int {
+        e(unsafe { syscall!(RENAMEAT, AT_FDCWD, old.as_ptr(), AT_FDCWD, new.as_ptr()) }) as c_int
+    }
+
+    fn rmdir(path: &CStr) -> c_int {
+        e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path.as_ptr(), AT_REMOVEDIR) }) as c_int
+    }
+
+    fn select(
+        nfds: c_int,
+        readfds: *mut fd_set,
+        writefds: *mut fd_set,
+        exceptfds: *mut fd_set,
+        timeout: *mut timeval,
+    ) -> c_int {
+        e(unsafe { syscall!(SELECT, nfds, readfds, writefds, exceptfds, timeout) }) as c_int
+    }
+
+    fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int {
+        e(unsafe { syscall!(SETITIMER, which, new, old) }) as c_int
+    }
+
+    fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
+        e(unsafe { syscall!(SETPGID, pid, pgid) }) as c_int
+    }
+
+    fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
+        e(unsafe { syscall!(SETREGID, rgid, egid) }) as c_int
+    }
+
+    fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
+        e(unsafe { syscall!(SETREUID, ruid, euid) }) as c_int
+    }
+
+    fn tcgetattr(fd: c_int, out: *mut termios) -> c_int {
+        Self::ioctl(fd, TCGETS, out as *mut c_void)
+    }
+
+    fn tcsetattr(fd: c_int, act: c_int, value: *const termios) -> c_int {
+        if act < 0 || act > 2 {
+            unsafe {
+                errno = EINVAL;
+            }
+            return -1;
+        }
+        // This is safe because ioctl shouldn't modify the value
+        Self::ioctl(fd, TCSETS + act as c_ulong, value as *mut c_void)
+    }
+
+    fn times(out: *mut tms) -> clock_t {
+        unsafe { syscall!(TIMES, out) as clock_t }
+    }
+
+    fn umask(mask: mode_t) -> mode_t {
+        unsafe { syscall!(UMASK, mask) as mode_t }
+    }
+
+    fn uname(utsname: *mut utsname) -> c_int {
+        e(unsafe { syscall!(UNAME, utsname, 0) }) as c_int
+    }
+
+    fn unlink(path: &CStr) -> c_int {
+        e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path.as_ptr(), 0) }) as c_int
+    }
+
+    fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
+        e(unsafe { syscall!(WAIT4, pid, stat_loc, options, 0) }) as pid_t
+    }
+
+    fn write(fildes: c_int, buf: &[u8]) -> ssize_t {
+        e(unsafe { syscall!(WRITE, fildes, buf.as_ptr(), buf.len()) }) as ssize_t
+    }
+}
diff --git a/src/platform/linux/signal.rs b/src/platform/linux/signal.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9ad5cff3b4150f3120712d25ef286635204c9205
--- /dev/null
+++ b/src/platform/linux/signal.rs
@@ -0,0 +1,40 @@
+use core::mem;
+
+use super::super::types::*;
+use super::super::PalSignal;
+use super::{e, Sys};
+
+impl PalSignal for Sys {
+    fn kill(pid: pid_t, sig: c_int) -> c_int {
+        e(unsafe { syscall!(KILL, pid, sig) }) as c_int
+    }
+
+    fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
+        e(unsafe { syscall!(KILL, -(pgrp as isize) as pid_t, sig) }) as c_int
+    }
+
+    fn raise(sig: c_int) -> c_int {
+        let tid = e(unsafe { syscall!(GETTID) }) as pid_t;
+        let ret = if tid == !0 {
+            -1
+        } else {
+            e(unsafe { syscall!(TKILL, tid, sig) }) as c_int
+        };
+
+        ret
+    }
+
+    unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int {
+        e(syscall!(
+            RT_SIGACTION,
+            sig,
+            act,
+            oact,
+            mem::size_of::<sigset_t>()
+        )) as c_int
+    }
+
+    fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
+        e(unsafe { syscall!(RT_SIGPROCMASK, how, set, oset, mem::size_of::<sigset_t>()) }) as c_int
+    }
+}
diff --git a/src/platform/linux/socket.rs b/src/platform/linux/socket.rs
new file mode 100644
index 0000000000000000000000000000000000000000..7b030b609cdbbc5c505de5fca11fdee120531973
--- /dev/null
+++ b/src/platform/linux/socket.rs
@@ -0,0 +1,119 @@
+use super::super::types::*;
+use super::super::PalSocket;
+use super::{e, Sys};
+
+impl PalSocket for Sys {
+    unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
+        e(syscall!(ACCEPT, socket, address, address_len)) as c_int
+    }
+
+    unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
+        e(syscall!(BIND, socket, address, address_len)) as c_int
+    }
+
+    unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
+        e(syscall!(CONNECT, socket, address, address_len)) as c_int
+    }
+
+    unsafe fn getpeername(
+        socket: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> c_int {
+        e(syscall!(GETPEERNAME, socket, address, address_len)) as c_int
+    }
+
+    unsafe fn getsockname(
+        socket: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> c_int {
+        e(syscall!(GETSOCKNAME, socket, address, address_len)) as c_int
+    }
+
+    fn getsockopt(
+        socket: c_int,
+        level: c_int,
+        option_name: c_int,
+        option_value: *mut c_void,
+        option_len: *mut socklen_t,
+    ) -> c_int {
+        e(unsafe {
+            syscall!(
+                GETSOCKOPT,
+                socket,
+                level,
+                option_name,
+                option_value,
+                option_len
+            )
+        }) as c_int
+    }
+
+    fn listen(socket: c_int, backlog: c_int) -> c_int {
+        e(unsafe { syscall!(LISTEN, socket, backlog) }) as c_int
+    }
+
+    unsafe fn recvfrom(
+        socket: c_int,
+        buf: *mut c_void,
+        len: size_t,
+        flags: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> ssize_t {
+        e(syscall!(
+            RECVFROM,
+            socket,
+            buf,
+            len,
+            flags,
+            address,
+            address_len
+        )) as ssize_t
+    }
+
+    unsafe fn sendto(
+        socket: c_int,
+        buf: *const c_void,
+        len: size_t,
+        flags: c_int,
+        dest_addr: *const sockaddr,
+        dest_len: socklen_t,
+    ) -> ssize_t {
+        e(syscall!(
+            SENDTO, socket, buf, len, flags, dest_addr, dest_len
+        )) as ssize_t
+    }
+
+    fn setsockopt(
+        socket: c_int,
+        level: c_int,
+        option_name: c_int,
+        option_value: *const c_void,
+        option_len: socklen_t,
+    ) -> c_int {
+        e(unsafe {
+            syscall!(
+                SETSOCKOPT,
+                socket,
+                level,
+                option_name,
+                option_value,
+                option_len
+            )
+        }) as c_int
+    }
+
+    fn shutdown(socket: c_int, how: c_int) -> c_int {
+        e(unsafe { syscall!(SHUTDOWN, socket, how) }) as c_int
+    }
+
+    unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
+        e(syscall!(SOCKET, domain, kind, protocol)) as c_int
+    }
+
+    fn socketpair(domain: c_int, kind: c_int, protocol: c_int, socket_vector: *mut c_int) -> c_int {
+        e(unsafe { syscall!(SOCKETPAIR, domain, kind, protocol, socket_vector) }) as c_int
+    }
+}
diff --git a/src/platform/src/lib.rs b/src/platform/mod.rs
similarity index 89%
rename from src/platform/src/lib.rs
rename to src/platform/mod.rs
index 2a634a4eef497a329e36353b13eee6b84be19610..53acee0e0f40c76f16be6f49f00cb8506856fdc9 100644
--- a/src/platform/src/lib.rs
+++ b/src/platform/mod.rs
@@ -1,22 +1,7 @@
-#![no_std]
-#![allow(non_camel_case_types)]
-#![feature(alloc, allocator_api, const_vec_new)]
-#![cfg_attr(target_os = "redox", feature(thread_local))]
-
-#[cfg_attr(target_os = "redox", macro_use)]
-extern crate alloc;
-
-#[cfg(target_os = "linux")]
-#[macro_use]
-extern crate sc;
-
-#[cfg(target_os = "redox")]
-extern crate syscall;
-
-#[cfg(target_os = "redox")]
-extern crate spin;
+use alloc::vec::Vec;
+use core::{fmt, ptr};
 
-pub use allocator::*;
+pub use self::allocator::*;
 
 #[cfg(not(feature = "ralloc"))]
 #[path = "allocator/dlmalloc.rs"]
@@ -26,7 +11,11 @@ mod allocator;
 #[path = "allocator/ralloc.rs"]
 mod allocator;
 
-pub use sys::*;
+pub use self::pal::{Pal, PalSignal, PalSocket};
+
+mod pal;
+
+pub use self::sys::Sys;
 
 #[cfg(all(not(feature = "no_std"), target_os = "linux"))]
 #[path = "linux/mod.rs"]
@@ -36,18 +25,12 @@ mod sys;
 #[path = "redox/mod.rs"]
 mod sys;
 
-pub mod rawfile;
-pub mod types;
-
-pub use rawfile::RawFile;
-
-use alloc::vec::Vec;
-use core::{fmt, ptr};
+pub use self::rawfile::RawFile;
 
-use types::*;
+pub mod rawfile;
 
-#[global_allocator]
-static ALLOCATOR: Allocator = Allocator;
+use self::types::*;
+pub mod types;
 
 //TODO #[thread_local]
 #[allow(non_upper_case_globals)]
@@ -145,7 +128,7 @@ pub struct FileWriter(pub c_int);
 
 impl FileWriter {
     pub fn write(&mut self, buf: &[u8]) -> isize {
-        write(self.0, buf)
+        Sys::write(self.0, buf)
     }
 }
 
@@ -167,7 +150,7 @@ pub struct FileReader(pub c_int);
 
 impl FileReader {
     pub fn read(&mut self, buf: &mut [u8]) -> isize {
-        read(self.0, buf)
+        Sys::read(self.0, buf)
     }
 }
 
@@ -177,7 +160,7 @@ impl Read for FileReader {
         match self.read(&mut buf) {
             0 => Ok(None),
             n if n < 0 => Err(()),
-            _ => Ok(Some(buf[0]))
+            _ => Ok(Some(buf[0])),
         }
     }
 }
@@ -275,13 +258,13 @@ impl Read for UnsafeStringReader {
 
 pub struct CountingWriter<T> {
     pub inner: T,
-    pub written: usize
+    pub written: usize,
 }
 impl<T> CountingWriter<T> {
-    pub /* const */ fn new(writer: T) -> Self {
+    pub fn new(writer: T) -> Self {
         Self {
             inner: writer,
-            written: 0
+            written: 0,
         }
     }
 }
diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..08981a5676db93642b5664af21c269e4acaeaa75
--- /dev/null
+++ b/src/platform/pal/mod.rs
@@ -0,0 +1,273 @@
+use core::ptr;
+
+use super::types::*;
+use c_str::CStr;
+
+pub use self::signal::PalSignal;
+mod signal;
+
+pub use self::socket::PalSocket;
+mod socket;
+
+pub trait Pal {
+    fn no_pal(name: &str) -> c_int;
+
+    fn access(path: &CStr, mode: c_int) -> c_int {
+        Self::no_pal("access")
+    }
+
+    fn brk(addr: *mut c_void) -> *mut c_void;
+
+    fn chdir(path: &CStr) -> c_int {
+        Self::no_pal("chdir")
+    }
+
+    fn chmod(path: &CStr, mode: mode_t) -> c_int {
+        Self::no_pal("chmod")
+    }
+
+    fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
+        Self::no_pal("chown")
+    }
+
+    fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
+        Self::no_pal("clock_gettime")
+    }
+
+    fn close(fildes: c_int) -> c_int {
+        Self::no_pal("close")
+    }
+
+    fn dup(fildes: c_int) -> c_int {
+        Self::no_pal("dup")
+    }
+
+    fn dup2(fildes: c_int, fildes2: c_int) -> c_int {
+        Self::no_pal("dup2")
+    }
+
+    unsafe fn execve(path: &CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
+        Self::no_pal("execve")
+    }
+
+    fn exit(status: c_int) -> !;
+
+    fn fchdir(fildes: c_int) -> c_int {
+        Self::no_pal("fchdir")
+    }
+
+    fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
+        Self::no_pal("fchmod")
+    }
+
+    fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
+        Self::no_pal("fchown")
+    }
+
+    fn flock(fd: c_int, operation: c_int) -> c_int {
+        Self::no_pal("flock")
+    }
+
+    fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
+        Self::no_pal("fstat")
+    }
+
+    fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
+        Self::no_pal("fcntl")
+    }
+
+    fn fork() -> pid_t {
+        Self::no_pal("fork")
+    }
+
+    fn fsync(fildes: c_int) -> c_int {
+        Self::no_pal("fsync")
+    }
+
+    fn ftruncate(fildes: c_int, length: off_t) -> c_int {
+        Self::no_pal("ftruncate")
+    }
+
+    fn futimens(fd: c_int, times: *const timespec) -> c_int {
+        Self::no_pal("futimens")
+    }
+
+    fn utimens(path: &CStr, times: *const timespec) -> c_int {
+        Self::no_pal("utimens")
+    }
+
+    fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
+        Self::no_pal("getcwd");
+        ptr::null_mut()
+    }
+
+    fn getdents(fd: c_int, dirents: *mut dirent, bytes: usize) -> c_int {
+        Self::no_pal("getdents")
+    }
+
+    fn getegid() -> gid_t {
+        Self::no_pal("getegid")
+    }
+
+    fn geteuid() -> uid_t {
+        Self::no_pal("geteuid")
+    }
+
+    fn getgid() -> gid_t {
+        Self::no_pal("getgid")
+    }
+
+    fn getrusage(who: c_int, r_usage: *mut rusage) -> c_int {
+        Self::no_pal("getrusage")
+    }
+
+    unsafe fn gethostname(name: *mut c_char, len: size_t) -> c_int {
+        Self::no_pal("gethostname")
+    }
+
+    fn getitimer(which: c_int, out: *mut itimerval) -> c_int {
+        Self::no_pal("getitimer")
+    }
+
+    fn getpgid(pid: pid_t) -> pid_t {
+        Self::no_pal("getpgid")
+    }
+
+    fn getpid() -> pid_t {
+        Self::no_pal("getpid")
+    }
+
+    fn getppid() -> pid_t {
+        Self::no_pal("getppid")
+    }
+
+    fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
+        Self::no_pal("gettimeofday")
+    }
+
+    fn getuid() -> uid_t {
+        Self::no_pal("getuid")
+    }
+
+    fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
+        Self::no_pal("ioctl")
+    }
+
+    fn isatty(fd: c_int) -> c_int {
+        Self::no_pal("isatty")
+    }
+
+    fn link(path1: &CStr, path2: &CStr) -> c_int {
+        Self::no_pal("link")
+    }
+
+    fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t {
+        Self::no_pal("lseek") as off_t
+    }
+
+    fn mkdir(path: &CStr, mode: mode_t) -> c_int {
+        Self::no_pal("mkdir")
+    }
+
+    fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
+        Self::no_pal("mkfifo")
+    }
+
+    unsafe fn mmap(
+        addr: *mut c_void,
+        len: usize,
+        prot: c_int,
+        flags: c_int,
+        fildes: c_int,
+        off: off_t,
+    ) -> *mut c_void {
+        Self::no_pal("mmap") as *mut c_void
+    }
+
+    unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
+        Self::no_pal("munmap")
+    }
+
+    fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
+        Self::no_pal("nanosleep")
+    }
+
+    fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
+        Self::no_pal("open")
+    }
+
+    fn pipe(fildes: &mut [c_int]) -> c_int {
+        Self::no_pal("pipe")
+    }
+
+    fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t {
+        Self::no_pal("read") as ssize_t
+    }
+
+    fn rename(old: &CStr, new: &CStr) -> c_int {
+        Self::no_pal("rename")
+    }
+
+    fn rmdir(path: &CStr) -> c_int {
+        Self::no_pal("rmdir")
+    }
+
+    fn select(
+        nfds: c_int,
+        readfds: *mut fd_set,
+        writefds: *mut fd_set,
+        exceptfds: *mut fd_set,
+        timeout: *mut timeval,
+    ) -> c_int {
+        Self::no_pal("select")
+    }
+
+    fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int {
+        Self::no_pal("setitimer")
+    }
+
+    fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
+        Self::no_pal("setpgid")
+    }
+
+    fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
+        Self::no_pal("setregid")
+    }
+
+    fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
+        Self::no_pal("setreuid")
+    }
+
+    fn tcgetattr(fd: c_int, out: *mut termios) -> c_int {
+        Self::no_pal("tcgetattr")
+    }
+
+    fn tcsetattr(fd: c_int, act: c_int, value: *const termios) -> c_int {
+        Self::no_pal("tcsetattr")
+    }
+
+    fn times(out: *mut tms) -> clock_t {
+        Self::no_pal("times") as clock_t
+    }
+
+    fn umask(mask: mode_t) -> mode_t {
+        Self::no_pal("umask");
+        0
+    }
+
+    fn uname(utsname: *mut utsname) -> c_int {
+        Self::no_pal("uname")
+    }
+
+    fn unlink(path: &CStr) -> c_int {
+        Self::no_pal("unlink")
+    }
+
+    fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
+        Self::no_pal("waitpid")
+    }
+
+    fn write(fildes: c_int, buf: &[u8]) -> ssize_t {
+        Self::no_pal("write") as ssize_t
+    }
+}
diff --git a/src/platform/pal/signal.rs b/src/platform/pal/signal.rs
new file mode 100644
index 0000000000000000000000000000000000000000..f8d69fd2c3086e9ba9523b8d38c3d4b648ef6263
--- /dev/null
+++ b/src/platform/pal/signal.rs
@@ -0,0 +1,24 @@
+use super::super::types::*;
+use super::super::Pal;
+
+pub trait PalSignal: Pal {
+    fn kill(pid: pid_t, sig: c_int) -> c_int {
+        Self::no_pal("kill")
+    }
+
+    fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
+        Self::no_pal("killpg")
+    }
+
+    fn raise(sig: c_int) -> c_int {
+        Self::no_pal("raise")
+    }
+
+    unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int {
+        Self::no_pal("sigaction")
+    }
+
+    fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
+        Self::no_pal("sigprocmask")
+    }
+}
diff --git a/src/platform/pal/socket.rs b/src/platform/pal/socket.rs
new file mode 100644
index 0000000000000000000000000000000000000000..aac4205687675c7b93c6e34a4d657c364fd54738
--- /dev/null
+++ b/src/platform/pal/socket.rs
@@ -0,0 +1,90 @@
+use super::super::types::*;
+use super::super::Pal;
+
+pub trait PalSocket: Pal {
+    unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
+        Self::no_pal("accept")
+    }
+
+    unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
+        Self::no_pal("bind")
+    }
+
+    unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
+        Self::no_pal("connect")
+    }
+
+    unsafe fn getpeername(
+        socket: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> c_int {
+        Self::no_pal("getpeername")
+    }
+
+    unsafe fn getsockname(
+        socket: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> c_int {
+        Self::no_pal("getsockname")
+    }
+
+    fn getsockopt(
+        socket: c_int,
+        level: c_int,
+        option_name: c_int,
+        option_value: *mut c_void,
+        option_len: *mut socklen_t,
+    ) -> c_int {
+        Self::no_pal("getsockopt")
+    }
+
+    fn listen(socket: c_int, backlog: c_int) -> c_int {
+        Self::no_pal("listen")
+    }
+
+    unsafe fn recvfrom(
+        socket: c_int,
+        buf: *mut c_void,
+        len: size_t,
+        flags: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> ssize_t {
+        Self::no_pal("recvfrom") as ssize_t
+    }
+
+    unsafe fn sendto(
+        socket: c_int,
+        buf: *const c_void,
+        len: size_t,
+        flags: c_int,
+        dest_addr: *const sockaddr,
+        dest_len: socklen_t,
+    ) -> ssize_t {
+        Self::no_pal("sendto") as ssize_t
+    }
+
+    fn setsockopt(
+        socket: c_int,
+        level: c_int,
+        option_name: c_int,
+        option_value: *const c_void,
+        option_len: socklen_t,
+    ) -> c_int {
+        Self::no_pal("setsockopt")
+    }
+
+    fn shutdown(socket: c_int, how: c_int) -> c_int {
+        Self::no_pal("shutdown")
+    }
+
+    unsafe fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
+        Self::no_pal("socket")
+    }
+
+    fn socketpair(domain: c_int, kind: c_int, protocol: c_int, socket_vector: *mut c_int) -> c_int {
+        Self::no_pal("socketpair")
+    }
+}
diff --git a/src/platform/src/rawfile.rs b/src/platform/rawfile.rs
similarity index 71%
rename from src/platform/src/rawfile.rs
rename to src/platform/rawfile.rs
index 2efc20d484fca07b5d2cf89f49d75e626af5b22c..1984217594028aa2bd24ced7d6429aabdcaa7d52 100644
--- a/src/platform/src/rawfile.rs
+++ b/src/platform/rawfile.rs
@@ -1,18 +1,20 @@
-use super::{close, dup, open, types::*};
 use core::ops::Deref;
 
+use super::{types::*, Pal, Sys};
+use c_str::CStr;
+
 pub struct RawFile(c_int);
 
 impl RawFile {
-    pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> Result<RawFile, ()> {
-        match open(path, oflag, mode) {
+    pub fn open(path: &CStr, oflag: c_int, mode: mode_t) -> Result<RawFile, ()> {
+        match Sys::open(path, oflag, mode) {
             -1 => Err(()),
             n => Ok(RawFile(n)),
         }
     }
 
     pub fn dup(&self) -> Result<RawFile, ()> {
-        match dup(self.0) {
+        match Sys::dup(self.0) {
             -1 => Err(()),
             n => Ok(RawFile(n)),
         }
@@ -33,7 +35,7 @@ impl RawFile {
 
 impl Drop for RawFile {
     fn drop(&mut self) {
-        let _ = close(self.0);
+        let _ = Sys::close(self.0);
     }
 }
 
diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d156392318dc77fe3a0c7f05c71bdfa5a1464bc4
--- /dev/null
+++ b/src/platform/redox/mod.rs
@@ -0,0 +1,748 @@
+//! sys/socket implementation, following http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html
+
+use alloc::btree_map::BTreeMap;
+use core::fmt::Write;
+use core::{mem, ptr, slice};
+use spin::{Mutex, MutexGuard, Once};
+use syscall::data::Stat as redox_stat;
+use syscall::data::TimeSpec as redox_timespec;
+use syscall::flag::*;
+use syscall::{self, Result};
+
+use super::types::*;
+use super::{errno, FileReader, FileWriter, Pal, RawFile, Read};
+use c_str::{CStr, CString};
+
+mod signal;
+mod socket;
+
+const EINVAL: c_int = 22;
+const ENOSYS: c_int = 38;
+const MAP_ANON: c_int = 1;
+
+static ANONYMOUS_MAPS: Once<Mutex<BTreeMap<usize, usize>>> = Once::new();
+
+fn anonymous_maps() -> MutexGuard<'static, BTreeMap<usize, usize>> {
+    ANONYMOUS_MAPS
+        .call_once(|| Mutex::new(BTreeMap::new()))
+        .lock()
+}
+
+fn e(sys: Result<usize>) -> usize {
+    match sys {
+        Ok(ok) => ok,
+        Err(err) => {
+            unsafe {
+                errno = err.errno as c_int;
+            }
+            !0
+        }
+    }
+}
+
+pub struct Sys;
+
+impl Pal for Sys {
+    fn no_pal(name: &str) -> c_int {
+        let _ = writeln!(FileWriter(2), "relibc: no_pal: {}", name);
+        unsafe {
+            errno = ENOSYS;
+        }
+        -1
+    }
+
+    fn access(path: &CStr, mode: c_int) -> c_int {
+        let fd = match RawFile::open(path, 0, 0) {
+            Ok(fd) => fd,
+            Err(_) => return -1,
+        };
+        if mode == F_OK {
+            return 0;
+        }
+
+        let mut stat = syscall::Stat::default();
+
+        if e(syscall::fstat(*fd as usize, &mut stat)) == !0 {
+            return -1;
+        }
+
+        let uid = e(syscall::getuid());
+        if uid == !0 {
+            return -1;
+        }
+        let gid = e(syscall::getgid());
+        if gid == !0 {
+            return -1;
+        }
+
+        let perms = if stat.st_uid as usize == uid {
+            // octal has max 7 characters, binary has max two. And we're interested
+            // in the 3rd digit
+            stat.st_mode >> ((7 / 2) * 2 & 0o7)
+        } else if stat.st_gid as usize == gid {
+            stat.st_mode >> ((7 / 2) & 0o7)
+        } else {
+            stat.st_mode & 0o7
+        };
+        if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
+            || (mode & W_OK == W_OK && perms & 0o2 != 0o2)
+            || (mode & X_OK == X_OK && perms & 0o1 != 0o1)
+        {
+            unsafe {
+                errno = EINVAL;
+            }
+            return -1;
+        }
+
+        0
+    }
+
+    fn brk(addr: *mut c_void) -> *mut c_void {
+        unsafe { syscall::brk(addr as usize).unwrap_or(0) as *mut c_void }
+    }
+
+    fn chdir(path: &CStr) -> c_int {
+        e(syscall::chdir(path.to_bytes())) as c_int
+    }
+
+    fn chmod(path: &CStr, mode: mode_t) -> c_int {
+        match syscall::open(path.to_bytes(), O_WRONLY) {
+            Err(err) => e(Err(err)) as c_int,
+            Ok(fd) => {
+                let res = syscall::fchmod(fd as usize, mode as u16);
+                let _ = syscall::close(fd);
+                e(res) as c_int
+            }
+        }
+    }
+
+    fn chown(path: &CStr, owner: uid_t, group: gid_t) -> c_int {
+        match syscall::open(path.to_bytes(), O_WRONLY) {
+            Err(err) => e(Err(err)) as c_int,
+            Ok(fd) => {
+                let res = syscall::fchown(fd as usize, owner as u32, group as u32);
+                let _ = syscall::close(fd);
+                e(res) as c_int
+            }
+        }
+    }
+
+    fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
+        let mut redox_tp = unsafe { redox_timespec::from(&*tp) };
+        match e(syscall::clock_gettime(clk_id as usize, &mut redox_tp)) as c_int {
+            -1 => -1,
+            _ => {
+                unsafe {
+                    (*tp).tv_sec = redox_tp.tv_sec;
+                    (*tp).tv_nsec = redox_tp.tv_nsec as i64;
+                };
+                0
+            }
+        }
+    }
+
+    fn close(fd: c_int) -> c_int {
+        e(syscall::close(fd as usize)) as c_int
+    }
+
+    fn dup(fd: c_int) -> c_int {
+        e(syscall::dup(fd as usize, &[])) as c_int
+    }
+
+    fn dup2(fd1: c_int, fd2: c_int) -> c_int {
+        e(syscall::dup2(fd1 as usize, fd2 as usize, &[])) as c_int
+    }
+
+    fn exit(status: c_int) -> ! {
+        let _ = syscall::exit(status as usize);
+        loop {}
+    }
+
+    unsafe fn execve(
+        path: &CStr,
+        mut argv: *const *mut c_char,
+        mut envp: *const *mut c_char,
+    ) -> c_int {
+        use alloc::Vec;
+
+        let fd = match RawFile::open(path, O_RDONLY as c_int, 0) {
+            Ok(fd) => fd,
+            Err(_) => return -1,
+        };
+
+        let mut len = 0;
+        while !(*argv.offset(len)).is_null() {
+            len += 1;
+        }
+
+        let mut args: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
+        while !(*argv).is_null() {
+            let arg = *argv;
+
+            let mut len = 0;
+            while *arg.offset(len) != 0 {
+                len += 1;
+            }
+            args.push([arg as usize, len as usize]);
+            argv = argv.offset(1);
+        }
+
+        let mut len = 0;
+        while !(*envp.offset(len)).is_null() {
+            len += 1;
+        }
+
+        let mut envs: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
+        while !(*envp).is_null() {
+            let env = *envp;
+
+            let mut len = 0;
+            while *env.offset(len) != 0 {
+                len += 1;
+            }
+            envs.push([env as usize, len as usize]);
+            envp = envp.offset(1);
+        }
+
+        e(syscall::fexec(*fd as usize, &args, &envs)) as c_int
+    }
+
+    fn fchdir(fd: c_int) -> c_int {
+        let path: &mut [u8] = &mut [0; 4096];
+        if e(syscall::fpath(fd as usize, path)) == !0 {
+            !0
+        } else {
+            e(syscall::chdir(path)) as c_int
+        }
+    }
+
+    fn fchmod(fd: c_int, mode: mode_t) -> c_int {
+        e(syscall::fchmod(fd as usize, mode as u16)) as c_int
+    }
+
+    fn fchown(fd: c_int, owner: uid_t, group: gid_t) -> c_int {
+        e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int
+    }
+
+    fn fcntl(fd: c_int, cmd: c_int, args: c_int) -> c_int {
+        e(syscall::fcntl(fd as usize, cmd as usize, args as usize)) as c_int
+    }
+
+    fn flock(_fd: c_int, _operation: c_int) -> c_int {
+        // TODO: Redox does not have file locking yet
+        0
+    }
+
+    fn fork() -> pid_t {
+        e(unsafe { syscall::clone(0) }) as pid_t
+    }
+
+    fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
+        let mut redox_buf: redox_stat = redox_stat::default();
+        match e(syscall::fstat(fildes as usize, &mut redox_buf)) {
+            0 => {
+                unsafe {
+                    if !buf.is_null() {
+                        (*buf).st_dev = redox_buf.st_dev as dev_t;
+                        (*buf).st_ino = redox_buf.st_ino as ino_t;
+                        (*buf).st_nlink = redox_buf.st_nlink as nlink_t;
+                        (*buf).st_mode = redox_buf.st_mode as mode_t;
+                        (*buf).st_uid = redox_buf.st_uid as uid_t;
+                        (*buf).st_gid = redox_buf.st_gid as gid_t;
+                        // TODO st_rdev
+                        (*buf).st_rdev = 0;
+                        (*buf).st_size = redox_buf.st_size as off_t;
+                        (*buf).st_blksize = redox_buf.st_blksize as blksize_t;
+                        (*buf).st_atim = timespec {
+                            tv_sec: redox_buf.st_atime as time_t,
+                            tv_nsec: redox_buf.st_atime_nsec as c_long,
+                        };
+                        (*buf).st_mtim = timespec {
+                            tv_sec: redox_buf.st_mtime as time_t,
+                            tv_nsec: redox_buf.st_mtime_nsec as c_long,
+                        };
+                        (*buf).st_ctim = timespec {
+                            tv_sec: redox_buf.st_ctime as time_t,
+                            tv_nsec: redox_buf.st_ctime_nsec as c_long,
+                        };
+                    }
+                }
+                0
+            }
+            _ => -1,
+        }
+    }
+
+    fn fsync(fd: c_int) -> c_int {
+        e(syscall::fsync(fd as usize)) as c_int
+    }
+
+    fn ftruncate(fd: c_int, len: off_t) -> c_int {
+        e(syscall::ftruncate(fd as usize, len as usize)) as c_int
+    }
+
+    fn futimens(fd: c_int, times: *const timespec) -> c_int {
+        let times = [unsafe { redox_timespec::from(&*times) }, unsafe {
+            redox_timespec::from(&*times.offset(1))
+        }];
+        e(syscall::futimens(fd as usize, &times)) as c_int
+    }
+
+    fn utimens(path: &CStr, times: *const timespec) -> c_int {
+        match syscall::open(path.to_bytes(), O_STAT) {
+            Err(err) => e(Err(err)) as c_int,
+            Ok(fd) => {
+                let res = Self::futimens(fd as c_int, times);
+                let _ = syscall::close(fd);
+                res
+            }
+        }
+    }
+
+    fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
+        let buf_slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size as usize - 1) };
+        let read = e(syscall::getcwd(buf_slice));
+        if read == !0 {
+            ptr::null_mut()
+        } else {
+            unsafe {
+                *buf.offset(read as isize + 1) = 0;
+            }
+            buf
+        }
+    }
+
+    fn getdents(fd: c_int, mut dirents: *mut dirent, mut bytes: usize) -> c_int {
+        let mut amount = 0;
+
+        let mut buf = [0; 1024];
+        let mut bindex = 0;
+        let mut blen = 0;
+
+        let mut name = [0; 256];
+        let mut nindex = 0;
+
+        loop {
+            if bindex >= blen {
+                bindex = 0;
+                blen = match syscall::read(fd as usize, &mut buf) {
+                    Ok(0) => return amount,
+                    Ok(n) => n,
+                    Err(err) => return -err.errno,
+                };
+            }
+
+            if buf[bindex] == b'\n' {
+                // Put a NUL byte either at the end, or if it's too big, at where it's truncated.
+                name[nindex.min(name.len() - 1)] = 0;
+                unsafe {
+                    *dirents = dirent {
+                        d_ino: 0,
+                        d_off: 0,
+                        d_reclen: mem::size_of::<dirent>() as c_ushort,
+                        d_type: 0,
+                        d_name: name,
+                    };
+                    dirents = dirents.offset(1);
+                }
+                amount += 1;
+                if bytes <= mem::size_of::<dirent>() {
+                    return amount;
+                }
+                bytes -= mem::size_of::<dirent>();
+            } else {
+                if nindex < name.len() {
+                    name[nindex] = buf[bindex] as c_char;
+                }
+                nindex += 1;
+                bindex += 1;
+            }
+        }
+    }
+
+    fn getegid() -> gid_t {
+        e(syscall::getegid()) as gid_t
+    }
+
+    fn geteuid() -> uid_t {
+        e(syscall::geteuid()) as uid_t
+    }
+
+    fn getgid() -> gid_t {
+        e(syscall::getgid()) as gid_t
+    }
+
+    unsafe fn gethostname(mut name: *mut c_char, len: size_t) -> c_int {
+        let fd = e(syscall::open("/etc/hostname", O_RDONLY)) as i32;
+        if fd < 0 {
+            return fd;
+        }
+        let mut reader = FileReader(fd);
+        for _ in 0..len {
+            match reader.read_u8() {
+                Ok(Some(b)) => {
+                    *name = b as c_char;
+                    name = name.offset(1);
+                }
+                Ok(None) => {
+                    *name = 0;
+                    break;
+                }
+                Err(()) => return -1,
+            }
+        }
+        0
+    }
+
+    fn getpgid(pid: pid_t) -> pid_t {
+        e(syscall::getpgid(pid as usize)) as pid_t
+    }
+
+    fn getpid() -> pid_t {
+        e(syscall::getpid()) as pid_t
+    }
+
+    fn getppid() -> pid_t {
+        e(syscall::getppid()) as pid_t
+    }
+
+    fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
+        let mut redox_tp = redox_timespec::default();
+        let err = e(syscall::clock_gettime(
+            syscall::CLOCK_REALTIME,
+            &mut redox_tp,
+        )) as c_int;
+        if err < 0 {
+            return err;
+        }
+        unsafe {
+            (*tp).tv_sec = redox_tp.tv_sec as time_t;
+            (*tp).tv_usec = (redox_tp.tv_nsec / 1000) as suseconds_t;
+
+            if !tzp.is_null() {
+                (*tzp).tz_minuteswest = 0;
+                (*tzp).tz_dsttime = 0;
+            }
+        }
+        0
+    }
+
+    fn getuid() -> uid_t {
+        e(syscall::getuid()) as pid_t
+    }
+
+    fn isatty(fd: c_int) -> c_int {
+        syscall::dup(fd as usize, b"termios")
+            .map(|fd| {
+                let _ = syscall::close(fd);
+                1
+            })
+            .unwrap_or(0)
+    }
+
+    fn link(path1: &CStr, path2: &CStr) -> c_int {
+        e(unsafe { syscall::link(path1.as_ptr() as *const u8, path2.as_ptr() as *const u8) })
+            as c_int
+    }
+
+    fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
+        e(syscall::lseek(
+            fd as usize,
+            offset as isize,
+            whence as usize,
+        )) as off_t
+    }
+
+    fn mkdir(path: &CStr, mode: mode_t) -> c_int {
+        let flags = O_CREAT | O_EXCL | O_CLOEXEC | O_DIRECTORY | mode as usize & 0o777;
+        match syscall::open(path.to_bytes(), flags) {
+            Ok(fd) => {
+                let _ = syscall::close(fd);
+                0
+            }
+            Err(err) => e(Err(err)) as c_int,
+        }
+    }
+
+    fn mkfifo(path: &CStr, mode: mode_t) -> c_int {
+        let flags = O_CREAT | MODE_FIFO as usize | mode as usize & 0o777;
+        match syscall::open(path.to_bytes(), flags) {
+            Ok(fd) => {
+                let _ = syscall::close(fd);
+                0
+            }
+            Err(err) => e(Err(err)) as c_int,
+        }
+    }
+
+    unsafe fn mmap(
+        _addr: *mut c_void,
+        len: usize,
+        _prot: c_int,
+        flags: c_int,
+        fildes: c_int,
+        off: off_t,
+    ) -> *mut c_void {
+        if flags & MAP_ANON == MAP_ANON {
+            let fd = e(syscall::open("memory:", 0)); // flags don't matter currently
+            if fd == !0 {
+                return !0 as *mut c_void;
+            }
+
+            let addr = e(syscall::fmap(fd, off as usize, len as usize));
+            if addr == !0 {
+                let _ = syscall::close(fd);
+                return !0 as *mut c_void;
+            }
+
+            anonymous_maps().insert(addr as usize, fd);
+            addr as *mut c_void
+        } else {
+            e(syscall::fmap(fildes as usize, off as usize, len as usize)) as *mut c_void
+        }
+    }
+
+    unsafe fn munmap(addr: *mut c_void, _len: usize) -> c_int {
+        if e(syscall::funmap(addr as usize)) == !0 {
+            return !0;
+        }
+        if let Some(fd) = anonymous_maps().remove(&(addr as usize)) {
+            let _ = syscall::close(fd);
+        }
+        0
+    }
+
+    fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
+        let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) };
+        let mut redox_rmtp: redox_timespec;
+        if rmtp.is_null() {
+            redox_rmtp = redox_timespec::default();
+        } else {
+            redox_rmtp = unsafe { redox_timespec::from(&*rmtp) };
+        }
+        match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int {
+            -1 => -1,
+            _ => {
+                unsafe {
+                    if !rmtp.is_null() {
+                        (*rmtp).tv_sec = redox_rmtp.tv_sec;
+                        (*rmtp).tv_nsec = redox_rmtp.tv_nsec as i64;
+                    }
+                }
+                0
+            }
+        }
+    }
+
+    fn open(path: &CStr, oflag: c_int, mode: mode_t) -> c_int {
+        e(syscall::open(
+            path.to_bytes(),
+            (oflag as usize) | (mode as usize),
+        )) as c_int
+    }
+
+    fn pipe(fds: &mut [c_int]) -> c_int {
+        let mut usize_fds: [usize; 2] = [0; 2];
+        let res = e(syscall::pipe2(&mut usize_fds, 0));
+        fds[0] = usize_fds[0] as c_int;
+        fds[1] = usize_fds[1] as c_int;
+        res as c_int
+    }
+
+    fn read(fd: c_int, buf: &mut [u8]) -> ssize_t {
+        e(syscall::read(fd as usize, buf)) as ssize_t
+    }
+
+    fn rename(oldpath: &CStr, newpath: &CStr) -> c_int {
+        match syscall::open(oldpath.to_bytes(), O_WRONLY) {
+            Ok(fd) => {
+                let retval = syscall::frename(fd, newpath.to_bytes());
+                let _ = syscall::close(fd);
+                e(retval) as c_int
+            }
+            err => e(err) as c_int,
+        }
+    }
+
+    fn rmdir(path: &CStr) -> c_int {
+        e(syscall::rmdir(path.to_bytes())) as c_int
+    }
+
+    fn select(
+        nfds: c_int,
+        readfds: *mut fd_set,
+        writefds: *mut fd_set,
+        exceptfds: *mut fd_set,
+        timeout: *mut timeval,
+    ) -> c_int {
+        fn isset(set: *mut fd_set, fd: usize) -> bool {
+            if set.is_null() {
+                return false;
+            }
+
+            let mask = 1 << (fd & (8 * mem::size_of::<c_ulong>() - 1));
+            unsafe { (*set).fds_bits[fd / (8 * mem::size_of::<c_ulong>())] & mask == mask }
+        }
+
+        let event_path = unsafe { CStr::from_bytes_with_nul_unchecked(b"event:\0") };
+        let event_file = match RawFile::open(event_path, 0, 0) {
+            Ok(file) => file,
+            Err(_) => return -1,
+        };
+
+        let mut total = 0;
+
+        for fd in 0..nfds as usize {
+            macro_rules! register {
+                ($fd:expr, $flags:expr) => {
+                    if Self::write(
+                        *event_file,
+                        &syscall::Event {
+                            id: $fd,
+                            flags: $flags,
+                            data: 0,
+                        },
+                    ) < 0
+                    {
+                        return -1;
+                    }
+                };
+            }
+            if isset(readfds, fd) {
+                register!(fd, syscall::EVENT_READ);
+                total += 1;
+            }
+            if isset(writefds, fd) {
+                register!(fd, syscall::EVENT_WRITE);
+                total += 1;
+            }
+            if isset(exceptfds, fd) {
+                total += 1;
+            }
+        }
+
+        const TIMEOUT_TOKEN: usize = 1;
+
+        let timeout_file = if timeout.is_null() {
+            None
+        } else {
+            let timeout_file = match RawFile::open(
+                &unsafe {
+                    CString::from_vec_unchecked(
+                        format!("time:{}", syscall::CLOCK_MONOTONIC).into_bytes(),
+                    )
+                },
+                0,
+                0,
+            ) {
+                Ok(file) => file,
+                Err(_) => return -1,
+            };
+            let timeout = unsafe { &*timeout };
+            if Self::write(
+                *timeout_file,
+                &syscall::TimeSpec {
+                    tv_sec: timeout.tv_sec,
+                    tv_nsec: timeout.tv_usec * 1000,
+                },
+            ) < 0
+            {
+                return -1;
+            }
+            if Self::write(
+                *event_file,
+                &syscall::Event {
+                    id: *timeout_file as usize,
+                    flags: syscall::EVENT_READ,
+                    data: TIMEOUT_TOKEN,
+                },
+            ) < 0
+            {
+                return -1;
+            }
+
+            Some(timeout_file)
+        };
+
+        let mut event = syscall::Event::default();
+        if Self::read(*event_file, &mut event) < 0 {
+            return -1;
+        }
+
+        if timeout_file.is_some() && event.data == TIMEOUT_TOKEN {
+            return 0;
+        }
+
+        // I really don't get why, but select wants me to return the total number
+        // of file descriptors that was inputted. I'm confused.
+        total
+    }
+
+    fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
+        e(syscall::setpgid(pid as usize, pgid as usize)) as c_int
+    }
+
+    fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
+        e(syscall::setregid(rgid as usize, egid as usize)) as c_int
+    }
+
+    fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
+        e(syscall::setreuid(ruid as usize, euid as usize)) as c_int
+    }
+
+    fn tcgetattr(fd: c_int, out: *mut termios) -> c_int {
+        let dup = e(syscall::dup(fd as usize, b"termios"));
+        if dup == !0 {
+            return -1;
+        }
+
+        let read = e(syscall::read(dup, unsafe {
+            slice::from_raw_parts_mut(out as *mut u8, mem::size_of::<termios>())
+        }));
+        let _ = syscall::close(dup);
+
+        if read == !0 {
+            return -1;
+        }
+        0
+    }
+
+    fn tcsetattr(fd: c_int, _act: c_int, value: *const termios) -> c_int {
+        let dup = e(syscall::dup(fd as usize, b"termios"));
+        if dup == !0 {
+            return -1;
+        }
+
+        let write = e(syscall::write(dup, unsafe {
+            slice::from_raw_parts(value as *const u8, mem::size_of::<termios>())
+        }));
+        let _ = syscall::close(dup);
+
+        if write == !0 {
+            return -1;
+        }
+        0
+    }
+
+    fn unlink(path: &CStr) -> c_int {
+        e(syscall::unlink(path.to_bytes())) as c_int
+    }
+
+    fn waitpid(mut pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
+        if pid == !0 {
+            pid = 0;
+        }
+        unsafe {
+            let mut temp: usize = 0;
+            let res = e(syscall::waitpid(pid as usize, &mut temp, options as usize));
+            if !stat_loc.is_null() {
+                *stat_loc = temp as c_int;
+            }
+            res as pid_t
+        }
+    }
+
+    fn write(fd: c_int, buf: &[u8]) -> ssize_t {
+        e(syscall::write(fd as usize, buf)) as ssize_t
+    }
+}
diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs
new file mode 100644
index 0000000000000000000000000000000000000000..abbf8bd0d3c2607056d300c9f96c15cabc3a85fb
--- /dev/null
+++ b/src/platform/redox/signal.rs
@@ -0,0 +1,62 @@
+use syscall;
+
+use super::super::types::*;
+use super::super::{Pal, PalSignal};
+use super::{e, Sys};
+
+#[thread_local]
+static mut SIG_HANDLER: Option<extern "C" fn(c_int)> = None;
+
+extern "C" fn sig_handler(sig: usize) {
+    if let Some(ref callback) = unsafe { SIG_HANDLER } {
+        callback(sig as c_int);
+    }
+}
+
+impl PalSignal for Sys {
+    fn kill(pid: pid_t, sig: c_int) -> c_int {
+        e(syscall::kill(pid as usize, sig as usize)) as c_int
+    }
+
+    fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
+        e(syscall::kill(-(pgrp as isize) as usize, sig as usize)) as c_int
+    }
+
+    fn raise(sig: c_int) -> c_int {
+        Self::kill(Self::getpid(), sig)
+    }
+
+    unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int {
+        if !oact.is_null() {
+            // Assumes the last sigaction() call was made by relibc and not a different one
+            if SIG_HANDLER.is_some() {
+                (*oact).sa_handler = SIG_HANDLER;
+            }
+        }
+        let act = if act.is_null() {
+            None
+        } else {
+            SIG_HANDLER = (*act).sa_handler;
+            let m = (*act).sa_mask;
+            Some(syscall::SigAction {
+                sa_handler: sig_handler,
+                sa_mask: [0, m as u64],
+                sa_flags: (*act).sa_flags as usize,
+            })
+        };
+        let mut old = syscall::SigAction::default();
+        let ret = e(syscall::sigaction(
+            sig as usize,
+            act.as_ref(),
+            if oact.is_null() { None } else { Some(&mut old) },
+        )) as c_int;
+        if !oact.is_null() {
+            let m = old.sa_mask;
+            (*oact).sa_mask = m[1] as c_ulong;
+            (*oact).sa_flags = old.sa_flags as c_ulong;
+        }
+        ret
+    }
+
+    //fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int;
+}
diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs
new file mode 100644
index 0000000000000000000000000000000000000000..501c4b899b77c26534de066f06a3b913db890f17
--- /dev/null
+++ b/src/platform/redox/socket.rs
@@ -0,0 +1,188 @@
+use core::{mem, ptr, slice};
+use syscall::flag::*;
+use syscall::{self, Result};
+
+use super::super::types::*;
+use super::super::{errno, Pal, PalSocket};
+use super::{e, Sys};
+
+macro_rules! bind_or_connect {
+    (bind $path:expr) => {
+        concat!("/", $path)
+    };
+    (connect $path:expr) => {
+        $path
+    };
+    ($mode:ident $socket:expr, $address:expr, $address_len:expr) => {{
+        if (*$address).sa_family as c_int != AF_INET {
+            errno = syscall::EAFNOSUPPORT;
+            return -1;
+        }
+        if ($address_len as usize) < mem::size_of::<sockaddr>() {
+            errno = syscall::EINVAL;
+            return -1;
+        }
+        let data = &*($address as *const sockaddr_in);
+        let addr = &data.sin_addr.s_addr;
+        let port = in_port_t::from_be(data.sin_port); // This is transmuted from bytes in BigEndian order
+        let path = format!(bind_or_connect!($mode "{}.{}.{}.{}:{}"), addr[0], addr[1], addr[2], addr[3], port);
+
+        // Duplicate the socket, and then duplicate the copy back to the original fd
+        let fd = e(syscall::dup($socket as usize, path.as_bytes()));
+        if (fd as c_int) < 0 {
+            return -1;
+        }
+        let result = syscall::dup2(fd, $socket as usize, &[]);
+        let _ = syscall::close(fd);
+        if (e(result) as c_int) < 0 {
+            return -1;
+        }
+        0
+    }}
+}
+
+unsafe fn inner_get_name(
+    local: bool,
+    socket: c_int,
+    address: *mut sockaddr,
+    address_len: *mut socklen_t,
+) -> Result<usize> {
+    // 32 should probably be large enough.
+    // Format: tcp:remote/local
+    // and since we only yet support IPv4 (I think)...
+    let mut buf = [0; 32];
+    let len = syscall::fpath(socket as usize, &mut buf)?;
+    let buf = &buf[..len];
+    assert!(&buf[..4] == b"tcp:" || &buf[..4] == b"udp:");
+    let buf = &buf[4..];
+
+    let mut parts = buf.split(|c| *c == b'/');
+    if local {
+        // Skip the remote part
+        parts.next();
+    }
+    let part = parts.next().expect("Invalid reply from netstack");
+
+    let data = slice::from_raw_parts_mut(
+        &mut (*address).data as *mut _ as *mut u8,
+        (*address).data.len(),
+    );
+
+    let len = data.len().min(part.len());
+    data[..len].copy_from_slice(&part[..len]);
+
+    *address_len = len as socklen_t;
+    Ok(0)
+}
+
+impl PalSocket for Sys {
+    unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
+        let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
+        if stream < 0 {
+            return -1;
+        }
+        if address != ptr::null_mut()
+            && address_len != ptr::null_mut()
+            && Self::getpeername(stream, address, address_len) < 0
+        {
+            return -1;
+        }
+        stream
+    }
+
+    unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
+        bind_or_connect!(bind socket, address, address_len)
+    }
+
+    unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
+        bind_or_connect!(connect socket, address, address_len)
+    }
+
+    unsafe fn getpeername(
+        socket: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> c_int {
+        e(inner_get_name(false, socket, address, address_len)) as c_int
+    }
+
+    unsafe fn getsockname(
+        socket: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> c_int {
+        e(inner_get_name(true, socket, address, address_len)) as c_int
+    }
+
+    unsafe fn recvfrom(
+        socket: c_int,
+        buf: *mut c_void,
+        len: size_t,
+        flags: c_int,
+        address: *mut sockaddr,
+        address_len: *mut socklen_t,
+    ) -> ssize_t {
+        if flags != 0 {
+            errno = syscall::EOPNOTSUPP;
+            return -1;
+        }
+        if address != ptr::null_mut()
+            && address_len != ptr::null_mut()
+            && Self::getpeername(socket, address, address_len) < 0
+        {
+            return -1;
+        }
+        Self::read(socket, slice::from_raw_parts_mut(buf as *mut u8, len))
+    }
+
+    unsafe fn sendto(
+        socket: c_int,
+        buf: *const c_void,
+        len: size_t,
+        flags: c_int,
+        dest_addr: *const sockaddr,
+        dest_len: socklen_t,
+    ) -> ssize_t {
+        if dest_addr != ptr::null() || dest_len != 0 {
+            errno = syscall::EISCONN;
+            return -1;
+        }
+        if flags != 0 {
+            errno = syscall::EOPNOTSUPP;
+            return -1;
+        }
+        Self::write(socket, slice::from_raw_parts(buf as *const u8, len))
+    }
+
+    unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int {
+        if domain != AF_INET {
+            errno = syscall::EAFNOSUPPORT;
+            return -1;
+        }
+        if protocol != 0 {
+            errno = syscall::EPROTONOSUPPORT;
+            return -1;
+        }
+
+        let mut flags = O_RDWR;
+        if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
+            kind &= !SOCK_NONBLOCK;
+            flags |= O_NONBLOCK;
+        }
+        if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
+            kind &= !SOCK_CLOEXEC;
+            flags |= O_CLOEXEC;
+        }
+
+        // The tcp: and udp: schemes allow using no path,
+        // and later specifying one using `dup`.
+        match kind {
+            SOCK_STREAM => e(syscall::open("tcp:", flags)) as c_int,
+            SOCK_DGRAM => e(syscall::open("udp:", flags)) as c_int,
+            _ => {
+                errno = syscall::EPROTOTYPE;
+                -1
+            }
+        }
+    }
+}
diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs
deleted file mode 100644
index 5446a52f1a47344903a3daa0acdc9ad2ebffe316..0000000000000000000000000000000000000000
--- a/src/platform/src/linux/mod.rs
+++ /dev/null
@@ -1,485 +0,0 @@
-use core::{mem, ptr};
-
-use errno;
-use types::*;
-
-const EINVAL: c_int = 22;
-
-const SIGCHLD: usize = 17;
-
-const TCGETS: c_ulong = 0x5401;
-const TCSETS: c_ulong = 0x5402;
-const TIOCGWINSZ: c_ulong = 0x5413;
-
-const AT_FDCWD: c_int = -100;
-const AT_EMPTY_PATH: c_int = 0x1000;
-const AT_REMOVEDIR: c_int = 0x200;
-const AT_SYMLINK_NOFOLLOW: c_int = 0x100;
-
-fn e(sys: usize) -> usize {
-    if (sys as isize) < 0 && (sys as isize) >= -256 {
-        unsafe {
-            errno = -(sys as isize) as c_int;
-        }
-        !0
-    } else {
-        sys
-    }
-}
-
-pub unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
-    e(syscall!(ACCEPT, socket, address, address_len)) as c_int
-}
-
-pub fn access(path: *const c_char, mode: c_int) -> c_int {
-    e(unsafe { syscall!(ACCESS, path, mode) }) as c_int
-}
-
-pub unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
-    e(syscall!(BIND, socket, address, address_len)) as c_int
-}
-
-pub fn brk(addr: *mut c_void) -> *mut c_void {
-    unsafe { syscall!(BRK, addr) as *mut c_void }
-}
-
-pub fn chdir(path: *const c_char) -> c_int {
-    e(unsafe { syscall!(CHDIR, path) }) as c_int
-}
-
-pub fn chmod(path: *const c_char, mode: mode_t) -> c_int {
-    e(unsafe { syscall!(FCHMODAT, AT_FDCWD, path, mode, 0) }) as c_int
-}
-
-pub fn chown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
-    e(unsafe { syscall!(FCHOWNAT, AT_FDCWD, path, owner as u32, group as u32) }) as c_int
-}
-
-pub fn close(fildes: c_int) -> c_int {
-    e(unsafe { syscall!(CLOSE, fildes) }) as c_int
-}
-
-pub unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
-    e(syscall!(CONNECT, socket, address, address_len)) as c_int
-}
-
-pub fn dup(fildes: c_int) -> c_int {
-    e(unsafe { syscall!(DUP, fildes) }) as c_int
-}
-
-pub fn dup2(fildes: c_int, fildes2: c_int) -> c_int {
-    e(unsafe { syscall!(DUP3, fildes, fildes2, 0) }) as c_int
-}
-
-pub fn execve(path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
-    e(unsafe { syscall!(EXECVE, path, argv, envp) }) as c_int
-}
-
-pub fn exit(status: c_int) -> ! {
-    unsafe {
-        syscall!(EXIT, status);
-    }
-    loop {}
-}
-
-pub fn fchdir(fildes: c_int) -> c_int {
-    e(unsafe { syscall!(FCHDIR, fildes) }) as c_int
-}
-
-pub fn fchmod(fildes: c_int, mode: mode_t) -> c_int {
-    e(unsafe { syscall!(FCHMOD, fildes, mode) }) as c_int
-}
-
-pub fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
-    e(unsafe { syscall!(FCHOWN, fildes, owner, group) }) as c_int
-}
-
-pub fn flock(fd: c_int, operation: c_int) -> c_int {
-    e(unsafe { syscall!(FLOCK, fd, operation) }) as c_int
-}
-
-pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
-    let empty_cstr: *const c_char = unsafe { ::cstr_from_bytes_with_nul_unchecked(b"\0") };
-    e(unsafe { syscall!(NEWFSTATAT, fildes, empty_cstr, buf, AT_EMPTY_PATH) }) as c_int
-}
-
-pub fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
-    e(unsafe { syscall!(FCNTL, fildes, cmd, arg) }) as c_int
-}
-
-pub fn fork() -> pid_t {
-    e(unsafe { syscall!(CLONE, SIGCHLD, 0) }) as pid_t
-}
-
-pub fn fsync(fildes: c_int) -> c_int {
-    e(unsafe { syscall!(FSYNC, fildes) }) as c_int
-}
-
-pub fn ftruncate(fildes: c_int, length: off_t) -> c_int {
-    e(unsafe { syscall!(FTRUNCATE, fildes, length) }) as c_int
-}
-
-pub fn futimens(fd: c_int, times: *const timespec) -> c_int {
-    e(unsafe { syscall!(UTIMENSAT, fd, ptr::null::<c_char>(), times, 0) }) as c_int
-}
-
-pub fn utimens(path: *const c_char, times: *const timespec) -> c_int {
-    e(unsafe { syscall!(UTIMENSAT, AT_FDCWD, path, times, 0) }) as c_int
-}
-
-pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
-    if e(unsafe { syscall!(GETCWD, buf, size) }) == !0 {
-        ptr::null_mut()
-    } else {
-        buf
-    }
-}
-
-pub fn getdents(fd: c_int, dirents: *mut dirent, bytes: usize) -> c_int {
-    unsafe { syscall!(GETDENTS64, fd, dirents, bytes) as c_int }
-}
-
-pub fn getegid() -> gid_t {
-    e(unsafe { syscall!(GETEGID) }) as gid_t
-}
-
-pub fn geteuid() -> uid_t {
-    e(unsafe { syscall!(GETEUID) }) as uid_t
-}
-
-pub fn getgid() -> gid_t {
-    e(unsafe { syscall!(GETGID) }) as gid_t
-}
-
-pub fn getrusage(who: c_int, r_usage: *mut rusage) -> c_int {
-    e(unsafe { syscall!(GETRUSAGE, who, r_usage) }) as c_int
-}
-
-pub unsafe fn gethostname(mut name: *mut c_char, len: size_t) -> c_int {
-    // len only needs to be mutable on linux
-    let mut len = len;
-
-    let mut uts = mem::uninitialized();
-    let err = uname(&mut uts);
-    if err < 0 {
-        mem::forget(uts);
-        return err;
-    }
-    for c in uts.nodename.iter() {
-        if len == 0 {
-            break;
-        }
-        len -= 1;
-
-        *name = *c;
-
-        if *name == 0 {
-            // We do want to copy the zero also, so we check this after the copying.
-            break;
-        }
-
-        name = name.offset(1);
-    }
-    0
-}
-
-pub fn getitimer(which: c_int, out: *mut itimerval) -> c_int {
-    e(unsafe { syscall!(GETITIMER, which, out) }) as c_int
-}
-
-pub unsafe fn getpeername(
-    socket: c_int,
-    address: *mut sockaddr,
-    address_len: *mut socklen_t,
-) -> c_int {
-    e(syscall!(GETPEERNAME, socket, address, address_len)) as c_int
-}
-
-pub fn getpgid(pid: pid_t) -> pid_t {
-    e(unsafe { syscall!(GETPGID, pid) }) as pid_t
-}
-
-pub fn getpid() -> pid_t {
-    e(unsafe { syscall!(GETPID) }) as pid_t
-}
-
-pub fn getppid() -> pid_t {
-    e(unsafe { syscall!(GETPPID) }) as pid_t
-}
-
-pub unsafe fn getsockname(
-    socket: c_int,
-    address: *mut sockaddr,
-    address_len: *mut socklen_t,
-) -> c_int {
-    e(syscall!(GETSOCKNAME, socket, address, address_len)) as c_int
-}
-
-pub fn getsockopt(
-    socket: c_int,
-    level: c_int,
-    option_name: c_int,
-    option_value: *mut c_void,
-    option_len: *mut socklen_t,
-) -> c_int {
-    e(unsafe {
-        syscall!(
-            GETSOCKOPT,
-            socket,
-            level,
-            option_name,
-            option_value,
-            option_len
-        )
-    }) as c_int
-}
-
-pub fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
-    e(unsafe { syscall!(GETTIMEOFDAY, tp, tzp) }) as c_int
-}
-
-pub fn getuid() -> uid_t {
-    e(unsafe { syscall!(GETUID) }) as uid_t
-}
-
-pub fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
-    // TODO: Somehow support varargs to syscall??
-    e(unsafe { syscall!(IOCTL, fd, request, out) }) as c_int
-}
-
-pub fn isatty(fd: c_int) -> c_int {
-    let mut winsize = winsize::default();
-    (ioctl(fd, TIOCGWINSZ, &mut winsize as *mut _ as *mut c_void) == 0) as c_int
-}
-
-pub fn kill(pid: pid_t, sig: c_int) -> c_int {
-    e(unsafe { syscall!(KILL, pid, sig) }) as c_int
-}
-
-pub fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
-    e(unsafe { syscall!(KILL, -(pgrp as isize) as pid_t, sig) }) as c_int
-}
-
-pub fn link(path1: *const c_char, path2: *const c_char) -> c_int {
-    e(unsafe { syscall!(LINKAT, AT_FDCWD, path1, AT_FDCWD, path2, 0) }) as c_int
-}
-
-pub fn listen(socket: c_int, backlog: c_int) -> c_int {
-    e(unsafe { syscall!(LISTEN, socket, backlog) }) as c_int
-}
-
-pub fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t {
-    e(unsafe { syscall!(LSEEK, fildes, offset, whence) }) as off_t
-}
-
-pub fn lstat(file: *const c_char, buf: *mut stat) -> c_int {
-    e(unsafe { syscall!(NEWFSTATAT, AT_FDCWD, file, buf, AT_SYMLINK_NOFOLLOW) }) as c_int
-}
-
-pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
-    e(unsafe { syscall!(MKDIRAT, AT_FDCWD, path, mode) }) as c_int
-}
-
-pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
-    e(unsafe { syscall!(MKNODAT, AT_FDCWD, path, mode, 0) }) as c_int
-}
-
-pub unsafe fn mmap(
-    addr: *mut c_void,
-    len: usize,
-    prot: c_int,
-    flags: c_int,
-    fildes: c_int,
-    off: off_t,
-) -> *mut c_void {
-    e(syscall!(MMAP, addr, len, prot, flags, fildes, off)) as *mut c_void
-}
-
-pub unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
-    e(syscall!(MUNMAP, addr, len)) as c_int
-}
-
-pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
-    e(unsafe { syscall!(NANOSLEEP, rqtp, rmtp) }) as c_int
-}
-
-pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int {
-    e(unsafe { syscall!(OPENAT, AT_FDCWD, path, oflag, mode) }) as c_int
-}
-
-pub fn pipe(fildes: &mut [c_int]) -> c_int {
-    e(unsafe { syscall!(PIPE2, fildes.as_mut_ptr(), 0) }) as c_int
-}
-
-pub fn raise(sig: c_int) -> c_int {
-    let tid = e(unsafe { syscall!(GETTID) }) as pid_t;
-    let ret = if tid == !0 {
-        -1
-    } else {
-        e(unsafe { syscall!(TKILL, tid, sig) }) as c_int
-    };
-
-    ret
-}
-
-pub fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t {
-    e(unsafe { syscall!(READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t
-}
-
-pub unsafe fn recvfrom(
-    socket: c_int,
-    buf: *mut c_void,
-    len: size_t,
-    flags: c_int,
-    address: *mut sockaddr,
-    address_len: *mut socklen_t,
-) -> ssize_t {
-    e(syscall!(
-        RECVFROM,
-        socket,
-        buf,
-        len,
-        flags,
-        address,
-        address_len
-    )) as ssize_t
-}
-
-pub fn rename(old: *const c_char, new: *const c_char) -> c_int {
-    e(unsafe { syscall!(RENAMEAT, AT_FDCWD, old, AT_FDCWD, new) }) as c_int
-}
-
-pub fn rmdir(path: *const c_char) -> c_int {
-    e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path, AT_REMOVEDIR) }) as c_int
-}
-
-pub fn select(
-    nfds: c_int,
-    readfds: *mut fd_set,
-    writefds: *mut fd_set,
-    exceptfds: *mut fd_set,
-    timeout: *mut timeval,
-) -> c_int {
-    e(unsafe { syscall!(SELECT, nfds, readfds, writefds, exceptfds, timeout) }) as c_int
-}
-
-pub unsafe fn sendto(
-    socket: c_int,
-    buf: *const c_void,
-    len: size_t,
-    flags: c_int,
-    dest_addr: *const sockaddr,
-    dest_len: socklen_t,
-) -> ssize_t {
-    e(syscall!(
-        SENDTO, socket, buf, len, flags, dest_addr, dest_len
-    )) as ssize_t
-}
-
-pub fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int {
-    e(unsafe { syscall!(SETITIMER, which, new, old) }) as c_int
-}
-
-pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
-    e(unsafe { syscall!(SETPGID, pid, pgid) }) as c_int
-}
-
-pub fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
-    e(unsafe { syscall!(SETREGID, rgid, egid) }) as c_int
-}
-
-pub fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
-    e(unsafe { syscall!(SETREUID, ruid, euid) }) as c_int
-}
-
-pub fn setsockopt(
-    socket: c_int,
-    level: c_int,
-    option_name: c_int,
-    option_value: *const c_void,
-    option_len: socklen_t,
-) -> c_int {
-    e(unsafe {
-        syscall!(
-            SETSOCKOPT,
-            socket,
-            level,
-            option_name,
-            option_value,
-            option_len
-        )
-    }) as c_int
-}
-
-pub fn shutdown(socket: c_int, how: c_int) -> c_int {
-    e(unsafe { syscall!(SHUTDOWN, socket, how) }) as c_int
-}
-
-pub unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int {
-    e(syscall!(
-        RT_SIGACTION,
-        sig,
-        act,
-        oact,
-        mem::size_of::<sigset_t>()
-    )) as c_int
-}
-
-pub fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
-    e(unsafe { syscall!(RT_SIGPROCMASK, how, set, oset, mem::size_of::<sigset_t>()) }) as c_int
-}
-
-pub fn stat(file: *const c_char, buf: *mut stat) -> c_int {
-    e(unsafe { syscall!(NEWFSTATAT, AT_FDCWD, file, buf, 0) }) as c_int
-}
-
-pub fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int {
-    e(unsafe { syscall!(SOCKET, domain, kind, protocol) }) as c_int
-}
-
-pub fn socketpair(domain: c_int, kind: c_int, protocol: c_int, socket_vector: *mut c_int) -> c_int {
-    e(unsafe { syscall!(SOCKETPAIR, domain, kind, protocol, socket_vector) }) as c_int
-}
-
-pub fn tcgetattr(fd: c_int, out: *mut termios) -> c_int {
-    ioctl(fd, TCGETS, out as *mut c_void)
-}
-
-pub fn tcsetattr(fd: c_int, act: c_int, value: *const termios) -> c_int {
-    if act < 0 || act > 2 {
-        unsafe {
-            errno = EINVAL;
-        }
-        return -1;
-    }
-    // This is safe because ioctl shouldn't modify the value
-    ioctl(fd, TCSETS + act as c_ulong, value as *mut c_void)
-}
-
-pub fn times(out: *mut tms) -> clock_t {
-    unsafe { syscall!(TIMES, out) as clock_t }
-}
-
-pub fn umask(mask: mode_t) -> mode_t {
-    unsafe { syscall!(UMASK, mask) as mode_t }
-}
-
-pub fn uname(utsname: *mut utsname) -> c_int {
-    e(unsafe { syscall!(UNAME, utsname, 0) }) as c_int
-}
-
-pub fn unlink(path: *const c_char) -> c_int {
-    e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path, 0) }) as c_int
-}
-
-pub fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
-    e(unsafe { syscall!(WAIT4, pid, stat_loc, options, 0) }) as pid_t
-}
-
-pub fn write(fildes: c_int, buf: &[u8]) -> ssize_t {
-    e(unsafe { syscall!(WRITE, fildes, buf.as_ptr(), buf.len()) }) as ssize_t
-}
-
-pub fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
-    e(unsafe { syscall!(CLOCK_GETTIME, clk_id, tp) }) as c_int
-}
diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs
deleted file mode 100644
index 1f4b996ace2e0493ae35bb703a5eb108b737c8c3..0000000000000000000000000000000000000000
--- a/src/platform/src/redox/mod.rs
+++ /dev/null
@@ -1,1114 +0,0 @@
-//! sys/socket implementation, following http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html
-
-use alloc::btree_map::BTreeMap;
-use core::fmt::Write;
-use core::{mem, ptr, slice};
-use spin::{Once, Mutex, MutexGuard};
-use syscall::data::Stat as redox_stat;
-use syscall::data::TimeSpec as redox_timespec;
-use syscall::flag::*;
-use syscall::{self, Result};
-
-use types::*;
-use *;
-
-const EINVAL: c_int = 22;
-const MAP_ANON: c_int = 1;
-
-#[thread_local]
-static mut SIG_HANDLER: Option<extern "C" fn(c_int)> = None;
-
-static ANONYMOUS_MAPS: Once<Mutex<BTreeMap<usize, usize>>> = Once::new();
-
-fn anonymous_maps() -> MutexGuard<'static, BTreeMap<usize, usize>> {
-    ANONYMOUS_MAPS.call_once(|| Mutex::new(BTreeMap::new())).lock()
-}
-
-extern "C" fn sig_handler(sig: usize) {
-    if let Some(ref callback) = unsafe { SIG_HANDLER } {
-        callback(sig as c_int);
-    }
-}
-
-fn e(sys: Result<usize>) -> usize {
-    match sys {
-        Ok(ok) => ok,
-        Err(err) => {
-            unsafe {
-                errno = err.errno as c_int;
-            }
-            !0
-        }
-    }
-}
-
-macro_rules! bind_or_connect {
-    (bind $path:expr) => {
-        concat!("/", $path)
-    };
-    (connect $path:expr) => {
-        $path
-    };
-    ($mode:ident $socket:expr, $address:expr, $address_len:expr) => {{
-        if (*$address).sa_family as c_int != AF_INET {
-            errno = syscall::EAFNOSUPPORT;
-            return -1;
-        }
-        if ($address_len as usize) < mem::size_of::<sockaddr>() {
-            errno = syscall::EINVAL;
-            return -1;
-        }
-        let data = &*($address as *const sockaddr_in);
-        let addr = &data.sin_addr.s_addr;
-        let port = in_port_t::from_be(data.sin_port); // This is transmuted from bytes in BigEndian order
-        let path = format!(bind_or_connect!($mode "{}.{}.{}.{}:{}"), addr[0], addr[1], addr[2], addr[3], port);
-
-        // Duplicate the socket, and then duplicate the copy back to the original fd
-        let fd = e(syscall::dup($socket as usize, path.as_bytes()));
-        if (fd as c_int) < 0 {
-            return -1;
-        }
-        let result = syscall::dup2(fd, $socket as usize, &[]);
-        let _ = syscall::close(fd);
-        if (e(result) as c_int) < 0 {
-            return -1;
-        }
-        0
-    }}
-}
-
-pub unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
-    let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
-    if stream < 0 {
-        return -1;
-    }
-    if address != ptr::null_mut()
-        && address_len != ptr::null_mut()
-        && getpeername(stream, address, address_len) < 0
-    {
-        return -1;
-    }
-    stream
-}
-
-pub fn access(path: *const c_char, mode: c_int) -> c_int {
-    let fd = match RawFile::open(path, 0, 0) {
-        Ok(fd) => fd,
-        Err(_) => return -1
-    };
-    if mode == F_OK {
-        return 0;
-    }
-
-    let mut stat = syscall::Stat::default();
-
-    if e(syscall::fstat(*fd as usize, &mut stat)) == !0 {
-        return -1;
-    }
-
-    let uid = e(syscall::getuid());
-    if uid == !0 {
-        return -1;
-    }
-    let gid = e(syscall::getgid());
-    if gid == !0 {
-        return -1;
-    }
-
-    let perms = if stat.st_uid as usize == uid {
-        // octal has max 7 characters, binary has max two. And we're interested
-        // in the 3rd digit
-        stat.st_mode >> ((7 / 2) * 2 & 0o7)
-    } else if stat.st_gid as usize == gid {
-        stat.st_mode >> ((7 / 2) & 0o7)
-    } else {
-        stat.st_mode & 0o7
-    };
-    if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
-            || (mode & W_OK == W_OK && perms & 0o2 != 0o2)
-            || (mode & X_OK == X_OK && perms & 0o1 != 0o1) {
-        unsafe {
-            errno = EINVAL;
-        }
-        return -1;
-    }
-
-    0
-}
-
-pub unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
-    bind_or_connect!(bind socket, address, address_len)
-}
-
-pub fn brk(addr: *mut c_void) -> *mut c_void {
-    unsafe { syscall::brk(addr as usize).unwrap_or(0) as *mut c_void }
-}
-
-pub fn chdir(path: *const c_char) -> c_int {
-    let path = unsafe { c_str(path) };
-    e(syscall::chdir(path)) as c_int
-}
-
-pub fn chmod(path: *const c_char, mode: mode_t) -> c_int {
-    let path = unsafe { c_str(path) };
-    match syscall::open(path, O_WRONLY) {
-        Err(err) => e(Err(err)) as c_int,
-        Ok(fd) => {
-            let res = syscall::fchmod(fd as usize, mode as u16);
-            let _ = syscall::close(fd);
-            e(res) as c_int
-        }
-    }
-}
-
-pub fn chown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
-    let path = unsafe { c_str(path) };
-    match syscall::open(path, O_WRONLY) {
-        Err(err) => e(Err(err)) as c_int,
-        Ok(fd) => {
-            let res = syscall::fchown(fd as usize, owner as u32, group as u32);
-            let _ = syscall::close(fd);
-            e(res) as c_int
-        }
-    }
-}
-
-pub fn close(fd: c_int) -> c_int {
-    e(syscall::close(fd as usize)) as c_int
-}
-
-pub unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
-    bind_or_connect!(connect socket, address, address_len)
-}
-
-pub fn dup(fd: c_int) -> c_int {
-    e(syscall::dup(fd as usize, &[])) as c_int
-}
-
-pub fn dup2(fd1: c_int, fd2: c_int) -> c_int {
-    e(syscall::dup2(fd1 as usize, fd2 as usize, &[])) as c_int
-}
-
-pub fn exit(status: c_int) -> ! {
-    let _ = syscall::exit(status as usize);
-    loop {}
-}
-
-pub unsafe extern "C" fn execve(
-    path: *const c_char,
-    mut argv: *const *mut c_char,
-    mut envp: *const *mut c_char,
-) -> c_int {
-    use alloc::Vec;
-
-    let fd = match RawFile::open(path, O_RDONLY as c_int, 0) {
-        Ok(fd) => fd,
-        Err(_) => return -1
-    };
-
-    let mut len = 0;
-    while !(*argv.offset(len)).is_null() {
-        len += 1;
-    }
-
-    let mut args: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
-    while !(*argv).is_null() {
-        let arg = *argv;
-
-        let mut len = 0;
-        while *arg.offset(len) != 0 {
-            len += 1;
-        }
-        args.push([arg as usize, len as usize]);
-        argv = argv.offset(1);
-    }
-
-    let mut len = 0;
-    while !(*envp.offset(len)).is_null() {
-        len += 1;
-    }
-
-    let mut envs: Vec<[usize; 2]> = Vec::with_capacity(len as usize);
-    while !(*envp).is_null() {
-        let env = *envp;
-
-        let mut len = 0;
-        while *env.offset(len) != 0 {
-            len += 1;
-        }
-        envs.push([env as usize, len as usize]);
-        envp = envp.offset(1);
-    }
-
-    e(syscall::fexec(*fd as usize, &args, &envs)) as c_int
-}
-
-pub fn fchdir(fd: c_int) -> c_int {
-    let path: &mut [u8] = &mut [0; 4096];
-    if e(syscall::fpath(fd as usize, path)) == !0 {
-        !0
-    } else {
-        e(syscall::chdir(path)) as c_int
-    }
-}
-
-pub fn fchmod(fd: c_int, mode: mode_t) -> c_int {
-    e(syscall::fchmod(fd as usize, mode as u16)) as c_int
-}
-
-pub fn fchown(fd: c_int, owner: uid_t, group: gid_t) -> c_int {
-    e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int
-}
-
-pub fn fcntl(fd: c_int, cmd: c_int, args: c_int) -> c_int {
-    e(syscall::fcntl(fd as usize, cmd as usize, args as usize)) as c_int
-}
-
-pub fn flock(_fd: c_int, _operation: c_int) -> c_int {
-    // TODO: Redox does not have file locking yet
-    0
-}
-
-pub fn fork() -> pid_t {
-    e(unsafe { syscall::clone(0) }) as pid_t
-}
-
-pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int {
-    let mut redox_buf: redox_stat = redox_stat::default();
-    match e(syscall::fstat(fildes as usize, &mut redox_buf)) {
-        0 => {
-            unsafe {
-                if !buf.is_null() {
-                    (*buf).st_dev = redox_buf.st_dev as dev_t;
-                    (*buf).st_ino = redox_buf.st_ino as ino_t;
-                    (*buf).st_nlink = redox_buf.st_nlink as nlink_t;
-                    (*buf).st_mode = redox_buf.st_mode as mode_t;
-                    (*buf).st_uid = redox_buf.st_uid as uid_t;
-                    (*buf).st_gid = redox_buf.st_gid as gid_t;
-                    // TODO st_rdev
-                    (*buf).st_rdev = 0;
-                    (*buf).st_size = redox_buf.st_size as off_t;
-                    (*buf).st_blksize = redox_buf.st_blksize as blksize_t;
-                    (*buf).st_atim = timespec {
-                        tv_sec: redox_buf.st_atime as time_t,
-                        tv_nsec: redox_buf.st_atime_nsec as c_long,
-                    };
-                    (*buf).st_mtim = timespec {
-                        tv_sec: redox_buf.st_mtime as time_t,
-                        tv_nsec: redox_buf.st_mtime_nsec as c_long,
-                    };
-                    (*buf).st_ctim = timespec {
-                        tv_sec: redox_buf.st_ctime as time_t,
-                        tv_nsec: redox_buf.st_ctime_nsec as c_long,
-                    };
-                }
-            }
-            0
-        }
-        _ => -1,
-    }
-}
-
-pub fn fsync(fd: c_int) -> c_int {
-    e(syscall::fsync(fd as usize)) as c_int
-}
-
-pub fn ftruncate(fd: c_int, len: off_t) -> c_int {
-    e(syscall::ftruncate(fd as usize, len as usize)) as c_int
-}
-
-pub fn futimens(fd: c_int, times: *const timespec) -> c_int {
-    let times = [unsafe { redox_timespec::from(&*times) }, unsafe {
-        redox_timespec::from(&*times.offset(1))
-    }];
-    e(syscall::futimens(fd as usize, &times)) as c_int
-}
-
-pub fn utimens(path: *const c_char, times: *const timespec) -> c_int {
-    let path = unsafe { c_str(path) };
-    match syscall::open(path, O_STAT) {
-        Err(err) => e(Err(err)) as c_int,
-        Ok(fd) => {
-            let res = futimens(fd as c_int, times);
-            let _ = syscall::close(fd);
-            res
-        }
-    }
-}
-
-pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char {
-    let buf_slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size as usize - 1) };
-    let read = e(syscall::getcwd(buf_slice));
-    if read == !0 {
-        ptr::null_mut()
-    } else {
-        unsafe {
-            *buf.offset(read as isize + 1) = 0;
-        }
-        buf
-    }
-}
-
-pub fn getdents(fd: c_int, mut dirents: *mut dirent, mut bytes: usize) -> c_int {
-    let mut amount = 0;
-
-    let mut buf = [0; 1024];
-    let mut bindex = 0;
-    let mut blen = 0;
-
-    let mut name = [0; 256];
-    let mut nindex = 0;
-
-    loop {
-        if bindex >= blen {
-            bindex = 0;
-            blen = match syscall::read(fd as usize, &mut buf) {
-                Ok(0) => return amount,
-                Ok(n) => n,
-                Err(err) => return -err.errno,
-            };
-        }
-
-        if buf[bindex] == b'\n' {
-            // Put a NUL byte either at the end, or if it's too big, at where it's truncated.
-            name[nindex.min(name.len() - 1)] = 0;
-            unsafe {
-                *dirents = dirent {
-                    d_ino: 0,
-                    d_off: 0,
-                    d_reclen: mem::size_of::<dirent>() as c_ushort,
-                    d_type: 0,
-                    d_name: name,
-                };
-                dirents = dirents.offset(1);
-            }
-            amount += 1;
-            if bytes <= mem::size_of::<dirent>() {
-                return amount;
-            }
-            bytes -= mem::size_of::<dirent>();
-        } else {
-            if nindex < name.len() {
-                name[nindex] = buf[bindex] as c_char;
-            }
-            nindex += 1;
-            bindex += 1;
-        }
-    }
-}
-
-pub fn getegid() -> gid_t {
-    e(syscall::getegid()) as gid_t
-}
-
-pub fn geteuid() -> uid_t {
-    e(syscall::geteuid()) as uid_t
-}
-
-pub fn getgid() -> gid_t {
-    e(syscall::getgid()) as gid_t
-}
-
-pub fn getrusage(who: c_int, r_usage: *mut rusage) -> c_int {
-    let _ = writeln!(
-        FileWriter(2),
-        "unimplemented: getrusage({}, {:p})",
-        who,
-        r_usage
-    );
-    -1
-}
-
-pub unsafe fn gethostname(mut name: *mut c_char, len: size_t) -> c_int {
-    let fd = e(syscall::open("/etc/hostname", O_RDONLY)) as i32;
-    if fd < 0 {
-        return fd;
-    }
-    let mut reader = FileReader(fd);
-    for _ in 0..len {
-        match reader.read_u8() {
-            Ok(Some(b)) => {
-                *name = b as c_char;
-                name = name.offset(1);
-            },
-            Ok(None) => {
-                *name = 0;
-                break;
-            },
-            Err(()) => return -1
-        }
-    }
-    0
-}
-
-unsafe fn inner_get_name(
-    local: bool,
-    socket: c_int,
-    address: *mut sockaddr,
-    address_len: *mut socklen_t,
-) -> Result<usize> {
-    // 32 should probably be large enough.
-    // Format: tcp:remote/local
-    // and since we only yet support IPv4 (I think)...
-    let mut buf = [0; 32];
-    let len = syscall::fpath(socket as usize, &mut buf)?;
-    let buf = &buf[..len];
-    assert!(&buf[..4] == b"tcp:" || &buf[..4] == b"udp:");
-    let buf = &buf[4..];
-
-    let mut parts = buf.split(|c| *c == b'/');
-    if local {
-        // Skip the remote part
-        parts.next();
-    }
-    let part = parts.next().expect("Invalid reply from netstack");
-
-    let data = slice::from_raw_parts_mut(
-        &mut (*address).data as *mut _ as *mut u8,
-        (*address).data.len(),
-    );
-
-    let len = data.len().min(part.len());
-    data[..len].copy_from_slice(&part[..len]);
-
-    *address_len = len as socklen_t;
-    Ok(0)
-}
-
-pub fn getitimer(which: c_int, out: *mut itimerval) -> c_int {
-    let _ = writeln!(
-        FileWriter(2),
-        "unimplemented: getitimer({}, {:p})",
-        which,
-        out
-    );
-
-    unsafe {
-        *out = itimerval::default();
-    }
-    0
-}
-
-pub unsafe fn getpeername(
-    socket: c_int,
-    address: *mut sockaddr,
-    address_len: *mut socklen_t,
-) -> c_int {
-    e(inner_get_name(false, socket, address, address_len)) as c_int
-}
-
-pub fn getpgid(pid: pid_t) -> pid_t {
-    e(syscall::getpgid(pid as usize)) as pid_t
-}
-
-pub fn getpid() -> pid_t {
-    e(syscall::getpid()) as pid_t
-}
-
-pub fn getppid() -> pid_t {
-    e(syscall::getppid()) as pid_t
-}
-
-pub unsafe fn getsockname(
-    socket: c_int,
-    address: *mut sockaddr,
-    address_len: *mut socklen_t,
-) -> c_int {
-    e(inner_get_name(true, socket, address, address_len)) as c_int
-}
-
-pub fn getsockopt(
-    socket: c_int,
-    level: c_int,
-    option_name: c_int,
-    option_value: *mut c_void,
-    option_len: *mut socklen_t,
-) -> c_int {
-    let _ = writeln!(
-        FileWriter(2),
-        "unimplemented: getsockopt({}, {}, {}, {:p}, {:p})",
-        socket,
-        level,
-        option_name,
-        option_value,
-        option_len
-    );
-    -1
-}
-
-pub fn gettimeofday(tp: *mut timeval, tzp: *mut timezone) -> c_int {
-    let mut redox_tp = redox_timespec::default();
-    let err = e(syscall::clock_gettime(
-        syscall::CLOCK_REALTIME,
-        &mut redox_tp,
-    )) as c_int;
-    if err < 0 {
-        return err;
-    }
-    unsafe {
-        (*tp).tv_sec = redox_tp.tv_sec as time_t;
-        (*tp).tv_usec = (redox_tp.tv_nsec / 1000) as suseconds_t;
-
-        if !tzp.is_null() {
-            (*tzp).tz_minuteswest = 0;
-            (*tzp).tz_dsttime = 0;
-        }
-    }
-    0
-}
-
-pub fn getuid() -> uid_t {
-    e(syscall::getuid()) as pid_t
-}
-
-pub fn isatty(fd: c_int) -> c_int {
-    syscall::dup(fd as usize, b"termios")
-        .map(|fd| {
-            let _ = syscall::close(fd);
-            1
-        })
-        .unwrap_or(0)
-}
-
-pub fn kill(pid: pid_t, sig: c_int) -> c_int {
-    e(syscall::kill(pid as usize, sig as usize)) as c_int
-}
-
-pub fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
-    e(syscall::kill(-(pgrp as isize) as usize, sig as usize)) as c_int
-}
-
-pub fn link(path1: *const c_char, path2: *const c_char) -> c_int {
-    let path1 = unsafe { c_str(path1) };
-    let path2 = unsafe { c_str(path2) };
-    e(unsafe { syscall::link(path1.as_ptr(), path2.as_ptr()) }) as c_int
-}
-
-pub fn listen(_socket: c_int, _backlog: c_int) -> c_int {
-    // TODO
-    0
-}
-
-pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
-    e(syscall::lseek(
-        fd as usize,
-        offset as isize,
-        whence as usize,
-    )) as off_t
-}
-
-pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int {
-    let path = unsafe { c_str(path) };
-    match syscall::open(path, O_STAT | O_NOFOLLOW) {
-        Err(err) => e(Err(err)) as c_int,
-        Ok(fd) => {
-            let res = fstat(fd as i32, buf);
-            let _ = syscall::close(fd);
-            res
-        }
-    }
-}
-
-pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
-    let flags = O_CREAT | O_EXCL | O_CLOEXEC | O_DIRECTORY | mode as usize & 0o777;
-    let path = unsafe { c_str(path) };
-    match syscall::open(path, flags) {
-        Ok(fd) => {
-            let _ = syscall::close(fd);
-            0
-        }
-        Err(err) => e(Err(err)) as c_int,
-    }
-}
-
-pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
-    let flags = O_CREAT | MODE_FIFO as usize | mode as usize & 0o777;
-    let path = unsafe { c_str(path) };
-    match syscall::open(path, flags) {
-        Ok(fd) => {
-            let _ = syscall::close(fd);
-            0
-        }
-        Err(err) => e(Err(err)) as c_int,
-    }
-}
-
-pub unsafe fn mmap(
-    _addr: *mut c_void,
-    len: usize,
-    _prot: c_int,
-    flags: c_int,
-    fildes: c_int,
-    off: off_t,
-) -> *mut c_void {
-    if flags & MAP_ANON == MAP_ANON {
-        let fd = e(syscall::open("memory:", 0)); // flags don't matter currently
-        if fd == !0 {
-            return !0 as *mut c_void;
-        }
-
-        let addr = e(syscall::fmap(fd, off as usize, len as usize));
-        if addr == !0 {
-            let _ = syscall::close(fd);
-            return !0 as *mut c_void;
-        }
-
-        anonymous_maps().insert(addr as usize, fd);
-        addr as *mut c_void
-    } else {
-        e(syscall::fmap(fildes as usize, off as usize, len as usize)) as *mut c_void
-    }
-}
-
-pub unsafe fn munmap(addr: *mut c_void, _len: usize) -> c_int {
-    if e(syscall::funmap(addr as usize)) == !0 {
-        return !0;
-    }
-    if let Some(fd) = anonymous_maps().remove(&(addr as usize)) {
-        let _ = syscall::close(fd);
-    }
-    0
-}
-
-pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
-    let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) };
-    let mut redox_rmtp: redox_timespec;
-    if rmtp.is_null() {
-        redox_rmtp = redox_timespec::default();
-    } else {
-        redox_rmtp = unsafe { redox_timespec::from(&*rmtp) };
-    }
-    match e(syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)) as c_int {
-        -1 => -1,
-        _ => {
-            unsafe {
-                if !rmtp.is_null() {
-                    (*rmtp).tv_sec = redox_rmtp.tv_sec;
-                    (*rmtp).tv_nsec = redox_rmtp.tv_nsec as i64;
-                }
-            }
-            0
-        }
-    }
-}
-
-pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int {
-    let path = unsafe { c_str(path) };
-    e(syscall::open(path, (oflag as usize) | (mode as usize))) as c_int
-}
-
-pub fn pipe(fds: &mut [c_int]) -> c_int {
-    let mut usize_fds: [usize; 2] = [0; 2];
-    let res = e(syscall::pipe2(&mut usize_fds, 0));
-    fds[0] = usize_fds[0] as c_int;
-    fds[1] = usize_fds[1] as c_int;
-    res as c_int
-}
-
-pub fn raise(sig: c_int) -> c_int {
-    kill(getpid(), sig)
-}
-
-pub fn read(fd: c_int, buf: &mut [u8]) -> ssize_t {
-    e(syscall::read(fd as usize, buf)) as ssize_t
-}
-
-pub unsafe fn recvfrom(
-    socket: c_int,
-    buf: *mut c_void,
-    len: size_t,
-    flags: c_int,
-    address: *mut sockaddr,
-    address_len: *mut socklen_t,
-) -> ssize_t {
-    if flags != 0 {
-        errno = syscall::EOPNOTSUPP;
-        return -1;
-    }
-    if address != ptr::null_mut()
-        && address_len != ptr::null_mut()
-        && getpeername(socket, address, address_len) < 0
-    {
-        return -1;
-    }
-    read(socket, slice::from_raw_parts_mut(buf as *mut u8, len))
-}
-
-pub fn rename(oldpath: *const c_char, newpath: *const c_char) -> c_int {
-    let (oldpath, newpath) = unsafe { (c_str(oldpath), c_str(newpath)) };
-    match syscall::open(oldpath, O_WRONLY) {
-        Ok(fd) => {
-            let retval = syscall::frename(fd, newpath);
-            let _ = syscall::close(fd);
-            e(retval) as c_int
-        }
-        err => e(err) as c_int,
-    }
-}
-
-pub fn rmdir(path: *const c_char) -> c_int {
-    let path = unsafe { c_str(path) };
-    e(syscall::rmdir(path)) as c_int
-}
-
-pub fn select(
-    nfds: c_int,
-    readfds: *mut fd_set,
-    writefds: *mut fd_set,
-    exceptfds: *mut fd_set,
-    timeout: *mut timeval,
-) -> c_int {
-    fn isset(set: *mut fd_set, fd: usize) -> bool {
-        if set.is_null() {
-            return false;
-        }
-
-        let mask = 1 << (fd & (8 * mem::size_of::<c_ulong>() - 1));
-        unsafe { (*set).fds_bits[fd / (8 * mem::size_of::<c_ulong>())] & mask == mask }
-    }
-
-    let event_file = match RawFile::open("event:\0".as_ptr() as *const c_char, 0, 0) {
-        Ok(file) => file,
-        Err(_) => return -1,
-    };
-
-    let mut total = 0;
-
-    for fd in 0..nfds as usize {
-        macro_rules! register {
-            ($fd:expr, $flags:expr) => {
-                if write(
-                    *event_file,
-                    &syscall::Event {
-                        id: $fd,
-                        flags: $flags,
-                        data: 0,
-                    },
-                ) < 0
-                {
-                    return -1;
-                }
-            };
-        }
-        if isset(readfds, fd) {
-            register!(fd, syscall::EVENT_READ);
-            total += 1;
-        }
-        if isset(writefds, fd) {
-            register!(fd, syscall::EVENT_WRITE);
-            total += 1;
-        }
-        if isset(exceptfds, fd) {
-            total += 1;
-        }
-    }
-
-    const TIMEOUT_TOKEN: usize = 1;
-
-    let timeout_file = if timeout.is_null() {
-        None
-    } else {
-        let timeout_file = match RawFile::open(
-            format!("time:{}\0", syscall::CLOCK_MONOTONIC).as_ptr() as *const c_char,
-            0,
-            0,
-        ) {
-            Ok(file) => file,
-            Err(_) => return -1,
-        };
-        let timeout = unsafe { &*timeout };
-        if write(
-            *timeout_file,
-            &syscall::TimeSpec {
-                tv_sec: timeout.tv_sec,
-                tv_nsec: timeout.tv_usec * 1000,
-            },
-        ) < 0
-        {
-            return -1;
-        }
-        if write(
-            *event_file,
-            &syscall::Event {
-                id: *timeout_file as usize,
-                flags: syscall::EVENT_READ,
-                data: TIMEOUT_TOKEN,
-            },
-        ) < 0
-        {
-            return -1;
-        }
-
-        Some(timeout_file)
-    };
-
-    let mut event = syscall::Event::default();
-    if read(*event_file, &mut event) < 0 {
-        return -1;
-    }
-
-    if timeout_file.is_some() && event.data == TIMEOUT_TOKEN {
-        return 0;
-    }
-
-    // I really don't get why, but select wants me to return the total number
-    // of file descriptors that was inputted. I'm confused.
-    total
-}
-
-pub unsafe fn sendto(
-    socket: c_int,
-    buf: *const c_void,
-    len: size_t,
-    flags: c_int,
-    dest_addr: *const sockaddr,
-    dest_len: socklen_t,
-) -> ssize_t {
-    if dest_addr != ptr::null() || dest_len != 0 {
-        errno = syscall::EISCONN;
-        return -1;
-    }
-    if flags != 0 {
-        errno = syscall::EOPNOTSUPP;
-        return -1;
-    }
-    write(socket, slice::from_raw_parts(buf as *const u8, len))
-}
-
-pub fn setitimer(which: c_int, new: *const itimerval, old: *mut itimerval) -> c_int {
-    let _ = writeln!(
-        FileWriter(2),
-        "unimplemented: setitimer({}, {:p}, {:p})",
-        which,
-        new,
-        old
-    );
-
-    unsafe {
-        *old = itimerval::default();
-    }
-    0
-}
-
-pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
-    e(syscall::setpgid(pid as usize, pgid as usize)) as c_int
-}
-
-pub fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
-    e(syscall::setregid(rgid as usize, egid as usize)) as c_int
-}
-
-pub fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
-    e(syscall::setreuid(ruid as usize, euid as usize)) as c_int
-}
-
-pub fn setsockopt(
-    socket: c_int,
-    level: c_int,
-    option_name: c_int,
-    option_value: *const c_void,
-    option_len: socklen_t,
-) -> c_int {
-    let _ = writeln!(
-        FileWriter(2),
-        "unimplemented: setsockopt({}, {}, {}, {:p}, {})",
-        socket,
-        level,
-        option_name,
-        option_value,
-        option_len
-    );
-    -1
-}
-
-pub fn shutdown(socket: c_int, how: c_int) -> c_int {
-    let _ = writeln!(
-        FileWriter(2),
-        "unimplemented: shutdown({}, {})",
-        socket,
-        how
-    );
-    -1
-}
-
-pub unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int {
-    if !oact.is_null() {
-        // Assumes the last sigaction() call was made by relibc and not a different one
-        if SIG_HANDLER.is_some() {
-            (*oact).sa_handler = SIG_HANDLER;
-        }
-    }
-    let act = if act.is_null() {
-        None
-    } else {
-        SIG_HANDLER = (*act).sa_handler;
-        let m = (*act).sa_mask;
-        Some(syscall::SigAction {
-            sa_handler: sig_handler,
-            sa_mask: [0, m as u64],
-            sa_flags: (*act).sa_flags as usize,
-        })
-    };
-    let mut old = syscall::SigAction::default();
-    let ret = e(syscall::sigaction(
-        sig as usize,
-        act.as_ref(),
-        if oact.is_null() { None } else { Some(&mut old) },
-    )) as c_int;
-    if !oact.is_null() {
-        let m = old.sa_mask;
-        (*oact).sa_mask = m[1] as c_ulong;
-        (*oact).sa_flags = old.sa_flags as c_ulong;
-    }
-    ret
-}
-
-pub fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
-    let _ = writeln!(
-        FileWriter(2),
-        "unimplemented: sigprocmask({}, {:p}, {:p})",
-        how,
-        set,
-        oset
-    );
-    -1
-}
-
-pub fn stat(path: *const c_char, buf: *mut stat) -> c_int {
-    let path = unsafe { c_str(path) };
-    match syscall::open(path, O_STAT) {
-        Err(err) => e(Err(err)) as c_int,
-        Ok(fd) => {
-            let res = fstat(fd as i32, buf);
-            let _ = syscall::close(fd);
-            res
-        }
-    }
-}
-
-pub unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int {
-    if domain != AF_INET {
-        errno = syscall::EAFNOSUPPORT;
-        return -1;
-    }
-    if protocol != 0 {
-        errno = syscall::EPROTONOSUPPORT;
-        return -1;
-    }
-
-    let mut flags = O_RDWR;
-    if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
-        kind &= !SOCK_NONBLOCK;
-        flags |= O_NONBLOCK;
-    }
-    if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
-        kind &= !SOCK_CLOEXEC;
-        flags |= O_CLOEXEC;
-    }
-
-    // The tcp: and udp: schemes allow using no path,
-    // and later specifying one using `dup`.
-    match kind {
-        SOCK_STREAM => e(syscall::open("tcp:", flags)) as c_int,
-        SOCK_DGRAM => e(syscall::open("udp:", flags)) as c_int,
-        _ => {
-            errno = syscall::EPROTOTYPE;
-            -1
-        }
-    }
-}
-
-pub fn socketpair(domain: c_int, kind: c_int, protocol: c_int, socket_vector: *mut c_int) -> c_int {
-    let _ = writeln!(
-        FileWriter(2),
-        "unimplemented: socketpair({}, {}, {}, {:p})",
-        domain,
-        kind,
-        protocol,
-        socket_vector
-    );
-    -1
-}
-
-pub fn tcgetattr(fd: c_int, out: *mut termios) -> c_int {
-    let dup = e(syscall::dup(fd as usize, b"termios"));
-    if dup == !0 {
-        return -1;
-    }
-
-    let read = e(syscall::read(dup, unsafe { slice::from_raw_parts_mut(
-        out as *mut u8,
-        mem::size_of::<termios>()
-    ) }));
-    let _ = syscall::close(dup);
-
-    if read == !0 {
-        return -1;
-    }
-    0
-}
-
-pub fn tcsetattr(fd: c_int, _act: c_int, value: *const termios) -> c_int {
-    let dup = e(syscall::dup(fd as usize, b"termios"));
-    if dup == !0 {
-        return -1;
-    }
-
-    let write = e(syscall::write(dup, unsafe { slice::from_raw_parts(
-        value as *const u8,
-        mem::size_of::<termios>()
-    ) }));
-    let _ = syscall::close(dup);
-
-    if write == !0 {
-        return -1;
-    }
-    0
-}
-
-pub fn times(out: *mut tms) -> clock_t {
-    let _ = writeln!(FileWriter(2), "unimplemented: times({:p})", out);
-    !0
-}
-
-pub fn umask(mask: mode_t) -> mode_t {
-    let _ = writeln!(FileWriter(2), "unimplemented: umask({})", mask);
-    0
-}
-
-pub fn unlink(path: *const c_char) -> c_int {
-    let path = unsafe { c_str(path) };
-    e(syscall::unlink(path)) as c_int
-}
-
-pub fn waitpid(mut pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
-    if pid == !0 {
-        pid = 0;
-    }
-    unsafe {
-        let mut temp: usize = 0;
-        let res = e(syscall::waitpid(pid as usize, &mut temp, options as usize));
-        if !stat_loc.is_null() {
-            *stat_loc = temp as c_int;
-        }
-        res as pid_t
-    }
-}
-
-pub fn write(fd: c_int, buf: &[u8]) -> ssize_t {
-    e(syscall::write(fd as usize, buf)) as ssize_t
-}
-
-pub fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
-    let mut redox_tp = unsafe { redox_timespec::from(&*tp) };
-    match e(syscall::clock_gettime(clk_id as usize, &mut redox_tp)) as c_int {
-        -1 => -1,
-        _ => {
-            unsafe {
-                (*tp).tv_sec = redox_tp.tv_sec;
-                (*tp).tv_nsec = redox_tp.tv_nsec as i64;
-            };
-            0
-        }
-    }
-}
diff --git a/src/platform/src/types.rs b/src/platform/types.rs
similarity index 99%
rename from src/platform/src/types.rs
rename to src/platform/types.rs
index bff380a3b873c3873486d2ae17477e0a9cf6a722..bcccee75fc42820e0b71c3adfa8902738f9a2c9f 100644
--- a/src/platform/src/types.rs
+++ b/src/platform/types.rs
@@ -257,5 +257,5 @@ pub struct termios {
     c_line: cc_t,
     c_cc: [cc_t; NCCS],
     __c_ispeed: speed_t,
-    __c_ospeed: speed_t
+    __c_ospeed: speed_t,
 }
diff --git a/src/pwd/Cargo.toml b/src/pwd/Cargo.toml
deleted file mode 100644
index 6273ec82edd9eeb65587238f78b044bbba01206c..0000000000000000000000000000000000000000
--- a/src/pwd/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "pwd"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-errno = { path = "../errno" }
-fcntl = { path = "../fcntl" }
-platform = { path = "../platform" }
diff --git a/src/pwd/build.rs b/src/pwd/build.rs
deleted file mode 100644
index 52d329c6ee267e2ca9559667eb7878d909132482..0000000000000000000000000000000000000000
--- a/src/pwd/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/pwd.h");
-}
diff --git a/src/semaphore/Cargo.toml b/src/semaphore/Cargo.toml
deleted file mode 100644
index a4e0960d99f1e296bca9c80704c3ec7f1121a283..0000000000000000000000000000000000000000
--- a/src/semaphore/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "semaphore"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/semaphore/build.rs b/src/semaphore/build.rs
deleted file mode 100644
index a5eba23b855e36c6ae35f2b94f007565fa7e5034..0000000000000000000000000000000000000000
--- a/src/semaphore/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/semaphore.h");
-}
diff --git a/src/setjmp/Cargo.toml b/src/setjmp/Cargo.toml
deleted file mode 100644
index 2826a4e54173cc544307218c6aee71c936c0e2a8..0000000000000000000000000000000000000000
--- a/src/setjmp/Cargo.toml
+++ /dev/null
@@ -1,4 +0,0 @@
-[package]
-name = "setjmp"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
diff --git a/src/sgtty/Cargo.toml b/src/sgtty/Cargo.toml
deleted file mode 100644
index d26f1d54ff0a8de863efbbd62840581cfa89c00a..0000000000000000000000000000000000000000
--- a/src/sgtty/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "sgtty"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
-sys_ioctl = { path = "../sys_ioctl" }
diff --git a/src/sgtty/build.rs b/src/sgtty/build.rs
deleted file mode 100644
index 7357fa95fb69b3273bba53c5c655eacde79b7662..0000000000000000000000000000000000000000
--- a/src/sgtty/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sgtty.h");
-}
diff --git a/src/signal/Cargo.toml b/src/signal/Cargo.toml
deleted file mode 100644
index c2a3bc938854c4c359793b45936202f24c2b2b9b..0000000000000000000000000000000000000000
--- a/src/signal/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "signal"
-version = "0.1.0"
-authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-errno = { path = "../errno" }
-platform = { path = "../platform" }
diff --git a/src/signal/build.rs b/src/signal/build.rs
deleted file mode 100644
index 011ccd1588c78697e4e700e9bbbd692ffbbd0f94..0000000000000000000000000000000000000000
--- a/src/signal/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/signal.h");
-}
diff --git a/src/start.rs b/src/start.rs
new file mode 100644
index 0000000000000000000000000000000000000000..02e739f82890fc25b97702b4bd86b1c6dcc38f74
--- /dev/null
+++ b/src/start.rs
@@ -0,0 +1,73 @@
+use alloc::Vec;
+use core::ptr;
+
+use header::stdio;
+use platform;
+use platform::types::*;
+use platform::{Pal, Sys};
+
+#[repr(C)]
+pub struct Stack {
+    argc: isize,
+    argv0: *const c_char,
+}
+
+impl Stack {
+    fn argc(&self) -> isize {
+        self.argc
+    }
+
+    fn argv(&self) -> *const *const c_char {
+        &self.argv0 as *const _
+    }
+
+    fn envp(&self) -> *const *const c_char {
+        unsafe { self.argv().offset(self.argc() + 1) }
+    }
+}
+
+#[inline(never)]
+#[no_mangle]
+pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! {
+    extern "C" {
+        fn main(argc: isize, argv: *const *const c_char, envp: *const *const c_char) -> c_int;
+    }
+
+    let argc = sp.argc();
+    let argv = sp.argv();
+
+    let envp = sp.envp();
+    let mut len = 0;
+    while *envp.offset(len) != ptr::null() {
+        len += 1;
+    }
+    platform::inner_environ = Vec::with_capacity(len as usize + 1);
+    for i in 0..len {
+        let mut item = *envp.offset(i);
+        let mut len = 0;
+        while *item.offset(len) != 0 {
+            len += 1;
+        }
+
+        let buf = platform::alloc(len as usize + 1) as *mut c_char;
+        for i in 0..=len {
+            *buf.offset(i) = *item.offset(i);
+        }
+        platform::inner_environ.push(buf);
+    }
+    platform::inner_environ.push(ptr::null_mut());
+    platform::environ = platform::inner_environ.as_mut_ptr();
+
+    // Initialize stdin/stdout/stderr, see https://github.com/rust-lang/rust/issues/51718
+    stdio::stdin = stdio::default_stdin.get();
+    stdio::stdout = stdio::default_stdout.get();
+    stdio::stderr = stdio::default_stderr.get();
+
+    Sys::exit(main(
+        argc,
+        argv,
+        // not envp, because programs like bash try to modify this *const*
+        // pointer :|
+        platform::environ as *const *const c_char,
+    ));
+}
diff --git a/src/stdio/Cargo.toml b/src/stdio/Cargo.toml
deleted file mode 100644
index 9931ddd6fd18cac764b8fe89420b377dc1fb5539..0000000000000000000000000000000000000000
--- a/src/stdio/Cargo.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-[package]
-name = "stdio"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-errno = { path = "../errno"}
-fcntl = { path = "../fcntl" }
-lazy_static = { version = "*", features = ["nightly", "spin_no_std"] }
-platform = { path = "../platform" }
-string = { path = "../string" }
-va_list = { path = "../../va_list", features = ["no_std"] }
diff --git a/src/stdio/build.rs b/src/stdio/build.rs
deleted file mode 100644
index 1689fbc5659a5c14d062b8e7cb398160e6f76861..0000000000000000000000000000000000000000
--- a/src/stdio/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/stdio.h");
-}
diff --git a/src/stdlib/Cargo.toml b/src/stdlib/Cargo.toml
deleted file mode 100644
index 61b603425d0dce0e8e64f5b422b2b127e897e05a..0000000000000000000000000000000000000000
--- a/src/stdlib/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-name = "stdlib"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
-ctype = { path = "../ctype" }
-errno = { path = "../errno" }
-rand = { version = "0.5.2", default-features = false }
-string = { path = "../string" }
-time = { path = "../time" }
-unistd = { path = "../unistd" }
-wchar = { path = "../wchar" }
-fcntl = { path = "../fcntl" }
diff --git a/src/stdlib/build.rs b/src/stdlib/build.rs
deleted file mode 100644
index 44430ddae61b9b13460de97841a4903800f6b52e..0000000000000000000000000000000000000000
--- a/src/stdlib/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/stdlib.h");
-}
diff --git a/src/string/Cargo.toml b/src/string/Cargo.toml
deleted file mode 100644
index 69a3f03d745c073286f4f85b055c7585c1c0ea99..0000000000000000000000000000000000000000
--- a/src/string/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "string"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-errno = { path = "../errno" }
-platform = { path = "../platform" }
-signal = { path = "../signal" }
diff --git a/src/string/build.rs b/src/string/build.rs
deleted file mode 100644
index ce8ad27c5eab899b202f37d77dc68497dc5d22c7..0000000000000000000000000000000000000000
--- a/src/string/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/string.h");
-}
diff --git a/src/strings/Cargo.toml b/src/strings/Cargo.toml
deleted file mode 100644
index 24e75867a8f66eaeac96f93536ea162ab4297254..0000000000000000000000000000000000000000
--- a/src/strings/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "strings"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/strings/build.rs b/src/strings/build.rs
deleted file mode 100644
index 574237034f7eb4648bcad866510068b950cd612d..0000000000000000000000000000000000000000
--- a/src/strings/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/strings.h");
-}
diff --git a/src/sys_file/Cargo.toml b/src/sys_file/Cargo.toml
deleted file mode 100644
index 1853666e93b14d74899f8d5f6600f38ab44075a2..0000000000000000000000000000000000000000
--- a/src/sys_file/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-name = "sys_file"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/sys_file/build.rs b/src/sys_file/build.rs
deleted file mode 100644
index 1009eaeebbc9f6cfe10e902e95529492e91fe529..0000000000000000000000000000000000000000
--- a/src/sys_file/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/file.h");
-}
diff --git a/src/sys_ioctl/Cargo.toml b/src/sys_ioctl/Cargo.toml
deleted file mode 100644
index 6f868b8c34dbfbf52c266cf3cf1d71c16d8a99a7..0000000000000000000000000000000000000000
--- a/src/sys_ioctl/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-name = "sys_ioctl"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/sys_ioctl/build.rs b/src/sys_ioctl/build.rs
deleted file mode 100644
index e82221d0b378d1ced02c2478d49de5b34aaa3b0c..0000000000000000000000000000000000000000
--- a/src/sys_ioctl/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/ioctl.h");
-}
diff --git a/src/sys_mman/Cargo.toml b/src/sys_mman/Cargo.toml
deleted file mode 100644
index 4f7c08b1e45e2bceabbe71ecf231df64e090d645..0000000000000000000000000000000000000000
--- a/src/sys_mman/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "sys_mman"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/sys_mman/build.rs b/src/sys_mman/build.rs
deleted file mode 100644
index 19d21bd491f769e36dd29ade3296f5e3263e1216..0000000000000000000000000000000000000000
--- a/src/sys_mman/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/mman.h");
-}
diff --git a/src/sys_resource/Cargo.toml b/src/sys_resource/Cargo.toml
deleted file mode 100644
index a1bea8424e5776df698d5222492d6feb034e4fb0..0000000000000000000000000000000000000000
--- a/src/sys_resource/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "sys_resource"
-version = "0.1.0"
-authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
-sys_time = { path = "../sys_time" }
diff --git a/src/sys_resource/build.rs b/src/sys_resource/build.rs
deleted file mode 100644
index a8c03a627ed6139aafd260a51a5e0ee664f9ab09..0000000000000000000000000000000000000000
--- a/src/sys_resource/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/resource.h");
-}
diff --git a/src/sys_select/Cargo.toml b/src/sys_select/Cargo.toml
deleted file mode 100644
index 09d7dcae7c54d3e3311a66891daeffc61169580e..0000000000000000000000000000000000000000
--- a/src/sys_select/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-name = "sys_select"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/sys_select/build.rs b/src/sys_select/build.rs
deleted file mode 100644
index 5314b67db984fce2c7a9996ffdc006cdd6338328..0000000000000000000000000000000000000000
--- a/src/sys_select/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/select.h");
-}
diff --git a/src/sys_socket/Cargo.toml b/src/sys_socket/Cargo.toml
deleted file mode 100644
index 0c3cc667e1c79cdb34280a0d6a151d86571e6128..0000000000000000000000000000000000000000
--- a/src/sys_socket/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "sys_socket"
-version = "0.1.0"
-authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/sys_socket/build.rs b/src/sys_socket/build.rs
deleted file mode 100644
index ad891ecb68eb3bbc69e6a63579c2f9770976317b..0000000000000000000000000000000000000000
--- a/src/sys_socket/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/socket.h");
-}
diff --git a/src/sys_stat/Cargo.toml b/src/sys_stat/Cargo.toml
deleted file mode 100644
index 4d04bee7d8496f13ac4c91f7a143b90636809880..0000000000000000000000000000000000000000
--- a/src/sys_stat/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "sys_stat"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/sys_stat/build.rs b/src/sys_stat/build.rs
deleted file mode 100644
index 0d79f3cce8e33284573c5102281cdec82917729a..0000000000000000000000000000000000000000
--- a/src/sys_stat/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/stat.h");
-}
diff --git a/src/sys_time/Cargo.toml b/src/sys_time/Cargo.toml
deleted file mode 100644
index 20b3ac9c6f4e5bfa7d2940dd18b05c893388e062..0000000000000000000000000000000000000000
--- a/src/sys_time/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "sys_time"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/sys_time/build.rs b/src/sys_time/build.rs
deleted file mode 100644
index 9d087ef9c1e3c50e9f1052194a6be433f1d59634..0000000000000000000000000000000000000000
--- a/src/sys_time/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/time.h");
-}
diff --git a/src/sys_times/Cargo.toml b/src/sys_times/Cargo.toml
deleted file mode 100644
index 31f1646396f8600eec2749dda168cde3325fba62..0000000000000000000000000000000000000000
--- a/src/sys_times/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-name = "sys_times"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/sys_times/build.rs b/src/sys_times/build.rs
deleted file mode 100644
index d93c16000a4bcdb2c3545b2b01205f21dcf50668..0000000000000000000000000000000000000000
--- a/src/sys_times/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/times.h");
-}
diff --git a/src/sys_un/Cargo.toml b/src/sys_un/Cargo.toml
deleted file mode 100644
index be0e821f659f03c34bc57f88b0586c682984d3cc..0000000000000000000000000000000000000000
--- a/src/sys_un/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "sys_un"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
-sys_socket = { path = "../sys_socket" }
diff --git a/src/sys_un/build.rs b/src/sys_un/build.rs
deleted file mode 100644
index fcf990a9ffc55d17e976d7e06a41f1f26d6abd37..0000000000000000000000000000000000000000
--- a/src/sys_un/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/un.h");
-}
diff --git a/src/sys_utsname/Cargo.toml b/src/sys_utsname/Cargo.toml
deleted file mode 100644
index 69edfcfea930b5e47b44a8a990d5815e88255479..0000000000000000000000000000000000000000
--- a/src/sys_utsname/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "sys_utsname"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[target.'cfg(target_os = "linux")'.dependencies]
-platform = { path = "../platform" }
diff --git a/src/sys_utsname/build.rs b/src/sys_utsname/build.rs
deleted file mode 100644
index 2f45974eee1e6de46fcc395093075039ef4a77a6..0000000000000000000000000000000000000000
--- a/src/sys_utsname/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/utsname.h");
-}
diff --git a/src/sys_wait/Cargo.toml b/src/sys_wait/Cargo.toml
deleted file mode 100644
index 44250ca7f724f152dccf672ad2615bcaf3db4b70..0000000000000000000000000000000000000000
--- a/src/sys_wait/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "sys_wait"
-version = "0.1.0"
-authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
-sys_resource = { path = "../sys_resource" }
diff --git a/src/sys_wait/build.rs b/src/sys_wait/build.rs
deleted file mode 100644
index 53a786af45a1777d808df37b585f122fa42701fb..0000000000000000000000000000000000000000
--- a/src/sys_wait/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/sys/wait.h");
-}
diff --git a/src/template/Cargo.toml b/src/template/Cargo.toml
deleted file mode 100644
index 844bcb55eb2106f1403f361011054514d502fac4..0000000000000000000000000000000000000000
--- a/src/template/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "template"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/template/build.rs b/src/template/build.rs
deleted file mode 100644
index 35b5d3bd872438fabe697c71cfab5de13dac60bc..0000000000000000000000000000000000000000
--- a/src/template/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-      .expect("failed to generate bindings")
-      .write_to_file("../../target/include/template.h");
-}
diff --git a/src/termios/Cargo.toml b/src/termios/Cargo.toml
deleted file mode 100644
index 4fa692f2fff4b6d52866576c2a98fa27751a8412..0000000000000000000000000000000000000000
--- a/src/termios/Cargo.toml
+++ /dev/null
@@ -1,10 +0,0 @@
-[package]
-name = "termios"
-version = "0.1.0"
-authors = ["jD91mZM2 <me@krake.one>"]
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/termios/build.rs b/src/termios/build.rs
deleted file mode 100644
index da15d4a9b482a03acf8a3277964660e5e4ea029c..0000000000000000000000000000000000000000
--- a/src/termios/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-      .expect("failed to generate bindings")
-      .write_to_file("../../target/include/termios.h");
-}
diff --git a/src/time/Cargo.toml b/src/time/Cargo.toml
deleted file mode 100644
index 1521354550ce2114a2716198fd2bc30a08321b29..0000000000000000000000000000000000000000
--- a/src/time/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "time"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
-errno = { path = "../errno" }
diff --git a/src/time/build.rs b/src/time/build.rs
deleted file mode 100644
index 7bc136af55e270baf7bd3da72f96c02bfc734916..0000000000000000000000000000000000000000
--- a/src/time/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/time.h");
-}
diff --git a/src/todo/wctype/lib.rs b/src/todo/wctype/lib.rs
deleted file mode 100644
index c0666b6d0920b8ebccd271a1c519251eb7f212e3..0000000000000000000000000000000000000000
--- a/src/todo/wctype/lib.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-// #[no_mangle]
-pub extern "C" fn iswalnum(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswalpha(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswcntrl(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswdigit(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswgraph(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswlower(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswprint(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswpunct(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswspace(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswupper(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswxdigit(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswblank(wc: wint_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn wctype(property: *const libc::c_char, locale: locale_t) -> wctype_t {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn iswctype(wc: wint_t, desc: wctype_t, locale: locale_t) -> libc::c_int {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn towlower(wc: wint_t, locale: locale_t) -> wint_t {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn towupper(wc: wint_t, locale: locale_t) -> wint_t {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn wctrans(property: *const libc::c_char, locale: locale_t) -> wctrans_t {
-    unimplemented!();
-}
-
-// #[no_mangle]
-pub extern "C" fn towctrans(wc: wint_t, desc: wctrans_t, locale: locale_t) -> wint_t {
-    unimplemented!();
-}
diff --git a/src/unistd/Cargo.toml b/src/unistd/Cargo.toml
deleted file mode 100644
index 138a8209f9c8ec342ff80d0aa8888487b3e7eff2..0000000000000000000000000000000000000000
--- a/src/unistd/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "unistd"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-errno = { path = "../errno" }
-platform = { path = "../platform" }
-stdio = { path = "../stdio" }
-string = { path = "../string" }
-sys_time = { path = "../sys_time" }
diff --git a/src/unistd/build.rs b/src/unistd/build.rs
deleted file mode 100644
index ca19204932d22489a046b27764f9d39ca22fd428..0000000000000000000000000000000000000000
--- a/src/unistd/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/unistd.h");
-}
diff --git a/src/utime/Cargo.toml b/src/utime/Cargo.toml
deleted file mode 100644
index 81bcd75cb3cfc2d9d77b44d1c5bcb09b82cceda8..0000000000000000000000000000000000000000
--- a/src/utime/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "utime"
-version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/utime/build.rs b/src/utime/build.rs
deleted file mode 100644
index eb7b3b921bda486375eaaf41dc15cd0b687b3c0f..0000000000000000000000000000000000000000
--- a/src/utime/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/utime.h");
-}
diff --git a/src/wchar/Cargo.toml b/src/wchar/Cargo.toml
deleted file mode 100644
index 97e412f20d966296a739e19c3859e811782901b9..0000000000000000000000000000000000000000
--- a/src/wchar/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-name = "wchar"
-version = "0.1.0"
-authors = ["Stephan Vedder <stephan.vedder@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[features]
-str_internals = []
-
-[dependencies]
-platform = { path = "../platform" }
-stdio = { path = "../stdio" }
-errno = { path = "../errno" }
-time = { path = "../time" }
-va_list = { path = "../../va_list", features = ["no_std"] }
\ No newline at end of file
diff --git a/src/wchar/build.rs b/src/wchar/build.rs
deleted file mode 100644
index 5b64a17833ecbbf57ae8892cffdbceb1f2cc1fe8..0000000000000000000000000000000000000000
--- a/src/wchar/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/wchar.h");
-}
diff --git a/src/wctype/Cargo.toml b/src/wctype/Cargo.toml
deleted file mode 100644
index abb1ba562f7fca5ffa268b8361befb612aea66f0..0000000000000000000000000000000000000000
--- a/src/wctype/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "wctype"
-version = "0.1.0"
-authors = ["Dan Robertson <danlrobertson89@gmail.com>"]
-build = "build.rs"
-
-[build-dependencies]
-cbindgen = { path = "../../cbindgen" }
-
-[dependencies]
-platform = { path = "../platform" }
diff --git a/src/wctype/build.rs b/src/wctype/build.rs
deleted file mode 100644
index d0b0702ceaf7025f58b141e3c71e3bb695727ab4..0000000000000000000000000000000000000000
--- a/src/wctype/build.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-extern crate cbindgen;
-
-use std::{env, fs};
-
-fn main() {
-    let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
-    fs::create_dir_all("../../target/include").expect("failed to create include directory");
-    cbindgen::generate(crate_dir)
-        .expect("failed to generate bindings")
-        .write_to_file("../../target/include/wctype.h");
-}