starry_api/imp/task/
execve.rs

1use core::ffi::c_char;
2
3use alloc::{string::ToString, vec::Vec};
4use axerrno::{LinuxError, LinuxResult};
5use axhal::arch::TrapFrame;
6use axtask::{TaskExtRef, current};
7use starry_core::mm::{load_user_app, map_trampoline};
8
9use crate::ptr::UserConstPtr;
10
11pub fn sys_execve(
12    tf: &mut TrapFrame,
13    path: UserConstPtr<c_char>,
14    argv: UserConstPtr<UserConstPtr<c_char>>,
15    envp: UserConstPtr<UserConstPtr<c_char>>,
16) -> LinuxResult<isize> {
17    let path = path.get_as_str()?.to_string();
18
19    let args = argv
20        .get_as_null_terminated()?
21        .iter()
22        .map(|arg| arg.get_as_str().map(Into::into))
23        .collect::<Result<Vec<_>, _>>()?;
24    let envs = envp
25        .get_as_null_terminated()?
26        .iter()
27        .map(|env| env.get_as_str().map(Into::into))
28        .collect::<Result<Vec<_>, _>>()?;
29
30    info!(
31        "sys_execve: path: {:?}, args: {:?}, envs: {:?}",
32        path, args, envs
33    );
34
35    let curr = current();
36    let curr_ext = curr.task_ext();
37
38    if curr_ext.thread.process().threads().len() > 1 {
39        // TODO: handle multi-thread case
40        error!("sys_execve: multi-thread not supported");
41        return Err(LinuxError::EAGAIN);
42    }
43
44    let mut aspace = curr_ext.process_data().aspace.lock();
45    aspace.unmap_user_areas()?;
46    map_trampoline(&mut aspace)?;
47    axhal::arch::flush_tlb(None);
48
49    let (entry_point, user_stack_base) =
50        load_user_app(&mut aspace, &args, &envs).map_err(|_| {
51            error!("Failed to load app {}", path);
52            LinuxError::ENOENT
53        })?;
54    drop(aspace);
55
56    let name = path
57        .rsplit_once('/')
58        .map_or(path.as_str(), |(_, name)| name);
59    curr.set_name(name);
60    *curr_ext.process_data().exe_path.write() = path;
61
62    // TODO: fd close-on-exec
63
64    tf.set_ip(entry_point.as_usize());
65    tf.set_sp(user_stack_base.as_usize());
66    Ok(0)
67}