2015-01-27 20:20:58 +00:00
|
|
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
2014-10-01 00:03:56 +00:00
|
|
|
// 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.
|
|
|
|
|
2014-11-25 00:21:39 +00:00
|
|
|
//! Implementation of `std::os` functionality for unix systems
|
|
|
|
|
2015-03-10 03:04:35 +00:00
|
|
|
#![allow(unused_imports)] // lots of cfg code here
|
|
|
|
|
2014-12-22 17:04:23 +00:00
|
|
|
use prelude::v1::*;
|
std: Stabilize portions of `std::os::$platform`
This commit starts to organize the `std::os::$platform` modules and in the
process stabilizes some of the functionality contained within. The organization
of these modules will reflect the organization of the standard library itself
with extension traits for primitives in the same corresponding module.
The OS-specific modules will grow more functionality over time including
concrete types that are not extending functionality of other structures, and
these will either go into the closest module in `std::os::$platform` or they
will grow a new module in the hierarchy.
The following items are now stable:
* `os::{unix, windows}`
* `unix::ffi`
* `unix::ffi::OsStrExt`
* `unix::ffi::OsStrExt::{from_bytes, as_bytes, to_cstring}`
* `unix::ffi::OsString`
* `unix::ffi::OsStringExt::{from_vec, into_vec}`
* `unix::process`
* `unix::process::CommandExt`
* `unix::process::CommandExt::{uid, gid}`
* `unix::process::ExitStatusExt`
* `unix::process::ExitStatusExt::signal`
* `unix::prelude`
* `windows::ffi`
* `windows::ffi::OsStringExt`
* `windows::ffi::OsStringExt::from_wide`
* `windows::ffi::OsStrExt`
* `windows::ffi::OsStrExt::encode_wide`
* `windows::prelude`
The following items remain unstable:
* `unix::io`
* `unix::io::{Fd, AsRawFd}`
* `unix::fs::{PermissionsExt, OpenOptionsExt}`
* `windows::io`
* `windows::io::{Handle, AsRawHandle}`
* `windows::io::{Socket, AsRawSocket}`
* `windows::fs`
* `windows::fs::OpenOptionsExt`
Due to the reorgnization of the platform extension modules, this commit is a
breaking change. Most imports can be fixed by adding the relevant libstd module
in the `use` path (such as `ffi` or `fs`).
[breaking-change]
2015-03-14 00:12:38 +00:00
|
|
|
use os::unix::prelude::*;
|
2014-11-25 00:21:39 +00:00
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
use error::Error as StdError;
|
2015-02-18 06:47:40 +00:00
|
|
|
use ffi::{CString, CStr, OsString, OsStr, AsOsStr};
|
2014-11-25 00:21:39 +00:00
|
|
|
use fmt;
|
2015-02-23 18:59:17 +00:00
|
|
|
use io;
|
2015-01-27 20:20:58 +00:00
|
|
|
use iter;
|
2015-01-04 03:42:21 +00:00
|
|
|
use libc::{self, c_int, c_char, c_void};
|
2015-01-27 20:20:58 +00:00
|
|
|
use mem;
|
2015-03-11 22:24:14 +00:00
|
|
|
#[allow(deprecated)] use old_io::{IoError, IoResult};
|
2014-12-15 04:03:00 +00:00
|
|
|
use ptr;
|
2015-02-23 18:59:17 +00:00
|
|
|
use path::{self, PathBuf};
|
2015-01-27 20:20:58 +00:00
|
|
|
use slice;
|
2014-11-25 21:28:35 +00:00
|
|
|
use str;
|
2015-01-27 20:20:58 +00:00
|
|
|
use sys::c;
|
2015-02-06 17:42:57 +00:00
|
|
|
use sys::fd;
|
2014-10-10 17:11:49 +00:00
|
|
|
use sys::fs::FileDesc;
|
2015-01-27 20:20:58 +00:00
|
|
|
use vec;
|
2014-10-01 00:03:56 +00:00
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
const BUF_BYTES: usize = 2048;
|
|
|
|
const TMPBUF_SZ: usize = 128;
|
2014-11-25 00:21:39 +00:00
|
|
|
|
2015-02-23 18:59:17 +00:00
|
|
|
fn bytes2path(b: &[u8]) -> PathBuf {
|
2015-03-18 16:14:54 +00:00
|
|
|
PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
|
2015-02-23 18:59:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn os2path(os: OsString) -> PathBuf {
|
|
|
|
bytes2path(os.as_bytes())
|
|
|
|
}
|
|
|
|
|
2014-10-01 00:03:56 +00:00
|
|
|
/// Returns the platform-specific value of errno
|
2015-01-27 20:20:58 +00:00
|
|
|
pub fn errno() -> i32 {
|
2014-10-01 00:03:56 +00:00
|
|
|
#[cfg(any(target_os = "macos",
|
|
|
|
target_os = "ios",
|
|
|
|
target_os = "freebsd"))]
|
2015-01-27 20:20:58 +00:00
|
|
|
unsafe fn errno_location() -> *const c_int {
|
|
|
|
extern { fn __error() -> *const c_int; }
|
|
|
|
__error()
|
2014-10-01 00:03:56 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 07:51:04 +00:00
|
|
|
#[cfg(target_os = "bitrig")]
|
|
|
|
fn errno_location() -> *const c_int {
|
|
|
|
extern {
|
|
|
|
fn __errno() -> *const c_int;
|
|
|
|
}
|
|
|
|
unsafe {
|
|
|
|
__errno()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-01 00:03:56 +00:00
|
|
|
#[cfg(target_os = "dragonfly")]
|
2015-01-27 20:20:58 +00:00
|
|
|
unsafe fn errno_location() -> *const c_int {
|
|
|
|
extern { fn __dfly_error() -> *const c_int; }
|
|
|
|
__dfly_error()
|
2014-10-01 00:03:56 +00:00
|
|
|
}
|
|
|
|
|
2015-01-29 07:19:28 +00:00
|
|
|
#[cfg(target_os = "openbsd")]
|
2015-02-05 17:56:10 +00:00
|
|
|
unsafe fn errno_location() -> *const c_int {
|
|
|
|
extern { fn __errno() -> *const c_int; }
|
|
|
|
__errno()
|
2015-01-29 07:19:28 +00:00
|
|
|
}
|
|
|
|
|
2014-10-01 00:03:56 +00:00
|
|
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
2015-01-27 20:20:58 +00:00
|
|
|
unsafe fn errno_location() -> *const c_int {
|
|
|
|
extern { fn __errno_location() -> *const c_int; }
|
|
|
|
__errno_location()
|
2014-10-01 00:03:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe {
|
2015-01-27 20:20:58 +00:00
|
|
|
(*errno_location()) as i32
|
2014-10-01 00:03:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get a detailed string description for the given error number
|
|
|
|
pub fn error_string(errno: i32) -> String {
|
|
|
|
#[cfg(target_os = "linux")]
|
2015-01-27 20:20:58 +00:00
|
|
|
extern {
|
|
|
|
#[link_name = "__xpg_strerror_r"]
|
|
|
|
fn strerror_r(errnum: c_int, buf: *mut c_char,
|
|
|
|
buflen: libc::size_t) -> c_int;
|
|
|
|
}
|
|
|
|
#[cfg(not(target_os = "linux"))]
|
|
|
|
extern {
|
|
|
|
fn strerror_r(errnum: c_int, buf: *mut c_char,
|
|
|
|
buflen: libc::size_t) -> c_int;
|
2014-10-01 00:03:56 +00:00
|
|
|
}
|
|
|
|
|
2015-01-01 04:40:24 +00:00
|
|
|
let mut buf = [0 as c_char; TMPBUF_SZ];
|
2014-10-01 00:03:56 +00:00
|
|
|
|
|
|
|
let p = buf.as_mut_ptr();
|
|
|
|
unsafe {
|
|
|
|
if strerror_r(errno as c_int, p, buf.len() as libc::size_t) < 0 {
|
|
|
|
panic!("strerror_r failure");
|
|
|
|
}
|
|
|
|
|
2014-11-25 21:28:35 +00:00
|
|
|
let p = p as *const _;
|
2015-02-18 06:47:40 +00:00
|
|
|
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_string()
|
2014-10-01 00:03:56 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-10 17:11:49 +00:00
|
|
|
|
2015-02-23 18:59:17 +00:00
|
|
|
pub fn getcwd() -> io::Result<PathBuf> {
|
2015-01-01 04:40:24 +00:00
|
|
|
let mut buf = [0 as c_char; BUF_BYTES];
|
2014-11-25 00:21:39 +00:00
|
|
|
unsafe {
|
|
|
|
if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
|
2015-02-23 18:59:17 +00:00
|
|
|
Err(io::Error::last_os_error())
|
2014-11-25 00:21:39 +00:00
|
|
|
} else {
|
2015-02-23 18:59:17 +00:00
|
|
|
Ok(bytes2path(CStr::from_ptr(buf.as_ptr()).to_bytes()))
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-23 18:59:17 +00:00
|
|
|
pub fn chdir(p: &path::Path) -> io::Result<()> {
|
|
|
|
let p = try!(CString::new(p.as_os_str().as_bytes()));
|
2015-01-27 20:20:58 +00:00
|
|
|
unsafe {
|
|
|
|
match libc::chdir(p.as_ptr()) == (0 as c_int) {
|
|
|
|
true => Ok(()),
|
2015-02-23 18:59:17 +00:00
|
|
|
false => Err(io::Error::last_os_error()),
|
2015-01-27 20:20:58 +00:00
|
|
|
}
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
2015-01-27 20:20:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct SplitPaths<'a> {
|
2015-02-02 19:04:58 +00:00
|
|
|
iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
|
2015-02-23 18:59:17 +00:00
|
|
|
fn(&'a [u8]) -> PathBuf>,
|
2015-01-27 20:20:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> {
|
|
|
|
fn is_colon(b: &u8) -> bool { *b == b':' }
|
2015-02-06 17:42:57 +00:00
|
|
|
let unparsed = unparsed.as_bytes();
|
2015-01-27 20:20:58 +00:00
|
|
|
SplitPaths {
|
|
|
|
iter: unparsed.split(is_colon as fn(&u8) -> bool)
|
2015-02-23 18:59:17 +00:00
|
|
|
.map(bytes2path as fn(&'a [u8]) -> PathBuf)
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
impl<'a> Iterator for SplitPaths<'a> {
|
2015-02-23 18:59:17 +00:00
|
|
|
type Item = PathBuf;
|
|
|
|
fn next(&mut self) -> Option<PathBuf> { self.iter.next() }
|
2015-01-27 20:20:58 +00:00
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct JoinPathsError;
|
|
|
|
|
|
|
|
pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
|
|
|
|
where I: Iterator<Item=T>, T: AsOsStr
|
|
|
|
{
|
2014-11-25 00:21:39 +00:00
|
|
|
let mut joined = Vec::new();
|
|
|
|
let sep = b':';
|
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
for (i, path) in paths.enumerate() {
|
2015-02-06 17:42:57 +00:00
|
|
|
let path = path.as_os_str().as_bytes();
|
2014-11-25 00:21:39 +00:00
|
|
|
if i > 0 { joined.push(sep) }
|
2015-01-27 20:20:58 +00:00
|
|
|
if path.contains(&sep) {
|
|
|
|
return Err(JoinPathsError)
|
|
|
|
}
|
2014-11-25 00:21:39 +00:00
|
|
|
joined.push_all(path);
|
|
|
|
}
|
2015-01-27 20:20:58 +00:00
|
|
|
Ok(OsStringExt::from_vec(joined))
|
|
|
|
}
|
2014-11-25 00:21:39 +00:00
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
impl fmt::Display for JoinPathsError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
"path segment contains separator `:`".fmt(f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl StdError for JoinPathsError {
|
|
|
|
fn description(&self) -> &str { "failed to join paths" }
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
|
2014-12-19 12:05:06 +00:00
|
|
|
#[cfg(target_os = "freebsd")]
|
2015-02-25 08:45:24 +00:00
|
|
|
pub fn current_exe() -> io::Result<PathBuf> {
|
2014-11-25 00:21:39 +00:00
|
|
|
unsafe {
|
|
|
|
use libc::funcs::bsd44::*;
|
|
|
|
use libc::consts::os::extra::*;
|
|
|
|
let mut mib = vec![CTL_KERN as c_int,
|
|
|
|
KERN_PROC as c_int,
|
|
|
|
KERN_PROC_PATHNAME as c_int,
|
|
|
|
-1 as c_int];
|
|
|
|
let mut sz: libc::size_t = 0;
|
|
|
|
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
|
|
|
|
ptr::null_mut(), &mut sz, ptr::null_mut(),
|
2015-02-17 14:47:49 +00:00
|
|
|
0 as libc::size_t);
|
2015-02-25 08:45:24 +00:00
|
|
|
if err != 0 { return Err(io::Error::last_os_error()); }
|
|
|
|
if sz == 0 { return Err(io::Error::last_os_error()); }
|
2014-11-25 00:21:39 +00:00
|
|
|
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
|
|
|
|
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
|
2014-12-22 20:56:18 +00:00
|
|
|
v.as_mut_ptr() as *mut libc::c_void, &mut sz,
|
2015-02-17 14:47:49 +00:00
|
|
|
ptr::null_mut(), 0 as libc::size_t);
|
2015-02-25 08:45:24 +00:00
|
|
|
if err != 0 { return Err(io::Error::last_os_error()); }
|
|
|
|
if sz == 0 { return Err(io::Error::last_os_error()); }
|
2014-11-25 00:21:39 +00:00
|
|
|
v.set_len(sz as uint - 1); // chop off trailing NUL
|
2015-03-15 17:30:43 +00:00
|
|
|
Ok(PathBuf::new::<OsString>(OsStringExt::from_vec(v)))
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-19 12:05:06 +00:00
|
|
|
#[cfg(target_os = "dragonfly")]
|
2015-02-23 18:59:17 +00:00
|
|
|
pub fn current_exe() -> io::Result<PathBuf> {
|
|
|
|
::fs::read_link("/proc/curproc/file")
|
2014-12-19 12:05:06 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 07:51:04 +00:00
|
|
|
#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
|
2015-02-23 18:59:17 +00:00
|
|
|
pub fn current_exe() -> io::Result<PathBuf> {
|
2015-01-30 07:15:28 +00:00
|
|
|
use sync::{StaticMutex, MUTEX_INIT};
|
|
|
|
static LOCK: StaticMutex = MUTEX_INIT;
|
|
|
|
|
2015-01-29 07:19:28 +00:00
|
|
|
extern {
|
2015-02-05 14:24:17 +00:00
|
|
|
fn rust_current_exe() -> *const c_char;
|
2015-01-29 07:19:28 +00:00
|
|
|
}
|
2015-01-30 07:15:28 +00:00
|
|
|
|
|
|
|
let _guard = LOCK.lock();
|
|
|
|
|
2015-01-29 07:19:28 +00:00
|
|
|
unsafe {
|
2015-02-05 14:24:17 +00:00
|
|
|
let v = rust_current_exe();
|
2015-01-29 07:19:28 +00:00
|
|
|
if v.is_null() {
|
2015-02-25 08:45:24 +00:00
|
|
|
Err(io::Error::last_os_error())
|
2015-01-29 07:19:28 +00:00
|
|
|
} else {
|
2015-02-26 05:16:41 +00:00
|
|
|
let vec = CStr::from_ptr(v).to_bytes().to_vec();
|
2015-03-15 17:30:43 +00:00
|
|
|
Ok(PathBuf::new::<OsString>(OsStringExt::from_vec(vec)))
|
2015-01-29 07:19:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-25 00:21:39 +00:00
|
|
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
2015-02-23 18:59:17 +00:00
|
|
|
pub fn current_exe() -> io::Result<PathBuf> {
|
|
|
|
::fs::read_link("/proc/self/exe")
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
2015-02-25 08:45:24 +00:00
|
|
|
pub fn current_exe() -> io::Result<PathBuf> {
|
2014-11-25 00:21:39 +00:00
|
|
|
unsafe {
|
|
|
|
use libc::funcs::extra::_NSGetExecutablePath;
|
|
|
|
let mut sz: u32 = 0;
|
|
|
|
_NSGetExecutablePath(ptr::null_mut(), &mut sz);
|
2015-02-25 08:45:24 +00:00
|
|
|
if sz == 0 { return Err(io::Error::last_os_error()); }
|
2014-11-25 00:21:39 +00:00
|
|
|
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
|
|
|
|
let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
|
2015-02-25 08:45:24 +00:00
|
|
|
if err != 0 { return Err(io::Error::last_os_error()); }
|
2014-11-25 00:21:39 +00:00
|
|
|
v.set_len(sz as uint - 1); // chop off trailing NUL
|
2015-03-18 16:14:54 +00:00
|
|
|
Ok(PathBuf::from(OsString::from_vec(v)))
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
pub struct Args {
|
|
|
|
iter: vec::IntoIter<OsString>,
|
|
|
|
_dont_send_or_sync_me: *mut (),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for Args {
|
|
|
|
type Item = OsString;
|
|
|
|
fn next(&mut self) -> Option<OsString> { self.iter.next() }
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
|
|
|
}
|
|
|
|
|
2015-02-16 10:15:30 +00:00
|
|
|
impl ExactSizeIterator for Args {
|
|
|
|
fn len(&self) -> usize { self.iter.len() }
|
|
|
|
}
|
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
/// Returns the command line arguments
|
|
|
|
///
|
|
|
|
/// Returns a list of the command line arguments.
|
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
pub fn args() -> Args {
|
|
|
|
extern {
|
|
|
|
// These functions are in crt_externs.h.
|
|
|
|
fn _NSGetArgc() -> *mut c_int;
|
|
|
|
fn _NSGetArgv() -> *mut *mut *mut c_char;
|
|
|
|
}
|
|
|
|
|
|
|
|
let vec = unsafe {
|
|
|
|
let (argc, argv) = (*_NSGetArgc() as isize,
|
|
|
|
*_NSGetArgv() as *const *const c_char);
|
2015-03-13 18:35:53 +00:00
|
|
|
(0.. argc as isize).map(|i| {
|
2015-02-19 02:02:58 +00:00
|
|
|
let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
|
2015-01-27 20:20:58 +00:00
|
|
|
OsStringExt::from_vec(bytes)
|
|
|
|
}).collect::<Vec<_>>()
|
|
|
|
};
|
|
|
|
Args {
|
|
|
|
iter: vec.into_iter(),
|
|
|
|
_dont_send_or_sync_me: 0 as *mut (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
|
|
|
|
// and use underscores in their names - they're most probably
|
|
|
|
// are considered private and therefore should be avoided
|
|
|
|
// Here is another way to get arguments using Objective C
|
|
|
|
// runtime
|
|
|
|
//
|
|
|
|
// In general it looks like:
|
|
|
|
// res = Vec::new()
|
|
|
|
// let args = [[NSProcessInfo processInfo] arguments]
|
2015-03-18 15:15:53 +00:00
|
|
|
// for i in (0..[args count])
|
2015-01-27 20:20:58 +00:00
|
|
|
// res.push([args objectAtIndex:i])
|
|
|
|
// res
|
|
|
|
#[cfg(target_os = "ios")]
|
|
|
|
pub fn args() -> Args {
|
|
|
|
use mem;
|
|
|
|
|
|
|
|
#[link(name = "objc")]
|
|
|
|
extern {
|
|
|
|
fn sel_registerName(name: *const libc::c_uchar) -> Sel;
|
|
|
|
fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
|
|
|
|
fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[link(name = "Foundation", kind = "framework")]
|
|
|
|
extern {}
|
|
|
|
|
|
|
|
type Sel = *const libc::c_void;
|
|
|
|
type NsId = *const libc::c_void;
|
|
|
|
|
|
|
|
let mut res = Vec::new();
|
|
|
|
|
2014-11-25 21:28:35 +00:00
|
|
|
unsafe {
|
2015-02-03 13:30:10 +00:00
|
|
|
let process_info_sel = sel_registerName("processInfo\0".as_ptr());
|
|
|
|
let arguments_sel = sel_registerName("arguments\0".as_ptr());
|
|
|
|
let utf8_sel = sel_registerName("UTF8String\0".as_ptr());
|
|
|
|
let count_sel = sel_registerName("count\0".as_ptr());
|
|
|
|
let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr());
|
2015-01-27 20:20:58 +00:00
|
|
|
|
|
|
|
let klass = objc_getClass("NSProcessInfo\0".as_ptr());
|
2015-02-03 13:30:10 +00:00
|
|
|
let info = objc_msgSend(klass, process_info_sel);
|
|
|
|
let args = objc_msgSend(info, arguments_sel);
|
2015-01-27 20:20:58 +00:00
|
|
|
|
2015-02-03 13:30:10 +00:00
|
|
|
let cnt: int = mem::transmute(objc_msgSend(args, count_sel));
|
2015-03-18 15:15:53 +00:00
|
|
|
for i in (0..cnt) {
|
2015-02-03 13:30:10 +00:00
|
|
|
let tmp = objc_msgSend(args, object_at_sel, i);
|
2015-01-27 20:20:58 +00:00
|
|
|
let utf_c_str: *const libc::c_char =
|
2015-02-03 13:30:10 +00:00
|
|
|
mem::transmute(objc_msgSend(tmp, utf8_sel));
|
2015-02-18 06:47:40 +00:00
|
|
|
let bytes = CStr::from_ptr(utf_c_str).to_bytes();
|
2015-02-03 13:30:10 +00:00
|
|
|
res.push(OsString::from_str(str::from_utf8(bytes).unwrap()))
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
2014-11-25 21:28:35 +00:00
|
|
|
}
|
2015-01-27 20:20:58 +00:00
|
|
|
|
|
|
|
Args { iter: res.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(any(target_os = "linux",
|
|
|
|
target_os = "android",
|
|
|
|
target_os = "freebsd",
|
2015-02-05 14:24:17 +00:00
|
|
|
target_os = "dragonfly",
|
2015-01-17 07:51:04 +00:00
|
|
|
target_os = "bitrig",
|
2015-02-05 14:24:17 +00:00
|
|
|
target_os = "openbsd"))]
|
2015-01-27 20:20:58 +00:00
|
|
|
pub fn args() -> Args {
|
|
|
|
use rt;
|
|
|
|
let bytes = rt::args::clone().unwrap_or(Vec::new());
|
|
|
|
let v: Vec<OsString> = bytes.into_iter().map(|v| {
|
|
|
|
OsStringExt::from_vec(v)
|
|
|
|
}).collect();
|
|
|
|
Args { iter: v.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Env {
|
|
|
|
iter: vec::IntoIter<(OsString, OsString)>,
|
|
|
|
_dont_send_or_sync_me: *mut (),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for Env {
|
|
|
|
type Item = (OsString, OsString);
|
|
|
|
fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() }
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
pub unsafe fn environ() -> *mut *const *const c_char {
|
|
|
|
extern { fn _NSGetEnviron() -> *mut *const *const c_char; }
|
|
|
|
_NSGetEnviron()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(target_os = "macos"))]
|
|
|
|
pub unsafe fn environ() -> *mut *const *const c_char {
|
|
|
|
extern { static mut environ: *const *const c_char; }
|
|
|
|
&mut environ
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
|
|
|
/// environment variables of the current process.
|
|
|
|
pub fn env() -> Env {
|
|
|
|
return unsafe {
|
|
|
|
let mut environ = *environ();
|
|
|
|
if environ as usize == 0 {
|
|
|
|
panic!("os::env() failure getting env string from OS: {}",
|
2015-03-11 22:24:14 +00:00
|
|
|
io::Error::last_os_error());
|
2015-01-27 20:20:58 +00:00
|
|
|
}
|
|
|
|
let mut result = Vec::new();
|
|
|
|
while *environ != ptr::null() {
|
2015-02-18 06:47:40 +00:00
|
|
|
result.push(parse(CStr::from_ptr(*environ).to_bytes()));
|
2015-01-27 20:20:58 +00:00
|
|
|
environ = environ.offset(1);
|
|
|
|
}
|
|
|
|
Env { iter: result.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
|
|
|
|
};
|
|
|
|
|
|
|
|
fn parse(input: &[u8]) -> (OsString, OsString) {
|
|
|
|
let mut it = input.splitn(1, |b| *b == b'=');
|
|
|
|
let key = it.next().unwrap().to_vec();
|
|
|
|
let default: &[u8] = &[];
|
|
|
|
let val = it.next().unwrap_or(default).to_vec();
|
|
|
|
(OsStringExt::from_vec(key), OsStringExt::from_vec(val))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn getenv(k: &OsStr) -> Option<OsString> {
|
2014-11-25 00:21:39 +00:00
|
|
|
unsafe {
|
2015-02-18 06:47:40 +00:00
|
|
|
let s = k.to_cstring().unwrap();
|
2015-01-27 20:20:58 +00:00
|
|
|
let s = libc::getenv(s.as_ptr()) as *const _;
|
|
|
|
if s.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
2015-02-18 06:47:40 +00:00
|
|
|
Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
|
2015-01-27 20:20:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn setenv(k: &OsStr, v: &OsStr) {
|
|
|
|
unsafe {
|
2015-02-18 06:47:40 +00:00
|
|
|
let k = k.to_cstring().unwrap();
|
|
|
|
let v = v.to_cstring().unwrap();
|
2015-01-27 20:20:58 +00:00
|
|
|
if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 {
|
2015-03-11 22:24:14 +00:00
|
|
|
panic!("failed setenv: {}", io::Error::last_os_error());
|
2015-01-27 20:20:58 +00:00
|
|
|
}
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-27 20:20:58 +00:00
|
|
|
|
|
|
|
pub fn unsetenv(n: &OsStr) {
|
|
|
|
unsafe {
|
2015-02-18 06:47:40 +00:00
|
|
|
let nbuf = n.to_cstring().unwrap();
|
2015-01-27 20:20:58 +00:00
|
|
|
if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
|
2015-03-11 22:24:14 +00:00
|
|
|
panic!("failed unsetenv: {}", io::Error::last_os_error());
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
2014-11-25 21:28:35 +00:00
|
|
|
}
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
|
2015-03-11 22:24:14 +00:00
|
|
|
#[allow(deprecated)]
|
2015-01-27 20:20:58 +00:00
|
|
|
pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
|
|
|
|
let mut fds = [0; 2];
|
|
|
|
if libc::pipe(fds.as_mut_ptr()) == 0 {
|
|
|
|
Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true)))
|
|
|
|
} else {
|
|
|
|
Err(IoError::last_error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn page_size() -> usize {
|
2014-11-25 00:21:39 +00:00
|
|
|
unsafe {
|
2015-01-27 20:20:58 +00:00
|
|
|
libc::sysconf(libc::_SC_PAGESIZE) as usize
|
2014-11-25 00:21:39 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-27 20:20:58 +00:00
|
|
|
|
2015-02-23 18:59:17 +00:00
|
|
|
pub fn temp_dir() -> PathBuf {
|
|
|
|
getenv("TMPDIR".as_os_str()).map(os2path).unwrap_or_else(|| {
|
2015-01-27 20:20:58 +00:00
|
|
|
if cfg!(target_os = "android") {
|
2015-03-18 16:14:54 +00:00
|
|
|
PathBuf::from("/data/local/tmp")
|
2015-01-27 20:20:58 +00:00
|
|
|
} else {
|
2015-03-18 16:14:54 +00:00
|
|
|
PathBuf::from("/tmp")
|
2015-01-27 20:20:58 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-02-23 18:59:17 +00:00
|
|
|
pub fn home_dir() -> Option<PathBuf> {
|
2015-02-02 19:04:58 +00:00
|
|
|
return getenv("HOME".as_os_str()).or_else(|| unsafe {
|
|
|
|
fallback()
|
2015-02-23 18:59:17 +00:00
|
|
|
}).map(os2path);
|
2015-02-02 19:04:58 +00:00
|
|
|
|
2015-02-03 13:30:10 +00:00
|
|
|
#[cfg(any(target_os = "android",
|
|
|
|
target_os = "ios"))]
|
2015-02-02 19:04:58 +00:00
|
|
|
unsafe fn fallback() -> Option<OsString> { None }
|
2015-02-03 13:30:10 +00:00
|
|
|
#[cfg(not(any(target_os = "android",
|
|
|
|
target_os = "ios")))]
|
2015-02-02 19:04:58 +00:00
|
|
|
unsafe fn fallback() -> Option<OsString> {
|
2015-03-10 03:04:35 +00:00
|
|
|
let amt = match libc::sysconf(c::_SC_GETPW_R_SIZE_MAX) {
|
2015-01-27 20:20:58 +00:00
|
|
|
n if n < 0 => 512 as usize,
|
|
|
|
n => n as usize,
|
|
|
|
};
|
|
|
|
let me = libc::getuid();
|
|
|
|
loop {
|
|
|
|
let mut buf = Vec::with_capacity(amt);
|
|
|
|
let mut passwd: c::passwd = mem::zeroed();
|
|
|
|
let mut result = 0 as *mut _;
|
|
|
|
match c::getpwuid_r(me, &mut passwd, buf.as_mut_ptr(),
|
|
|
|
buf.capacity() as libc::size_t,
|
|
|
|
&mut result) {
|
|
|
|
0 if !result.is_null() => {}
|
|
|
|
_ => return None
|
|
|
|
}
|
|
|
|
let ptr = passwd.pw_dir as *const _;
|
2015-02-18 06:47:40 +00:00
|
|
|
let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
|
2015-01-27 20:20:58 +00:00
|
|
|
return Some(OsStringExt::from_vec(bytes))
|
|
|
|
}
|
2015-02-02 19:04:58 +00:00
|
|
|
}
|
2015-01-27 20:20:58 +00:00
|
|
|
}
|