wasmer_wasix/syscalls/wasix/
proc_spawn2.rs

1use super::*;
2use crate::syscalls::*;
3
4/// Spawns a new sub-process (posix-spawn style).
5///
6/// Legacy delimiter-based API: `args` and `envs` are single strings with entries
7/// separated by line feeds. Prefer `proc_spawn3` for proper string lists.
8///
9/// ## Parameters
10///
11/// * `name` - Name of the process to be spawned
12/// * `args` - List of the arguments to pass the process
13///   (entries are separated by line feeds)
14/// * `envs` - List of the environment variables to pass process
15///
16/// ## Return
17///
18/// On success, writes the child PID to `ret` and returns `Errno::Success`.
19/// On failure, returns an error code.
20#[instrument(
21    level = "trace",
22    skip_all,
23    fields(name = field::Empty, full_path = field::Empty, pid = field::Empty, tid = field::Empty, %args_len),
24    ret)]
25pub fn proc_spawn2<M: MemorySize>(
26    mut ctx: FunctionEnvMut<'_, WasiEnv>,
27    name: WasmPtr<u8, M>,
28    name_len: M::Offset,
29    args: WasmPtr<u8, M>,
30    args_len: M::Offset,
31    envs: WasmPtr<u8, M>,
32    envs_len: M::Offset,
33    fd_ops: WasmPtr<ProcSpawnFdOp<M>, M>,
34    fd_ops_len: M::Offset,
35    signal_actions: WasmPtr<SignalDisposition, M>,
36    signal_actions_len: M::Offset,
37    search_path: Bool,
38    path: WasmPtr<u8, M>,
39    path_len: M::Offset,
40    ret: WasmPtr<Pid, M>,
41) -> Result<Errno, WasiError> {
42    WasiEnv::do_pending_operations(&mut ctx)?;
43
44    let memory = unsafe { ctx.data().memory_view(&ctx) };
45    let mut name = unsafe { get_input_str_ok!(&memory, name, name_len) };
46    Span::current().record("name", name.as_str());
47    let args = unsafe { get_input_str_ok!(&memory, args, args_len) };
48    let args = parse_delimited_string_list(&args);
49
50    let envs = if !envs.is_null() {
51        let envs = unsafe { get_input_str_ok!(&memory, envs, envs_len) };
52        Some(wasi_try_ok!(parse_delimited_env_list(&envs)))
53    } else {
54        None
55    };
56
57    let signals = if !signal_actions.is_null() {
58        let signal_actions = wasi_try_mem_ok!(signal_actions.slice(&memory, signal_actions_len));
59        let mut vec = Vec::with_capacity(signal_actions.len() as usize);
60        for s in wasi_try_mem_ok!(signal_actions.access()).iter() {
61            vec.push(*s);
62        }
63        Some(vec)
64    } else {
65        None
66    };
67
68    let fd_ops = if !fd_ops.is_null() {
69        let fd_ops = wasi_try_mem_ok!(fd_ops.slice(&memory, fd_ops_len));
70        let mut vec = Vec::with_capacity(fd_ops.len() as usize);
71        for s in wasi_try_mem_ok!(fd_ops.access()).iter() {
72            vec.push(*s);
73        }
74        vec
75    } else {
76        vec![]
77    };
78
79    let path = if path.is_null() {
80        None
81    } else {
82        Some(unsafe { get_input_str_ok!(&memory, path, path_len) })
83    };
84
85    proc_spawn3_impl(
86        ctx,
87        &mut name,
88        args,
89        envs,
90        fd_ops,
91        signals,
92        search_path,
93        path.as_deref(),
94        ret,
95    )
96}