1use std::{
2 ffi::{CStr, CString},
3 iter::once,
4 os::unix::prelude::OsStrExt,
5 path::{Path, PathBuf},
6};
7
8fn path_to_c_string(path: &Path) -> CString {
9 CString::from_vec_with_nul(
10 path.as_os_str()
11 .as_bytes()
12 .iter()
13 .copied()
14 .chain(once(0))
15 .collect(),
16 )
17 .unwrap()
18}
19
20pub fn exec_with_options(options: ExecOptions) -> ! {
21 let (bin_addr, bin_header, opt_interp) =
22 crate::loader::load(&options.executable, options.interpreter);
23 let path = path_to_c_string(&options.executable);
24 let interp_addr = opt_interp.map(|(addr, _)| addr);
25 let sp = crate::stack::make_stack(
26 interp_addr,
27 bin_addr,
28 bin_header,
29 &path,
30 &options.args,
31 &options.env,
32 );
33 let entry = match opt_interp {
34 Some((interp_addr, interp_header)) => {
35 let interp_entry: usize = interp_header.e_entry.try_into().unwrap();
36 interp_addr + interp_entry
37 }
38 None => {
39 let bin_entry: usize = bin_header.e_entry.try_into().unwrap();
40 bin_addr + bin_entry
41 }
42 };
43 unsafe { crate::run::run(sp, entry) }
44}
45
46pub fn exec(path: &Path, args: &[impl AsRef<CStr>], env: &[impl AsRef<CStr>]) -> ! {
47 let mut options = ExecOptions::new(path);
48 options.args(args);
49 options.env_pairs(env);
50
51 exec_with_options(options)
52}
53
54pub struct ExecOptions {
55 pub executable: PathBuf,
56 pub args: Vec<CString>,
57 pub env: Vec<CString>,
58 interpreter: crate::loader::Interpreter,
59}
60
61impl ExecOptions {
62 pub fn new(executable: impl AsRef<Path>) -> Self {
63 Self {
64 executable: executable.as_ref().to_owned(),
65 args: vec![],
66 env: vec![],
67 interpreter: crate::loader::Interpreter::FromHeader,
68 }
69 }
70
71 pub fn arg(&mut self, value: impl AsRef<CStr>) -> &mut Self {
72 self.args.push(value.as_ref().to_owned());
73 self
74 }
75
76 pub fn args(&mut self, values: impl IntoIterator<Item = impl AsRef<CStr>>) -> &mut Self {
77 self.args
78 .extend(values.into_iter().map(|v| v.as_ref().to_owned()));
79 self
80 }
81
82 pub fn env(&mut self, key: impl AsRef<CStr>, value: impl AsRef<CStr>) -> &mut Self {
83 let mut pair = key.as_ref().to_bytes().to_vec();
84 pair.push(b'=');
85 pair.extend(value.as_ref().to_bytes());
86 self.env.push(CString::new(pair).unwrap());
87 self
88 }
89
90 pub fn env_pairs(&mut self, pairs: impl IntoIterator<Item = impl AsRef<CStr>>) -> &mut Self {
91 self.env
92 .extend(pairs.into_iter().map(|v| v.as_ref().to_owned()));
93 self
94 }
95
96 pub fn envs(
97 &mut self,
98 pairs: impl IntoIterator<Item = (impl AsRef<CStr>, impl AsRef<CStr>)>,
99 ) -> &mut Self {
100 for (key, value) in pairs {
101 self.env(key, value);
102 }
103 self
104 }
105
106 pub fn override_interpreter(&mut self, interpreter: Option<impl AsRef<Path>>) -> &mut Self {
107 self.interpreter = match interpreter {
108 Some(path) => crate::loader::Interpreter::Path(path.as_ref().to_owned()),
109 None => crate::loader::Interpreter::None,
110 };
111 self
112 }
113}