@@ -89,6 +89,7 @@ impl Command {
89
89
// The child calls `mem::forget` to leak the lock, which is crucial because
90
90
// releasing a lock is not async-signal-safe.
91
91
let env_lock = sys:: env:: env_read_lock ( ) ;
92
+
92
93
let pid = unsafe { self . do_fork ( ) ? } ;
93
94
94
95
if pid == 0 {
@@ -276,7 +277,7 @@ impl Command {
276
277
unsafe fn do_exec (
277
278
& mut self ,
278
279
stdio : ChildPipes ,
279
- maybe_envp : Option < & CStringArray > ,
280
+ mut maybe_envp : Option < & CStringArray > ,
280
281
) -> Result < !, io:: Error > {
281
282
use crate :: sys:: { self , cvt_r} ;
282
283
@@ -378,13 +379,15 @@ impl Command {
378
379
callback ( ) ?;
379
380
}
380
381
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.
386
382
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.
388
391
struct Reset ( * const * const libc:: c_char ) ;
389
392
390
393
impl Drop for Reset {
@@ -397,9 +400,18 @@ impl Command {
397
400
398
401
_reset = Some ( Reset ( * sys:: env:: environ ( ) ) ) ;
399
402
* 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 ( ) ) ;
400
414
}
401
-
402
- libc:: execvp ( self . get_program_cstr ( ) . as_ptr ( ) , self . get_argv ( ) . as_ptr ( ) ) ;
403
415
Err ( io:: Error :: last_os_error ( ) )
404
416
}
405
417
@@ -453,7 +465,7 @@ impl Command {
453
465
454
466
if self . get_gid ( ) . is_some ( )
455
467
|| self . get_uid ( ) . is_some ( )
456
- || ( self . env_saw_path ( ) && ! self . program_is_path ( ) )
468
+ || self . use_child_path ( )
457
469
|| !self . get_closures ( ) . is_empty ( )
458
470
|| self . get_groups ( ) . is_some ( )
459
471
|| self . get_chroot ( ) . is_some ( )
@@ -793,6 +805,7 @@ impl Command {
793
805
// Safety: -1 indicates we don't have a pidfd.
794
806
let mut p = Process :: new ( 0 , -1 ) ;
795
807
808
+ // FIXME: if a list of paths to search is passed then retry for every path.
796
809
let spawn_res = spawn_fn (
797
810
& mut p. pid ,
798
811
self . get_program_cstr ( ) . as_ptr ( ) ,
0 commit comments