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