Auto merge of #281 - lemonrock:getprogname, r=alexcrichton

Getprogname

Added `getprogname()` and `setprogname()` for all BSDs and Solaris (including Mac OS X).

Added `program_invocation_short_name` global, for Linux (glibc and Musl) which is effectively the same thing, and is what compatibility libraries like `libbsd` use to implement `getprogname()`.

Added `__progname` global for Android, which, whilst not quite the same as `getprogname` or `program_invocation_short_name`, is better than using argv[0], as it (a) avoids a common bug with no arguments (b) avoids a common bug with a NULL string in argv[0] and (c) incorporates Android's chosen name for an unknown process.
diff --git a/src/unix/notbsd/android/b32.rs b/src/unix/notbsd/android/b32.rs
index 1e0c2ed..3a295cc 100644
--- a/src/unix/notbsd/android/b32.rs
+++ b/src/unix/notbsd/android/b32.rs
@@ -1,4 +1,7 @@
+pub type c_long = i32;
+pub type c_ulong = u32;
 pub type mode_t = u16;
+pub type off64_t = ::c_longlong;
 
 s! {
     pub struct sigaction {
@@ -7,9 +10,118 @@
         pub sa_flags: ::c_ulong,
         pub sa_restorer: ::dox::Option<extern fn()>,
     }
+
+    pub struct stat {
+        pub st_dev: ::c_ulonglong,
+        __pad0: [::c_uchar; 4],
+        __st_ino: ::ino_t,
+        pub st_mode: ::c_uint,
+        pub st_nlink: ::c_uint,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: ::c_ulonglong,
+        __pad3: [::c_uchar; 4],
+        pub st_size: ::c_longlong,
+        pub st_blksize: ::blksize_t,
+        pub st_blocks: ::c_ulonglong,
+        pub st_atime: ::c_ulong,
+        pub st_atime_nsec: ::c_ulong,
+        pub st_mtime: ::c_ulong,
+        pub st_mtime_nsec: ::c_ulong,
+        pub st_ctime: ::c_ulong,
+        pub st_ctime_nsec: ::c_ulong,
+        pub st_ino: ::c_ulonglong,
+    }
+
+    pub struct stat64 {
+        pub st_dev: ::c_ulonglong,
+        __pad0: [::c_uchar; 4],
+        __st_ino: ::ino_t,
+        pub st_mode: ::c_uint,
+        pub st_nlink: ::c_uint,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: ::c_ulonglong,
+        __pad3: [::c_uchar; 4],
+        pub st_size: ::c_longlong,
+        pub st_blksize: ::blksize_t,
+        pub st_blocks: ::c_ulonglong,
+        pub st_atime: ::c_ulong,
+        pub st_atime_nsec: ::c_ulong,
+        pub st_mtime: ::c_ulong,
+        pub st_mtime_nsec: ::c_ulong,
+        pub st_ctime: ::c_ulong,
+        pub st_ctime_nsec: ::c_ulong,
+        pub st_ino: ::c_ulonglong,
+    }
+
+    pub struct pthread_attr_t {
+        pub flags: ::uint32_t,
+        pub stack_base: *mut ::c_void,
+        pub stack_size: ::size_t,
+        pub guard_size: ::size_t,
+        pub sched_policy: ::int32_t,
+        pub sched_priority: ::int32_t,
+    }
+
+    pub struct pthread_mutex_t { value: ::c_int }
+
+    pub struct pthread_cond_t { value: ::c_int }
+
+    pub struct pthread_rwlock_t {
+        lock: pthread_mutex_t,
+        cond: pthread_cond_t,
+        numLocks: ::c_int,
+        writerThreadId: ::c_int,
+        pendingReaders: ::c_int,
+        pendingWriters: ::c_int,
+        attr: i32,
+        __reserved: [::c_char; 12],
+    }
+
+    pub struct passwd {
+        pub pw_name: *mut ::c_char,
+        pub pw_passwd: *mut ::c_char,
+        pub pw_uid: ::uid_t,
+        pub pw_gid: ::gid_t,
+        pub pw_dir: *mut ::c_char,
+        pub pw_shell: *mut ::c_char,
+    }
+
+    pub struct statfs {
+        pub f_type: ::uint32_t,
+        pub f_bsize: ::uint32_t,
+        pub f_blocks: ::uint64_t,
+        pub f_bfree: ::uint64_t,
+        pub f_bavail: ::uint64_t,
+        pub f_files: ::uint64_t,
+        pub f_ffree: ::uint64_t,
+        pub f_fsid: ::__fsid_t,
+        pub f_namelen: ::uint32_t,
+        pub f_frsize: ::uint32_t,
+        pub f_flags: ::uint32_t,
+        pub f_spare: [::uint32_t; 4],
+    }
 }
 
 pub const SYS_gettid: ::c_long = 224;
+pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+    value: 0,
+};
+pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+    value: 0,
+};
+pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+    lock: PTHREAD_MUTEX_INITIALIZER,
+    cond: PTHREAD_COND_INITIALIZER,
+    numLocks: 0,
+    writerThreadId: 0,
+    pendingReaders: 0,
+    pendingWriters: 0,
+    attr: 0,
+    __reserved: [0; 12],
+};
+pub const PTHREAD_STACK_MIN: ::size_t = 4096 * 2;
 
 extern {
     pub fn timegm64(tm: *const ::tm) -> ::time64_t;
diff --git a/src/unix/notbsd/android/b64.rs b/src/unix/notbsd/android/b64.rs
index d538023..98b643f 100644
--- a/src/unix/notbsd/android/b64.rs
+++ b/src/unix/notbsd/android/b64.rs
@@ -1,4 +1,9 @@
+// The following definitions are correct for aarch64 and may be wrong for x86_64
+
+pub type c_long = i64;
+pub type c_ulong = u64;
 pub type mode_t = u32;
+pub type off64_t = i64;
 
 s! {
     pub struct sigaction {
@@ -7,9 +12,126 @@
         pub sa_mask: ::sigset_t,
         _restorer: *mut ::c_void,
     }
+
+    pub struct stat {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_mode: ::c_uint,
+        pub st_nlink: ::c_uint,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: ::dev_t,
+        __pad1: ::c_ulong,
+        pub st_size: ::off64_t,
+        pub st_blksize: ::c_int,
+        __pad2: ::c_int,
+        pub st_blocks: ::c_long,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_ulong,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_ulong,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_ulong,
+        __unused4: ::c_uint,
+        __unused5: ::c_uint,
+    }
+
+    pub struct stat64 {
+        pub st_dev: ::dev_t,
+        pub st_ino: ::ino_t,
+        pub st_mode: ::c_uint,
+        pub st_nlink: ::c_uint,
+        pub st_uid: ::uid_t,
+        pub st_gid: ::gid_t,
+        pub st_rdev: ::dev_t,
+        __pad1: ::c_ulong,
+        pub st_size: ::off64_t,
+        pub st_blksize: ::c_int,
+        __pad2: ::c_int,
+        pub st_blocks: ::c_long,
+        pub st_atime: ::time_t,
+        pub st_atime_nsec: ::c_ulong,
+        pub st_mtime: ::time_t,
+        pub st_mtime_nsec: ::c_ulong,
+        pub st_ctime: ::time_t,
+        pub st_ctime_nsec: ::c_ulong,
+        __unused4: ::c_uint,
+        __unused5: ::c_uint,
+    }
+
+    pub struct pthread_attr_t {
+        pub flags: ::uint32_t,
+        pub stack_base: *mut ::c_void,
+        pub stack_size: ::size_t,
+        pub guard_size: ::size_t,
+        pub sched_policy: ::int32_t,
+        pub sched_priority: ::int32_t,
+        __reserved: [::c_char; 16],
+    }
+
+    pub struct pthread_mutex_t {
+        value: ::c_int,
+        __reserved: [::c_char; 36],
+    }
+
+    pub struct pthread_cond_t {
+        value: ::c_int,
+        __reserved: [::c_char; 44],
+    }
+
+    pub struct pthread_rwlock_t {
+        numLocks: ::c_int,
+        writerThreadId: ::c_int,
+        pendingReaders: ::c_int,
+        pendingWriters: ::c_int,
+        attr: i32,
+        __reserved: [::c_char; 36],
+    }
+
+    pub struct passwd {
+        pub pw_name: *mut ::c_char,
+        pub pw_passwd: *mut ::c_char,
+        pub pw_uid: ::uid_t,
+        pub pw_gid: ::gid_t,
+        pub pw_gecos: *mut ::c_char,
+        pub pw_dir: *mut ::c_char,
+        pub pw_shell: *mut ::c_char,
+    }
+
+    pub struct statfs {
+        pub f_type: ::uint64_t,
+        pub f_bsize: ::uint64_t,
+        pub f_blocks: ::uint64_t,
+        pub f_bfree: ::uint64_t,
+        pub f_bavail: ::uint64_t,
+        pub f_files: ::uint64_t,
+        pub f_ffree: ::uint64_t,
+        pub f_fsid: ::__fsid_t,
+        pub f_namelen: ::uint64_t,
+        pub f_frsize: ::uint64_t,
+        pub f_flags: ::uint64_t,
+        pub f_spare: [::uint64_t; 4],
+    }
 }
 
 pub const SYS_gettid: ::c_long = 178;
+pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+    value: 0,
+    __reserved: [0; 36],
+};
+pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+    value: 0,
+    __reserved: [0; 44],
+};
+pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+    numLocks: 0,
+    writerThreadId: 0,
+    pendingReaders: 0,
+    pendingWriters: 0,
+    attr: 0,
+    __reserved: [0; 36],
+};
+pub const PTHREAD_STACK_MIN: ::size_t = 4096 * 4;
 
 extern {
     pub fn timegm(tm: *const ::tm) -> ::time64_t;
diff --git a/src/unix/notbsd/android/mod.rs b/src/unix/notbsd/android/mod.rs
index a1ed99d..7cfde94 100644
--- a/src/unix/notbsd/android/mod.rs
+++ b/src/unix/notbsd/android/mod.rs
@@ -1,75 +1,28 @@
 //! Android-specific definitions for linux-like values
 
 pub type c_char = u8;
-pub type c_long = i32;
-pub type c_ulong = u32;
-pub type clock_t = i32;
-pub type time_t = i32;
-pub type suseconds_t = i32;
+pub type clock_t = ::c_long;
+pub type time_t = ::c_long;
+pub type suseconds_t = ::c_long;
 pub type wchar_t = u32;
-pub type off_t = i32;
-pub type off64_t = i64;
-pub type ino_t = u32;
-pub type blkcnt_t = u32;
-pub type blksize_t = u32;
-pub type dev_t = u32;
+pub type off_t = ::c_long;
+pub type blkcnt_t = ::c_ulong;
+pub type blksize_t = ::c_ulong;
 pub type nlink_t = u32;
 pub type useconds_t = u32;
 pub type socklen_t = i32;
-pub type pthread_t = c_long;
+pub type pthread_t = ::c_long;
 pub type pthread_mutexattr_t = ::c_long;
-pub type sigset_t = c_ulong;
-pub type time64_t = i64;
+pub type sigset_t = ::c_ulong;
+pub type time64_t = i64; // N/A on android
 pub type fsfilcnt_t = ::c_ulong;
 pub type fsblkcnt_t = ::c_ulong;
 pub type nfds_t = ::c_uint;
-pub type rlim_t = c_ulong;
+pub type rlim_t = ::c_ulong;
+pub type dev_t = ::c_ulong;
+pub type ino_t = ::c_ulong;
 
 s! {
-    pub struct stat {
-        pub st_dev: ::c_ulonglong,
-        __pad0: [::c_uchar; 4],
-        __st_ino: ::ino_t,
-        pub st_mode: ::c_uint,
-        pub st_nlink: ::c_uint,
-        pub st_uid: ::uid_t,
-        pub st_gid: ::gid_t,
-        pub st_rdev: ::c_ulonglong,
-        __pad3: [::c_uchar; 4],
-        pub st_size: ::c_longlong,
-        pub st_blksize: blksize_t,
-        pub st_blocks: ::c_ulonglong,
-        pub st_atime: ::c_ulong,
-        pub st_atime_nsec: ::c_ulong,
-        pub st_mtime: ::c_ulong,
-        pub st_mtime_nsec: ::c_ulong,
-        pub st_ctime: ::c_ulong,
-        pub st_ctime_nsec: ::c_ulong,
-        pub st_ino: ::c_ulonglong,
-    }
-
-    pub struct stat64 {
-        pub st_dev: ::c_ulonglong,
-        __pad0: [::c_uchar; 4],
-        __st_ino: ::ino_t,
-        pub st_mode: ::c_uint,
-        pub st_nlink: ::c_uint,
-        pub st_uid: ::uid_t,
-        pub st_gid: ::gid_t,
-        pub st_rdev: ::c_ulonglong,
-        __pad3: [::c_uchar; 4],
-        pub st_size: ::c_longlong,
-        pub st_blksize: blksize_t,
-        pub st_blocks: ::c_ulonglong,
-        pub st_atime: ::c_ulong,
-        pub st_atime_nsec: ::c_ulong,
-        pub st_mtime: ::c_ulong,
-        pub st_mtime_nsec: ::c_ulong,
-        pub st_ctime: ::c_ulong,
-        pub st_ctime_nsec: ::c_ulong,
-        pub st_ino: ::c_ulonglong,
-    }
-
     pub struct dirent {
         pub d_ino: u64,
         pub d_off: i64,
@@ -91,38 +44,6 @@
         pub rlim_max: u64,
     }
 
-    pub struct pthread_attr_t {
-        pub flags: ::uint32_t,
-        pub stack_base: *mut ::c_void,
-        pub stack_size: ::size_t,
-        pub guard_size: ::size_t,
-        pub sched_policy: ::int32_t,
-        pub sched_priority: ::int32_t,
-    }
-
-    pub struct pthread_mutex_t { value: ::c_int }
-
-    pub struct pthread_cond_t { value: ::c_int }
-
-    pub struct pthread_rwlock_t {
-        lock: pthread_mutex_t,
-        cond: pthread_cond_t,
-        numLocks: ::c_int,
-        writerThreadId: ::c_int,
-        pendingReaders: ::c_int,
-        pendingWriters: ::c_int,
-        reserved: [*mut ::c_void; 4],
-    }
-
-    pub struct passwd {
-        pub pw_name: *mut ::c_char,
-        pub pw_passwd: *mut ::c_char,
-        pub pw_uid: ::uid_t,
-        pub pw_gid: ::gid_t,
-        pub pw_dir: *mut ::c_char,
-        pub pw_shell: *mut ::c_char,
-    }
-
     pub struct stack_t {
         pub ss_sp: *mut ::c_void,
         pub ss_flags: ::c_int,
@@ -136,21 +57,6 @@
         pub _pad: [::c_int; 29],
     }
 
-    pub struct statfs {
-        pub f_type: ::uint32_t,
-        pub f_bsize: ::uint32_t,
-        pub f_blocks: ::uint64_t,
-        pub f_bfree: ::uint64_t,
-        pub f_bavail: ::uint64_t,
-        pub f_files: ::uint64_t,
-        pub f_ffree: ::uint64_t,
-        pub f_fsid: ::__fsid_t,
-        pub f_namelen: ::uint32_t,
-        pub f_frsize: ::uint32_t,
-        pub f_flags: ::uint32_t,
-        pub f_spare: [::uint32_t; 4],
-    }
-
     pub struct __fsid_t {
         __val: [::c_int; 2],
     }
@@ -251,22 +157,6 @@
 pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 85;
 pub const _SC_NPROCESSORS_ONLN: ::c_int = 97;
 
-pub const PTHREAD_STACK_MIN: ::size_t = 8192;
-pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
-    value: 0,
-};
-pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
-    value: 0,
-};
-pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
-    lock: PTHREAD_MUTEX_INITIALIZER,
-    cond: PTHREAD_COND_INITIALIZER,
-    numLocks: 0,
-    writerThreadId: 0,
-    pendingReaders: 0,
-    pendingWriters: 0,
-    reserved: [0 as *mut _; 4],
-};
 pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1;
 
 pub const FIOCLEX: ::c_int = 0x5451;
diff --git a/src/unix/notbsd/linux/other/b32/x86.rs b/src/unix/notbsd/linux/other/b32/x86.rs
index 1b215a9..e6d78de 100644
--- a/src/unix/notbsd/linux/other/b32/x86.rs
+++ b/src/unix/notbsd/linux/other/b32/x86.rs
@@ -1,9 +1,30 @@
 pub type c_char = i8;
 pub type wchar_t = i32;
+pub type greg_t = i32;
 
 s! {
+    pub struct _libc_fpreg {
+        pub significand: [u16; 4],
+        pub exponent: u16,
+    }
+
+    pub struct _libc_fpstate {
+        pub cw: ::c_ulong,
+        pub sw: ::c_ulong,
+        pub tag: ::c_ulong,
+        pub ipoff: ::c_ulong,
+        pub cssel: ::c_ulong,
+        pub dataoff: ::c_ulong,
+        pub datasel: ::c_ulong,
+        pub _st: [_libc_fpreg; 8],
+        pub status: ::c_ulong,
+    }
+
     pub struct mcontext_t {
-        __private: [u32; 22]
+        pub gregs: [greg_t; 19],
+        pub fpregs: *mut _libc_fpstate,
+        pub oldmask: ::c_ulong,
+        pub cr2: ::c_ulong,
     }
 
     pub struct ucontext_t {
diff --git a/src/unix/notbsd/linux/other/b64/x86_64.rs b/src/unix/notbsd/linux/other/b64/x86_64.rs
index 6903c62..7103267 100644
--- a/src/unix/notbsd/linux/other/b64/x86_64.rs
+++ b/src/unix/notbsd/linux/other/b64/x86_64.rs
@@ -4,6 +4,7 @@
 pub type wchar_t = i32;
 pub type nlink_t = u64;
 pub type blksize_t = i64;
+pub type greg_t = i64;
 
 s! {
     pub struct stat {
@@ -52,8 +53,34 @@
         __size: [u64; 7]
     }
 
+    pub struct _libc_fpxreg {
+        pub significand: [u16; 4],
+        pub exponent: u16,
+        __private: [u16; 3],
+    }
+
+    pub struct _libc_xmmreg {
+        pub element: [u32; 4],
+    }
+
+    pub struct _libc_fpstate {
+        pub cwd: u16,
+        pub swd: u16,
+        pub ftw: u16,
+        pub fop: u16,
+        pub rip: u64,
+        pub rdp: u64,
+        pub mxcsr: u32,
+        pub mxcr_mask: u32,
+        pub _st: [_libc_fpxreg; 8],
+        pub _xmm: [_libc_xmmreg; 16],
+        __private: [u64; 12],
+    }
+
     pub struct mcontext_t {
-        __private: [u64; 32],
+        pub gregs: [greg_t; 23],
+        pub fpregs: *mut _libc_fpstate,
+        __private: [u64; 8],
     }
 
     pub struct ucontext_t {