use std::ffi::CString;
use std::ptr;
use crate::CoreError;
#[derive(Clone)]
pub(super) enum ExecArgv {
Dynamic(Vec<CString>),
}
#[derive(Clone)]
pub(super) struct ExecContext {
pub(super) argv: ExecArgv,
envp: Option<Vec<CString>>,
pub(super) cwd: Option<CString>,
}
impl ExecContext {
pub(super) fn new(
argv: Vec<String>,
env: Option<Vec<String>>,
cwd: Option<String>,
) -> Result<Self, CoreError> {
if argv.is_empty() {
return Err(CoreError::sys(libc::EINVAL, "exec argv empty"));
}
let c_argv: Vec<CString> = argv
.into_iter()
.map(|s| {
CString::new(s).map_err(|_| CoreError::sys(libc::EINVAL, "exec argv contains nul"))
})
.collect::<Result<_, _>>()?;
let c_envp = match env {
Some(vars) => Some(
vars.into_iter()
.map(|s| {
CString::new(s)
.map_err(|_| CoreError::sys(libc::EINVAL, "exec env contains nul"))
})
.collect::<Result<Vec<_>, _>>()?,
),
None => None,
};
let c_cwd = match cwd {
Some(c) => Some(
CString::new(c)
.map_err(|_| CoreError::sys(libc::EINVAL, "exec cwd contains nul"))?,
),
None => None,
};
Ok(Self {
argv: ExecArgv::Dynamic(c_argv),
envp: c_envp,
cwd: c_cwd,
})
}
pub(super) fn get_argv_ptrs(&self) -> Vec<*mut libc::c_char> {
let mut ptrs = Vec::new();
match &self.argv {
ExecArgv::Dynamic(v) => {
for s in v {
ptrs.push(s.as_ptr() as *mut libc::c_char);
}
}
}
ptrs.push(ptr::null_mut());
ptrs
}
pub(super) fn get_envp_ptrs(&self) -> Option<Vec<*mut libc::c_char>> {
self.envp.as_ref().map(|envp| {
let mut ptrs = Vec::new();
for s in envp {
ptrs.push(s.as_ptr() as *mut libc::c_char);
}
ptrs.push(ptr::null_mut());
ptrs
})
}
}