11#[ cfg( all( test,  not( target_os = "emscripten" ) ) ) ]  
22mod  tests; 
33
4- use  libc:: { EXIT_FAILURE ,  EXIT_SUCCESS ,  c_char ,   c_int,  gid_t,  pid_t,  uid_t} ; 
4+ use  libc:: { EXIT_FAILURE ,  EXIT_SUCCESS ,  c_int,  gid_t,  pid_t,  uid_t} ; 
55
6+ pub  use  self :: cstring_array:: CStringArray ; 
7+ use  self :: cstring_array:: CStringIter ; 
68use  crate :: collections:: BTreeMap ; 
79use  crate :: ffi:: { CStr ,  CString ,  OsStr ,  OsString } ; 
810use  crate :: os:: unix:: prelude:: * ; 
@@ -14,7 +16,9 @@ use crate::sys::fs::OpenOptions;
1416use  crate :: sys:: pipe:: { self ,  AnonPipe } ; 
1517use  crate :: sys:: process:: env:: { CommandEnv ,  CommandEnvs } ; 
1618use  crate :: sys_common:: { FromInner ,  IntoInner } ; 
17- use  crate :: { fmt,  io,  ptr} ; 
19+ use  crate :: { fmt,  io} ; 
20+ 
21+ mod  cstring_array; 
1822
1923cfg_if:: cfg_if! { 
2024    if  #[ cfg( target_os = "fuchsia" ) ]  { 
@@ -77,13 +81,7 @@ cfg_if::cfg_if! {
7781
7882pub  struct  Command  { 
7983    program :  CString , 
80-     args :  Vec < CString > , 
81-     /// Exactly what will be passed to `execvp`. 
82- /// 
83- /// First element is a pointer to `program`, followed by pointers to 
84- /// `args`, followed by a `null`. Be careful when modifying `program` or 
85- /// `args` to properly update this as well. 
86- argv :  Argv , 
84+     args :  CStringArray , 
8785    env :  CommandEnv , 
8886
8987    program_kind :  ProgramKind , 
@@ -102,14 +100,6 @@ pub struct Command {
102100    pgroup :  Option < pid_t > , 
103101} 
104102
105- // Create a new type for argv, so that we can make it `Send` and `Sync` 
106- struct  Argv ( Vec < * const  c_char > ) ; 
107- 
108- // It is safe to make `Argv` `Send` and `Sync`, because it contains 
109- // pointers to memory owned by `Command.args` 
110- unsafe  impl  Send  for  Argv  { } 
111- unsafe  impl  Sync  for  Argv  { } 
112- 
113103// passed back to std::process with the pipes connected to the child, if any 
114104// were requested 
115105pub  struct  StdioPipes  { 
@@ -171,42 +161,17 @@ impl ProgramKind {
171161} 
172162
173163impl  Command  { 
174-     #[ cfg( not( target_os = "linux" ) ) ]  
175164    pub  fn  new ( program :  & OsStr )  -> Command  { 
176165        let  mut  saw_nul = false ; 
177166        let  program_kind = ProgramKind :: new ( program. as_ref ( ) ) ; 
178167        let  program = os2c ( program,  & mut  saw_nul) ; 
168+         let  mut  args = CStringArray :: with_capacity ( 1 ) ; 
169+         args. push ( program. clone ( ) ) ; 
179170        Command  { 
180-             argv :  Argv ( vec ! [ program. as_ptr( ) ,  ptr:: null( ) ] ) , 
181-             args :  vec ! [ program. clone( ) ] , 
182171            program, 
183-             program_kind , 
172+             args , 
184173            env :  Default :: default ( ) , 
185-             cwd :  None , 
186-             chroot :  None , 
187-             uid :  None , 
188-             gid :  None , 
189-             saw_nul, 
190-             closures :  Vec :: new ( ) , 
191-             groups :  None , 
192-             stdin :  None , 
193-             stdout :  None , 
194-             stderr :  None , 
195-             pgroup :  None , 
196-         } 
197-     } 
198- 
199-     #[ cfg( target_os = "linux" ) ]  
200-     pub  fn  new ( program :  & OsStr )  -> Command  { 
201-         let  mut  saw_nul = false ; 
202-         let  program_kind = ProgramKind :: new ( program. as_ref ( ) ) ; 
203-         let  program = os2c ( program,  & mut  saw_nul) ; 
204-         Command  { 
205-             argv :  Argv ( vec ! [ program. as_ptr( ) ,  ptr:: null( ) ] ) , 
206-             args :  vec ! [ program. clone( ) ] , 
207-             program, 
208174            program_kind, 
209-             env :  Default :: default ( ) , 
210175            cwd :  None , 
211176            chroot :  None , 
212177            uid :  None , 
@@ -217,6 +182,7 @@ impl Command {
217182            stdin :  None , 
218183            stdout :  None , 
219184            stderr :  None , 
185+             #[ cfg( target_os = "linux" ) ]  
220186            create_pidfd :  false , 
221187            pgroup :  None , 
222188        } 
@@ -225,20 +191,11 @@ impl Command {
225191    pub  fn  set_arg_0 ( & mut  self ,  arg :  & OsStr )  { 
226192        // Set a new arg0 
227193        let  arg = os2c ( arg,  & mut  self . saw_nul ) ; 
228-         debug_assert ! ( self . argv. 0 . len( )  > 1 ) ; 
229-         self . argv . 0 [ 0 ]  = arg. as_ptr ( ) ; 
230-         self . args [ 0 ]  = arg; 
194+         self . args . write ( 0 ,  arg) ; 
231195    } 
232196
233197    pub  fn  arg ( & mut  self ,  arg :  & OsStr )  { 
234-         // Overwrite the trailing null pointer in `argv` and then add a new null 
235-         // pointer. 
236198        let  arg = os2c ( arg,  & mut  self . saw_nul ) ; 
237-         self . argv . 0 [ self . args . len ( ) ]  = arg. as_ptr ( ) ; 
238-         self . argv . 0 . push ( ptr:: null ( ) ) ; 
239- 
240-         // Also make sure we keep track of the owned value to schedule a 
241-         // destructor for this memory. 
242199        self . args . push ( arg) ; 
243200    } 
244201
@@ -295,6 +252,8 @@ impl Command {
295252
296253    pub  fn  get_args ( & self )  -> CommandArgs < ' _ >  { 
297254        let  mut  iter = self . args . iter ( ) ; 
255+         // argv[0] contains the program name, but we are only interested in the 
256+         // arguments so skip it. 
298257        iter. next ( ) ; 
299258        CommandArgs  {  iter } 
300259    } 
@@ -307,12 +266,12 @@ impl Command {
307266        self . cwd . as_ref ( ) . map ( |cs| Path :: new ( OsStr :: from_bytes ( cs. as_bytes ( ) ) ) ) 
308267    } 
309268
310-     pub  fn  get_argv ( & self )  -> & Vec < * const   c_char >  { 
311-         & self . argv . 0 
269+     pub  fn  get_argv ( & self )  -> & CStringArray  { 
270+         & self . args 
312271    } 
313272
314273    pub  fn  get_program_cstr ( & self )  -> & CStr  { 
315-         & * self . program 
274+         & self . program 
316275    } 
317276
318277    #[ allow( dead_code) ]  
@@ -405,32 +364,6 @@ fn os2c(s: &OsStr, saw_nul: &mut bool) -> CString {
405364    } ) 
406365} 
407366
408- // Helper type to manage ownership of the strings within a C-style array. 
409- pub  struct  CStringArray  { 
410-     items :  Vec < CString > , 
411-     ptrs :  Vec < * const  c_char > , 
412- } 
413- 
414- impl  CStringArray  { 
415-     pub  fn  with_capacity ( capacity :  usize )  -> Self  { 
416-         let  mut  result = CStringArray  { 
417-             items :  Vec :: with_capacity ( capacity) , 
418-             ptrs :  Vec :: with_capacity ( capacity + 1 ) , 
419-         } ; 
420-         result. ptrs . push ( ptr:: null ( ) ) ; 
421-         result
422-     } 
423-     pub  fn  push ( & mut  self ,  item :  CString )  { 
424-         let  l = self . ptrs . len ( ) ; 
425-         self . ptrs [ l - 1 ]  = item. as_ptr ( ) ; 
426-         self . ptrs . push ( ptr:: null ( ) ) ; 
427-         self . items . push ( item) ; 
428-     } 
429-     pub  fn  as_ptr ( & self )  -> * const  * const  c_char  { 
430-         self . ptrs . as_ptr ( ) 
431-     } 
432- } 
433- 
434367fn  construct_envp ( env :  BTreeMap < OsString ,  OsString > ,  saw_nul :  & mut  bool )  -> CStringArray  { 
435368    let  mut  result = CStringArray :: with_capacity ( env. len ( ) ) ; 
436369    for  ( mut  k,  v)  in  env { 
@@ -619,14 +552,16 @@ impl fmt::Debug for Command {
619552                    write ! ( f,  "{}={value:?} " ,  key. to_string_lossy( ) ) ?; 
620553                } 
621554            } 
622-             if  self . program  != self . args [ 0 ]  { 
555+ 
556+             if  * self . program  != self . args [ 0 ]  { 
623557                write ! ( f,  "[{:?}] " ,  self . program) ?; 
624558            } 
625-             write ! ( f,  "{:?}" ,  self . args[ 0 ] ) ?; 
559+             write ! ( f,  "{:?}" ,  & self . args[ 0 ] ) ?; 
626560
627-             for  arg in  & self . args [ 1 .. ]  { 
561+             for  arg in  self . get_args ( )  { 
628562                write ! ( f,  " {:?}" ,  arg) ?; 
629563            } 
564+ 
630565            Ok ( ( ) ) 
631566        } 
632567    } 
@@ -658,14 +593,16 @@ impl From<u8> for ExitCode {
658593} 
659594
660595pub  struct  CommandArgs < ' a >  { 
661-     iter :  crate :: slice :: Iter < ' a ,   CString > , 
596+     iter :  CStringIter < ' a > , 
662597} 
663598
664599impl < ' a >  Iterator  for  CommandArgs < ' a >  { 
665600    type  Item  = & ' a  OsStr ; 
601+ 
666602    fn  next ( & mut  self )  -> Option < & ' a  OsStr >  { 
667-         self . iter . next ( ) . map ( |cs| OsStr :: from_bytes ( cs. as_bytes ( ) ) ) 
603+         self . iter . next ( ) . map ( |cs| OsStr :: from_bytes ( cs. to_bytes ( ) ) ) 
668604    } 
605+ 
669606    fn  size_hint ( & self )  -> ( usize ,  Option < usize > )  { 
670607        self . iter . size_hint ( ) 
671608    } 
@@ -675,6 +612,7 @@ impl<'a> ExactSizeIterator for CommandArgs<'a> {
675612    fn  len ( & self )  -> usize  { 
676613        self . iter . len ( ) 
677614    } 
615+ 
678616    fn  is_empty ( & self )  -> bool  { 
679617        self . iter . is_empty ( ) 
680618    } 
0 commit comments