1
1
//! Safe wrappers around functions found in libc "unistd.h" header
2
2
3
3
use errno:: { self , Errno } ;
4
- use { Error , Result , NixPath } ;
4
+ use { Error , Result , NixPath , IntoRef , TerminatedSlice } ;
5
5
use fcntl:: { fcntl, FdFlag , OFlag } ;
6
6
use fcntl:: FcntlArg :: F_SETFD ;
7
7
use libc:: { self , c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
@@ -552,25 +552,19 @@ pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<Uid>, group: Option<Gi
552
552
Errno :: result ( res) . map ( drop)
553
553
}
554
554
555
- fn to_exec_array ( args : & [ CString ] ) -> Vec < * const c_char > {
556
- let mut args_p: Vec < * const c_char > = args. iter ( ) . map ( |s| s. as_ptr ( ) ) . collect ( ) ;
557
- args_p. push ( ptr:: null ( ) ) ;
558
- args_p
559
- }
560
-
561
555
/// Replace the current process image with a new one (see
562
556
/// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
563
557
///
564
558
/// See the `::nix::unistd::execve` system call for additional details. `execv`
565
559
/// performs the same action but does not allow for customization of the
566
560
/// environment for the new process.
567
561
#[ inline]
568
- pub fn execv ( path : & CString , argv : & [ CString ] ) -> Result < Void > {
569
- let args_p = to_exec_array ( argv) ;
562
+ pub fn execv < ' a , P : ? Sized + NixPath , A : IntoRef < ' a , TerminatedSlice < & ' a c_char > > > ( path : & P , argv : A ) -> Result < Void > {
563
+ let args_p = argv. into_ref ( ) ;
570
564
571
- unsafe {
572
- libc:: execv ( path . as_ptr ( ) , args_p. as_ptr ( ) )
573
- } ;
565
+ try! ( path . with_nix_path ( |cstr| {
566
+ unsafe { libc:: execv ( cstr . as_ptr ( ) , args_p. as_ptr ( ) ) }
567
+ } ) ) ;
574
568
575
569
Err ( Error :: Sys ( Errno :: last ( ) ) )
576
570
}
@@ -589,13 +583,13 @@ pub fn execv(path: &CString, argv: &[CString]) -> Result<Void> {
589
583
/// in the `args` list is an argument to the new process. Each element in the
590
584
/// `env` list should be a string in the form "key=value".
591
585
#[ inline]
592
- pub fn execve ( path : & CString , args : & [ CString ] , env : & [ CString ] ) -> Result < Void > {
593
- let args_p = to_exec_array ( args) ;
594
- let env_p = to_exec_array ( env) ;
586
+ pub fn execve < ' a , ' e , P : ? Sized + NixPath , A : IntoRef < ' a , TerminatedSlice < & ' a c_char > > , E : IntoRef < ' e , TerminatedSlice < & ' e c_char > > > ( path : & P , args : A , env : E ) -> Result < Void > {
587
+ let args_p = args. into_ref ( ) ;
588
+ let env_p = env. into_ref ( ) ;
595
589
596
- unsafe {
597
- libc:: execve ( path . as_ptr ( ) , args_p. as_ptr ( ) , env_p. as_ptr ( ) )
598
- } ;
590
+ try! ( path . with_nix_path ( |cstr| {
591
+ unsafe { libc:: execve ( cstr . as_ptr ( ) , args_p. as_ptr ( ) , env_p. as_ptr ( ) ) }
592
+ } ) ) ;
599
593
600
594
Err ( Error :: Sys ( Errno :: last ( ) ) )
601
595
}
@@ -610,12 +604,14 @@ pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<Void>
610
604
/// would not work if "bash" was specified for the path argument, but `execvp`
611
605
/// would assuming that a bash executable was on the system `PATH`.
612
606
#[ inline]
613
- pub fn execvp ( filename : & CString , args : & [ CString ] ) -> Result < Void > {
614
- let args_p = to_exec_array ( args) ;
607
+ pub fn execvp < ' a , P : ? Sized + NixPath , A : IntoRef < ' a , TerminatedSlice < & ' a c_char > > > ( filename : & P , args : A ) -> Result < Void > {
608
+ let args_p = args. into_ref ( ) ;
615
609
616
- unsafe {
617
- libc:: execvp ( filename. as_ptr ( ) , args_p. as_ptr ( ) )
618
- } ;
610
+ try!( filename. with_nix_path ( |cstr| {
611
+ unsafe {
612
+ libc:: execvp ( cstr. as_ptr ( ) , args_p. as_ptr ( ) )
613
+ }
614
+ } ) ) ;
619
615
620
616
Err ( Error :: Sys ( Errno :: last ( ) ) )
621
617
}
@@ -633,9 +629,9 @@ pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
633
629
#[ cfg( any( target_os = "android" , target_os = "dragonfly" , target_os = "freebsd" ,
634
630
target_os = "netbsd" , target_os = "openbsd" , target_os = "linux" ) ) ]
635
631
#[ inline]
636
- pub fn fexecve ( fd : RawFd , args : & [ CString ] , env : & [ CString ] ) -> Result < Void > {
637
- let args_p = to_exec_array ( args) ;
638
- let env_p = to_exec_array ( env) ;
632
+ pub fn fexecve < ' a , ' e , A : IntoRef < ' a , TerminatedSlice < & ' a c_char > > , E : IntoRef < ' e , TerminatedSlice < & ' e c_char > > > ( fd : RawFd , args : A , env : E ) -> Result < Void > {
633
+ let args_p = args. into_ref ( ) ;
634
+ let env_p = env. into_ref ( ) ;
639
635
640
636
unsafe {
641
637
libc:: fexecve ( fd, args_p. as_ptr ( ) , env_p. as_ptr ( ) )
@@ -656,10 +652,10 @@ pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
656
652
/// is referenced as a file descriptor to the base directory plus a path.
657
653
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
658
654
#[ inline]
659
- pub fn execveat ( dirfd : RawFd , pathname : & CString , args : & [ CString ] ,
660
- env : & [ CString ] , flags : super :: fcntl:: AtFlags ) -> Result < Void > {
661
- let args_p = to_exec_array ( args) ;
662
- let env_p = to_exec_array ( env) ;
655
+ pub fn execveat < ' a , ' e , A : IntoRef < ' a , TerminatedSlice < & ' a c_char > > , E : IntoRef < ' e , TerminatedSlice < & ' e c_char > > > ( dirfd : RawFd , pathname : & CString , args : A ,
656
+ env : E , flags : super :: fcntl:: AtFlags ) -> Result < Void > {
657
+ let args_p = args. into_ref ( ) ;
658
+ let env_p = env. into_ref ( ) ;
663
659
664
660
unsafe {
665
661
libc:: syscall ( libc:: SYS_execveat , dirfd, pathname. as_ptr ( ) ,
0 commit comments