1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
use std::{
    ffi::{CStr, CString},
    iter::once,
    os::unix::prelude::OsStrExt,
    path::Path,
};

fn path_to_c_string(path: &Path) -> CString {
    CString::from_vec_with_nul(
        path.as_os_str()
            .as_bytes()
            .iter()
            .copied()
            .chain(once(0))
            .collect(),
    )
    .unwrap()
}

pub fn exec(path: &Path, args: &[impl AsRef<CStr>], env: &[impl AsRef<CStr>]) -> ! {
    let (bin_addr, bin_header, opt_interp) = crate::loader::load(path);
    let path = path_to_c_string(path);
    let interp_addr = opt_interp.map(|(addr, _)| addr);
    let sp = crate::stack::make_stack(interp_addr, bin_addr, bin_header, &path, args, env);
    let entry = match opt_interp {
        Some((interp_addr, interp_header)) => {
            let interp_entry: usize = interp_header.e_entry.try_into().unwrap();
            interp_addr + interp_entry
        }
        None => {
            let bin_entry: usize = bin_header.e_entry.try_into().unwrap();
            bin_addr + bin_entry
        }
    };
    unsafe { crate::run::run(sp, entry) }
}