@@ -49,6 +49,12 @@ static REAL_EXECVPE: AtomicPtr<libc::c_void> = {
4949 AtomicPtr :: new ( ptr)
5050} ;
5151
52+ #[ ctor]
53+ static REAL_EXECVP : AtomicPtr < libc:: c_void > = {
54+ let ptr = unsafe { libc:: dlsym ( RTLD_NEXT , c"execvp" . as_ptr ( ) as * const _ ) } ;
55+ AtomicPtr :: new ( ptr)
56+ } ;
57+
5258#[ ctor]
5359static REAL_EXECVP_OPENBSD : AtomicPtr < libc:: c_void > = {
5460 let ptr = unsafe { libc:: dlsym ( RTLD_NEXT , c"execvP" . as_ptr ( ) as * const _ ) } ;
@@ -180,7 +186,8 @@ pub unsafe extern "C" fn rust_execve(
180186
181187/// Rust implementation of execvpe (GNU extension)
182188///
183- /// Called from C shim for: execvpe, execvp, execlp
189+ /// Called from C shim for: execvpe
190+ /// On platforms where execvpe is available, execlp and execvp are also routed here.
184191///
185192/// # Safety
186193/// This function is unsafe because it:
@@ -226,6 +233,52 @@ pub unsafe extern "C" fn rust_execvpe(
226233 }
227234}
228235
236+ /// Rust implementation of execvp
237+ ///
238+ /// Called from C shim for: execvp, execlp (on platforms where execvpe is not available)
239+ ///
240+ /// Unlike `rust_execvpe`, this function does not take an explicit `envp` argument.
241+ /// The real `execvp` uses the process's `environ`, so no environment doctoring is
242+ /// performed here (same approach as `popen` and `system`).
243+ ///
244+ /// # Safety
245+ /// This function is unsafe because it:
246+ /// - Dereferences raw pointers
247+ /// - Calls the real execvp function
248+ #[ cfg( has_symbol_execvp) ]
249+ #[ unsafe( no_mangle) ]
250+ pub unsafe extern "C" fn rust_execvp (
251+ file : * const c_char ,
252+ argv : * const * const c_char ,
253+ ) -> c_int {
254+ type ExecvpFunc = unsafe extern "C" fn (
255+ file : * const c_char ,
256+ argv : * const * const c_char ,
257+ ) -> c_int ;
258+
259+ unsafe {
260+ report ( || {
261+ let result = Execution {
262+ executable : as_path_buf ( file) ?,
263+ arguments : as_string_vec ( argv) ?,
264+ working_dir : working_dir ( ) ?,
265+ environment : std:: env:: vars ( ) . collect ( ) ,
266+ } ;
267+ Ok ( result)
268+ } ) ;
269+
270+ let func_ptr = REAL_EXECVP . load ( Ordering :: SeqCst ) ;
271+ if !func_ptr. is_null ( ) {
272+ let real_func_ptr: ExecvpFunc = std:: mem:: transmute ( func_ptr) ;
273+ real_func_ptr ( file, argv)
274+ } else {
275+ log:: error!( "Real execvp function not found" ) ;
276+ set_errno ( libc:: ENOSYS ) ;
277+ -1
278+ }
279+ }
280+ }
281+
229282/// Rust implementation of execvP (BSD extension)
230283///
231284/// Called from C shim for: execvP
0 commit comments