Skip to content

Commit dfcf1d0

Browse files
committed
Revert "env: use Command::exec() instead of libc::execvp()"
This reverts commit e27da7e.
1 parent 57e2842 commit dfcf1d0

File tree

1 file changed

+38
-15
lines changed

1 file changed

+38
-15
lines changed

src/uu/env/src/env.rs

Lines changed: 38 additions & 15 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 progname subcommand subcommands unsets setenv putenv spawnp SIGSEGV SIGBUS sigaction
6+
// spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets setenv putenv spawnp SIGSEGV SIGBUS sigaction
77

88
pub mod native_int_str;
99
pub mod split_iterator;
@@ -21,14 +21,16 @@ 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;
2426
use std::borrow::Cow;
2527
use std::env;
28+
#[cfg(unix)]
29+
use std::ffi::CString;
2630
use std::ffi::{OsStr, OsString};
2731
use std::io::{self, Write};
2832
#[cfg(unix)]
2933
use std::os::unix::ffi::OsStrExt;
30-
#[cfg(unix)]
31-
use std::os::unix::process::CommandExt;
3234

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

605607
#[cfg(unix)]
606608
{
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 => {
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) => {
617637
uucore::show_error!(
618638
"{}",
619639
translate!(
@@ -623,16 +643,19 @@ impl EnvAppData {
623643
);
624644
Err(126.into())
625645
}
626-
_ => {
646+
Err(_) => {
627647
uucore::show_error!(
628648
"{}",
629649
translate!(
630650
"env-error-unknown",
631-
"error" => err
651+
"error" => "execvp failed"
632652
)
633653
);
634654
Err(126.into())
635655
}
656+
Ok(_) => {
657+
unreachable!("execvp should never return on success")
658+
}
636659
}
637660
}
638661

0 commit comments

Comments
 (0)