wasmer_wasix/syscalls/wasix/
proc_exec3.rs

1use wasmer::FromToNativeWasmType;
2
3use super::*;
4use crate::syscalls::*;
5
6/// Replaces the current process with a new process.
7///
8/// Legacy delimiter-based API: `args` and `envs` are single strings with entries
9/// separated by line feeds. Prefer `proc_exec4` for proper string lists.
10///
11/// ## Parameters
12///
13/// * `name` - Name of the process to be spawned
14/// * `args` - List of the arguments to pass the process
15///   (entries are separated by line feeds)
16/// * `envs` - List of the environment variables to pass process
17///
18/// ## Return
19///
20/// If the execution fails, returns an error code. Does not return otherwise.
21#[instrument(level = "trace", skip_all, fields(name = field::Empty, %args_len), ret)]
22pub fn proc_exec3<M: MemorySize>(
23    mut ctx: FunctionEnvMut<'_, WasiEnv>,
24    name: WasmPtr<u8, M>,
25    name_len: M::Offset,
26    args: WasmPtr<u8, M>,
27    args_len: M::Offset,
28    envs: WasmPtr<u8, M>,
29    envs_len: M::Offset,
30    search_path: Bool,
31    path: WasmPtr<u8, M>,
32    path_len: M::Offset,
33) -> Result<Errno, WasiError> {
34    WasiEnv::do_pending_operations(&mut ctx)?;
35
36    // If we were just restored the stack then we were woken after a deep sleep
37    if let Some(exit_code) = unsafe { handle_rewind::<M, i32>(&mut ctx) } {
38        // We should never get here as the process will be terminated
39        // in the `WasiEnv::do_pending_operations()` call
40        let exit_code = ExitCode::from_native(exit_code);
41        ctx.data().process.terminate(exit_code);
42        return Err(WasiError::Exit(exit_code));
43    }
44
45    let memory = unsafe { ctx.data().memory_view(&ctx) };
46    let mut name = name.read_utf8_string(&memory, name_len).map_err(|err| {
47        warn!("failed to execve as the name could not be read - {}", err);
48        WasiError::Exit(Errno::Inval.into())
49    })?;
50    Span::current().record("name", name.as_str());
51    let args = args.read_utf8_string(&memory, args_len).map_err(|err| {
52        warn!("failed to execve as the args could not be read - {}", err);
53        WasiError::Exit(Errno::Inval.into())
54    })?;
55    let mut args = parse_delimited_exec_args(&args);
56    if args.is_empty() {
57        // POSIX expects argv[0] to be present even if caller passed empty argv.
58        args.push(name.clone());
59    }
60
61    let envs = if !envs.is_null() {
62        let envs = envs.read_utf8_string(&memory, envs_len).map_err(|err| {
63            warn!("failed to execve as the envs could not be read - {}", err);
64            WasiError::Exit(Errno::Inval.into())
65        })?;
66        Some(parse_delimited_env_list(&envs).map_err(|err| WasiError::Exit(err.into()))?)
67    } else {
68        None
69    };
70
71    let path = if path.is_null() {
72        None
73    } else {
74        Some(path.read_utf8_string(&memory, path_len).map_err(|err| {
75            warn!("failed to execve as the path could not be read - {}", err);
76            WasiError::Exit(Errno::Inval.into())
77        })?)
78    };
79
80    proc_exec4_impl::<M>(ctx, &mut name, args, envs, search_path, path.as_deref())
81}