summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/unistd.rs22
-rw-r--r--test/test_unistd.rs57
3 files changed, 58 insertions, 23 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 28c01a41..cc29e7ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased] - ReleaseDate
### Added
### Changed
+- Changed unistd::{execv,execve,execvp,execvpe,fexecve,execveat} to take both `&[&CStr]` and `&[CString]` as its list argument(s).
+ (#[1278](https://github.com/nix-rust/nix/pull/1278))
### Fixed
### Removed
diff --git a/src/unistd.rs b/src/unistd.rs
index d53b438c..06f997f4 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -12,9 +12,9 @@ use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
uid_t, gid_t, mode_t, PATH_MAX};
use std::{fmt, mem, ptr};
use std::convert::Infallible;
-use std::ffi::{CStr, OsString};
+use std::ffi::{CStr, CString, OsString};
#[cfg(not(target_os = "redox"))]
-use std::ffi::{CString, OsStr};
+use std::ffi::{OsStr};
use std::os::unix::ffi::OsStringExt;
#[cfg(not(target_os = "redox"))]
use std::os::unix::ffi::OsStrExt;
@@ -715,9 +715,9 @@ pub fn fchownat<P: ?Sized + NixPath>(
Errno::result(res).map(drop)
}
-fn to_exec_array(args: &[&CStr]) -> Vec<*const c_char> {
+fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char> {
use std::iter::once;
- args.iter().map(|s| s.as_ptr()).chain(once(ptr::null())).collect()
+ args.iter().map(|s| s.as_ref().as_ptr()).chain(once(ptr::null())).collect()
}
/// Replace the current process image with a new one (see
@@ -727,7 +727,7 @@ fn to_exec_array(args: &[&CStr]) -> Vec<*const c_char> {
/// performs the same action but does not allow for customization of the
/// environment for the new process.
#[inline]
-pub fn execv(path: &CStr, argv: &[&CStr]) -> Result<Infallible> {
+pub fn execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible> {
let args_p = to_exec_array(argv);
unsafe {
@@ -751,7 +751,7 @@ pub fn execv(path: &CStr, argv: &[&CStr]) -> Result<Infallible> {
/// in the `args` list is an argument to the new process. Each element in the
/// `env` list should be a string in the form "key=value".
#[inline]
-pub fn execve(path: &CStr, args: &[&CStr], env: &[&CStr]) -> Result<Infallible> {
+pub fn execve<SA: AsRef<CStr>, SE: AsRef<CStr>>(path: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
let args_p = to_exec_array(args);
let env_p = to_exec_array(env);
@@ -772,7 +772,7 @@ pub fn execve(path: &CStr, args: &[&CStr], env: &[&CStr]) -> Result<Infallible>
/// would not work if "bash" was specified for the path argument, but `execvp`
/// would assuming that a bash executable was on the system `PATH`.
#[inline]
-pub fn execvp(filename: &CStr, args: &[&CStr]) -> Result<Infallible> {
+pub fn execvp<S: AsRef<CStr>>(filename: &CStr, args: &[S]) -> Result<Infallible> {
let args_p = to_exec_array(args);
unsafe {
@@ -792,7 +792,7 @@ pub fn execvp(filename: &CStr, args: &[&CStr]) -> Result<Infallible> {
#[cfg(any(target_os = "haiku",
target_os = "linux",
target_os = "openbsd"))]
-pub fn execvpe(filename: &CStr, args: &[&CStr], env: &[&CStr]) -> Result<Infallible> {
+pub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(filename: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
let args_p = to_exec_array(args);
let env_p = to_exec_array(env);
@@ -820,7 +820,7 @@ pub fn execvpe(filename: &CStr, args: &[&CStr], env: &[&CStr]) -> Result<Infalli
target_os = "linux",
target_os = "freebsd"))]
#[inline]
-pub fn fexecve(fd: RawFd, args: &[&CStr], env: &[&CStr]) -> Result<Infallible> {
+pub fn fexecve<SA: AsRef<CStr> ,SE: AsRef<CStr>>(fd: RawFd, args: &[SA], env: &[SE]) -> Result<Infallible> {
let args_p = to_exec_array(args);
let env_p = to_exec_array(env);
@@ -843,8 +843,8 @@ pub fn fexecve(fd: RawFd, args: &[&CStr], env: &[&CStr]) -> Result<Infallible> {
/// is referenced as a file descriptor to the base directory plus a path.
#[cfg(any(target_os = "android", target_os = "linux"))]
#[inline]
-pub fn execveat(dirfd: RawFd, pathname: &CStr, args: &[&CStr],
- env: &[&CStr], flags: super::fcntl::AtFlags) -> Result<Infallible> {
+pub fn execveat<SA: AsRef<CStr>,SE: AsRef<CStr>>(dirfd: RawFd, pathname: &CStr, args: &[SA],
+ env: &[SE], flags: super::fcntl::AtFlags) -> Result<Infallible> {
let args_p = to_exec_array(args);
let env_p = to_exec_array(env);
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index 8fe1d432..0b2a810a 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -256,8 +256,38 @@ fn test_initgroups() {
#[cfg(not(target_os = "redox"))]
macro_rules! execve_test_factory(
($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => (
- #[test]
- fn $test_name() {
+
+ #[cfg(test)]
+ mod $test_name {
+ use super::*;
+
+ fn syscall_cstr_ref() -> Result<std::convert::Infallible, nix::Error> {
+ $syscall(
+ $exe,
+ $(CString::new($pathname).unwrap().as_c_str(), )*
+ &[CString::new(b"".as_ref()).unwrap().as_c_str(),
+ CString::new(b"-c".as_ref()).unwrap().as_c_str(),
+ CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
+ .as_ref()).unwrap().as_c_str()],
+ &[CString::new(b"foo=bar".as_ref()).unwrap().as_c_str(),
+ CString::new(b"baz=quux".as_ref()).unwrap().as_c_str()]
+ $(, $flags)*)
+ }
+
+ fn syscall_cstring() -> Result<std::convert::Infallible, nix::Error> {
+ $syscall(
+ $exe,
+ $(CString::new($pathname).unwrap().as_c_str(), )*
+ &[CString::new(b"".as_ref()).unwrap(),
+ CString::new(b"-c".as_ref()).unwrap(),
+ CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
+ .as_ref()).unwrap()],
+ &[CString::new(b"foo=bar".as_ref()).unwrap(),
+ CString::new(b"baz=quux".as_ref()).unwrap()]
+ $(, $flags)*)
+ }
+
+ fn common_test(syscall: fn() -> Result<std::convert::Infallible, nix::Error>) {
if "execveat" == stringify!($syscall) {
// Though undocumented, Docker's default seccomp profile seems to
// block this syscall. https://github.com/nix-rust/nix/issues/1122
@@ -276,16 +306,7 @@ macro_rules! execve_test_factory(
Child => {
// Make `writer` be the stdout of the new process.
dup2(writer, 1).unwrap();
- let r = $syscall(
- $exe,
- $(CString::new($pathname).unwrap().as_c_str(), )*
- &[CString::new(b"".as_ref()).unwrap().as_c_str(),
- CString::new(b"-c".as_ref()).unwrap().as_c_str(),
- CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
- .as_ref()).unwrap().as_c_str()],
- &[CString::new(b"foo=bar".as_ref()).unwrap().as_c_str(),
- CString::new(b"baz=quux".as_ref()).unwrap().as_c_str()]
- $(, $flags)*);
+ let r = syscall();
let _ = std::io::stderr()
.write_all(format!("{:?}", r).as_bytes());
// Should only get here in event of error
@@ -307,6 +328,18 @@ macro_rules! execve_test_factory(
}
}
}
+
+ #[test]
+ fn test_cstr_ref() {
+ common_test(syscall_cstr_ref);
+ }
+
+ #[test]
+ fn test_cstring() {
+ common_test(syscall_cstring);
+ }
+ }
+
)
);