diff --git a/Cargo.lock b/Cargo.lock
index 035268ce4d3bf1eb3acd247dd723cd3917235c54..24e95adbbf64f692eb0734859233a011fcae6f29 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -199,6 +199,7 @@ dependencies = [
  "compiler_builtins 0.1.0 (git+https://github.com/rust-lang-nursery/compiler-builtins.git)",
  "fcntl 0.1.0",
  "platform 0.1.0",
+ "string 0.1.0",
  "unistd 0.1.0",
 ]
 
@@ -364,6 +365,14 @@ dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "string"
+version = "0.1.0"
+dependencies = [
+ "cbindgen 0.5.0",
+ "platform 0.1.0",
+]
+
 [[package]]
 name = "strsim"
 version = "0.7.0"
diff --git a/Cargo.toml b/Cargo.toml
index ac7c7f864d4ec51156557669c8176fab3cca95bb..15ad2717e7ad6b06ba0bd9b545a9660554920bd4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,7 @@ members = ["crt0"]
 compiler_builtins = { git = "https://github.com/rust-lang-nursery/compiler-builtins.git", default-features = false, features = ["mem"] }
 platform = { path = "platform" }
 fcntl = { path = "fcntl" }
+string = { path = "string" }
 unistd = { path = "unistd" }
 
 [profile.dev]
diff --git a/crt0/src/lib.rs b/crt0/src/lib.rs
index 47ff4842987bccb4da0c6a6efe12dfcb08de59ac..c16d2d7449f25d4230e7e5b7b6c1429ccbdade06 100644
--- a/crt0/src/lib.rs
+++ b/crt0/src/lib.rs
@@ -17,18 +17,37 @@ pub unsafe extern "C" fn _start() {
         :
         :
         :
-        : "intel"
+        : "intel", "volatile"
     );
 }
 
+#[repr(C)]
+pub struct Stack {
+    argc: isize,
+    argv0: *const u8,
+}
+
+impl Stack {
+    fn argc(&self) -> isize {
+        self.argc
+    }
+
+    fn argv(&self) -> *const *const u8 {
+        &self.argv0 as *const *const u8
+    }
+}
+
 #[inline(never)]
 #[no_mangle]
-pub unsafe extern "C" fn _start_rust(sp: usize) -> ! {
+pub unsafe extern "C" fn _start_rust(sp: &'static Stack) -> ! {
     extern "C" {
-        fn main(argc: c_int, argv: *const *const c_char) -> c_int;
+        fn main(argc: isize, argv: *const *const u8) -> c_int;
     }
 
-    platform::exit(main(0, 0 as *const *const c_char));
+    let argc = sp.argc();
+    let argv = sp.argv();
+
+    platform::exit(main(argc, argv));
 }
 
 #[lang = "panic_fmt"]
diff --git a/include/stddef.h b/include/stddef.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa0bc7daf528f082aab9958c1054fa0f716e9a03
--- /dev/null
+++ b/include/stddef.h
@@ -0,0 +1,12 @@
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+#define NULL 0
+
+typedef signed long long ptrdiff_t;
+
+typedef unsigned char wchar_t;
+
+typedef unsigned long long size_t;
+
+#endif /* _STDDEF_H */
diff --git a/include/sys/types.h b/include/sys/types.h
index 3a65d4d00ddd88743e03f6bbbc211fa00944b141..6f770aa64c19aa215a00a8c898ad6a1d66a68c45 100644
--- a/include/sys/types.h
+++ b/include/sys/types.h
@@ -10,7 +10,6 @@ typedef long off_t;
 
 typedef int pid_t;
 
-typedef unsigned long size_t;
 typedef long ssize_t;
 
 typedef int useconds_t;
diff --git a/src/lib.rs b/src/lib.rs
index d49813d1e7e121f51b42fbe4f7a301c446696906..5eda04b6e8575b338f54a25dc0be0055718c5722 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,11 +5,9 @@ extern crate compiler_builtins;
 extern crate platform;
 
 extern crate fcntl;
+extern crate string;
 extern crate unistd;
 
-pub use fcntl::*;
-pub use unistd::*;
-
 use core::fmt;
 
 struct PanicWriter;
diff --git a/string/Cargo.toml b/string/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..2e110e97a9a59a304a24ddeb6bbfe6dac7946792
--- /dev/null
+++ b/string/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "string"
+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/string/build.rs b/string/build.rs
new file mode 100644
index 0000000000000000000000000000000000000000..1aca9f78199a6c6a06eab01a8d6a5d8369b81ef5
--- /dev/null
+++ b/string/build.rs
@@ -0,0 +1,11 @@
+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/string/cbindgen.toml b/string/cbindgen.toml
new file mode 100644
index 0000000000000000000000000000000000000000..b7762a3faa288497fd2c964fbdbdb65954f68db3
--- /dev/null
+++ b/string/cbindgen.toml
@@ -0,0 +1,6 @@
+sys_includes = ["stddef.h"]
+include_guard = "_STRING_H"
+language = "C"
+
+[enum]
+prefix_with_name = true
diff --git a/string/src/lib.rs b/string/src/lib.rs
new file mode 100644
index 0000000000000000000000000000000000000000..12b4ea3dbc03a320fc7be349ad1ea6fe76055f50
--- /dev/null
+++ b/string/src/lib.rs
@@ -0,0 +1,28 @@
+//! string implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html
+
+#![no_std]
+
+extern crate platform;
+
+use platform::types::*;
+
+#[no_mangle]
+pub unsafe extern "C" fn strlen(s: *const c_char) -> size_t {
+    let mut size = 0;
+
+    loop {
+        if *s.offset(size) == 0 {
+            break;
+        }
+        size += 1;
+    }
+
+    size as size_t
+}
+
+/*
+#[no_mangle]
+pub extern "C" fn func(args) -> c_int {
+    unimplemented!();
+}
+*/
diff --git a/tests/.gitignore b/tests/.gitignore
index 0348d78de95bbda30622e9b2852fc236b42ca4fa..5c6fa79146ac30c76feaebe8d249a270c4c997b5 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,3 +1,4 @@
+/args
 /create
 /create.out
 /write
diff --git a/tests/Makefile b/tests/Makefile
index 1f638014e5e6d860398be7f516029203c501e304..dfbab932985d83e9033aae60f732b75e1492c412 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,14 +1,15 @@
 BINS=\
+	args \
 	create \
 	write
 
 all: $(BINS)
 
 clean:
-	rm -f $(BINS)
+	rm -f $(BINS) *.out
 
 run: $(BINS)
-	for bin in $(BINS); do echo "\\033[1m$${bin}\\033[0m"; ./$${bin}; done
+	for bin in $(BINS); do echo "\\033[1m$${bin}\\033[0m"; ./$${bin} test args; done
 
 %: %.c
 	gcc -nostdinc -nostdlib -I ../include -I ../target/include ../target/debug/libcrt0.a $< ../target/debug/libc.a -o $@
diff --git a/tests/args.c b/tests/args.c
new file mode 100644
index 0000000000000000000000000000000000000000..70686673e49c8d11e76c799c23df7e4eb41807ba
--- /dev/null
+++ b/tests/args.c
@@ -0,0 +1,11 @@
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+    int i;
+    for(i = 0; i < argc; i++) {
+        write(STDOUT_FILENO, argv[i], strlen(argv[i]));
+        write(STDOUT_FILENO, " ", 1);
+    }
+    write(STDOUT_FILENO, "\n", 1);
+}
diff --git a/unistd/cbindgen.toml b/unistd/cbindgen.toml
index 259e4fadf236a580c35a4e995ae39e362322c873..cf1de270d4e51c0643f3858b8327402b09fcdd1e 100644
--- a/unistd/cbindgen.toml
+++ b/unistd/cbindgen.toml
@@ -1,4 +1,4 @@
-sys_includes = ["stdint.h", "sys/types.h"]
+sys_includes = ["stddef.h", "stdint.h", "sys/types.h"]
 include_guard = "_UNISTD_H"
 language = "C"
 
diff --git a/unistd/src/lib.rs b/unistd/src/lib.rs
index de23c114485ae6f07c777d300f0b3d157012a6cb..66905beae6564fe1b05b95b962c00fa201242396 100644
--- a/unistd/src/lib.rs
+++ b/unistd/src/lib.rs
@@ -6,8 +6,6 @@ extern crate platform;
 
 pub use platform::types::*;
 
-pub const NULL: c_int = 0;
-
 pub const R_OK: c_int = 1;
 pub const W_OK: c_int = 2;
 pub const X_OK: c_int = 4;
@@ -101,20 +99,20 @@ pub extern "C" fn encrypt(block: [c_char; 64], edflag: c_int) {
     unimplemented!();
 }
 
-#[no_mangle]
-pub extern "C" fn execl(path: *const c_char, arg0: *const c_char /* TODO: , mut args: ... */) -> c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn execle(path: *const c_char, arg0: *const c_char /* TODO: , mut args: ... */) -> c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn execlp(file: *const c_char, arg0: *const c_char /* TODO: , mut args: ... */) -> c_int {
-    unimplemented!();
-}
+// #[no_mangle]
+// pub extern "C" fn execl(path: *const c_char, arg0: *const c_char /* TODO: , mut args: ... */) -> c_int {
+//     unimplemented!();
+// }
+//
+// #[no_mangle]
+// pub extern "C" fn execle(path: *const c_char, arg0: *const c_char /* TODO: , mut args: ... */) -> c_int {
+//     unimplemented!();
+// }
+//
+// #[no_mangle]
+// pub extern "C" fn execlp(file: *const c_char, arg0: *const c_char /* TODO: , mut args: ... */) -> c_int {
+//     unimplemented!();
+// }
 
 #[no_mangle]
 pub extern "C" fn execv(path: *const c_char, argv: *const *mut c_char) -> c_int {