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) }
}