Add more bindings for signals and select/pselect
diff --git a/src/dox.rs b/src/dox.rs
index 9432b88..10e3934 100644
--- a/src/dox.rs
+++ b/src/dox.rs
@@ -5,6 +5,7 @@
     pub use std::option::Option;
     pub use std::clone::Clone;
     pub use std::marker::Copy;
+    pub use std::mem;
 }
 
 #[cfg(dox)]
@@ -43,6 +44,22 @@
         )
     }
 
+    #[lang = "div"]
+    pub trait Div<RHS> {
+        type Output;
+        fn div(self, rhs: RHS) -> Self::Output;
+    }
+
+    macro_rules! impl_div {
+        ($($i:ident)*) => ($(
+            impl Div<$i> for $i {
+                type Output = $i;
+                fn div(self, rhs: $i) -> $i { self / rhs }
+            }
+        )*)
+    }
+    each_int!(impl_div);
+
     #[lang = "shl"]
     pub trait Shl<RHS> {
         type Output;
@@ -106,4 +123,8 @@
         )*)
     }
     each_int!(impl_bitor);
+
+    pub mod mem {
+        pub fn size_of_val<T>(_: &T) -> usize { 4 }
+    }
 }
diff --git a/src/lib.rs b/src/lib.rs
index 797c539..6a5ae86 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,7 +10,7 @@
 
 //! Crate docs
 
-#![allow(bad_style, raw_pointer_derive, improper_ctypes)]
+#![allow(bad_style, raw_pointer_derive, overflowing_literals, improper_ctypes)]
 #![cfg_attr(dox, feature(no_core, lang_items))]
 #![cfg_attr(dox, no_core)]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/macros.rs b/src/macros.rs
index bb5d9ee..7cd8a24 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -47,6 +47,24 @@
     )*)
 }
 
+macro_rules! f {
+    ($(pub fn $i:ident($($arg:ident: $argty:ty),*) -> $ret:ty {
+        $($body:stmt);*
+    })*) => ($(
+        #[inline]
+        #[cfg(not(dox))]
+        pub unsafe extern fn $i($($arg: $argty),*) -> $ret {
+            $($body);*
+        }
+
+        #[cfg(dox)]
+        #[allow(dead_code)]
+        pub unsafe extern fn $i($($arg: $argty),*) -> $ret {
+            loop {}
+        }
+    )*)
+}
+
 macro_rules! __item {
     ($i:item) => ($i)
 }
diff --git a/src/unix/bsd/mod.rs b/src/unix/bsd/mod.rs
index 8c8460e..ca73806 100644
--- a/src/unix/bsd/mod.rs
+++ b/src/unix/bsd/mod.rs
@@ -62,20 +62,69 @@
         pub ifa_dstaddr: *mut ::sockaddr,
         pub ifa_data: *mut ::c_void
     }
+
+    pub struct fd_set {
+        fds_bits: [i32; FD_SETSIZE / 32],
+    }
 }
 
-pub const FIOCLEX: c_ulong = 0x20006601;
-pub const FIONBIO: ::c_int = 0x8004667e;
+pub const FIOCLEX: ::c_ulong = 0x20006601;
+pub const FIONBIO: ::c_ulong = 0x8004667e;
 
 pub const SA_ONSTACK: ::c_int = 0x0001;
 pub const SA_SIGINFO: ::c_int = 0x0040;
+pub const SA_RESTART: ::c_int = 0x0002;
+pub const SA_RESETHAND: ::c_int = 0x0004;
+pub const SA_NOCLDSTOP: ::c_int = 0x0008;
+pub const SA_NODEFER: ::c_int = 0x0010;
+pub const SA_NOCLDWAIT: ::c_int = 0x0020;
 
+pub const SIGCHLD: ::c_int = 20;
 pub const SIGBUS: ::c_int = 10;
 pub const SIG_SETMASK: ::c_int = 3;
 
 pub const IPV6_MULTICAST_LOOP: ::c_int = 11;
 pub const IPV6_V6ONLY: ::c_int = 27;
 
+pub const FD_SETSIZE: usize = 1024;
+
+f! {
+    pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () {
+        let fd = fd as usize;
+        (*set).fds_bits[fd / 32] &= !(1 << (fd % 32));
+        return
+    }
+
+    pub fn FD_ISSET(fd: ::c_int, set: *mut fd_set) -> bool {
+        let fd = fd as usize;
+        return ((*set).fds_bits[fd / 32] & (1 << (fd % 32))) != 0
+    }
+
+    pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () {
+        let fd = fd as usize;
+        (*set).fds_bits[fd / 32] |= 1 << (fd % 32);
+        return
+    }
+
+    pub fn FD_ZERO(set: *mut fd_set) -> () {
+        for slot in (*set).fds_bits.iter_mut() {
+            *slot = 0;
+        }
+    }
+
+    pub fn WIFEXITED(status: ::c_int) -> bool {
+        (status & 0x7f) == 0
+    }
+
+    pub fn WEXITSTATUS(status: ::c_int) -> ::c_int {
+        status >> 8
+    }
+
+    pub fn WTERMSIG(status: ::c_int) -> ::c_int {
+        status & 0o177
+    }
+}
+
 extern {
     pub fn mincore(addr: *const ::c_void, len: ::size_t,
                    vec: *mut c_char) -> ::c_int;
diff --git a/src/unix/mod.rs b/src/unix/mod.rs
index c780586..f29596e 100644
--- a/src/unix/mod.rs
+++ b/src/unix/mod.rs
@@ -505,6 +505,25 @@
                           align: ::size_t,
                           size: ::size_t) -> ::c_int;
     pub fn sigemptyset(set: *mut sigset_t) -> ::c_int;
+    #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"),
+               link_name = "select$1050")]
+    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+               link_name = "select$UNIX2003")]
+    pub fn select(nfds: ::c_int,
+                  readfs: *mut fd_set,
+                  writefds: *mut fd_set,
+                  errorfds: *mut fd_set,
+                  timeout: *mut timeval) -> ::c_int;
+    #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"),
+               link_name = "pselect$1050")]
+    #[cfg_attr(all(target_os = "macos", target_arch = "x86"),
+               link_name = "pselect$UNIX2003")]
+    pub fn pselect(nfds: ::c_int,
+                   readfs: *mut fd_set,
+                   writefds: *mut fd_set,
+                   errorfds: *mut fd_set,
+                   timeout: *const timespec,
+                   sigmask: *const sigset_t) -> ::c_int;
 }
 
 cfg_if! {
diff --git a/src/unix/notbsd/android/mod.rs b/src/unix/notbsd/android/mod.rs
index e26bcea..ee2765a 100644
--- a/src/unix/notbsd/android/mod.rs
+++ b/src/unix/notbsd/android/mod.rs
@@ -179,7 +179,9 @@
 
 pub const SA_ONSTACK: ::c_ulong = 0x08000000;
 pub const SA_SIGINFO: ::c_ulong = 0x00000004;
+pub const SA_NOCLDWAIT: ::c_int = 0x00000002;
 
+pub const SIGCHLD: ::c_int = 17;
 pub const SIGBUS: ::c_int = 7;
 pub const SIG_SETMASK: ::c_int = 2;
 
diff --git a/src/unix/notbsd/linux/mips.rs b/src/unix/notbsd/linux/mips.rs
index 607e6a1..ea9947c 100644
--- a/src/unix/notbsd/linux/mips.rs
+++ b/src/unix/notbsd/linux/mips.rs
@@ -202,11 +202,13 @@
 pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
 
 pub const FIOCLEX: ::c_ulong = 0x6601;
-pub const FIONBIO: ::c_int = 0x667e;
+pub const FIONBIO: ::c_ulong = 0x667e;
 
 pub const SA_ONSTACK: ::c_ulong = 0x08000000;
 pub const SA_SIGINFO: ::c_ulong = 0x00000008;
+pub const SA_NOCLDWAIT: ::c_int = 0x00010000;
 
+pub const SIGCHLD: ::c_int = 18;
 pub const SIGBUS: ::c_int = 10;
 
 pub const SIG_SETMASK: ::c_int = 3;
diff --git a/src/unix/notbsd/linux/notmips/mod.rs b/src/unix/notbsd/linux/notmips/mod.rs
index f69b1ac..1b01327 100644
--- a/src/unix/notbsd/linux/notmips/mod.rs
+++ b/src/unix/notbsd/linux/notmips/mod.rs
@@ -167,11 +167,13 @@
 pub const SO_REUSEPORT: ::c_int = 15;
 
 pub const FIOCLEX: ::c_ulong = 0x5451;
-pub const FIONBIO: ::c_int = 0x5421;
+pub const FIONBIO: ::c_ulong = 0x5421;
 
 pub const SA_ONSTACK: ::c_ulong = 0x08000000;
 pub const SA_SIGINFO: ::c_ulong = 0x00000004;
+pub const SA_NOCLDWAIT: ::c_int = 0x00000002;
 
+pub const SIGCHLD: ::c_int = 17;
 pub const SIGBUS: ::c_int = 7;
 pub const SIG_SETMASK: ::c_int = 2;
 
diff --git a/src/unix/notbsd/mod.rs b/src/unix/notbsd/mod.rs
index cd7547c..2cc900e 100644
--- a/src/unix/notbsd/mod.rs
+++ b/src/unix/notbsd/mod.rs
@@ -1,3 +1,5 @@
+use dox::mem;
+
 pub type rlim_t = c_ulong;
 pub type sa_family_t = u16;
 pub type pthread_key_t = ::c_uint;
@@ -66,8 +68,18 @@
         pub sll_halen: ::c_uchar,
         pub sll_addr: [::c_uchar; 8]
     }
+
+    pub struct fd_set {
+        fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE],
+    }
 }
 
+// intentionally not public, only used for fd_set
+#[cfg(target_pointer_width = "32")]
+const ULONG_SIZE: usize = 32;
+#[cfg(target_pointer_width = "64")]
+const ULONG_SIZE: usize = 64;
+
 pub const EXIT_FAILURE: ::c_int = 1;
 pub const EXIT_SUCCESS: ::c_int = 0;
 pub const RAND_MAX: ::c_int = 2147483647;
@@ -287,6 +299,53 @@
 
 pub const SIGSTKSZ: ::size_t = 8192;
 
+pub const SA_NODEFER: ::c_int = 0x40000000;
+pub const SA_RESETHAND: ::c_int = 0x80000000;
+pub const SA_RESTART: ::c_int = 0x10000000;
+pub const SA_NOCLDSTOP: ::c_int = 0x00000001;
+
+pub const FD_SETSIZE: usize = 1024;
+
+f! {
+    pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () {
+        let fd = fd as usize;
+        let size = mem::size_of_val(&(*set).fds_bits[0]);
+        (*set).fds_bits[fd / size] &= !(1 << (fd % size));
+        return
+    }
+
+    pub fn FD_ISSET(fd: ::c_int, set: *mut fd_set) -> bool {
+        let fd = fd as usize;
+        let size = mem::size_of_val(&(*set).fds_bits[0]);
+        return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0
+    }
+
+    pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () {
+        let fd = fd as usize;
+        let size = mem::size_of_val(&(*set).fds_bits[0]);
+        (*set).fds_bits[fd / size] |= 1 << (fd % size);
+        return
+    }
+
+    pub fn FD_ZERO(set: *mut fd_set) -> () {
+        for slot in (*set).fds_bits.iter_mut() {
+            *slot = 0;
+        }
+    }
+
+    pub fn WIFEXITED(status: ::c_int) -> bool {
+        (status & 0xff) == 0
+    }
+
+    pub fn WEXITSTATUS(status: ::c_int) -> ::c_int {
+        (status >> 8) & 0xff
+    }
+
+    pub fn WTERMSIG(status: ::c_int) -> ::c_int {
+        status & 0x7f
+    }
+}
+
 extern {
     pub fn fdatasync(fd: ::c_int) -> ::c_int;
     pub fn mincore(addr: *mut ::c_void, len: ::size_t,