@@ -446,132 +446,129 @@ fn spawn_process_os(config: p::ProcessConfig,
446446 assert_eq ! ( ret, 0 ) ;
447447 }
448448
449- let pipe = os:: pipe ( ) ;
450- let mut input = file:: FileDesc :: new ( pipe. input , true ) ;
451- let mut output = file:: FileDesc :: new ( pipe. out , true ) ;
449+ let dirp = dir. map ( |p| p. to_c_str ( ) ) ;
450+ let dirp = dirp. as_ref ( ) . map ( |c| c. with_ref ( |p| p) ) . unwrap_or ( ptr:: null ( ) ) ;
451+
452+ with_envp ( env, proc ( envp) {
453+ with_argv ( config. program , config. args , proc ( argv) unsafe {
454+ let pipe = os:: pipe ( ) ;
455+ let mut input = file:: FileDesc :: new ( pipe. input , true ) ;
456+ let mut output = file:: FileDesc :: new ( pipe. out , true ) ;
457+
458+ set_cloexec ( output. fd ( ) ) ;
459+
460+ let pid = fork ( ) ;
461+ if pid < 0 {
462+ fail ! ( "failure in fork: {}" , os:: last_os_error( ) ) ;
463+ } else if pid > 0 {
464+ drop ( output) ;
465+ let mut bytes = [ 0 , ..4 ] ;
466+ return match input. inner_read ( bytes) {
467+ Ok ( 4 ) => {
468+ let errno = ( bytes[ 0 ] << 24 ) as i32 |
469+ ( bytes[ 1 ] << 16 ) as i32 |
470+ ( bytes[ 2 ] << 8 ) as i32 |
471+ ( bytes[ 3 ] << 0 ) as i32 ;
472+ Err ( super :: translate_error ( errno, false ) )
473+ }
474+ Err ( e) => {
475+ assert ! ( e. kind == io:: BrokenPipe ||
476+ e. kind == io:: EndOfFile ,
477+ "unexpected error: {}" , e) ;
478+ Ok ( SpawnProcessResult {
479+ pid : pid,
480+ handle : ptr:: null ( )
481+ } )
482+ }
483+ Ok ( ..) => fail ! ( "short read on the cloexec pipe" ) ,
484+ } ;
485+ }
486+ drop ( input) ;
487+
488+ fn fail ( output : & mut file:: FileDesc ) -> ! {
489+ let errno = os:: errno ( ) ;
490+ let bytes = [
491+ ( errno << 24 ) as u8 ,
492+ ( errno << 16 ) as u8 ,
493+ ( errno << 8 ) as u8 ,
494+ ( errno << 0 ) as u8 ,
495+ ] ;
496+ assert ! ( output. inner_write( bytes) . is_ok( ) ) ;
497+ unsafe { libc:: _exit ( 1 ) }
498+ }
452499
453- unsafe { set_cloexec ( output . fd ( ) ) } ;
500+ rustrt :: rust_unset_sigprocmask ( ) ;
454501
455- unsafe {
456- let pid = fork ( ) ;
457- if pid < 0 {
458- fail ! ( "failure in fork: {}" , os:: last_os_error( ) ) ;
459- } else if pid > 0 {
460- drop ( output) ;
461- let mut bytes = [ 0 , ..4 ] ;
462- return match input. inner_read ( bytes) {
463- Ok ( 4 ) => {
464- let errno = ( bytes[ 0 ] << 24 ) as i32 |
465- ( bytes[ 1 ] << 16 ) as i32 |
466- ( bytes[ 2 ] << 8 ) as i32 |
467- ( bytes[ 3 ] << 0 ) as i32 ;
468- Err ( super :: translate_error ( errno, false ) )
469- }
470- Err ( e) => {
471- assert ! ( e. kind == io:: BrokenPipe ||
472- e. kind == io:: EndOfFile ,
473- "unexpected error: {}" , e) ;
474- Ok ( SpawnProcessResult {
475- pid : pid,
476- handle : ptr:: null ( )
477- } )
502+ if in_fd == -1 {
503+ let _ = libc:: close ( libc:: STDIN_FILENO ) ;
504+ } else if retry ( || dup2 ( in_fd, 0 ) ) == -1 {
505+ fail ( & mut output) ;
506+ }
507+ if out_fd == -1 {
508+ let _ = libc:: close ( libc:: STDOUT_FILENO ) ;
509+ } else if retry ( || dup2 ( out_fd, 1 ) ) == -1 {
510+ fail ( & mut output) ;
511+ }
512+ if err_fd == -1 {
513+ let _ = libc:: close ( libc:: STDERR_FILENO ) ;
514+ } else if retry ( || dup2 ( err_fd, 2 ) ) == -1 {
515+ fail ( & mut output) ;
516+ }
517+ // close all other fds
518+ for fd in range ( 3 , getdtablesize ( ) ) . rev ( ) {
519+ if fd != output. fd ( ) {
520+ let _ = close ( fd as c_int ) ;
478521 }
479- Ok ( ..) => fail ! ( "short read on the cloexec pipe" ) ,
480- } ;
481- }
482- drop ( input) ;
483-
484- fn fail ( output : & mut file:: FileDesc ) -> ! {
485- let errno = os:: errno ( ) ;
486- let bytes = [
487- ( errno << 24 ) as u8 ,
488- ( errno << 16 ) as u8 ,
489- ( errno << 8 ) as u8 ,
490- ( errno << 0 ) as u8 ,
491- ] ;
492- assert ! ( output. inner_write( bytes) . is_ok( ) ) ;
493- unsafe { libc:: _exit ( 1 ) }
494- }
495-
496- rustrt:: rust_unset_sigprocmask ( ) ;
497-
498- if in_fd == -1 {
499- let _ = libc:: close ( libc:: STDIN_FILENO ) ;
500- } else if retry ( || dup2 ( in_fd, 0 ) ) == -1 {
501- fail ( & mut output) ;
502- }
503- if out_fd == -1 {
504- let _ = libc:: close ( libc:: STDOUT_FILENO ) ;
505- } else if retry ( || dup2 ( out_fd, 1 ) ) == -1 {
506- fail ( & mut output) ;
507- }
508- if err_fd == -1 {
509- let _ = libc:: close ( libc:: STDERR_FILENO ) ;
510- } else if retry ( || dup2 ( err_fd, 2 ) ) == -1 {
511- fail ( & mut output) ;
512- }
513- // close all other fds
514- for fd in range ( 3 , getdtablesize ( ) ) . rev ( ) {
515- if fd != output. fd ( ) {
516- let _ = close ( fd as c_int ) ;
517522 }
518- }
519523
520- match config. gid {
521- Some ( u) => {
522- if libc:: setgid ( u as libc:: gid_t ) != 0 {
523- fail ( & mut output) ;
524+ match config. gid {
525+ Some ( u) => {
526+ if libc:: setgid ( u as libc:: gid_t ) != 0 {
527+ fail ( & mut output) ;
528+ }
524529 }
530+ None => { }
525531 }
526- None => { }
527- }
528- match config. uid {
529- Some ( u) => {
530- // When dropping privileges from root, the `setgroups` call will
531- // remove any extraneous groups. If we don't call this, then
532- // even though our uid has dropped, we may still have groups
533- // that enable us to do super-user things. This will fail if we
534- // aren't root, so don't bother checking the return value, this
535- // is just done as an optimistic privilege dropping function.
536- extern {
537- fn setgroups ( ngroups : libc:: c_int ,
538- ptr : * libc:: c_void ) -> libc:: c_int ;
539- }
540- let _ = setgroups ( 0 , 0 as * libc:: c_void ) ;
532+ match config. uid {
533+ Some ( u) => {
534+ // When dropping privileges from root, the `setgroups` call will
535+ // remove any extraneous groups. If we don't call this, then
536+ // even though our uid has dropped, we may still have groups
537+ // that enable us to do super-user things. This will fail if we
538+ // aren't root, so don't bother checking the return value, this
539+ // is just done as an optimistic privilege dropping function.
540+ extern {
541+ fn setgroups ( ngroups : libc:: c_int ,
542+ ptr : * libc:: c_void ) -> libc:: c_int ;
543+ }
544+ let _ = setgroups ( 0 , 0 as * libc:: c_void ) ;
541545
542- if libc:: setuid ( u as libc:: uid_t ) != 0 {
543- fail ( & mut output) ;
546+ if libc:: setuid ( u as libc:: uid_t ) != 0 {
547+ fail ( & mut output) ;
548+ }
544549 }
550+ None => { }
551+ }
552+ if config. detach {
553+ // Don't check the error of setsid because it fails if we're the
554+ // process leader already. We just forked so it shouldn't return
555+ // error, but ignore it anyway.
556+ let _ = libc:: setsid ( ) ;
545557 }
546- None => { }
547- }
548- if config. detach {
549- // Don't check the error of setsid because it fails if we're the
550- // process leader already. We just forked so it shouldn't return
551- // error, but ignore it anyway.
552- let _ = libc:: setsid ( ) ;
553- }
554-
555- with_dirp ( dir, |dirp| {
556558 if !dirp. is_null ( ) && chdir ( dirp) == -1 {
557559 fail ( & mut output) ;
558560 }
559- } ) ;
560-
561- with_envp ( env, |envp| {
562561 if !envp. is_null ( ) {
563562 set_environ ( envp) ;
564563 }
565- with_argv ( config. program , config. args , |argv| {
566- let _ = execvp ( * argv, argv) ;
567- fail ( & mut output) ;
568- } )
564+ let _ = execvp ( * argv, argv) ;
565+ fail ( & mut output) ;
569566 } )
570- }
567+ } )
571568}
572569
573570#[ cfg( unix) ]
574- fn with_argv < T > ( prog : & str , args : & [ ~str ] , cb : | * * libc:: c_char | -> T ) -> T {
571+ fn with_argv < T > ( prog : & str , args : & [ ~str ] , cb : proc : ( * * libc:: c_char ) -> T ) -> T {
575572 use std:: slice;
576573
577574 // We can't directly convert `str`s into `*char`s, as someone needs to hold
@@ -597,7 +594,7 @@ fn with_argv<T>(prog: &str, args: &[~str], cb: |**libc::c_char| -> T) -> T {
597594}
598595
599596#[ cfg( unix) ]
600- fn with_envp < T > ( env : Option < ~[ ( ~str , ~str ) ] > , cb : | * c_void| -> T ) -> T {
597+ fn with_envp < T > ( env : Option < ~[ ( ~str , ~str ) ] > , cb : proc : ( * c_void ) -> T ) -> T {
601598 use std:: slice;
602599
603600 // On posixy systems we can pass a char** for envp, which is a
@@ -645,6 +642,7 @@ fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: |*mut c_void| -> T) -> T {
645642 }
646643}
647644
645+ #[ cfg( windows) ]
648646fn with_dirp < T > ( d : Option < & Path > , cb : |* libc:: c_char | -> T ) -> T {
649647 match d {
650648 Some ( dir) => dir. with_c_str ( |buf| cb ( buf) ) ,
0 commit comments