Skip to content

Commit 61c4513

Browse files
committed
refactor to_exec_array
1 parent 2fd13d4 commit 61c4513

File tree

3 files changed

+55
-56
lines changed

3 files changed

+55
-56
lines changed

src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,3 +412,14 @@ where
412412
None => Ok(f(ptr::null())),
413413
}
414414
}
415+
416+
#[cfg(feature = "process")]
417+
pub(crate) fn c_slice_to_pointers<S: AsRef<CStr>>(
418+
slice: &[S],
419+
) -> Box<[*const libc::c_char]> {
420+
slice
421+
.iter()
422+
.map(|s| s.as_ref().as_ptr())
423+
.chain(std::iter::once(std::ptr::null()))
424+
.collect()
425+
}

src/spawn.rs

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -343,21 +343,6 @@ impl Drop for PosixSpawnFileActions {
343343
}
344344
}
345345

346-
// The POSIX standard requires those `args` and `envp` to be of type `*const *mut [c_char]`,
347-
// but implementations won't modify them, making the `mut` type redundant. Considering this,
348-
// Nix does not expose this mutability, but we have to change the interface when calling the
349-
// underlying libc interfaces , this helper function does the conversion job.
350-
//
351-
// SAFETY:
352-
// It is safe to add the mutability in types as implementations won't mutable them.
353-
unsafe fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*mut libc::c_char> {
354-
use std::iter::once;
355-
args.iter()
356-
.map(|s| s.as_ref().as_ptr().cast_mut())
357-
.chain(once(std::ptr::null_mut()))
358-
.collect()
359-
}
360-
361346
/// Create a new child process from the specified process image. See
362347
/// [posix_spawn](https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html).
363348
pub fn posix_spawn<P, SA, SE>(
@@ -374,19 +359,24 @@ where
374359
{
375360
let mut pid = 0;
376361

377-
let ret = unsafe {
378-
let args_p = to_exec_array(args);
379-
let env_p = to_exec_array(envp);
380-
362+
let ret = {
381363
path.with_nix_path(|c_str| {
382-
libc::posix_spawn(
383-
&mut pid as *mut libc::pid_t,
384-
c_str.as_ptr(),
385-
&file_actions.fa as *const libc::posix_spawn_file_actions_t,
386-
&attr.attr as *const libc::posix_spawnattr_t,
387-
args_p.as_ptr(),
388-
env_p.as_ptr(),
389-
)
364+
let args_p = crate::c_slice_to_pointers(args);
365+
let env_p = crate::c_slice_to_pointers(envp);
366+
367+
// SAFETY: The POSIX standard specifies `argv` and `envp` as `*const *mut c_char`,
368+
// but also requires that these arrays and their strings must not be modified,
369+
// so passing immutable data is sound.
370+
unsafe {
371+
libc::posix_spawn(
372+
&mut pid as *mut libc::pid_t,
373+
c_str.as_ptr(),
374+
&file_actions.fa as *const libc::posix_spawn_file_actions_t,
375+
&attr.attr as *const libc::posix_spawnattr_t,
376+
args_p.as_ptr() as *const *mut _,
377+
env_p.as_ptr() as *const *mut _,
378+
)
379+
}
390380
})?
391381
};
392382

@@ -408,18 +398,23 @@ pub fn posix_spawnp<SA: AsRef<CStr>, SE: AsRef<CStr>>(
408398
) -> Result<Pid> {
409399
let mut pid = 0;
410400

411-
let ret = unsafe {
412-
let args_p = to_exec_array(args);
413-
let env_p = to_exec_array(envp);
414-
415-
libc::posix_spawnp(
416-
&mut pid as *mut libc::pid_t,
417-
path.as_ptr(),
418-
&file_actions.fa as *const libc::posix_spawn_file_actions_t,
419-
&attr.attr as *const libc::posix_spawnattr_t,
420-
args_p.as_ptr(),
421-
env_p.as_ptr(),
422-
)
401+
let ret = {
402+
let args_p = crate::c_slice_to_pointers(args);
403+
let env_p = crate::c_slice_to_pointers(envp);
404+
405+
// SAFETY: The POSIX standard specifies `argv` and `envp` as `*const *mut c_char`,
406+
// but also states that these arrays and their strings shall not be modified,
407+
// so passing immutable data is sound.
408+
unsafe {
409+
libc::posix_spawnp(
410+
&mut pid as *mut libc::pid_t,
411+
path.as_ptr(),
412+
&file_actions.fa as *const libc::posix_spawn_file_actions_t,
413+
&attr.attr as *const libc::posix_spawnattr_t,
414+
args_p.as_ptr() as *const *mut _,
415+
env_p.as_ptr() as *const *mut _,
416+
)
417+
}
423418
};
424419

425420
if ret != 0 {

src/unistd.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,13 +1079,6 @@ pub fn fchownat<Fd: std::os::fd::AsFd, P: ?Sized + NixPath>(
10791079

10801080
feature! {
10811081
#![feature = "process"]
1082-
fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char> {
1083-
use std::iter::once;
1084-
args.iter()
1085-
.map(|s| s.as_ref().as_ptr())
1086-
.chain(once(ptr::null()))
1087-
.collect()
1088-
}
10891082

10901083
/// Replace the current process image with a new one (see
10911084
/// [exec(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
@@ -1095,7 +1088,7 @@ fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char> {
10951088
/// environment for the new process.
10961089
#[inline]
10971090
pub fn execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible> {
1098-
let args_p = to_exec_array(argv);
1091+
let args_p = crate::c_slice_to_pointers(argv);
10991092

11001093
unsafe { libc::execv(path.as_ptr(), args_p.as_ptr()) };
11011094

@@ -1120,8 +1113,8 @@ pub fn execve<SA: AsRef<CStr>, SE: AsRef<CStr>>(
11201113
args: &[SA],
11211114
env: &[SE],
11221115
) -> Result<Infallible> {
1123-
let args_p = to_exec_array(args);
1124-
let env_p = to_exec_array(env);
1116+
let args_p = crate::c_slice_to_pointers(args);
1117+
let env_p = crate::c_slice_to_pointers(env);
11251118

11261119
unsafe { libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) };
11271120

@@ -1142,7 +1135,7 @@ pub fn execvp<S: AsRef<CStr>>(
11421135
filename: &CStr,
11431136
args: &[S],
11441137
) -> Result<Infallible> {
1145-
let args_p = to_exec_array(args);
1138+
let args_p = crate::c_slice_to_pointers(args);
11461139

11471140
unsafe { libc::execvp(filename.as_ptr(), args_p.as_ptr()) };
11481141

@@ -1162,8 +1155,8 @@ pub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(
11621155
args: &[SA],
11631156
env: &[SE],
11641157
) -> Result<Infallible> {
1165-
let args_p = to_exec_array(args);
1166-
let env_p = to_exec_array(env);
1158+
let args_p = crate::c_slice_to_pointers(args);
1159+
let env_p = crate::c_slice_to_pointers(env);
11671160

11681161
unsafe {
11691162
libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
@@ -1191,8 +1184,8 @@ pub fn fexecve<Fd: std::os::fd::AsFd, SA: AsRef<CStr>, SE: AsRef<CStr>>(
11911184
) -> Result<Infallible> {
11921185
use std::os::fd::AsRawFd;
11931186

1194-
let args_p = to_exec_array(args);
1195-
let env_p = to_exec_array(env);
1187+
let args_p = crate::c_slice_to_pointers(args);
1188+
let env_p = crate::c_slice_to_pointers(env);
11961189

11971190
unsafe { libc::fexecve(fd.as_fd().as_raw_fd(), args_p.as_ptr(), env_p.as_ptr()) };
11981191

@@ -1220,8 +1213,8 @@ pub fn execveat<Fd: std::os::fd::AsFd, SA: AsRef<CStr>, SE: AsRef<CStr>>(
12201213
) -> Result<Infallible> {
12211214
use std::os::fd::AsRawFd;
12221215

1223-
let args_p = to_exec_array(args);
1224-
let env_p = to_exec_array(env);
1216+
let args_p = crate::c_slice_to_pointers(args);
1217+
let env_p = crate::c_slice_to_pointers(env);
12251218

12261219
unsafe {
12271220
libc::syscall(

0 commit comments

Comments
 (0)