Skip to content

Commit b4ec20a

Browse files
committed
nice: use Command::exec() instead of libc::execvp()
No need to use the unsafe `libc::execvp()`, the standard rust library provides the functionality via the safe function `Command::exec()`. Signed-off-by: Etienne Cordonnier <[email protected]>
1 parent aaa0610 commit b4ec20a

File tree

1 file changed

+15
-38
lines changed

1 file changed

+15
-38
lines changed

src/uu/env/src/env.rs

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
// spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets setenv putenv spawnp SIGSEGV SIGBUS sigaction
6+
// spell-checker:ignore (ToDO) chdir progname subcommand subcommands unsets setenv putenv spawnp SIGSEGV SIGBUS sigaction
77

88
pub mod native_int_str;
99
pub mod split_iterator;
@@ -21,16 +21,14 @@ use native_int_str::{
2121
use nix::libc;
2222
#[cfg(unix)]
2323
use nix::sys::signal::{SigHandler::SigIgn, Signal, signal};
24-
#[cfg(unix)]
25-
use nix::unistd::execvp;
2624
use std::borrow::Cow;
2725
use std::env;
28-
#[cfg(unix)]
29-
use std::ffi::CString;
3026
use std::ffi::{OsStr, OsString};
3127
use std::io::{self, Write};
3228
#[cfg(unix)]
3329
use std::os::unix::ffi::OsStrExt;
30+
#[cfg(unix)]
31+
use std::os::unix::process::CommandExt;
3432

3533
use uucore::display::Quotable;
3634
use uucore::error::{ExitCode, UError, UResult, USimpleError, UUsageError};
@@ -606,34 +604,16 @@ impl EnvAppData {
606604

607605
#[cfg(unix)]
608606
{
609-
// Convert program name to CString.
610-
let Ok(prog_cstring) = CString::new(prog.as_bytes()) else {
611-
return Err(self.make_error_no_such_file_or_dir(&prog));
612-
};
613-
614-
// Prepare arguments for execvp.
615-
let mut argv = Vec::new();
616-
617-
// Convert arg0 to CString.
618-
let Ok(arg0_cstring) = CString::new(arg0.as_bytes()) else {
619-
return Err(self.make_error_no_such_file_or_dir(&prog));
620-
};
621-
argv.push(arg0_cstring);
622-
623-
// Convert remaining arguments to CString.
624-
for arg in args {
625-
let Ok(arg_cstring) = CString::new(arg.as_bytes()) else {
626-
return Err(self.make_error_no_such_file_or_dir(&prog));
627-
};
628-
argv.push(arg_cstring);
629-
}
630-
631-
// Execute the program using execvp. this replaces the current
632-
// process. The execvp function takes care of appending a NULL
633-
// argument to the argument list so that we don't have to.
634-
match execvp(&prog_cstring, &argv) {
635-
Err(nix::errno::Errno::ENOENT) => Err(self.make_error_no_such_file_or_dir(&prog)),
636-
Err(nix::errno::Errno::EACCES) => {
607+
// Execute the program using exec, which replaces the current process.
608+
let err = std::process::Command::new(&*prog)
609+
.arg0(&*arg0)
610+
.args(args)
611+
.exec();
612+
613+
// exec() only returns if there was an error
614+
match err.kind() {
615+
io::ErrorKind::NotFound => Err(self.make_error_no_such_file_or_dir(&prog)),
616+
io::ErrorKind::PermissionDenied => {
637617
uucore::show_error!(
638618
"{}",
639619
translate!(
@@ -643,19 +623,16 @@ impl EnvAppData {
643623
);
644624
Err(126.into())
645625
}
646-
Err(_) => {
626+
_ => {
647627
uucore::show_error!(
648628
"{}",
649629
translate!(
650630
"env-error-unknown",
651-
"error" => "execvp failed"
631+
"error" => err
652632
)
653633
);
654634
Err(126.into())
655635
}
656-
Ok(_) => {
657-
unreachable!("execvp should never return on success")
658-
}
659636
}
660637
}
661638

0 commit comments

Comments
 (0)