@@ -24,6 +24,7 @@ use prelude::*;
24
24
use ptr;
25
25
use task;
26
26
use vec:: ImmutableVector ;
27
+ use vec;
27
28
28
29
/**
29
30
* A value representing a child process.
@@ -690,46 +691,58 @@ fn spawn_process_os(prog: &str, args: &[~str],
690
691
}
691
692
692
693
#[ cfg( unix) ]
693
- fn with_argv < T > ( prog : & str , args : & [ ~str ] ,
694
- cb : & fn ( * * libc:: c_char ) -> T ) -> T {
695
- let mut argptrs = ~[ prog. as_c_str ( |b| b) ] ;
696
- let mut tmps = ~[ ] ;
694
+ fn with_argv < T > ( prog : & str , args : & [ ~str ] , cb : & fn ( * * libc:: c_char ) -> T ) -> T {
695
+ // We can't directly convert `str`s into `*char`s, as someone needs to hold
696
+ // a reference to the intermediary byte buffers. So first build an array to
697
+ // hold all the ~[u8] byte strings.
698
+ let mut tmps = vec:: with_capacity ( args. len ( ) + 1 ) ;
699
+
700
+ tmps. push ( prog. to_owned ( ) . to_c_str ( ) ) ;
701
+
697
702
foreach arg in args. iter ( ) {
698
- let t = @( * arg) . clone ( ) ;
699
- tmps. push ( t) ;
700
- argptrs. push ( t. as_c_str ( |b| b) ) ;
703
+ tmps. push ( arg. to_owned ( ) . to_c_str ( ) ) ;
701
704
}
702
- argptrs. push ( ptr:: null ( ) ) ;
703
- argptrs. as_imm_buf ( |buf, _len| cb ( buf) )
705
+
706
+ // Next, convert each of the byte strings into a pointer. This is
707
+ // technically unsafe as the caller could leak these pointers out of our
708
+ // scope.
709
+ let mut ptrs = do tmps. map |tmp| {
710
+ tmp. as_imm_buf ( |buf, _| buf as * libc:: c_char )
711
+ } ;
712
+
713
+ // Finally, make sure we add a null pointer.
714
+ ptrs. push ( ptr:: null ( ) ) ;
715
+
716
+ ptrs. as_imm_buf ( |buf, _| cb ( buf) )
704
717
}
705
718
706
719
#[ cfg( unix) ]
707
720
fn with_envp < T > ( env : Option < & [ ( ~str , ~str ) ] > , cb : & fn ( * c_void ) -> T ) -> T {
708
- // On posixy systems we can pass a char** for envp, which is
709
- // a null-terminated array of "k=v\n" strings.
721
+ // On posixy systems we can pass a char** for envp, which is a
722
+ // null-terminated array of "k=v\n" strings. Like `with_argv`, we have to
723
+ // have a temporary buffer to hold the intermediary `~[u8]` byte strings.
710
724
match env {
711
- Some ( es) => {
712
- let mut tmps = ~[ ] ;
713
- let mut ptrs = ~[ ] ;
714
-
715
- foreach pair in es. iter ( ) {
716
- // Use of match here is just to workaround limitations
717
- // in the stage0 irrefutable pattern impl.
718
- match pair {
719
- & ( ref k, ref v) => {
720
- let kv = @fmt ! ( "%s=%s" , * k, * v) ;
721
- tmps. push ( kv) ;
722
- ptrs. push ( kv. as_c_str ( |b| b) ) ;
723
- }
725
+ Some ( env) => {
726
+ let mut tmps = vec:: with_capacity ( env. len ( ) ) ;
727
+
728
+ foreach pair in env. iter ( ) {
729
+ // Use of match here is just to workaround limitations
730
+ // in the stage0 irrefutable pattern impl.
731
+ let kv = fmt ! ( "%s=%s" , pair. first( ) , pair. second( ) ) ;
732
+ tmps. push ( kv. to_c_str ( ) ) ;
724
733
}
725
- }
726
734
727
- ptrs. push ( ptr:: null ( ) ) ;
728
- ptrs. as_imm_buf ( |p, _len|
729
- unsafe { cb ( :: cast:: transmute ( p) ) }
730
- )
731
- }
732
- _ => cb ( ptr:: null ( ) )
735
+ // Once again, this is unsafe.
736
+ let mut ptrs = do tmps. map |tmp| {
737
+ tmp. as_imm_buf ( |buf, _| buf as * libc:: c_char )
738
+ } ;
739
+ ptrs. push ( ptr:: null ( ) ) ;
740
+
741
+ do ptrs. as_imm_buf |buf, _| {
742
+ unsafe { cb( cast:: transmute( buf) ) }
743
+ }
744
+ }
745
+ _ => cb ( ptr:: null ( ) )
733
746
}
734
747
}
735
748
@@ -739,23 +752,25 @@ fn with_envp<T>(env: Option<&[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T {
739
752
// rather a concatenation of null-terminated k=v\0 sequences, with a final
740
753
// \0 to terminate.
741
754
match env {
742
- Some ( es) => {
743
- let mut blk = ~[ ] ;
744
- foreach pair in es. iter ( ) {
745
- let kv = fmt ! ( "%s=%s" , pair. first( ) , pair. second( ) ) ;
746
- blk. push_all ( kv. to_bytes_with_null ( ) ) ;
755
+ Some ( env) => {
756
+ let mut blk = ~[ ] ;
757
+
758
+ foreach pair in env. iter ( ) {
759
+ let kv = fmt ! ( "%s=%s" , pair. first( ) , pair. second( ) ) ;
760
+ blk. push_all ( kv. to_c_str ( ) ) ;
761
+ }
762
+
763
+ blk. push ( 0 ) ;
764
+
765
+ do blk. as_imm_buf |p, _len| {
766
+ unsafe { cb ( cast:: transmute ( p) ) }
767
+ }
747
768
}
748
- blk. push ( 0 ) ;
749
- blk. as_imm_buf ( |p, _len|
750
- unsafe { cb ( :: cast:: transmute ( p) ) }
751
- )
752
- }
753
- _ => cb ( ptr:: mut_null ( ) )
769
+ _ => cb ( ptr:: mut_null ( ) )
754
770
}
755
771
}
756
772
757
- fn with_dirp < T > ( d : Option < & Path > ,
758
- cb : & fn ( * libc:: c_char ) -> T ) -> T {
773
+ fn with_dirp < T > ( d : Option < & Path > , cb : & fn ( * libc:: c_char ) -> T ) -> T {
759
774
match d {
760
775
Some ( dir) => dir. to_str ( ) . as_c_str ( cb) ,
761
776
None => cb ( ptr:: null ( ) )
0 commit comments