Paul Sajna 7 years ago
parent
commit
608a6fcfad

+ 3 - 0
.gitmodules

@@ -7,3 +7,6 @@
 [submodule "ralloc"]
 	path = ralloc
 	url = https://github.com/redox-os/ralloc.git
+[submodule "va_list"]
+	path = va_list
+	url = https://github.com/redox-os/va_list-rs.git

+ 28 - 3
Cargo.lock

@@ -97,6 +97,11 @@ name = "fuchsia-zircon-sys"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "gcc"
+version = "0.3.54"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "grp"
 version = "0.1.0"
@@ -140,6 +145,14 @@ dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "mman"
+version = "0.1.0"
+dependencies = [
+ "cbindgen 0.5.0",
+ "platform 0.1.0",
+]
+
 [[package]]
 name = "num-traits"
 version = "0.2.1"
@@ -177,6 +190,7 @@ dependencies = [
 name = "platform"
 version = "0.1.0"
 dependencies = [
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -197,6 +211,7 @@ dependencies = [
 name = "ralloc_shim"
 version = "0.1.1"
 dependencies = [
+ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -231,6 +246,7 @@ dependencies = [
  "ctype 0.1.0",
  "fcntl 0.1.0",
  "grp 0.1.0",
+ "mman 0.1.0",
  "platform 0.1.0",
  "stdio 0.1.0",
  "stdlib 0.1.0",
@@ -411,7 +427,7 @@ version = "0.1.0"
 dependencies = [
  "cbindgen 0.5.0",
  "platform 0.1.0",
- "va_list 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "va_list 0.1.0",
 ]
 
 [[package]]
@@ -529,7 +545,16 @@ dependencies = [
 [[package]]
 name = "va_list"
 version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "va_list-helper 0.0.2",
+]
+
+[[package]]
+name = "va_list-helper"
+version = "0.0.2"
+dependencies = [
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "vec_map"
@@ -575,6 +600,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "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 gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
 "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)" = "56aebce561378d99a0bb578f8cb15b6114d2a1814a6c7949bbe646d968bb4fa9"
@@ -618,7 +644,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "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 va_list 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7365862faee55ed0dbc112491aa5f0451ca01bf98afcc6463183b5aaa5bd3128"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"

+ 1 - 0
Cargo.toml

@@ -17,6 +17,7 @@ ctype = { path = "src/ctype" }
 fcntl = { path = "src/fcntl" }
 grp = { path = "src/grp" }
 semaphore = { path = "src/semaphore" }
+mman = { path = "src/mman" }
 stdio = { path = "src/stdio" }
 stdlib = { path = "src/stdlib" }
 string = { path = "src/string" }

+ 4 - 1
platform/Cargo.toml

@@ -3,5 +3,8 @@ name = "platform"
 version = "0.1.0"
 authors = ["Jeremy Soller <[email protected]>"]
 
-[dependencies]
+[target.'cfg(target_os = "linux")'.dependencies]
 sc = "0.2"
+
+[target.'cfg(target_os = "redox")'.dependencies]
+redox_syscall = "0.1"

+ 16 - 1
platform/src/lib.rs

@@ -20,7 +20,22 @@ pub mod types;
 
 use core::fmt;
 
-use types::c_int;
+use types::*;
+
+pub unsafe fn c_str(s: *const c_char) -> &'static [u8] {
+    use core::slice;
+
+    let mut size = 0;
+
+    loop {
+        if *s.offset(size) == 0 {
+            break;
+        }
+        size += 1;
+    }
+
+    slice::from_raw_parts(s as *const u8, size as usize)
+}
 
 pub struct FileWriter(pub c_int);
 

+ 18 - 2
platform/src/redox/mod.rs

@@ -1,8 +1,24 @@
+use syscall;
+
+use c_str;
+use types::*;
+
+pub fn close(fd: c_int) -> c_int {
+    syscall::close(fd as usize);
+    0
+}
+
 pub fn exit(status: c_int) -> ! {
-    syscall::exit(status);
+    syscall::exit(status as usize);
+    loop {}
+}
+
+pub fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int {
+    let path = unsafe { c_str(path) };
+    syscall::open(path, (oflag as usize) | (mode as usize)).unwrap() as c_int
 }
 
 pub fn write(fd: c_int, buf: &[u8]) -> ssize_t {
-    syscall::write(fd, buf);
+    syscall::write(fd as usize, buf);
     buf.len() as ssize_t
 }

+ 1 - 1
ralloc

@@ -1 +1 @@
-Subproject commit b521bac28702de86c7c4eef9641ec83c6ac38224
+Subproject commit 31b781a287748c10671a6c7e4415093d2dd4df4a

+ 11 - 0
src/mman/Cargo.toml

@@ -0,0 +1,11 @@
+[package]
+name = "mman"
+version = "0.1.0"
+authors = ["Jeremy Soller <[email protected]>"]
+build = "build.rs"
+
+[build-dependencies]
+cbindgen = { path = "../../cbindgen" }
+
+[dependencies]
+platform = { path = "../../platform" }

+ 11 - 0
src/mman/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/mman.h");
+}

+ 6 - 0
src/mman/cbindgen.toml

@@ -0,0 +1,6 @@
+sys_includes = []
+include_guard = "_MMAN_H"
+language = "C"
+
+[enum]
+prefix_with_name = true

+ 66 - 0
src/mman/src/lib.rs

@@ -0,0 +1,66 @@
+#![no_std]
+
+extern crate platform;
+
+use platform::types::*;
+
+#[no_mangle]
+pub extern "C" fn mlock(addr: *const c_void, len: usize) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn mlockall(flags: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn mmap(
+    addr: *mut c_void,
+    len: usize,
+    prot: c_int,
+    flags: c_int,
+    fildes: c_int,
+    off: off_t,
+) -> *mut c_void {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn mprotect(addr: *mut c_void, len: usize, prot: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn msync(addr: *mut c_void, len: usize, flags: c_int) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn munlock(addr: *const c_void, len: usize) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn munlockall() -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn munmap(addr: *mut c_void, len: usize) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn shm_open(
+    name: *const c_char,
+    oflag: c_int,
+    mode: mode_t,
+) -> c_int {
+    unimplemented!();
+}
+
+#[no_mangle]
+pub extern "C" fn shm_unlink(name: *const c_char) -> c_int {
+    unimplemented!();
+}

+ 1 - 1
src/stdio/Cargo.toml

@@ -9,4 +9,4 @@ cbindgen = { path = "../../cbindgen" }
 
 [dependencies]
 platform = { path = "../../platform" }
-va_list = { version = "0.1", features = ["no_std"] }
+va_list = { path = "../../va_list", features = ["no_std"] }

+ 1 - 2
src/stdlib/src/lib.rs

@@ -116,8 +116,7 @@ pub unsafe extern "C" fn exit(status: c_int) {
     use core::mem;
 
     for i in (0..ATEXIT_FUNCS.len()).rev() {
-        if ATEXIT_FUNCS[i] != None {
-            let func = mem::transmute::<usize, extern "C" fn()>(ATEXIT_FUNCS[i].unwrap());
+        if let Some(func) = ATEXIT_FUNCS[i] {
             (func)();
         }
     }

+ 1 - 10
src/string/src/lib.rs

@@ -104,16 +104,7 @@ pub extern "C" fn strerror(errnum: c_int) -> *mut c_char {
 
 #[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
+    platform::c_str(s).len() as size_t
 }
 
 #[no_mangle]

+ 0 - 60
src/todo/mman/lib.rs

@@ -1,60 +0,0 @@
-#[no_mangle]
-pub extern "C" fn mlock(addr: *const libc::c_void, len: usize) -> libc::c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn mlockall(flags: libc::c_int) -> libc::c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn mmap(
-    addr: *mut libc::c_void,
-    len: usize,
-    prot: libc::c_int,
-    flags: libc::c_int,
-    fildes: libc::c_int,
-    off: off_t,
-) -> *mut libc::c_void {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn mprotect(addr: *mut libc::c_void, len: usize, prot: libc::c_int) -> libc::c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn msync(addr: *mut libc::c_void, len: usize, flags: libc::c_int) -> libc::c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn munlock(addr: *const libc::c_void, len: usize) -> libc::c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn munlockall() -> libc::c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn munmap(addr: *mut libc::c_void, len: usize) -> libc::c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn shm_open(
-    name: *const libc::c_char,
-    oflag: libc::c_int,
-    mode: mode_t,
-) -> libc::c_int {
-    unimplemented!();
-}
-
-#[no_mangle]
-pub extern "C" fn shm_unlink(name: *const libc::c_char) -> libc::c_int {
-    unimplemented!();
-}

+ 22 - 0
src/todo/oldlib/dns/answer.rs

@@ -0,0 +1,22 @@
+// Copyright 2016 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::String;
+use alloc::Vec;
+
+#[derive(Clone, Debug)]
+pub struct DnsAnswer {
+    pub name: String,
+    pub a_type: u16,
+    pub a_class: u16,
+    pub ttl_a: u16,
+    pub ttl_b: u16,
+    pub data: Vec<u8>
+}

+ 210 - 0
src/todo/oldlib/dns/mod.rs

@@ -0,0 +1,210 @@
+// Copyright 2016 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.
+
+pub use self::answer::DnsAnswer;
+pub use self::query::DnsQuery;
+
+use core::slice;
+use core::u16;
+use alloc::String;
+use alloc::Vec;
+
+mod answer;
+mod query;
+
+#[allow(non_camel_case_types)]
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(packed)]
+pub struct n16 {
+    inner: u16
+}
+
+impl n16 {
+    pub fn as_bytes(&self) -> &[u8] {
+        unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) }
+    }
+
+    pub fn from_bytes(bytes: &[u8]) -> Self {
+        n16 {
+            inner: unsafe { slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len()/2)[0] }
+        }
+    }
+}
+
+impl From<u16> for n16 {
+    fn from(value: u16) -> Self {
+        n16 {
+            inner: value.to_be()
+        }
+    }
+}
+
+impl From<n16> for u16 {
+    fn from(value: n16) -> Self {
+        u16::from_be(value.inner)
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct Dns {
+    pub transaction_id: u16,
+    pub flags: u16,
+    pub queries: Vec<DnsQuery>,
+    pub answers: Vec<DnsAnswer>
+}
+
+impl Dns {
+    pub fn compile(&self) -> Vec<u8> {
+        let mut data = Vec::new();
+
+        macro_rules! push_u8 {
+            ($value:expr) => {
+                data.push($value);
+            };
+        };
+
+        macro_rules! push_n16 {
+            ($value:expr) => {
+                data.extend_from_slice(n16::from($value).as_bytes());
+            };
+        };
+
+        push_n16!(self.transaction_id);
+        push_n16!(self.flags);
+        push_n16!(self.queries.len() as u16);
+        push_n16!(self.answers.len() as u16);
+        push_n16!(0);
+        push_n16!(0);
+
+        for query in self.queries.iter() {
+            for part in query.name.split('.') {
+                push_u8!(part.len() as u8);
+                data.extend_from_slice(part.as_bytes());
+            }
+            push_u8!(0);
+            push_n16!(query.q_type);
+            push_n16!(query.q_class);
+        }
+
+        data
+    }
+
+    pub fn parse(data: &[u8]) -> Result<Self, String> {
+        let name_ind = 0b11000000;
+        let mut i = 0;
+
+        macro_rules! pop_u8 {
+            () => {
+                {
+                    i += 1;
+                    if i > data.len() {
+                        return Err(format!("{}: {}: pop_u8", file!(), line!()));
+                    }
+                    data[i - 1]
+                }
+            };
+        };
+
+        macro_rules! pop_n16 {
+            () => {
+                {
+                    i += 2;
+                    if i > data.len() {
+                        return Err(format!("{}: {}: pop_n16", file!(), line!()));
+                    }
+                    u16::from(n16::from_bytes(&data[i - 2 .. i]))
+                }
+            };
+        };
+
+        macro_rules! pop_data {
+            () => {
+                {
+                    let mut data = Vec::new();
+
+                    let data_len = pop_n16!();
+                    for _data_i in 0..data_len {
+                        data.push(pop_u8!());
+                    }
+
+                    data
+                }
+            };
+        };
+
+        macro_rules! pop_name {
+            () => {
+                {
+                    let mut name = String::new();
+                    let old_i = i;
+
+                    loop {
+                        let name_len = pop_u8!();
+                        if name_len & name_ind == name_ind {
+                            i -= 1;
+                            i = (pop_n16!() - ((name_ind as u16) << 8)) as usize;
+                            continue;
+                        }
+                        if name_len == 0 {
+                            break;
+                        }
+                        if ! name.is_empty() {
+                            name.push('.');
+                        }
+                        for _name_i in 0..name_len {
+                            name.push(pop_u8!() as char);
+                        }
+                    }
+
+                    if i <= old_i {
+                        i = old_i + 2;
+                    }
+
+                    name
+                }
+            };
+        };
+
+        let transaction_id = pop_n16!();
+        let flags = pop_n16!();
+        let queries_len = pop_n16!();
+        let answers_len = pop_n16!();
+        pop_n16!();
+        pop_n16!();
+
+        let mut queries = Vec::new();
+        for _query_i in 0..queries_len {
+            queries.push(DnsQuery {
+                name: pop_name!(),
+                q_type: pop_n16!(),
+                q_class: pop_n16!()
+            });
+        }
+
+        let mut answers = Vec::new();
+        for _answer_i in 0..answers_len {
+            answers.push(DnsAnswer {
+                name: pop_name!(),
+                a_type: pop_n16!(),
+                a_class: pop_n16!(),
+                ttl_a: pop_n16!(),
+                ttl_b: pop_n16!(),
+                data: pop_data!()
+            });
+        }
+
+        Ok(Dns {
+            transaction_id: transaction_id,
+            flags: flags,
+            queries: queries,
+            answers: answers,
+        })
+    }
+}

+ 18 - 0
src/todo/oldlib/dns/query.rs

@@ -0,0 +1,18 @@
+// Copyright 2016 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::String;
+
+#[derive(Clone, Debug)]
+pub struct DnsQuery {
+    pub name: String,
+    pub q_type: u16,
+    pub q_class: u16
+}

+ 51 - 0
src/todo/oldlib/event.rs

@@ -0,0 +1,51 @@
+use core::slice;
+use libc::{c_int, c_uint};
+use syscall::error::{Error, EINVAL};
+use types::{fd_set, pollfd, timeval, FD_SETSIZE, POLLIN, POLLOUT, NFDBITS};
+
+libc_fn!(unsafe poll(fds: *mut pollfd, nfds: c_uint, timeout: c_int) -> Result<c_int> {
+    let fds = slice::from_raw_parts_mut(fds, nfds as usize);
+
+    let mut ret = 0;
+    for fd in fds.iter_mut() {
+        // always ready for read or write
+        fd.revents = fd.events & (POLLIN | POLLOUT);
+        if fd.revents != 0 {
+            ret += 1;
+        }
+    }
+
+    Ok(ret)
+});
+
+libc_fn!(unsafe select(nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, _timeout: *mut timeval) -> Result<c_int> {
+    if nfds < 0 || nfds > FD_SETSIZE as i32 {
+        return Err(Error::new(EINVAL));
+    }
+
+    let mut ret = 0;
+    for i in 0..nfds as usize {
+        if ! readfds.is_null() {
+            // always ready to read
+            if ((*readfds).fds_bits[i/NFDBITS] & (1 << (i % NFDBITS))) != 0 {
+                ret += 1;
+            }
+        }
+
+        if ! writefds.is_null() {
+            // always ready to write
+            if ((*writefds).fds_bits[i/NFDBITS] & (1 << (i % NFDBITS))) != 0 {
+                ret += 1;
+            }
+        }
+
+        if ! errorfds.is_null() {
+            // report no errors
+            if ((*errorfds).fds_bits[i/NFDBITS] & (1 << (i % NFDBITS))) != 0 {
+                (*errorfds).fds_bits[i/NFDBITS] &= !(1 << (i % NFDBITS));
+            }
+        }
+    }
+
+    Ok(ret)
+});

+ 188 - 0
src/todo/oldlib/file.rs

@@ -0,0 +1,188 @@
+use syscall::{self, O_CLOEXEC, O_STAT, O_CREAT, O_EXCL, O_DIRECTORY, O_WRONLY, O_NOFOLLOW, TimeSpec};
+use core::slice;
+use libc::{c_int, c_char, off_t, mode_t, size_t, ssize_t};
+use ::types::{utimbuf, timeval};
+
+pub const PATH_MAX: usize = 4096;
+
+
+libc_fn!(unsafe access(path: *mut c_char, _amode: c_int) -> Result<c_int> {
+    // XXX amode
+    ::RawFile::open(::cstr_to_slice(path), O_CLOEXEC | O_STAT)?;
+    Ok(0)
+});
+
+libc_fn!(unsafe _close(file: c_int) -> Result<c_int> {
+    Ok(syscall::close(file as usize)? as c_int)
+});
+
+libc_fn!(unsafe dup(file: c_int) -> Result<c_int> {
+    Ok(syscall::dup(file as usize, &[])? as c_int)
+});
+
+libc_fn!(unsafe dup2(file: c_int, newfile: c_int) -> Result<c_int> {
+    Ok(syscall::dup2(file as usize, newfile as usize, &[])? as c_int)
+});
+
+libc_fn!(unsafe _fstat(file: c_int, st: *mut syscall::Stat) -> Result<c_int> {
+    Ok(syscall::fstat(file as usize, &mut *st)? as c_int)
+});
+
+libc_fn!(unsafe _fsync(file: c_int) -> Result<c_int> {
+    Ok(syscall::fsync(file as usize)? as c_int)
+});
+
+libc_fn!(unsafe ftruncate(file: c_int, len: off_t) -> Result<c_int> {
+    Ok(syscall::ftruncate(file as usize, len as usize)? as c_int)
+});
+
+libc_fn!(unsafe _lseek(file: c_int, ptr: off_t, dir: c_int) -> Result<off_t> {
+    Ok(syscall::lseek(file as usize, ptr as isize, dir as usize)? as off_t)
+});
+
+
+libc_fn!(unsafe mkdir(path: *mut c_char, mode: mode_t) -> Result<c_int> {
+    let flags = O_CREAT | O_EXCL | O_CLOEXEC | O_DIRECTORY | (mode as usize & 0o777);
+    ::RawFile::open(::cstr_to_slice(path), flags)?;
+    Ok(0)
+});
+
+libc_fn!(unsafe _open(path: *mut c_char, flags: c_int, mode: mode_t) -> Result<c_int> {
+    let mut path = ::cstr_to_slice(path);
+    // XXX hack; use better method if possible
+    if path == b"/dev/null" {
+        path = b"null:"
+    }
+    Ok(syscall::open(path, flags as usize | (mode as usize & 0o777))? as c_int)
+});
+
+libc_fn!(unsafe pipe(pipefd: *mut [c_int; 2]) -> c_int {
+    pipe2(pipefd, 0)
+});
+
+libc_fn!(unsafe pipe2(pipefd: *mut [c_int; 2], flags: c_int) -> Result<c_int> {
+    let mut syspipefd = [(*pipefd)[0] as usize, (*pipefd)[1] as usize];
+    syscall::pipe2(&mut syspipefd, flags as usize)?;
+    (*pipefd)[0] = syspipefd[0] as c_int;
+    (*pipefd)[1] = syspipefd[1] as c_int;
+    Ok(0)
+});
+
+libc_fn!(unsafe _read(file: c_int, buf: *mut c_char, len: c_int) -> Result<c_int> {
+    let buf = slice::from_raw_parts_mut(buf as *mut u8, len as usize);
+    Ok(syscall::read(file as usize, buf)? as c_int)
+});
+
+libc_fn!(unsafe rmdir(path: *mut c_char) -> Result<c_int> {
+    Ok(syscall::rmdir(::cstr_to_slice(path))? as c_int)
+});
+
+libc_fn!(unsafe _stat(path: *const c_char, st: *mut syscall::Stat) -> Result<c_int> {
+    let fd = ::RawFile::open(::cstr_to_slice(path), O_CLOEXEC | O_STAT)?;
+    Ok(syscall::fstat(*fd, &mut *st)? as c_int)
+});
+
+libc_fn!(unsafe lstat(path: *const c_char, st: *mut syscall::Stat) -> Result<c_int> {
+    let fd = ::RawFile::open(::cstr_to_slice(path), O_CLOEXEC | O_STAT | O_NOFOLLOW)?;
+    Ok(syscall::fstat(*fd, &mut *st)? as c_int)
+});
+
+libc_fn!(unsafe _unlink(path: *mut c_char) -> Result<c_int> {
+    Ok(syscall::unlink(::cstr_to_slice(path))? as c_int)
+});
+
+libc_fn!(unsafe _write(file: c_int, buf: *const c_char, len: c_int) -> Result<c_int> {
+    let buf = slice::from_raw_parts(buf as *const u8, len as usize);
+    Ok(syscall::write(file as usize, buf)? as c_int)
+});
+
+libc_fn!(unsafe chmod(path: *mut c_char, mode: mode_t) -> Result<c_int> {
+    Ok(syscall::chmod(::cstr_to_slice(path), mode as usize)? as c_int)
+});
+
+libc_fn!(unsafe realpath(path: *const c_char, resolved_path: *mut c_char) -> Result<*mut c_char> {
+    let fd = ::RawFile::open(::cstr_to_slice(path), O_STAT)?;
+
+    let resolved_path = ::MallocNull::new(resolved_path, PATH_MAX);
+    let buf = slice::from_raw_parts_mut(resolved_path.as_mut_ptr() as *mut u8, PATH_MAX-1);
+    let length = syscall::fpath(*fd, buf)?;
+    buf[length] = b'\0';
+
+    Ok(resolved_path.into_raw())
+});
+
+libc_fn!(unsafe _rename(old: *const c_char, new: *const c_char) -> Result<c_int> {
+    // XXX fix this horror when the kernel provides rename() or link()
+    let old = ::cstr_to_slice(old);
+    let new = ::cstr_to_slice(new);
+    let buf = ::file_read_all(old)?;
+
+    let mut stat = syscall::Stat::default();
+    let fd = ::RawFile::open(old, syscall::O_STAT)?;
+    syscall::fstat(*fd, &mut stat)?;
+    drop(fd);
+    let mode = (stat.st_mode & 0o777) as usize;
+
+    let fd = ::RawFile::open(new, O_CREAT | O_WRONLY | mode)?;
+    syscall::write(*fd, &buf)?;
+    syscall::unlink(old)?;
+    Ok(0)
+});
+
+libc_fn!(fsync(fd: c_int) -> Result<c_int> {
+    Ok(syscall::fsync(fd as usize)? as c_int)
+});
+
+libc_fn!(unsafe symlink(path1: *const c_char, path2: *const c_char) -> Result<c_int> {
+    let fd = ::RawFile::open(::cstr_to_slice(path2), syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777)?;
+    syscall::write(*fd, ::cstr_to_slice(path1))?;
+    Ok(0)
+});
+
+libc_fn!(unsafe readlink(path: *const c_char, buf: *const c_char, bufsize: size_t) -> Result<ssize_t> {
+    let fd = ::RawFile::open(::cstr_to_slice(path), syscall::O_SYMLINK | syscall::O_RDONLY)?;
+    let count = syscall::read(*fd, slice::from_raw_parts_mut(buf as *mut u8, bufsize))?;
+    Ok(count as ssize_t)
+});
+
+libc_fn!(unsafe utime(path: *mut c_char, times: *const utimbuf) -> Result<c_int> {
+    let times = if times.is_null() {
+        let mut tp = TimeSpec::default();
+        syscall::clock_gettime(syscall::flag::CLOCK_REALTIME, &mut tp)?;
+        [tp, tp]
+    } else {
+        [TimeSpec { tv_sec: (*times).actime, tv_nsec: 0 },
+         TimeSpec { tv_sec: (*times).modtime, tv_nsec: 0 }]
+    };
+    let fd = ::RawFile::open(::cstr_to_slice(path), 0)?;
+    syscall::futimens(*fd, &times)?;
+    Ok(0)
+});
+
+libc_fn!(unsafe utimes(path: *mut c_char, times: *const [timeval; 2]) -> Result<c_int> {
+    let times =  [TimeSpec { tv_sec: (*times)[0].tv_sec, tv_nsec: (*times)[0].tv_usec as i32 * 1000 },
+                  TimeSpec { tv_sec: (*times)[1].tv_sec, tv_nsec: (*times)[0].tv_usec as i32 * 1000 }];
+    let fd = ::RawFile::open(::cstr_to_slice(path), 0)?;
+    syscall::futimens(*fd, &times)?;
+    Ok(0)
+});
+
+libc_fn!(unsafe futimens(fd: c_int, times: *const [TimeSpec; 2]) -> Result<c_int> {
+    // XXX UTIME_NOW and UTIME_OMIT (in redoxfs?)
+    syscall::futimens(fd as usize, &*times)?;
+    Ok(0)
+});
+
+// XXX variadic
+libc_fn!(_fcntl(file: c_int, cmd: c_int, arg: c_int) -> Result<c_int> {
+    Ok(syscall::fcntl(file as usize, cmd as usize, arg as usize)? as c_int)
+});
+
+libc_fn!(_isatty(file: c_int) -> c_int {
+    if let Ok(fd) = syscall::dup(file as usize, b"termios") {
+        let _ = syscall::close(fd);
+        1
+    } else {
+        0
+    }
+});

+ 94 - 0
src/todo/oldlib/folder.rs

@@ -0,0 +1,94 @@
+extern crate libc;
+extern crate core;
+use ::{c_int, c_char};
+use syscall::{self, O_CLOEXEC, O_RDONLY, O_DIRECTORY};
+use core::ptr::null;
+use core::default::Default;
+use alloc::boxed::Box;
+use ::file::PATH_MAX;
+use ::types::{ino_t, off_t};
+use libc::*;
+
+#[repr(C)]
+pub struct dirent {
+    pub d_ino: ino_t,
+    pub d_off: off_t,
+    pub d_reclen: c_ushort,
+    pub d_type: c_uchar,
+    pub d_name: [c_char; PATH_MAX]
+}
+impl core::default::Default for dirent {
+    fn default() -> dirent {
+        dirent {
+            d_ino: 0,
+            d_off: 0,
+            d_reclen: 0,
+            d_type: 0,
+            d_name: [0; PATH_MAX],
+        }
+    }
+}
+
+pub struct DIR {
+    pub fd: ::RawFile,
+    pub ent: dirent,
+    pub buf: [u8; PATH_MAX],
+    pub count: usize,
+    pub pos: usize
+}
+
+libc_fn!(unsafe opendir(path: *mut c_char) -> Result<*mut DIR> {
+    let path = ::cstr_to_slice(path);
+    let fd = ::RawFile::open(path, O_RDONLY | O_CLOEXEC | O_DIRECTORY)?;
+    let dir = Box::new(DIR {
+        fd,
+        ent: dirent::default(),
+        buf: [0; PATH_MAX],
+        count: 0,
+        pos: 0
+
+    });
+    Ok(Box::into_raw(dir))
+});
+
+libc_fn!(unsafe readdir(dir: *mut DIR) -> Result<*const dirent> {
+    if let Some(dir) = dir.as_mut() {
+        let mut i = 0;
+        'outer: while i < PATH_MAX - 1 {
+            while dir.pos < dir.count {
+                dir.ent.d_name[i] = dir.buf[dir.pos] as c_char;
+                dir.pos += 1;
+                if dir.buf[dir.pos-1] == b'\n' {
+                    break 'outer;
+                }
+                i += 1;
+            }
+            dir.count = syscall::read(*dir.fd, &mut dir.buf)?;
+            if dir.count == 0 {
+                break;
+            }
+            dir.pos = 0;
+        }
+        if i != 0 {
+            dir.ent.d_name[i] = 0;
+            return Ok(&dir.ent);
+        }
+    }
+    Ok(null())
+});
+
+libc_fn!(unsafe rewinddir(dir: *mut DIR) {
+    if let Some(dir) = dir.as_mut() {
+        dir.count = 0;
+        let _ = syscall::lseek(*dir.fd, 0, syscall::SEEK_SET);
+    }
+});
+
+libc_fn!(unsafe closedir(dir: *mut DIR) -> Result<c_int> {
+    Box::from_raw(dir);
+    Ok(0)
+});
+
+libc_fn!(unsafe dirfd(dir: *mut DIR) -> Result<c_int> {
+    Ok(*(*dir).fd as i32)
+});

+ 107 - 0
src/todo/oldlib/hostname.rs

@@ -0,0 +1,107 @@
+use core::ptr::null;
+use core::{mem, str, slice};
+use alloc::vec::IntoIter;
+use alloc::string::ToString;
+use alloc::{Vec, String};
+use ::dns::{Dns, DnsQuery};
+use syscall::{self, Result, EINVAL, Error};
+use libc::{c_char, size_t, c_int};
+use ::types::{in_addr, hostent};
+
+static mut HOST_ENTRY: hostent = hostent { h_name: null(), h_aliases: null(), h_addrtype: 0, h_length: 0, h_addr_list: null() };
+static mut HOST_NAME: Option<Vec<u8>> = None;
+static mut HOST_ALIASES: [*const c_char; 1] = [null()];
+static mut HOST_ADDR: Option<in_addr> = None;
+static mut HOST_ADDR_LIST: [*const c_char; 2] = [null(); 2];
+
+struct LookupHost(IntoIter<in_addr>);
+
+impl Iterator for LookupHost {
+    type Item = in_addr;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+// Modified from rust/sys/redox/net/mod.rs
+fn lookup_host(host: &str) -> Result<LookupHost> {
+    // XXX better error handling
+    let ip_string = String::from_utf8(::file_read_all("/etc/net/ip")?)
+        .or(Err(Error::new(syscall::EIO)))?;
+    let ip: Vec<u8> = ip_string.trim().split(".").map(|part| part.parse::<u8>()
+                               .unwrap_or(0)).collect();
+
+    let dns_string = String::from_utf8(::file_read_all("/etc/net/dns")?)
+        .or(Err(Error::new(syscall::EIO)))?;
+    let dns: Vec<u8> = dns_string.trim().split(".").map(|part| part.parse::<u8>()
+                                 .unwrap_or(0)).collect();
+
+    if ip.len() == 4 && dns.len() == 4 {
+        let mut timespec = syscall::TimeSpec::default();
+        syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut timespec).unwrap();
+        let tid = (timespec.tv_nsec >> 16) as u16;
+
+        let packet = Dns {
+            transaction_id: tid,
+            flags: 0x0100,
+            queries: vec![DnsQuery {
+                name: host.to_string(),
+                q_type: 0x0001,
+                q_class: 0x0001,
+            }],
+            answers: vec![]
+        };
+
+        let packet_data = packet.compile();
+
+        let fd = ::RawFile::open(format!("udp:/{}.{}.{}.{}:0",
+                                         ip[0], ip[1], ip[2], ip[3]).as_bytes(),
+                                 syscall::O_RDWR)?;
+
+        let timeout = syscall::TimeSpec {
+            tv_sec: 5,
+            tv_nsec: 0,
+        };
+        let rt = fd.dup(b"read_timeout")?;
+        syscall::write(*rt, &timeout)?;
+        drop(rt);
+        let wt = fd.dup(b"write_timeout")?;
+        syscall::write(*wt, &timeout)?;
+        drop(wt);
+
+        let sendrecvfd = fd.dup(format!("{}.{}.{}.{}:53", dns[0], dns[1], dns[2], dns[3]).as_bytes())?;
+        syscall::write(*sendrecvfd, &packet_data)?;
+        let mut buf = [0; 65536];
+        let count = syscall::read(*sendrecvfd, &mut buf)?;
+        drop(sendrecvfd);
+        drop(fd);
+
+        match Dns::parse(&buf[.. count]) {
+            Ok(response) => {
+                let mut addrs = vec![];
+                for answer in response.answers.iter() {
+                    if answer.a_type == 0x0001 && answer.a_class == 0x0001
+                       && answer.data.len() == 4
+                    {
+                        let addr = in_addr {
+                            s_addr: [answer.data[0], answer.data[1], answer.data[2], answer.data[3]]
+                        };
+                        addrs.push(addr);
+                    }
+                }
+                Ok(LookupHost(addrs.into_iter()))
+            },
+            Err(_err) => Err(Error::new(EINVAL))
+        }
+    } else {
+        Err(Error::new(EINVAL))
+    }
+}
+
+libc_fn!(unsafe gethostname(name: *mut c_char, namelen: size_t) -> Result<c_int> {
+    let slice = slice::from_raw_parts_mut(name as *mut u8, namelen);
+    let fd = ::RawFile::open("/etc/hostname", syscall::O_RDONLY)?;
+    let len = syscall::read(*fd, &mut slice[..namelen-1])?;
+    slice[len] = b'\0';
+    Ok(0)
+});

+ 211 - 0
src/todo/oldlib/lib.rs

@@ -0,0 +1,211 @@
+#![no_std]
+#![feature(
+    alloc,
+    allocator_api,
+    alloc_system,
+    compiler_builtins_lib,
+    const_fn,
+    const_ptr_null,
+    core_intrinsics,
+    global_allocator,
+    lang_items,
+    linkage,
+    const_size_of,
+    const_cell_new,
+)]
+
+#[macro_use]
+extern crate alloc;
+extern crate alloc_system;
+extern crate byteorder;
+extern crate compiler_builtins;
+extern crate libc;
+extern crate syscall;
+extern crate redox_termios;
+
+use alloc::Vec;
+use alloc::String;
+use alloc::fmt::Write;
+use alloc::boxed::Box;
+use core::{ptr, mem, intrinsics, slice, str};
+use libc::{c_int, c_void, c_char, size_t};
+
+#[macro_use]
+mod macros;
+mod types;
+mod dns;
+mod mallocnull;
+mod rawfile;
+pub mod event;
+pub mod process;
+pub mod file;
+pub mod folder;
+pub mod time;
+pub mod unimpl;
+pub mod user;
+pub mod redox;
+pub mod socket;
+pub mod hostname;
+pub mod termios;
+pub mod netdb;
+
+pub use mallocnull::MallocNull;
+pub use rawfile::RawFile;
+
+#[global_allocator]
+static ALLOCATOR: alloc_system::System = alloc_system::System;
+
+extern "C" {
+    // Newlib uses this function instead of just a global to support reentrancy
+    pub fn __errno() -> *mut c_int;
+    pub fn malloc(size: size_t) -> *mut c_void;
+    pub fn free(ptr: *mut c_void);
+    pub fn strlen(s: *const c_char) -> size_t;
+    pub fn __libc_fini_array();
+    pub static mut environ: *mut *mut c_char;
+}
+
+pub unsafe fn cstr_to_slice<'a>(buf: *const c_char) -> &'a [u8] {
+    slice::from_raw_parts(buf as *const u8, ::strlen(buf) as usize)
+}
+pub unsafe fn cstr_to_slice_mut<'a>(buf: *const c_char) -> &'a mut [u8] {
+    slice::from_raw_parts_mut(buf as *mut u8, ::strlen(buf) as usize)
+}
+
+pub fn file_read_all<T: AsRef<[u8]>>(path: T) -> syscall::Result<Vec<u8>> {
+    let fd = RawFile::open(path, syscall::O_RDONLY)?;
+
+    let mut st = syscall::Stat::default();
+    syscall::fstat(*fd, &mut st)?;
+    let size = st.st_size as usize;
+
+    let mut buf = Vec::with_capacity(size);
+    unsafe { buf.set_len(size) };
+    syscall::read(*fd, buf.as_mut_slice())?;
+
+    Ok(buf)
+}
+
+/// Implements an `Iterator` which returns on either newline or EOF.
+#[derive(Clone, Copy)]
+pub struct RawLineBuffer {
+    fd: usize,
+    cur: usize,
+    read: usize,
+    buf: [u8; 8 * 1024],
+}
+
+impl Default for RawLineBuffer {
+    fn default() -> RawLineBuffer {
+        RawLineBuffer {
+            fd: 0,
+            cur: 0,
+            read: 0,
+            buf: unsafe { mem::uninitialized() },
+        }
+    }
+}
+
+impl RawLineBuffer {
+    fn new(fd: usize) -> RawLineBuffer {
+        RawLineBuffer {
+            fd: fd,
+            cur: 0,
+            read: 0,
+            buf: unsafe { mem::uninitialized() },
+        }
+    }
+}
+
+impl Iterator for RawLineBuffer {
+    type Item = syscall::Result<Box<str>>;
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.cur != 0 && self.read != 0 {
+            if let Some(mut pos) = self.buf[self.cur..self.read].iter().position(
+                |&x| x == b'\n',
+            )
+            {
+                pos += self.cur + 1;
+                let line = unsafe { str::from_utf8_unchecked(&self.buf[self.cur..pos]) };
+                let boxed_array: Box<[u8]> = Box::from(line.as_bytes());
+                let boxed_line: Box<str> = unsafe { mem::transmute(boxed_array) };
+                self.cur = pos;
+                return Some(Ok(boxed_line));
+            }
+
+            let mut temp: [u8; 8 * 1024] = unsafe { mem::uninitialized() };
+            unsafe {
+                ptr::copy(self.buf[self.cur..].as_ptr(), temp.as_mut_ptr(), self.read);
+                ptr::swap(self.buf.as_mut_ptr(), temp.as_mut_ptr());
+            };
+
+            self.read -= self.cur;
+            self.cur = 0;
+        }
+
+        let end = match syscall::read(self.fd, &mut self.buf[self.cur..]).unwrap() {
+            0 => return None,
+            read => {
+                self.read += read;
+                self.buf[..self.read]
+                    .iter()
+                    .position(|&x| x == b'\n')
+                    .unwrap_or(0)
+            }
+        };
+
+        self.cur = end;
+        let line = unsafe { str::from_utf8_unchecked(&self.buf[..end]) };
+        let boxed_array: Box<[u8]> = Box::from(line.as_bytes());
+        let boxed_line: Box<str> = unsafe { mem::transmute(boxed_array) };
+
+        Some(Ok(boxed_line))
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn __errno_location() -> *mut c_int {
+    __errno()
+}
+
+#[lang = "eh_personality"]
+pub extern "C" fn eh_personality() {}
+
+#[lang = "panic_fmt"]
+#[linkage = "weak"]
+#[no_mangle]
+pub extern "C" fn rust_begin_unwind(_msg: core::fmt::Arguments,
+                               _file: &'static str,
+                               _line: u32,
+                               _col: u32) -> ! {
+   let mut s = String::new();
+    let _ = s.write_fmt(_msg);
+    let _ = syscall::write(2, _file.as_bytes());
+    let _ = syscall::write(2, "\n".as_bytes());
+    let _ = syscall::write(2, s.as_bytes());
+    let _ = syscall::write(2, "\n".as_bytes());
+    unsafe { intrinsics::abort() }
+}
+
+libc_fn!(unsafe initialize_standard_library() {
+    let mut buf = file_read_all("env:").unwrap();
+    let size = buf.len();
+    buf.push(0);
+
+    let mut vars = Vec::new();
+
+    vars.push(&mut buf[0] as *mut u8 as *mut c_char);
+    for i in 0..size {
+        if buf[i] == b'\n' {
+            if i != size - 1 {
+                vars.push(&mut buf[i + 1] as *mut u8 as *mut c_char);
+            }
+            buf[i] = b'\0';
+        }
+    }
+    vars.push(ptr::null_mut());
+
+    environ = vars.as_mut_ptr();
+    mem::forget(vars); // Do not free memory
+    mem::forget(buf);
+});

+ 120 - 0
src/todo/oldlib/macros.rs

@@ -0,0 +1,120 @@
+use core::ptr;
+use core::any::Any;
+
+
+/// This struct converts to `NULL` for raw pointers, and `-1` for signed
+/// integers.
+pub struct Fail;
+
+impl<T: Any> Into<*const T> for Fail {
+    #[inline(always)]
+    fn into(self) -> *const T {
+        ptr::null()
+    }
+}
+
+impl<T: Any> Into<*mut T> for Fail {
+    #[inline(always)]
+    fn into(self) -> *mut T {
+        ptr::null_mut()
+    }
+}
+
+macro_rules! int_fail {
+    ($type:ty) => (
+        impl Into<$type> for Fail {
+            #[inline(always)]
+            fn into(self) -> $type {
+                -1
+            }
+        }
+    )
+}
+
+int_fail!(i8);
+int_fail!(i16);
+int_fail!(i32);
+int_fail!(i64);
+int_fail!(isize);
+
+/// If `res` is `Err(..)`, set `errno` and return `-1` or `NULL`, otherwise
+/// unwrap.
+macro_rules! try_call {
+    ($res:expr) => (
+        match $res {
+            Ok(val) => val,
+            Err(err) => {
+                *::__errno() = err.errno;
+                return ::macros::Fail.into();
+            }
+        }
+    );
+}
+
+/// Declares a libc function. The body should return syscall::Result, which
+/// is used to set errno on error with try_call!
+///
+/// ```
+/// libc_fn!(foo(arg: c_int) -> c_int) {
+///     Ok(arg)
+/// }
+/// ```
+///
+/// The `unsafe` keyword can be added to make the function unsafe:
+///
+/// ```
+/// libc_fn!(unsafe foo(arg: c_int) -> c_int) {
+///     Ok(arg)
+/// }
+/// ```
+macro_rules! libc_fn {
+    // The next 2 cases handle Result return values, and convert to errno+return
+    // Call with arguments and return value
+    ($name:ident($($aname:ident : $atype:ty),*) -> Result<$rtype:ty> $content:block) => {
+        #[no_mangle]
+        pub extern "C" fn $name($($aname: $atype,)*) -> $rtype {
+            #[inline(always)]
+            fn inner($($aname: $atype,)*) -> ::syscall::Result<$rtype> {
+                $content
+            }
+            unsafe { try_call!(inner($($aname,)*)) }
+        }
+    };
+    // Call with `unsafe` keyword (and arguments, return value)
+    (unsafe $name:ident($($aname:ident : $atype:ty),*) -> Result<$rtype:ty> $content:block) => {
+        #[no_mangle]
+        pub unsafe extern "C" fn $name($($aname: $atype,)*) -> $rtype {
+            #[inline(always)]
+            unsafe fn inner($($aname: $atype,)*) -> ::syscall::Result<$rtype> {
+                $content
+            }
+            try_call!(inner($($aname,)*))
+        }
+    };
+    // The next 2 cases handle non-Result return values
+    ($name:ident($($aname:ident : $atype:ty),*) -> $rtype:ty $content:block) => {
+        #[no_mangle]
+        pub extern "C" fn $name($($aname: $atype,)*) -> $rtype {
+            $content
+        }
+    };
+    (unsafe $name:ident($($aname:ident : $atype:ty),*) -> $rtype:ty $content:block) => {
+        #[no_mangle]
+        pub unsafe extern "C" fn $name($($aname: $atype,)*) -> $rtype {
+            $content
+        }
+    };
+    // The next 2 cases handle calls with no return value
+    ($name:ident($($aname:ident : $atype:ty),*) $content:block) => {
+        #[no_mangle]
+        pub extern "C" fn $name($($aname: $atype,)*) {
+            $content
+        }
+    };
+    (unsafe $name:ident($($aname:ident : $atype:ty),*) $content:block) => {
+        #[no_mangle]
+        pub unsafe extern "C" fn $name($($aname: $atype,)*) {
+            $content
+        }
+    };
+}

+ 46 - 0
src/todo/oldlib/mallocnull.rs

@@ -0,0 +1,46 @@
+use core::mem;
+use libc::{c_void, size_t};
+
+/// Malloc memory if pointer is null, and free on drop
+pub struct MallocNull<T> {
+    value: *mut T,
+    free_on_drop: bool
+}
+
+impl<T> MallocNull<T> {
+    pub fn new(ptr: *mut T, size: usize) -> MallocNull<T> {
+        if ptr.is_null() {
+            MallocNull {
+                value: unsafe { ::malloc(size as size_t) as *mut T },
+                free_on_drop: true
+            }
+	    } else {
+            MallocNull {
+                value: ptr,
+                free_on_drop: false
+            }
+        }
+    }
+    
+    pub fn into_raw(self) -> *mut T {
+        let ptr = self.value;
+        mem::forget(self);
+        ptr
+    }
+
+    pub fn as_ptr(&self) -> *const T {
+        self.value
+    }
+
+    pub fn as_mut_ptr(&self) -> *mut T {
+        self.value
+    }
+}
+
+impl<T> Drop for MallocNull<T> {
+    fn drop(&mut self) {
+        if self.free_on_drop {
+            unsafe { ::free(self.value as *mut c_void) };
+        }
+    }
+}

+ 727 - 0
src/todo/oldlib/netdb.rs

@@ -0,0 +1,727 @@
+use libc;
+use types::{in_addr, sockaddr, socklen_t};
+use RawLineBuffer;
+use core::ptr::null;
+use core::{mem, str};
+use alloc::vec::IntoIter;
+use alloc::string::ToString;
+use alloc::{Vec, String};
+use alloc::str::SplitWhitespace;
+use alloc::boxed::Box;
+use dns::{Dns, DnsQuery};
+use syscall::{self, Result, EINVAL, Error};
+use libc::c_char;
+
+const MAXADDRS: usize = 35;
+const MAXALIASES: usize = 35;
+
+struct LookupHost(IntoIter<in_addr>);
+
+impl Iterator for LookupHost {
+    type Item = in_addr;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+#[repr(C)]
+pub struct hostent {
+    h_name: *const libc::c_char,
+    h_aliases: *const *const libc::c_char,
+    h_addrtype: libc::c_int,
+    h_length: libc::c_int,
+    h_addr_list: *const *const libc::c_char,
+}
+
+/*
+ *#[repr(C)]
+ *pub struct netent {
+ *    n_name: *const libc::c_char, [> official name of net <]
+ *    n_aliases: *const *const libc::c_char, [> alias list <]
+ *    n_addrtype: libc::c_int, [> net address type <]
+ *    n_net: libc::c_ulong, [> network # <]
+ *}
+ */
+
+#[repr(C)]
+pub struct servent {
+    s_name: *const libc::c_char, /* official service name */
+    s_aliases: *const *const libc::c_char, /* alias list */
+    s_port: libc::c_int, /* port # */
+    s_proto: *const libc::c_char, /* protocol to use */
+}
+
+#[repr(C)]
+pub struct protoent {
+    p_name: *const libc::c_char, /* official protocol name */
+    p_aliases: *const *const libc::c_char, /* alias list */
+    p_proto: libc::c_int, /* protocol # */
+}
+
+#[repr(C)]
+pub struct addrinfo {
+    ai_flags: libc::c_int, /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+    ai_family: libc::c_int, /* PF_xxx */
+    ai_socktype: libc::c_int, /* SOCK_xxx */
+    ai_protocol: libc::c_int, /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+    ai_addrlen: libc::size_t, /* length of ai_addr */
+    ai_canonname: *const libc::c_char, /* canonical name for hostname */
+    ai_addr: *const sockaddr, /* binary address */
+    ai_next: *const addrinfo, /* next structure in linked list */
+}
+
+static mut HOSTDB: usize = 0;
+//static mut NETDB: usize = 0;
+static mut PROTODB: usize = 0;
+static mut SERVDB: usize = 0;
+
+/*
+ *static mut NET_ENTRY: netent = netent {
+ *    n_name: 0 as *const libc::c_char,
+ *    n_aliases: 0 as *const *const libc::c_char,
+ *    n_addrtype: 0,
+ *    n_net: 0 as u64,
+ *};
+ *static mut NET_NAME: Option<Vec<u8>> = None;
+ *static mut NET_ALIASES: [*const c_char; MAXALIASES] = [null(); MAXALIASES];
+ *static mut NET_NUM: Option<u64> = None;
+ */
+
+static mut HOST_ENTRY: hostent = hostent {
+    h_name: 0 as *const libc::c_char,
+    h_aliases: 0 as *const *const libc::c_char,
+    h_addrtype: 0,
+    h_length: 0,
+    h_addr_list: 0 as *const *const libc::c_char,
+};
+static mut HOST_NAME: Option<Vec<u8>> = None;
+static mut HOST_ALIASES: Option<Vec<Vec<u8>>> = None; 
+static mut HOST_ADDR: Option<in_addr> = None;
+static mut HOST_ADDR_LIST: [*const c_char; 2] = [null(); 2];
+static mut H_LINE: RawLineBuffer = RawLineBuffer {
+    fd: 0,
+    cur: 0,
+    read: 0,
+    buf: [0; 8 * 1024],
+};
+
+static mut PROTO_ENTRY: protoent = protoent {
+    p_name: 0 as *const libc::c_char,
+    p_aliases: 0 as *const *const libc::c_char,
+    p_proto: 0 as libc::c_int,
+};
+static mut PROTO_NAME: Option<Vec<u8>> = None;
+static mut PROTO_ALIASES: Option<Vec<Vec<u8>>> = None;
+static mut PROTO_NUM: Option<libc::c_int> = None;
+static mut P_LINE: RawLineBuffer = RawLineBuffer {
+    fd: 0,
+    cur: 0,
+    read: 0,
+    buf: [0; 8 * 1024],
+};
+
+static mut SERV_ENTRY: servent = servent {
+    s_name: 0 as *const libc::c_char,
+    s_aliases: 0 as *const *const libc::c_char,
+    s_port: 0 as libc::c_int,
+    s_proto: 0 as *const libc::c_char,
+};
+static mut SERV_NAME: Option<Vec<u8>> = None;
+static mut SERV_ALIASES: Option<Vec<Vec<u8>>> = None;
+static mut SERV_PORT: Option<libc::c_int> = None;
+static mut SERV_PROTO: Option<Vec<u8>> = None;
+static mut S_LINE: RawLineBuffer = RawLineBuffer {
+    fd: 0,
+    cur: 0,
+    read: 0,
+    buf: [0; 8 * 1024],
+};
+
+
+fn lookup_host(host: &str) -> Result<LookupHost> {
+    // XXX better error handling
+    let ip_string = String::from_utf8(::file_read_all("/etc/net/ip")?).or(Err(
+        Error::new(syscall::EIO),
+    ))?;
+    let ip: Vec<u8> = ip_string
+        .trim()
+        .split(".")
+        .map(|part| part.parse::<u8>().unwrap_or(0))
+        .collect();
+
+    let dns_string = String::from_utf8(::file_read_all("/etc/net/dns")?).or(Err(
+        Error::new(syscall::EIO),
+    ))?;
+    let dns: Vec<u8> = dns_string
+        .trim()
+        .split(".")
+        .map(|part| part.parse::<u8>().unwrap_or(0))
+        .collect();
+
+    if ip.len() == 4 && dns.len() == 4 {
+        let mut timespec = syscall::TimeSpec::default();
+        syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut timespec).unwrap();
+        let tid = (timespec.tv_nsec >> 16) as u16;
+
+        let packet = Dns {
+            transaction_id: tid,
+            flags: 0x0100,
+            queries: vec![
+                DnsQuery {
+                    name: host.to_string(),
+                    q_type: 0x0001,
+                    q_class: 0x0001,
+                },
+            ],
+            answers: vec![],
+        };
+
+        let packet_data = packet.compile();
+
+        let fd = ::RawFile::open(
+            format!("udp:/{}.{}.{}.{}:0", ip[0], ip[1], ip[2], ip[3]).as_bytes(),
+            syscall::O_RDWR,
+        )?;
+
+        let timeout = syscall::TimeSpec {
+            tv_sec: 5,
+            tv_nsec: 0,
+        };
+        let rt = fd.dup(b"read_timeout")?;
+        syscall::write(*rt, &timeout)?;
+        drop(rt);
+        let wt = fd.dup(b"write_timeout")?;
+        syscall::write(*wt, &timeout)?;
+        drop(wt);
+
+        let sendrecvfd = fd.dup(
+            format!("{}.{}.{}.{}:53", dns[0], dns[1], dns[2], dns[3])
+                .as_bytes(),
+        )?;
+        syscall::write(*sendrecvfd, &packet_data)?;
+        let mut buf = [0; 65536];
+        let count = syscall::read(*sendrecvfd, &mut buf)?;
+        drop(sendrecvfd);
+        drop(fd);
+
+        match Dns::parse(&buf[..count]) {
+            Ok(response) => {
+                let mut addrs = vec![];
+                for answer in response.answers.iter() {
+                    if answer.a_type == 0x0001 && answer.a_class == 0x0001 &&
+                        answer.data.len() == 4
+                    {
+                        let addr = in_addr {
+                            s_addr: [
+                                answer.data[0],
+                                answer.data[1],
+                                answer.data[2],
+                                answer.data[3],
+                            ],
+                        };
+                        addrs.push(addr);
+                    }
+                }
+                Ok(LookupHost(addrs.into_iter()))
+            }
+            Err(_err) => Err(Error::new(EINVAL)),
+        }
+    } else {
+        Err(Error::new(EINVAL))
+    }
+}
+
+unsafe fn lookup_addr(addr: in_addr) -> Result<Vec<Vec<u8>>> {
+    // XXX better error handling
+    let ip_string = String::from_utf8(::file_read_all("/etc/net/ip")?).or(Err(
+        Error::new(syscall::EIO),
+    ))?;
+    let ip: Vec<u8> = ip_string
+        .trim()
+        .split(".")
+        .map(|part| part.parse::<u8>().unwrap_or(0))
+        .collect();
+
+    let dns_string = String::from_utf8(::file_read_all("/etc/net/dns")?).or(Err(
+        Error::new(syscall::EIO),
+    ))?;
+    let dns: Vec<u8> = dns_string
+        .trim()
+        .split(".")
+        .map(|part| part.parse::<u8>().unwrap_or(0))
+        .collect();
+    
+    let mut addr_vec: Vec<u8> = addr.s_addr.to_vec(); 
+    addr_vec.reverse();
+    let mut name: Vec<u8> = vec![]; 
+    for octet in addr_vec {
+        for ch in format!("{}", octet).as_bytes() {
+            name.push(*ch);
+        }
+        name.push(b"."[0]);
+    }
+    name.pop();
+    for ch in b".IN-ADDR.ARPA" {
+        name.push(*ch);
+    }
+    let _ = syscall::write(2, name.as_slice());
+    let _ = syscall::write(2, "\n".as_bytes());
+
+    if ip.len() == 4 && dns.len() == 4 {
+        let mut timespec = syscall::TimeSpec::default();
+        syscall::clock_gettime(syscall::CLOCK_REALTIME, &mut timespec).unwrap();
+        let tid = (timespec.tv_nsec >> 16) as u16;
+
+        let packet = Dns {
+            transaction_id: tid,
+            flags: 0x0100,
+            queries: vec![
+                DnsQuery {
+                    name: String::from_utf8(name).unwrap(),
+                    q_type: 0x000C,
+                    q_class: 0x0001,
+                },
+            ],
+            answers: vec![],
+        };
+
+        let packet_data = packet.compile();
+
+        let fd = ::RawFile::open(
+            format!("udp:/{}.{}.{}.{}:0", ip[0], ip[1], ip[2], ip[3]).as_bytes(),
+            syscall::O_RDWR,
+        )?;
+
+        let timeout = syscall::TimeSpec {
+            tv_sec: 5,
+            tv_nsec: 0,
+        };
+        let rt = fd.dup(b"read_timeout")?;
+        syscall::write(*rt, &timeout)?;
+        drop(rt);
+        let wt = fd.dup(b"write_timeout")?;
+        syscall::write(*wt, &timeout)?;
+        drop(wt);
+
+        let sendrecvfd = fd.dup(
+            format!("{}.{}.{}.{}:53", dns[0], dns[1], dns[2], dns[3])
+                .as_bytes(),
+        )?;
+        syscall::write(*sendrecvfd, &packet_data)?;
+        let mut buf = [0; 65536];
+        let count = syscall::read(*sendrecvfd, &mut buf)?;
+        drop(sendrecvfd);
+        drop(fd);
+
+        match Dns::parse(&buf[..count]) {
+            Ok(response) => {
+                let _ = syscall::write(2, format!("{:?}", response).as_bytes());
+                let _ = syscall::write(2, "\n".as_bytes());
+                let mut names = vec![];
+                for answer in response.answers.iter() {
+     
+                    if answer.a_type == 0x000C && answer.a_class == 0x0001 
+                    {
+                        // answer.data is encoded kinda weird.
+                        // Basically length-prefixed strings for each 
+                        // subsection of the domain. 
+                        // We need to parse this to insert periods where
+                        // they belong (ie at the end of each string)
+                        let data = parse_data(answer.data.clone());
+                        names.push(data);
+                    }
+                }
+                Ok(names)
+            }
+            Err(_err) => Err(Error::new(EINVAL)),
+        }
+    } else {
+        Err(Error::new(EINVAL))
+    }
+}
+
+fn parse_data(mut data: Vec<u8>) -> Vec<u8> {
+    let mut cursor = 0;
+    let mut offset = 0;
+    let mut index = 0; 
+    let mut output = data.clone();
+    while index < data.len() - 1 {
+        offset = data[index] as usize;
+        index = cursor + offset + 1;
+        output[index] = '.' as u8;
+        cursor = index;
+    }
+    //we don't want an extra period at the end
+    output.pop(); 
+    return output 
+}
+
+
+
+libc_fn!(unsafe endhostent() {
+    let _ = syscall::close(HOSTDB);
+});
+
+/*
+ *libc_fn!(unsafe endnetent()  {
+ *    let _ = syscall::close(NETDB);
+ *});
+ */
+
+libc_fn!(unsafe endprotoent() {
+    let _ = syscall::close(PROTODB);
+});
+
+libc_fn!(unsafe endservent() {
+    let _ = syscall::close(SERVDB);
+});
+
+
+libc_fn!(unsafe gethostbyaddr(v: *const libc::c_void, length: socklen_t, format: libc::c_int) -> Result <*const hostent> {
+    let mut addr: in_addr = *(v as *mut in_addr);
+    match lookup_addr(addr) {
+        Ok(s) => {
+            HOST_ADDR_LIST = [addr.s_addr.as_mut_ptr() as *const c_char, null()];
+            let host_name = s[0].to_vec();
+            HOST_ENTRY = hostent {
+                h_name: host_name.as_ptr() as *const c_char,
+                h_aliases: [null();2].as_mut_ptr(),
+                h_addrtype: format,
+                h_length: length as i32,
+                h_addr_list: HOST_ADDR_LIST.as_ptr()
+            };
+            HOST_NAME = Some(host_name);
+            return Ok(&HOST_ENTRY)
+        }
+        Err(err) => Err(err)
+    }
+});
+
+libc_fn!(unsafe gethostbyname(name: *const c_char) -> Result<*const hostent> {
+    // XXX h_errno
+    let mut addr = mem::uninitialized();
+    let mut host_addr = if ::socket::inet_aton(name, &mut addr) == 1 {
+        addr
+    } else {
+        // XXX
+        let mut host = lookup_host(str::from_utf8_unchecked(::cstr_to_slice(name)))?;
+        host.next().ok_or(Error::new(syscall::ENOENT))? // XXX
+    };
+
+    let host_name: Vec<u8> = ::cstr_to_slice(name).to_vec();
+    HOST_ADDR_LIST = [host_addr.s_addr.as_mut_ptr() as *const c_char, null()];
+    HOST_ADDR = Some(host_addr);
+
+    HOST_ENTRY = hostent {
+        h_name: host_name.as_ptr() as *const c_char,
+        h_aliases: [null();2].as_mut_ptr(),
+        h_addrtype: ::socket::AF_INET,
+        h_length: 4,
+        h_addr_list: HOST_ADDR_LIST.as_ptr()
+    };
+
+    HOST_NAME = Some(host_name);
+
+    Ok(&HOST_ENTRY as *const hostent)
+});
+
+libc_fn!(unsafe gethostent() -> *const hostent {
+    if HOSTDB == 0 {
+        HOSTDB = syscall::open("/etc/hosts", syscall::O_RDONLY).unwrap();
+        H_LINE = RawLineBuffer::new(HOSTDB);
+    } 
+
+    let mut r: Box<str> = Box::default(); 
+    while r.is_empty() || r.split_whitespace().next() == None || r.starts_with("#") {
+        r = match H_LINE.next() {
+            Some(Ok(s)) => s,
+            Some(Err(_)) => return null(),
+            None => return null(),
+        };
+    }
+
+
+    let mut iter: SplitWhitespace = r.split_whitespace();
+    
+    let mut addr_vec = iter.next().unwrap().as_bytes().to_vec();
+    addr_vec.push(b'\0');
+    let addr_cstr = addr_vec.as_slice().as_ptr() as *const i8;
+    let mut addr = mem::uninitialized();
+    ::socket::inet_aton(addr_cstr, &mut addr);
+    HOST_ADDR_LIST = [addr.s_addr.as_mut_ptr() as *const c_char, null()];
+    HOST_ADDR = Some(addr);
+
+    let mut host_name = iter.next().unwrap().as_bytes().to_vec();
+    host_name.push(b'\0');
+    
+    let mut host_aliases: Vec<Vec<u8>> = Vec::new(); 
+    
+    loop {
+        let mut alias = match iter.next() {
+            Some(s) => s.as_bytes().to_vec(),
+            None => break
+        };
+        alias.push(b'\0');
+        host_aliases.push(alias);
+    }
+
+    //push a 0 so c doesn't segfault when it tries to read the next entry
+    host_aliases.push(vec![b'\0']);
+
+    HOST_ENTRY = hostent { 
+        h_name: host_name.as_ptr() as *const c_char,
+        h_aliases: host_aliases.as_slice().as_ptr() as *const *const i8,
+        h_addrtype: ::socket::AF_INET, 
+        h_length: 4,
+        h_addr_list: HOST_ADDR_LIST.as_ptr()
+    };
+        HOST_ALIASES = Some(host_aliases);
+        HOST_NAME = Some(host_name); 
+        &HOST_ENTRY as *const hostent
+});
+
+/*
+ *libc_fn!(getnetbyaddr(net: libc::uint32_t, net_type: libc::c_int) -> Result<*const netent> {
+ *    if NETDB == 0 {
+ *        NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
+ *    }
+ *});
+ *
+ *libc_fn!(getnetbyname(name: *const libc::c_char) -> Result<*const netent> {
+ *    if NETDB == 0 {
+ *        NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
+ *    }
+ *});
+ *
+ */
+
+
+/*
+ *libc_fn!(getnetent() -> Result<*const netent> {
+ *    if NETDB == 0 {
+ *        NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
+ *    }
+ *
+ *});
+ */
+
+libc_fn!(unsafe getprotobyname(name: *const libc::c_char) -> Result<*const protoent> {
+    setprotoent(0);
+    let mut p: *const protoent;
+    while {p=getprotoent();
+           p!=null()} {
+        if libc::strcmp((*p).p_name, name) == 0 {
+            return Ok(p);
+        }
+        loop {
+            let mut cp = (*p).p_aliases;
+            if cp == null() {
+                break;
+            }
+			if libc::strcmp(*cp, name) == 0 {
+			    return Ok(p);
+			}
+			cp = cp.offset(1);
+	    }
+    } 
+    endprotoent();
+    Err(Error::new(syscall::ENOENT))
+});
+
+libc_fn!(unsafe getprotobynumber(number: libc::c_int) -> Result<*const protoent> {
+    setprotoent(0);
+    let mut p: *const protoent;
+    while {p=getprotoent();
+           p!=null()} {
+        if (*p).p_proto == number {
+            return Ok(p);
+        }
+    }
+    endprotoent();
+    Err(Error::new(syscall::ENOENT))
+ });
+
+libc_fn!(unsafe getprotoent() -> *const protoent {
+    if PROTODB == 0 {
+        PROTODB = syscall::open("/etc/protocols", syscall::O_RDONLY).unwrap();
+        P_LINE = RawLineBuffer::new(PROTODB);
+    } 
+
+    let mut r: Box<str> = Box::default(); 
+    while r.is_empty() || r.split_whitespace().next() == None || r.starts_with("#") {
+        r = match P_LINE.next() {
+            Some(Ok(s)) => s,
+            Some(Err(_)) => return null(),
+            None => return null(),
+        };
+    }
+
+    let mut iter: SplitWhitespace = r.split_whitespace();
+    let mut proto_name: Vec<u8> = iter.next().unwrap().as_bytes().to_vec(); 
+    proto_name.push(b'\0');
+    
+    let mut num = iter.next().unwrap().as_bytes().to_vec();
+    num.push(b'\0');
+    PROTO_NUM = Some(libc::atoi(num.as_slice().as_ptr() as *mut i8)); 
+
+    let mut proto_aliases: Vec<Vec<u8>> = Vec::new(); 
+    loop {
+        let mut alias = match iter.next() {
+            Some(s) => s.as_bytes().to_vec(),
+            None => break
+        };
+        alias.push(b'\0');
+        proto_aliases.push(alias);
+    }
+    //push a 0 so c doesn't segfault when it tries to read the next entry
+    proto_aliases.push(vec![b'\0']);
+
+    PROTO_ENTRY = protoent { 
+        p_name: proto_name.as_slice().as_ptr() as *const c_char,
+        p_aliases: proto_aliases.iter().map(|x| x.as_ptr() as *const i8).collect::<Vec<*const i8>>().as_ptr(),
+        p_proto: PROTO_NUM.unwrap()           
+    };
+    PROTO_ALIASES = Some(proto_aliases);
+    PROTO_NAME = Some(proto_name); 
+    &PROTO_ENTRY as *const protoent
+});
+
+libc_fn!(unsafe getservbyname(name: *const libc::c_char, proto: *const libc::c_char) -> Result<*const servent> {
+    setservent(0);
+    let mut p: *const servent;
+    while {p=getservent();
+           p!=null()} {
+        if libc::strcmp((*p).s_name, name) == 0 && libc::strcmp((*p).s_proto, proto) == 0 {
+            return Ok(p);
+        }
+        loop {
+            let mut cp = (*p).s_aliases;
+            if cp == null() {
+                break;
+            }
+			if libc::strcmp(*cp, name) == 0 && libc::strcmp((*p).s_proto, proto) == 0 {
+			    return Ok(p);
+			}
+			cp = cp.offset(1);
+	    }
+    }
+    Err(Error::new(syscall::ENOENT))
+});
+
+libc_fn!(unsafe getservbyport(port: libc::c_int, proto: *const libc::c_char) -> Result<*const servent> {
+    setprotoent(0);
+    let mut p: *const servent;
+    while {p=getservent();
+           p!=null()} {
+        if (*p).s_port == port && libc::strcmp((*p).s_proto, proto) == 0 {
+            return Ok(p);
+        }
+    }
+    endprotoent();
+    Err(Error::new(syscall::ENOENT))
+
+});
+
+libc_fn!(unsafe getservent() -> *const servent {
+    if SERVDB == 0 {
+        SERVDB = syscall::open("/etc/services", syscall::O_RDONLY).unwrap();
+        S_LINE = RawLineBuffer::new(SERVDB);
+    } 
+
+    let mut r: Box<str> = Box::default(); 
+    while r.is_empty() || r.split_whitespace().next() == None || r.starts_with("#") {
+        r = match S_LINE.next() {
+            Some(Ok(s)) => s,
+            Some(Err(_)) => return null(),
+            None => return null(),
+        };
+    }
+    let mut iter: SplitWhitespace = r.split_whitespace();
+
+    let mut serv_name: Vec<u8> = iter.next().unwrap().as_bytes().to_vec(); 
+    serv_name.push(b'\0');
+
+    let port_proto = iter.next().unwrap();
+    let mut split = port_proto.split("/");
+    let port = libc::atoi(split.next().unwrap().as_ptr() as *const i8);
+    SERV_PORT = Some(port);
+    let proto = split.next().unwrap().as_bytes().to_vec();
+
+    let mut serv_aliases: Vec<Vec<u8>> = Vec::new(); 
+    loop {
+        let mut alias = match iter.next() {
+            Some(s) => s.as_bytes().to_vec(),
+            None => break
+        };
+        alias.push(b'\0');
+        serv_aliases.push(alias);
+    }
+    //push a 0 so c doesn't segfault when it tries to read the next entry
+    serv_aliases.push(vec![b'\0']);
+
+    SERV_ENTRY = servent { 
+        s_name: serv_name.as_slice().as_ptr() as *const c_char,
+        s_aliases: serv_aliases.iter().map(|x| x.as_ptr() as *const i8).collect::<Vec<*const i8>>().as_ptr(),
+        s_port: SERV_PORT.unwrap(),
+        s_proto: proto.as_slice().as_ptr() as *const c_char            
+    };
+
+    SERV_ALIASES = Some(serv_aliases);
+    SERV_NAME = Some(serv_name); 
+    SERV_PROTO = Some(proto);
+    &SERV_ENTRY as *const servent
+
+});
+
+libc_fn!(unsafe sethostent(stayopen: libc::c_int)  {
+    if HOSTDB == 0 {
+        HOSTDB = syscall::open("/etc/hosts", syscall::O_RDONLY).unwrap();
+    } else {
+        let _ = syscall::lseek(HOSTDB, 0, syscall::SEEK_SET);
+    }
+    H_LINE = RawLineBuffer::new(HOSTDB);
+});
+
+/*
+ *libc_fn!(unsafe setnetent(stayopen: libc::c_int)  {
+ *    if NETDB == 0 {
+ *        NETDB = syscall::open("/etc/networks", syscall::O_RDONLY).unwrap();
+ *    } else {
+ *        let _ = syscall::lseek(NETDB, 0, syscall::SEEK_SET);
+ *    }
+ *});
+ */
+
+libc_fn!(unsafe setprotoent(stayopen: libc::c_int)  {
+    if PROTODB == 0 {
+        PROTODB = syscall::open("/etc/protocols", syscall::O_RDONLY).unwrap();
+    } else {
+        let _ = syscall::lseek(PROTODB, 0, syscall::SEEK_SET);
+    }
+    P_LINE = RawLineBuffer::new(PROTODB);
+});
+
+libc_fn!(unsafe setservent(stayopen: libc::c_int)  {
+    if SERVDB == 0 {
+        SERVDB = syscall::open("/etc/services", syscall::O_RDONLY).unwrap();
+    } else {
+        let _ = syscall::lseek(SERVDB, 0, syscall::SEEK_SET);
+    }
+    S_LINE = RawLineBuffer::new(SERVDB);
+});
+
+//libc_fn!(getaddrinfo(node: *const libc::c_char, service: *const libc::c_char, hints: *const addrinfo, res: *mut *mut addrinfo) -> libc::c_int {
+
+//});
+
+//libc_fn!(getnameinfo(addr: *const sockaddr, addrlen: socklen_t, host: *mut libc::c_char, hostlen: socklen_t, serv: *mut libc::c_char, servlen: socklen_t, flags: libc::c_int) -> libc::c_int {
+
+//});
+
+//libc_fn!(freeaddrinfo(res: *mut addrinfo)  {
+
+//});
+
+//libc_fn!(gai_strerror(errcode: libc::c_int) -> *const libc::c_char {
+
+//});

+ 207 - 0
src/todo/oldlib/process.rs

@@ -0,0 +1,207 @@
+use libc::{c_char, c_int, c_void, size_t, gid_t, uid_t, ptrdiff_t};
+use ::types::pid_t;
+use core::slice;
+use alloc::Vec;
+use syscall::error::{Error, EINVAL};
+use syscall;
+
+const MAXPATHLEN: usize = 1024;
+static mut CURR_BRK: usize = 0;
+
+libc_fn!(unsafe chdir(path: *const c_char) -> Result<c_int> {
+    Ok(syscall::chdir(::cstr_to_slice(path))? as c_int)
+});
+
+libc_fn!(unsafe fchdir(fd: c_int) -> Result<c_int> {
+    let mut buf = [0; MAXPATHLEN];
+    let length = syscall::fpath(fd as usize, &mut buf)?;
+    Ok(syscall::chdir(&buf[0..length])? as c_int)
+});
+
+libc_fn!(unsafe _exit(code: c_int) {
+    ::__libc_fini_array();
+    syscall::exit(code as usize).unwrap();
+});
+
+libc_fn!(unsafe _execve(name: *const c_char, argv: *const *const c_char, env: *const *const c_char) -> Result<c_int> {
+    let mut env = env;
+    while !(*env).is_null() {
+        let slice = ::cstr_to_slice(*env);
+        // Should always contain a =, but worth checking
+        if let Some(sep) = slice.iter().position(|&c| c == b'=') {
+            let mut path = b"env:".to_vec();
+            path.extend_from_slice(&slice[..sep]);
+            if let Ok(fd) = ::RawFile::open(&path, syscall::O_WRONLY | syscall::O_CREAT) {
+                let _ = syscall::write(*fd, &slice[sep+1..]);
+            }
+        }
+        env = env.offset(1);
+    }
+
+    let mut args: Vec<[usize; 2]> = Vec::new();
+    let mut arg = argv;
+    while !(*arg).is_null() {
+        args.push([*arg as usize, ::strlen(*arg)]);
+        arg = arg.offset(1);
+    }
+
+    Ok(syscall::execve(::cstr_to_slice(name), &args)? as c_int)
+});
+
+libc_fn!(unsafe _fork() -> Result<c_int> {
+    Ok(syscall::clone(0)? as c_int)
+});
+
+libc_fn!(unsafe vfork() -> Result<c_int> {
+    Ok(syscall::clone(syscall::CLONE_VFORK)? as c_int)
+});
+
+libc_fn!(unsafe getcwd(buf: *mut c_char, size: size_t) -> Result<*const c_char> {
+    let mut size = size;
+    if size == 0 {
+        size = ::file::PATH_MAX;
+    }
+    let buf = ::MallocNull::new(buf, size);
+    let slice = slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, size);
+    let count = syscall::getcwd(&mut slice[..size-1])?;
+    slice[count] = b'\0';
+    Ok(buf.into_raw())
+    // FIXME: buffer too small
+});
+
+libc_fn!(unsafe getwd(buf: *mut c_char) -> Result<*const c_char> {
+
+    if buf.is_null() {
+        Err(Error::new(EINVAL))
+    } else {
+        let mut tmp: [u8; MAXPATHLEN] = [0; MAXPATHLEN];
+        syscall::getcwd(&mut tmp)?;
+        slice::from_raw_parts_mut(buf as *mut u8, MAXPATHLEN)
+            .copy_from_slice(&mut tmp);
+        Ok(buf)
+    }
+});
+
+libc_fn!(unsafe _getpid() -> pid_t {
+    syscall::getpid().unwrap() as pid_t
+});
+
+libc_fn!(unsafe getppid() -> pid_t {
+    syscall::getppid().unwrap() as pid_t
+});
+
+libc_fn!(unsafe getegid() -> gid_t {
+    syscall::getegid().unwrap() as gid_t
+});
+
+libc_fn!(unsafe geteuid() -> uid_t {
+    syscall::geteuid().unwrap() as uid_t
+});
+
+libc_fn!(unsafe getgid() -> gid_t {
+    syscall::getgid().unwrap() as gid_t
+});
+
+libc_fn!(unsafe getuid() -> uid_t {
+    syscall::getuid().unwrap() as uid_t
+});
+
+libc_fn!(unsafe _kill(pid: c_int, sig: c_int) -> Result<c_int> {
+    Ok(syscall::kill(pid as usize, sig as usize)? as c_int)
+});
+
+libc_fn!(unsafe _brk(end_data_segment: *mut c_void) -> Result<c_int> {
+    CURR_BRK = syscall::brk(end_data_segment as usize)?;
+    Ok(0)
+});
+
+libc_fn!(unsafe _sbrk(increment: ptrdiff_t) -> *mut c_void {
+    if CURR_BRK == 0 {
+        CURR_BRK = syscall::brk(0).unwrap();
+    }
+    let old_brk = CURR_BRK;
+    if increment != 0 {
+        let addr = if increment >= 0 {
+            old_brk + increment as usize
+        } else {
+            old_brk - (-increment) as usize
+        };
+        CURR_BRK = match syscall::brk(addr) {
+            Ok(x) => x,
+            Err(err) => {
+                *::__errno() = err.errno;
+                return -1 as isize as *mut c_void;
+            }
+        }
+    }
+    old_brk as *mut c_void
+});
+
+libc_fn!(unsafe _sched_yield() -> Result<c_int> {
+    Ok(syscall::sched_yield()? as c_int)
+});
+
+libc_fn!(unsafe _system(s: *const c_char) -> Result<c_int> {
+    match syscall::clone(0)? {
+        0 => {
+            let shell = "/bin/sh";
+            let arg1 = "-c";
+            let args = [
+                [shell.as_ptr() as usize, shell.len()],
+                [arg1.as_ptr() as usize, arg1.len()],
+                [s as usize, ::strlen(s)]
+            ];
+            syscall::execve(shell, &args)?;
+            syscall::exit(100)?;
+            unreachable!()
+        }
+        pid => {
+            let mut status = 0;
+            syscall::waitpid(pid, &mut status, 0)?;
+            Ok(status as c_int)
+        }
+    }
+});
+
+libc_fn!(unsafe setregid(rgid: gid_t, egid: gid_t) -> Result<c_int> {
+    Ok(syscall::setregid(rgid as usize, egid as usize)? as c_int)
+});
+
+libc_fn!(unsafe setegid(egid: gid_t) -> Result<c_int> {
+    Ok(syscall::setregid(-1isize as usize, egid as usize)? as c_int)
+});
+
+libc_fn!(unsafe setgid(gid: gid_t) -> Result<c_int> {
+    Ok(syscall::setregid(gid as usize, gid as usize)? as c_int)
+});
+
+libc_fn!(unsafe setreuid(ruid: uid_t, euid: uid_t) -> Result<c_int> {
+    Ok(syscall::setreuid(ruid as usize, euid as usize)? as c_int)
+});
+
+libc_fn!(unsafe seteuid(euid: uid_t) -> Result<c_int> {
+    Ok(syscall::setreuid(-1isize as usize, euid as usize)? as c_int)
+});
+
+libc_fn!(unsafe setuid(uid: uid_t) -> Result<c_int> {
+    Ok(syscall::setreuid(uid as usize, uid as usize)? as c_int)
+});
+
+libc_fn!(unsafe _wait(status: *mut c_int) -> Result<c_int> {
+    let mut buf = 0;
+    let res = syscall::waitpid(0, &mut buf, 0)?;
+    *status = buf as c_int;
+    Ok(res as c_int)
+});
+
+libc_fn!(unsafe waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> Result<c_int> {
+    let mut buf = 0;
+    let pid = if pid == -1 {
+        0
+    } else {
+        pid as usize
+    };
+    let res = syscall::waitpid(pid as usize, &mut buf, options as usize)?;
+    *status = buf as c_int;
+    Ok(res as c_int)
+});

+ 28 - 0
src/todo/oldlib/rawfile.rs

@@ -0,0 +1,28 @@
+use syscall;
+use core::ops::Deref;
+
+pub struct RawFile(usize);
+
+impl RawFile {
+    pub fn open<T: AsRef<[u8]>>(path: T, flags: usize) -> syscall::Result<RawFile> {
+        syscall::open(path, flags).map(RawFile)
+    }
+
+    pub fn dup(&self, buf: &[u8]) -> syscall::Result<RawFile> {
+        syscall::dup(self.0, buf).map(RawFile)
+    }
+}
+
+impl Drop for RawFile {
+    fn drop(&mut self) {
+        let _ = syscall::close(self.0);
+    }
+}
+
+impl Deref for RawFile {
+    type Target = usize;
+
+    fn deref(&self) -> &usize {
+        &self.0
+    }
+}

+ 40 - 0
src/todo/oldlib/redox.rs

@@ -0,0 +1,40 @@
+use syscall;
+use libc::{c_int, c_char, c_void, size_t};
+use core::slice;
+
+libc_fn!(unsafe redox_fevent(file: c_int, flags: c_int) -> Result<c_int> {
+    Ok(syscall::fevent(file as usize, flags as usize)? as c_int)
+});
+
+libc_fn!(unsafe redox_fpath(file: c_int, buf: *mut c_char, len: size_t) -> Result<c_int> {
+    let buf = slice::from_raw_parts_mut(buf as *mut u8, len);
+    Ok(syscall::fpath(file as usize, buf)? as c_int)
+});
+
+libc_fn!(unsafe redox_fmap(file: c_int, offset: size_t, size: size_t) -> Result<*mut c_void> {
+    Ok(syscall::fmap(file as usize, offset, size)? as *mut c_void)
+});
+
+libc_fn!(unsafe redox_funmap(addr: *mut c_void) -> Result<c_int> {
+    Ok(syscall::funmap(addr as usize)? as c_int)
+});
+
+libc_fn!(unsafe redox_physalloc(size: size_t) -> Result<*mut c_void> {
+    Ok(syscall::physalloc(size)? as *mut c_void)
+});
+
+libc_fn!(unsafe redox_physfree(physical_address: *mut c_void, size: size_t) -> Result<c_int> {
+    Ok(syscall::physfree(physical_address as usize, size)? as c_int)
+});
+
+libc_fn!(unsafe redox_physmap(physical_address: *mut c_void, size: size_t, flags: c_int) -> Result<*mut c_void> {
+    Ok(syscall::physmap(physical_address as usize, size, flags as usize)? as *mut c_void)
+});
+
+libc_fn!(unsafe redox_physunmap(virtual_address: *mut c_void) -> Result<c_int> {
+    Ok(syscall::physunmap(virtual_address as usize)? as c_int)
+});
+
+libc_fn!(unsafe redox_virttophys(virtual_address: *mut c_void) -> Result<*mut c_void> {
+    Ok(syscall::virttophys(virtual_address as usize)? as *mut c_void)
+});

+ 248 - 0
src/todo/oldlib/socket.rs

@@ -0,0 +1,248 @@
+use core::str::{self, FromStr};
+use core::mem;
+use core::ptr;
+use libc::{c_int, c_char, size_t, c_void, ssize_t};
+use ::types::{socklen_t, in_addr, sockaddr, sockaddr_in};
+use syscall::{self, O_RDWR};
+use syscall::error::{Error, EPROTOTYPE, EPROTONOSUPPORT, EAFNOSUPPORT, EINVAL, EOPNOTSUPP, ENOBUFS, ENOSPC};
+use core::slice;
+use byteorder::{BigEndian, ByteOrder};
+
+
+pub const AF_INET: c_int = 2;
+pub const SOCK_STREAM: c_int = 1;
+pub const SOCK_DGRAM: c_int = 2;
+
+static mut NTOA_ADDR: [c_char; 16] = [0; 16];
+
+libc_fn!(unsafe inet_aton(cp: *const c_char, inp: *mut in_addr) -> c_int {
+    // TODO: octal/hex
+    inet_pton(AF_INET, cp, inp as *mut c_void)
+});
+
+libc_fn!(unsafe inet_ntoa(addr: in_addr) -> *const c_char {
+    inet_ntop(AF_INET, &addr as *const in_addr as *const c_void, NTOA_ADDR.as_mut_ptr(), 16)
+});
+
+libc_fn!(unsafe inet_pton(domain: c_int, src: *const c_char, dest: *mut c_void) -> Result<c_int> {
+    if domain != AF_INET {
+        Err(Error::new(EAFNOSUPPORT))
+    } else {
+        let s_addr = &mut ((*(dest as *mut in_addr)).s_addr);
+        let mut octets = str::from_utf8_unchecked(::cstr_to_slice(src)).split('.');
+        for i in 0..4 {
+            if let Some(n) = octets.next().and_then(|x| u8::from_str(x).ok()) {
+                s_addr[i] = n;
+            } else {
+                return Ok(0);
+            }
+        }
+        if octets.next() == None {
+            Ok(1) // Success
+        } else {
+            Ok(0)
+        }
+    }
+});
+
+libc_fn!(unsafe inet_ntop(domain: c_int, src: *const c_void, dest: *mut c_char, size: socklen_t) -> Result<*const c_char> {
+    if domain != AF_INET {
+        Err(Error::new(EAFNOSUPPORT))
+    } else if size < 16 {
+        Err(Error::new(ENOSPC))
+    } else {
+        let s_addr = (&*(src as *const in_addr)).s_addr;
+        let addr = format!("{}.{}.{}.{}\0", s_addr[0], s_addr[1], s_addr[2], s_addr[3]);
+        ptr::copy(addr.as_ptr() as *const c_char, dest, addr.len());
+        Ok(dest)
+    }
+});
+
+libc_fn!(unsafe socket(domain: c_int, type_: c_int, protocol: c_int) -> Result<c_int> {
+    if domain != AF_INET {
+        Err(Error::new(EAFNOSUPPORT))
+    } else if protocol != 0 {
+        Err(Error::new(EPROTONOSUPPORT))
+    } else {
+        let fd = match type_ {
+            SOCK_STREAM => syscall::open("tcp:", O_RDWR),
+            SOCK_DGRAM => syscall::open("udp:", O_RDWR),
+            _ => Err(Error::new(EPROTOTYPE))
+        }?;
+        Ok(fd as c_int)
+    }
+});
+
+libc_fn!(unsafe connect(socket: c_int, address: *const sockaddr, _address_len: socklen_t) -> Result<c_int> {
+    // XXX with UDP, should recieve messages only from that peer after this
+    // XXX Check address_len
+    if (*address).sa_family as i32 != AF_INET {
+        return Err(Error::new(EINVAL))
+    };
+    let address = &*(address as *const sockaddr_in);
+    let s_addr =address.sin_addr.s_addr;
+    let path = format!("{}.{}.{}.{}:{}", s_addr[0], s_addr[1], s_addr[2], s_addr[3], ntohs(address.sin_port));
+    let fd = syscall::dup(socket as usize, path.as_bytes())?;
+    let ret = syscall::dup2(fd, socket as usize, &vec![]);
+    let _ = syscall::close(fd);
+    ret?;
+    Ok(0)
+});
+
+libc_fn!(unsafe bind(socket: c_int, address: *const sockaddr, _address_len: socklen_t) -> Result<c_int> {
+    // XXX Check address_len
+    if (*address).sa_family as i32 != AF_INET {
+        return Err(Error::new(EINVAL))
+    };
+    let address = &*(address as *const sockaddr_in);
+    let s_addr =address.sin_addr.s_addr;
+    let path = format!("/{}.{}.{}.{}:{}", s_addr[0], s_addr[1], s_addr[2], s_addr[3], ntohs(address.sin_port));
+    let fd = syscall::dup(socket as usize, path.as_bytes())?;
+    let ret = syscall::dup2(fd, socket as usize, &vec![]);
+    let _ = syscall::close(fd);
+    ret?;
+    Ok(0)
+});
+
+libc_fn!(unsafe listen(_socket: c_int, _backlog: c_int) -> Result<c_int> {
+    // TODO
+    Ok(0)
+});
+
+libc_fn!(unsafe recv(socket: c_int, buffer: *mut c_void, length: size_t, flags: c_int) -> Result<ssize_t> {
+    // XXX flags
+    if flags != 0 {
+        Err(Error::new(EOPNOTSUPP))
+    } else {
+        let buf = slice::from_raw_parts_mut(buffer as *mut u8, length);
+        Ok(syscall::read(socket as usize, buf)? as ssize_t)
+    }
+});
+
+libc_fn!(unsafe send(socket: c_int, buffer: *const c_void, length: size_t, flags: c_int) -> Result<ssize_t> {
+    if flags != 0 {
+        Err(Error::new(EOPNOTSUPP))
+    } else {
+        let buf = slice::from_raw_parts(buffer as *const u8, length);
+        Ok(syscall::write(socket as usize, buf)? as ssize_t)
+    }
+});
+
+libc_fn!(unsafe recvfrom(socket: c_int, buffer: *mut c_void, length: size_t, flags: c_int, _address: *const sockaddr, _address_len: *const socklen_t) -> Result<ssize_t>  {
+    let fd = syscall::dup(socket as usize, b"listen")?;
+    let mut path = [0; 4096];
+    syscall::fpath(socket as usize, &mut path)?;
+    // XXX process path and write to address
+    let ret = recv(socket, buffer, length, flags);
+    syscall::close(fd)?;
+    Ok(ret)
+});
+
+libc_fn!(unsafe sendto(socket: c_int, message: *const c_void, length: size_t, flags: c_int, dest_addr: *const sockaddr, _dest_len: socklen_t) -> Result<ssize_t> {
+    // XXX test dest_len
+    if (*dest_addr).sa_family as i32 == AF_INET {
+        let addr = &*(dest_addr as *const sockaddr_in);
+        let s_addr = addr.sin_addr.s_addr;
+        let url = format!("{}.{}.{}.{}:{}", s_addr[0], s_addr[1], s_addr[2], s_addr[3], ntohs(addr.sin_port));
+        let fd = syscall::dup(socket as usize, url.as_bytes())?;
+        let ret = send(fd as c_int, message, length, flags);
+        syscall::close(fd)?;
+        Ok(ret)
+    } else {
+        Err(Error::new(EOPNOTSUPP))
+    }
+});
+
+libc_fn!(unsafe getpeername(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> Result<c_int> {
+    // XXX will need to be changed for other sockaddr types
+    if *address_len < mem::size_of::<sockaddr_in>() {
+        return Err(Error::new(ENOBUFS));
+    }
+    *address_len = mem::size_of::<sockaddr_in>();
+    let addr = &mut *(address as *mut sockaddr_in);
+    addr.sin_family = AF_INET as u16;
+
+    let mut path = [0; 4096];
+    syscall::fpath(socket as usize, &mut path)?;
+    let start;
+    let sep;
+    let end;
+    {
+        let mut iter = path.iter();
+        start = iter.position(|x| *x == b':').ok_or(Error::new(EINVAL))? + 1;
+        sep = start + iter.position(|x| *x == b':').ok_or(Error::new(EINVAL))?;
+        end = sep + 1 + iter.position(|x| *x == b'/').ok_or(Error::new(EINVAL))?;
+    }
+    path[sep] = b'\0';
+
+    if inet_aton(&path[start] as *const u8 as *const c_char, &mut addr.sin_addr) == 1 {
+        if let Ok(port) = u16::from_str(str::from_utf8_unchecked(&path[sep+1..end])) {
+            addr.sin_port = htons(port);
+            Ok(0)
+        } else {
+            Err(Error::new(EINVAL))
+        }
+    } else {
+        Err(Error::new(EINVAL)) // ?
+    }
+});
+
+libc_fn!(unsafe getsockname(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> Result<c_int> {
+    // XXX will need to be changed for other sockaddr types
+    if *address_len < mem::size_of::<sockaddr_in>() {
+        return Err(Error::new(ENOBUFS));
+    }
+    *address_len = mem::size_of::<sockaddr_in>();
+    let addr = &mut *(address as *mut sockaddr_in);
+    addr.sin_family = AF_INET as u16;
+
+    let mut path = [0; 4096];
+    syscall::fpath(socket as usize, &mut path)?;
+    let start;
+    let sep;
+    let end;
+    {
+        let mut iter = path.iter();
+        start = iter.position(|x| *x == b'/').ok_or(Error::new(EINVAL))? + 1;
+        sep = start + iter.position(|x| *x == b':').ok_or(Error::new(EINVAL))?;
+        end = sep + 1 + iter.position(|x| *x == b'\0').ok_or(Error::new(EINVAL))?;
+    }
+    path[sep] = b'\0';
+
+    if inet_aton(&path[start] as *const u8 as *const c_char, &mut addr.sin_addr) == 1 {
+        if let Ok(port) = u16::from_str(str::from_utf8_unchecked(&path[sep+1..end])) {
+            addr.sin_port = htons(port);
+            Ok(0)
+        } else {
+            Err(Error::new(EINVAL))
+        }
+    } else {
+        Err(Error::new(EINVAL)) // ?
+    }
+});
+
+libc_fn!(htonl(hostlong: u32) -> [u8; 4] {
+    let mut netlong = [0; 4];
+    BigEndian::write_u32(&mut netlong, hostlong);
+    netlong
+});
+
+libc_fn!(htons(hostshort: u16) -> [u8; 2] {
+    let mut netshort = [0; 2];
+    BigEndian::write_u16(&mut netshort, hostshort);
+    netshort
+});
+
+libc_fn!(ntohl(netlong: [u8; 4]) -> u32 {
+    BigEndian::read_u32(&netlong)
+});
+
+libc_fn!(ntohs(netshort: [u8; 2]) -> u16 {
+    BigEndian::read_u16(&netshort)
+});
+
+libc_fn!(setsockopt(socket: c_int, level: c_int, option_name: c_int, option_value: *const c_void, option_len: socklen_t) -> Result<c_int> {
+    syscall::write(2, format!("unimplemented: setsockopt({}, {}, {}, {:?}, {})\n",
+                              socket, level, option_name, option_value, option_len).as_bytes()).unwrap();
+    Err(Error::new(syscall::ENOSYS))
+});

+ 93 - 0
src/todo/oldlib/termios.rs

@@ -0,0 +1,93 @@
+#![allow(non_camel_case_types)]
+
+use libc::{self, c_int};
+use redox_termios::{tcflag_t, Termios};
+use syscall::{self, EINVAL, Error};
+use ::types::pid_t;
+
+type speed_t = libc::c_uint;
+
+// tcsetattr args
+pub const TCSANOW:   tcflag_t = 0x1;
+pub const TCSADRAIN: tcflag_t = 0x2;
+pub const TCSAFLUSH: tcflag_t = 0x4;
+
+// tcflush args
+pub const TCIFLUSH:  tcflag_t = 0x1;
+pub const TCIOFLUSH: tcflag_t = 0x3;
+pub const TCOFLUSH:  tcflag_t = 0x2;
+
+// tcflow args
+pub const TCIOFF: tcflag_t = 0x1;
+pub const TCION:  tcflag_t = 0x2;
+pub const TCOOFF: tcflag_t = 0x4;
+pub const TCOON:  tcflag_t = 0x8;
+
+libc_fn!(unsafe tcgetattr(fd: c_int, tio: *mut Termios) -> Result<c_int> {
+    let fd = syscall::dup(fd as usize, b"termios")?;
+    let res = syscall::read(fd, &mut *tio);
+    let _ = syscall::close(fd);
+
+    if res? == (&*tio).len() {
+        Ok(0)
+    } else {
+        Err(Error::new(EINVAL))
+    }
+});
+
+libc_fn!(unsafe tcsetattr(fd: c_int, _arg: c_int, tio: *mut Termios) -> Result<c_int> {
+    let fd = syscall::dup(fd as usize, b"termios")?;
+    let res = syscall::write(fd, &*tio);
+    let _ = syscall::close(fd);
+
+    if res? == (&*tio).len() {
+        Ok(0)
+    } else {
+        Err(Error::new(EINVAL))
+    }
+});
+
+libc_fn!(cfgetispeed(_tio: *mut Termios) -> speed_t {
+    // TODO
+    0 as speed_t
+});
+
+libc_fn!(cfgetospeed(_tio: *mut Termios) -> speed_t {
+    // TODO
+    0 as speed_t
+});
+
+libc_fn!(cfsetispeed(_tio: *mut Termios, _speed: speed_t) -> Result<c_int> {
+    // TODO
+    Ok(0)
+});
+
+libc_fn!(cfsetospeed(_tio: *mut Termios, _speed: speed_t) -> Result<c_int> {
+    // TODO
+    Ok(0)
+});
+
+libc_fn!(tcdrain(_i: c_int) -> Result<c_int> {
+    // TODO
+    Ok(0)
+});
+
+libc_fn!(tcflow(_fd: c_int, _arg: c_int) -> Result<c_int> {
+    // TODO
+    Ok(0)
+});
+
+libc_fn!(tcflush(_fd: c_int, _arg: c_int) -> Result<c_int> {
+    // TODO
+    Ok(0)
+});
+
+libc_fn!(unsafe tcgetsid(_fd: c_int) -> pid_t {
+    // TODO
+    ::process::_getpid()
+});
+
+libc_fn!(tcsendbreak(_fd: c_int, _arg: c_int) -> Result<c_int> {
+    // TODO
+    Ok(0)
+});

+ 25 - 0
src/todo/oldlib/time.rs

@@ -0,0 +1,25 @@
+use syscall;
+use syscall::data::TimeSpec;
+use syscall::error::{Error, EFAULT};
+use libc::{c_int, c_void};
+use types::timeval;
+
+libc_fn!(unsafe clock_gettime(clk_id: c_int, tp: *mut TimeSpec) -> Result<c_int> {
+    Ok(syscall::clock_gettime(clk_id as usize, &mut *tp)? as c_int)
+});
+
+libc_fn!(unsafe _gettimeofday(tv: *mut timeval, _tz: *const c_void) -> Result<c_int> {
+    if !tv.is_null() {
+        let mut tp = TimeSpec::default();
+        syscall::clock_gettime(syscall::flag::CLOCK_REALTIME, &mut tp)?;
+        (*tv).tv_sec = tp.tv_sec;
+        (*tv).tv_usec = (tp.tv_nsec / 1000) as i64;
+        Ok(0)
+    } else {
+        Err(Error::new(EFAULT))
+    }
+});
+
+libc_fn!(unsafe nanosleep(req: *const TimeSpec, rem: *mut TimeSpec) -> Result<c_int> {
+    Ok(syscall::nanosleep(&*req, &mut *rem)? as c_int)
+});

+ 110 - 0
src/todo/oldlib/types.rs

@@ -0,0 +1,110 @@
+#![allow(non_camel_case_types, dead_code)]
+
+use libc;
+
+pub type pid_t = libc::c_int;
+
+pub type time_t = i64;
+pub type suseconds_t = libc::c_long;
+
+// Socket related types
+pub type in_addr_t = [u8; 4];
+pub type sa_family_t = u16;
+pub type socklen_t = libc::size_t;
+pub type in_port_t = [u8; 2];
+
+// Statvfs types
+pub type dev_t = libc::c_ulong;
+pub type ino_t = libc::c_ulong;
+pub type mode_t = libc::c_uint;
+pub type nlink_t = libc::c_ulong;
+pub type uid_t = libc::c_uint;
+pub type gid_t = libc::c_uint;
+pub type off_t = libc::c_long;
+pub type blksize_t = libc::c_long;
+pub type blkcnt_t = libc::c_long;
+pub type fsblkcnt_t = libc::c_ulong;
+pub type fsfilcnt_t = libc::c_ulong;
+pub type __fsword_t = libc::c_long;
+
+#[repr(C)]
+pub struct fsid_t {
+    __val: [libc::c_int; 2]
+}
+
+#[repr(C)]
+#[derive(Clone,Copy)]
+pub struct in_addr {
+    pub s_addr: in_addr_t
+}
+
+#[repr(C)]
+pub struct sockaddr {
+    pub sa_family: sa_family_t,
+    sa_data: [libc::c_char; 14]
+}
+
+#[repr(C)]
+pub struct sockaddr_in {
+    pub sin_family: sa_family_t,
+    pub sin_port: in_port_t,
+    pub sin_addr: in_addr,
+    __pad: [u8; 8]
+}
+
+#[repr(C)]
+pub struct hostent {
+    pub h_name: *const libc::c_char,
+    pub h_aliases: *const *const libc::c_char,
+    pub h_addrtype: libc::c_int,
+    pub h_length: libc::c_int,
+    pub h_addr_list: *const *const libc::c_char
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct timeval {
+    pub tv_sec: time_t,
+    pub tv_usec: suseconds_t
+}
+
+#[repr(C)]
+pub struct utimbuf {
+    pub actime: time_t,
+    pub modtime: time_t
+}
+
+pub type fd_mask = libc::c_ulong;
+pub const FD_SETSIZE: usize = 64;
+pub const NFDBITS: usize = 8 * 8; // Bits in a fd_mask
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct fd_set {
+    pub fds_bits: [fd_mask; (FD_SETSIZE + NFDBITS - 1) / NFDBITS]
+}
+
+pub const POLLIN: libc::c_short = 0x0001;
+pub const POLLPRI: libc::c_short = 0x0002;
+pub const POLLOUT: libc::c_short = 0x0004;
+pub const POLLERR: libc::c_short = 0x0008;
+pub const POLLHUP: libc::c_short = 0x0010;
+pub const POLLNVAL: libc::c_short = 0x0020;
+
+#[repr(C)]
+pub struct pollfd {
+    pub fd: libc::c_int,
+    pub events: libc::c_short,
+    pub revents: libc::c_short,
+}
+
+#[repr(C)]
+pub struct passwd {
+    pub pw_name: *const libc::c_char,
+    pub pw_passwd: *const libc::c_char,
+    pub pw_uid: libc::uid_t,
+    pub pw_gid: libc::gid_t,
+    pub pw_gecos: *const libc::c_char,
+    pub pw_dir: *const libc::c_char,
+    pub pw_shell: *const libc::c_char
+}

+ 66 - 0
src/todo/oldlib/unimpl.rs

@@ -0,0 +1,66 @@
+use syscall;
+use libc::{c_uint, c_int, c_char, gid_t, uid_t, c_void, c_long, mode_t};
+use syscall::error::{Error, EACCES, EPERM, EINVAL};
+
+#[allow(non_camel_case_types)]
+type clock_t = c_long;
+
+macro_rules! UNIMPL {
+    // Call with arguments and return value
+    ($func:ident, $err:ident) => {{
+         let err = Error::new($err);
+         let _ = syscall::write(2, format!("unimplemented: {}: {}\n",
+             stringify!($func), err).as_bytes());
+         Err(err)
+    }};
+}
+
+libc_fn!(alarm(_seconds: c_uint) -> c_uint {
+    let _ = syscall::write(2, "unimplemented: alarm\n".as_bytes());
+    0
+});
+
+libc_fn!(chown(_path: *mut c_char, _order: uid_t, _group: gid_t) -> Result<c_int> {
+    UNIMPL!(chown, EACCES)
+});
+
+libc_fn!(_getdtablesize() -> Result<c_int> {
+    Ok(65536)
+});
+
+// XXX variadic
+libc_fn!(_ioctl(_file: c_int, _request: c_int) -> Result<c_int> {
+    UNIMPL!(_ioctl, EINVAL)
+});
+
+libc_fn!(_link(_old: *const c_char, _new: *const c_char) -> Result<c_int> {
+    UNIMPL!(_link, EPERM)
+});
+
+/*
+libc_fn!(sysconf(_name: c_int) -> Result<c_long> {
+    UNIMPL!(sysconf, EINVAL)
+});
+*/
+
+// XXX type of argument pointer
+libc_fn!(_times(_buf: *mut c_void) -> Result<clock_t> {
+    UNIMPL!(_times, EINVAL)
+});
+
+libc_fn!(umask(_mode: mode_t) -> mode_t {
+    // All permissions granted
+    0o000
+});
+
+libc_fn!(ttyname(_fd: c_int) -> Result<*const c_char> {
+    UNIMPL!(ttyname, EINVAL)
+});
+
+libc_fn!(fpathconf(_fildes: c_int, _name: c_int) -> Result<c_long> {
+    UNIMPL!(fpathconf, EINVAL)
+});
+
+libc_fn!(getlogin() -> Result<*const c_char> {
+    UNIMPL!(getlogin, EINVAL)
+});

+ 95 - 0
src/todo/oldlib/user.rs

@@ -0,0 +1,95 @@
+use core::ptr::null;
+use libc::{uid_t, gid_t, c_char};
+use ::types::passwd;
+use syscall::{Error, ENOENT};
+use alloc::string::{String, ToString};
+use core::str::FromStr;
+
+static mut PASSWD: passwd = passwd {
+    pw_name: null(),
+    pw_passwd: null(),
+    pw_uid: 0,
+    pw_gid: 0,
+    pw_gecos: null(),
+    pw_dir: null(),
+    pw_shell: null()
+};
+
+static mut PW_NAME: Option<String> = None;
+static mut PW_PASSWD: Option<String> = None;
+static mut PW_GECOS: Option<String> = None;
+static mut PW_DIR: Option<String> = None;
+static mut PW_SHELL: Option<String> = None;
+
+macro_rules! try_opt {
+    ($e:expr) =>(
+        match $e {
+            Some(v) => v,
+            None => return None,
+        }
+    )
+}
+
+unsafe fn parse_passwd(pwd: &str) -> Option<*const passwd> {
+    let mut parts = pwd.split(';');
+
+    let name = try_opt!(parts.next()).to_string() + "\0";
+    let passwd = try_opt!(parts.next()).to_string() + "\0";
+    let uid = if let Ok(uid) = uid_t::from_str(try_opt!(parts.next())) {
+        uid
+    } else {
+        return None
+    };
+    let gid = if let Ok(gid) = gid_t::from_str(try_opt!(parts.next())) {
+        gid
+    } else {
+        return None
+    };
+    let gecos = try_opt!(parts.next()).to_string() + "\0";
+    let dir = try_opt!(parts.next()).to_string() + "\0";
+    let shell = try_opt!(parts.next()).to_string() + "\0";
+
+    PASSWD = passwd {
+        pw_name: name.as_ptr() as *const c_char,
+        pw_passwd: passwd.as_ptr() as *const c_char,
+        pw_uid: uid,
+        pw_gid: gid,
+        pw_gecos: gecos.as_ptr() as *const c_char,
+        pw_dir: dir.as_ptr() as *const c_char,
+        pw_shell: shell.as_ptr() as *const c_char
+    };
+
+    PW_NAME = Some(name);
+    PW_PASSWD = Some(passwd);
+    PW_GECOS = Some(gecos);
+    PW_DIR = Some(dir);
+    PW_SHELL = Some(shell);
+
+    Some(&PASSWD as *const _)
+}
+
+libc_fn!(unsafe getpwnam(name: *const c_char) -> Result<*const passwd> {
+    if let Ok(passwd_string) = String::from_utf8(::file_read_all("/etc/passwd")?) {
+        for line in passwd_string.lines() {
+            if line.split(';').nth(0).map(str::as_bytes) == Some(::cstr_to_slice(name)) {
+                if let Some(pass) = parse_passwd(line) {
+                    return Ok(pass);
+                }
+            }
+        }
+    }
+    Err(Error::new(ENOENT))
+});
+
+libc_fn!(unsafe getpwuid(uid: uid_t) -> Result<*const passwd> {
+    if let Ok(passwd_string) = String::from_utf8(::file_read_all("/etc/passwd")?) {
+        for line in passwd_string.lines() {
+            if line.split(';').nth(2).map(uid_t::from_str) == Some(Ok(uid)) {
+                if let Some(pass) = parse_passwd(line) {
+                    return Ok(pass);
+                }
+            }
+        }
+    }
+    Err(Error::new(ENOENT))
+});

+ 1 - 0
tests/Makefile

@@ -16,6 +16,7 @@ run: $(BINS)
 
 %: %.c
 	gcc \
+		-fno-stack-protector \
 		-nostdinc \
 		-nostdlib \
 		-I ../include \

+ 1 - 0
va_list

@@ -0,0 +1 @@
+Subproject commit 4762a184501beedbb58ea218f0c84fea85685c35