@@ -47,6 +47,8 @@ use crate::vm::VirtualMachine;
47
47
#[ cfg( unix) ]
48
48
use crate :: obj:: objdict:: PyMapping ;
49
49
#[ cfg( unix) ]
50
+ use crate :: obj:: objlist:: PyListRef ;
51
+ #[ cfg( unix) ]
50
52
use crate :: pyobject:: PyIterable ;
51
53
#[ cfg( unix) ]
52
54
use std:: convert:: TryFrom ;
@@ -1271,6 +1273,33 @@ fn os_chmod(
1271
1273
Ok ( ( ) )
1272
1274
}
1273
1275
1276
+ #[ cfg( unix) ]
1277
+ fn os_execv (
1278
+ path : PyStringRef ,
1279
+ argv_list : Either < PyListRef , PyTupleRef > ,
1280
+ vm : & VirtualMachine ,
1281
+ ) -> PyResult < ( ) > {
1282
+ let path = ffi:: CString :: new ( path. as_str ( ) )
1283
+ . map_err ( |_| vm. new_value_error ( "embedded null character" . to_owned ( ) ) ) ?;
1284
+
1285
+ let argv: Vec < ffi:: CString > = match argv_list {
1286
+ Either :: A ( list) => vm. extract_elements ( list. as_object ( ) ) ?,
1287
+ Either :: B ( tuple) => vm. extract_elements ( tuple. as_object ( ) ) ?,
1288
+ } ;
1289
+ let argv: Vec < & ffi:: CStr > = argv. iter ( ) . map ( |entry| entry. as_c_str ( ) ) . collect ( ) ;
1290
+
1291
+ if argv. is_empty ( ) {
1292
+ return Err ( vm. new_value_error ( "execv() arg 2 must not be empty" . to_owned ( ) ) ) ;
1293
+ }
1294
+ if argv. first ( ) . unwrap ( ) . to_bytes ( ) . is_empty ( ) {
1295
+ return Err ( vm. new_value_error ( "execv() arg 2 first element cannot be empty" . to_owned ( ) ) ) ;
1296
+ }
1297
+
1298
+ unistd:: execv ( & path, & argv)
1299
+ . map ( |_ok| ( ) )
1300
+ . map_err ( |err| convert_nix_error ( vm, err) )
1301
+ }
1302
+
1274
1303
fn os_fspath ( path : PyPathLike , vm : & VirtualMachine ) -> PyResult {
1275
1304
path. mode . process_path ( path. path , vm)
1276
1305
}
@@ -2171,6 +2200,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
2171
2200
SupportFunc :: new( vm, "lchown" , os_lchown, None , None , None ) ,
2172
2201
SupportFunc :: new( vm, "fchown" , os_fchown, Some ( true ) , None , Some ( true ) ) ,
2173
2202
SupportFunc :: new( vm, "umask" , os_umask, Some ( false ) , Some ( false ) , Some ( false ) ) ,
2203
+ SupportFunc :: new( vm, "execv" , os_execv, None , None , None ) ,
2174
2204
] ) ;
2175
2205
let supports_fd = PySet :: default ( ) . into_ref ( vm) ;
2176
2206
let supports_dir_fd = PySet :: default ( ) . into_ref ( vm) ;
@@ -2268,6 +2298,7 @@ fn extend_module_platform_specific(vm: &VirtualMachine, module: &PyObjectRef) {
2268
2298
2269
2299
extend_module ! ( vm, module, {
2270
2300
"chmod" => ctx. new_function( os_chmod) ,
2301
+ "execv" => ctx. new_function( os_execv) , // TODO: windows
2271
2302
"get_inheritable" => ctx. new_function( os_get_inheritable) , // TODO: windows
2272
2303
"get_blocking" => ctx. new_function( os_get_blocking) ,
2273
2304
"getppid" => ctx. new_function( os_getppid) ,
0 commit comments