summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2017-08-20 23:20:01 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2017-08-20 23:20:01 +0000
commit97caa0ca0d70f92119fcd9eb5d82b8acda637470 (patch)
treef97dfdf31f02be3406cd10d492f93d45c6993689
parente2f9531aa0ac533bc9328943eb0aac883d10c625 (diff)
parentd9f1b3df600b9e70c8a64baae9c8e39d2ce733a0 (diff)
downloadnix-97caa0ca0d70f92119fcd9eb5d82b8acda637470.zip
Merge #727
727: unistd: add fexecve() r=Susurrus This adds fexecve(). It is available in libc since 0.2.29. Ref: http://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/unistd.rs31
-rw-r--r--test/test.rs2
-rw-r--r--test/test_unistd.rs29
4 files changed, 54 insertions, 10 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88c266a5..f9ec8fa1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#647](https://github.com/nix-rust/nix/pull/647))
- Added the `pid()` method to `WaitStatus` for extracting the PID.
([#722](https://github.com/nix-rust/nix/pull/722))
+- Added `nix::unistd:fexecve`.
+ ([#727](https://github.com/nix-rust/nix/pull/727))
### Changed
- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))
diff --git a/src/unistd.rs b/src/unistd.rs
index 86cce832..af38cf2d 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -593,6 +593,37 @@ pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
Err(Error::Sys(Errno::last()))
}
+/// Replace the current process image with a new one (see
+/// [fexecve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)).
+///
+/// The `fexecve` function allows for another process to be "called" which will
+/// replace the current process image. That is, this process becomes the new
+/// command that is run. On success, this function will not return. Instead,
+/// the new program will run until it exits.
+///
+/// This function is similar to `execve`, except that the program to be executed
+/// is referenced as a file descriptor instead of a path.
+///
+/// # Errors
+///
+/// If an error occurs, this function will return with an indication of the
+/// cause of failure. See
+/// [fexecve(2)#errors](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html#tag_16_111_05)
+/// for a list of error conditions.
+#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
+ target_os = "netbsd", target_os = "openbsd", target_os = "linux"))]
+#[inline]
+pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
+ let args_p = to_exec_array(args);
+ let env_p = to_exec_array(env);
+
+ unsafe {
+ libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr())
+ };
+
+ Err(Error::Sys(Errno::last()))
+}
+
/// Daemonize this process by detaching from the controlling terminal (see
/// [daemon(3)](http://man7.org/linux/man-pages/man3/daemon.3.html)).
///
diff --git a/test/test.rs b/test/test.rs
index 1d22b59a..1b73c4ff 100644
--- a/test/test.rs
+++ b/test/test.rs
@@ -1,4 +1,6 @@
#[macro_use]
+extern crate cfg_if;
+#[macro_use]
extern crate nix;
#[macro_use]
extern crate lazy_static;
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index 09143c58..adf73579 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -105,7 +105,7 @@ mod linux_android {
}
macro_rules! execve_test_factory(
- ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => (
+ ($test_name:ident, $syscall:ident, $exe: expr) => (
#[test]
fn $test_name() {
#[allow(unused_variables)]
@@ -119,19 +119,13 @@ macro_rules! execve_test_factory(
// The tests make sure not to do that, though.
match fork().unwrap() {
Child => {
- #[cfg(not(target_os = "android"))]
- const SH_PATH: &'static [u8] = $unix_sh;
-
- #[cfg(target_os = "android")]
- const SH_PATH: &'static [u8] = $android_sh;
-
// Close stdout.
close(1).unwrap();
// Make `writer` be the stdout of the new process.
dup(writer).unwrap();
// exec!
$syscall(
- &CString::new(SH_PATH).unwrap(),
+ $exe,
&[CString::new(b"".as_ref()).unwrap(),
CString::new(b"-c".as_ref()).unwrap(),
CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
@@ -156,6 +150,23 @@ macro_rules! execve_test_factory(
)
);
+cfg_if!{
+ if #[cfg(target_os = "android")] {
+ execve_test_factory!(test_execve, execve, &CString::new("/system/bin/sh").unwrap());
+ execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
+ } else if #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "linux", ))] {
+ execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
+ execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
+ } else if #[cfg(any(target_os = "ios", target_os = "macos", ))] {
+ execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
+ // No fexecve() on macos/ios.
+ }
+}
+
#[test]
fn test_fchdir() {
// fchdir changes the process's cwd
@@ -231,8 +242,6 @@ fn test_lseek64() {
close(tmpfd).unwrap();
}
-execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");
-
#[test]
fn test_fpathconf_limited() {
let f = tempfile().unwrap();