Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 15 additions & 38 deletions src/uu/env/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

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

pub mod native_int_str;
pub mod split_iterator;
Expand All @@ -21,16 +21,14 @@ use native_int_str::{
use nix::libc;
#[cfg(unix)]
use nix::sys::signal::{SigHandler::SigIgn, Signal, signal};
#[cfg(unix)]
use nix::unistd::execvp;
use std::borrow::Cow;
use std::env;
#[cfg(unix)]
use std::ffi::CString;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
#[cfg(unix)]
use std::os::unix::ffi::OsStrExt;
#[cfg(unix)]
use std::os::unix::process::CommandExt;

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

#[cfg(unix)]
{
// Convert program name to CString.
let Ok(prog_cstring) = CString::new(prog.as_bytes()) else {
return Err(self.make_error_no_such_file_or_dir(&prog));
};

// Prepare arguments for execvp.
let mut argv = Vec::new();

// Convert arg0 to CString.
let Ok(arg0_cstring) = CString::new(arg0.as_bytes()) else {
return Err(self.make_error_no_such_file_or_dir(&prog));
};
argv.push(arg0_cstring);

// Convert remaining arguments to CString.
for arg in args {
let Ok(arg_cstring) = CString::new(arg.as_bytes()) else {
return Err(self.make_error_no_such_file_or_dir(&prog));
};
argv.push(arg_cstring);
}

// Execute the program using execvp. this replaces the current
// process. The execvp function takes care of appending a NULL
// argument to the argument list so that we don't have to.
match execvp(&prog_cstring, &argv) {
Err(nix::errno::Errno::ENOENT) => Err(self.make_error_no_such_file_or_dir(&prog)),
Err(nix::errno::Errno::EACCES) => {
// Execute the program using exec, which replaces the current process.
let err = std::process::Command::new(&*prog)
.arg0(&*arg0)
.args(args)
.exec();

// exec() only returns if there was an error
match err.kind() {
io::ErrorKind::NotFound => Err(self.make_error_no_such_file_or_dir(&prog)),
io::ErrorKind::PermissionDenied => {
uucore::show_error!(
"{}",
translate!(
Expand All @@ -643,19 +623,16 @@ impl EnvAppData {
);
Err(126.into())
}
Err(_) => {
_ => {
uucore::show_error!(
"{}",
translate!(
"env-error-unknown",
"error" => "execvp failed"
"error" => err
)
);
Err(126.into())
}
Ok(_) => {
unreachable!("execvp should never return on success")
}
}
}

Expand Down
Loading