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