@@ -89,6 +89,7 @@ impl Command {
8989 // The child calls `mem::forget` to leak the lock, which is crucial because
9090 // releasing a lock is not async-signal-safe.
9191 let env_lock = sys:: env:: env_read_lock ( ) ;
92+
9293 let pid = unsafe { self . do_fork ( ) ? } ;
9394
9495 if pid == 0 {
@@ -276,7 +277,7 @@ impl Command {
276277 unsafe fn do_exec (
277278 & mut self ,
278279 stdio : ChildPipes ,
279- maybe_envp : Option < & CStringArray > ,
280+ mut maybe_envp : Option < & CStringArray > ,
280281 ) -> Result < !, io:: Error > {
281282 use crate :: sys:: { self , cvt_r} ;
282283
@@ -378,13 +379,15 @@ impl Command {
378379 callback ( ) ?;
379380 }
380381
381- // Although we're performing an exec here we may also return with an
382- // error from this function (without actually exec'ing) in which case we
383- // want to be sure to restore the global environment back to what it
384- // once was, ensuring that our temporary override, when free'd, doesn't
385- // corrupt our process's environment.
386382 let mut _reset = None ;
387- if let Some ( envp) = maybe_envp {
383+ if let Some ( envp) = maybe_envp
384+ && self . use_child_path ( )
385+ {
386+ // Although we're performing an exec here we may also return with an
387+ // error from this function (without actually exec'ing) in which case we
388+ // want to be sure to restore the global environment back to what it
389+ // once was, ensuring that our temporary override, when free'd, doesn't
390+ // corrupt our process's environment.
388391 struct Reset ( * const * const libc:: c_char ) ;
389392
390393 impl Drop for Reset {
@@ -397,9 +400,18 @@ impl Command {
397400
398401 _reset = Some ( Reset ( * sys:: env:: environ ( ) ) ) ;
399402 * sys:: env:: environ ( ) = envp. as_ptr ( ) ;
403+ // We've set the environment, no need to set it again.
404+ maybe_envp = None ;
405+ }
406+ if let Some ( envp) = maybe_envp {
407+ libc:: execvpe (
408+ self . get_program_cstr ( ) . as_ptr ( ) ,
409+ self . get_argv ( ) . as_ptr ( ) ,
410+ envp. as_ptr ( ) ,
411+ ) ;
412+ } else {
413+ libc:: execvp ( self . get_program_cstr ( ) . as_ptr ( ) , self . get_argv ( ) . as_ptr ( ) ) ;
400414 }
401-
402- libc:: execvp ( self . get_program_cstr ( ) . as_ptr ( ) , self . get_argv ( ) . as_ptr ( ) ) ;
403415 Err ( io:: Error :: last_os_error ( ) )
404416 }
405417
@@ -453,7 +465,7 @@ impl Command {
453465
454466 if self . get_gid ( ) . is_some ( )
455467 || self . get_uid ( ) . is_some ( )
456- || ( self . env_saw_path ( ) && ! self . program_is_path ( ) )
468+ || self . use_child_path ( )
457469 || !self . get_closures ( ) . is_empty ( )
458470 || self . get_groups ( ) . is_some ( )
459471 || self . get_chroot ( ) . is_some ( )
@@ -793,6 +805,7 @@ impl Command {
793805 // Safety: -1 indicates we don't have a pidfd.
794806 let mut p = Process :: new ( 0 , -1 ) ;
795807
808+ // FIXME: if a list of paths to search is passed then retry for every path.
796809 let spawn_res = spawn_fn (
797810 & mut p. pid ,
798811 self . get_program_cstr ( ) . as_ptr ( ) ,
0 commit comments