Skip to content

Commit

Permalink
make execvpe available for all platforms
Browse files Browse the repository at this point in the history
- execvpe is as GNU extension of libc.
- redone in Rust to make it available on all systems.
- this also makes the feature flag obsolete.
  • Loading branch information
Mic92 committed Apr 13, 2016
1 parent 85c53a9 commit 7e2cd68
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 20 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ build = "build.rs"

[features]
eventfd = []
execvpe = []
preadv_pwritev = []
signalfd = []

Expand Down
45 changes: 26 additions & 19 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,13 +366,37 @@ pub fn pause() -> Result<()> {
Errno::result(res).map(drop)
}

pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
use std::env;
use std::ffi::OsString;
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;

if filename.as_bytes().iter().find(|c| **c == b'/').is_some() {
return execve(filename, args, env);
}

let paths = match env::var_os("PATH") {
Some(val) => val,
None => OsString::from("/usr/local/bin:/bin:/usr/bin"),
};

let name = OsStr::from_bytes(&filename.as_bytes());
let mut res = Err(Error::Sys(Errno::ENOENT));
for path in env::split_paths(&paths) {
let p = path.with_file_name(name);
let p2 = &CString::new(p.as_os_str().as_bytes()).unwrap();
res = execve(p2, args, env);
}

return res;
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
use sys::syscall::{syscall, SYSPIVOTROOT};
use {Errno, Result, NixPath};

#[cfg(feature = "execvpe")]
use std::ffi::CString;

pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
new_root: &P1, put_old: &P2) -> Result<()> {
Expand All @@ -387,22 +411,5 @@ mod linux {
Errno::result(res).map(drop)
}

#[inline]
#[cfg(feature = "execvpe")]
pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
use std::ptr;
use libc::c_char;

let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
args_p.push(ptr::null());

let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
env_p.push(ptr::null());

unsafe {
super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
};

Err(Error::Sys(Errno::last()))
}
}

0 comments on commit 7e2cd68

Please sign in to comment.