use crate::{
handles::{FromRawHandle, OwnedHandle, RawHandle},
Deserializer, FnOnceObject, Receiver,
};
pub(crate) fn start_root() {}
pub(crate) fn crossmist_main(mut args: std::env::Args) -> ! {
let handle: RawHandle = parse_raw_handle(
&args
.next()
.expect("Expected one CLI argument for crossmist"),
);
enable_cloexec(handle).expect("Failed to set O_CLOEXEC for the file descriptor");
let mut entry_rx = unsafe { Receiver::<(Vec<u8>, Vec<RawHandle>)>::from_raw_handle(handle) };
let (entry_data, entry_handles) = entry_rx
.recv()
.expect("Failed to read entry for crossmist")
.expect("No entry passed");
std::mem::forget(entry_rx);
for handle in &entry_handles {
enable_cloexec(*handle).expect("Failed to set O_CLOEXEC for the file descriptor");
}
let entry_handles = entry_handles
.into_iter()
.map(|handle| unsafe { OwnedHandle::from_raw_handle(handle) })
.collect();
let mut deserializer = Deserializer::new(entry_data, entry_handles);
let entry: Box<dyn FnOnceObject<(RawHandle,), Output = i32>> =
unsafe { deserializer.deserialize() }.expect("Failed to deserialize entry");
std::process::exit(entry.call_object_once((handle,)))
}
fn parse_raw_handle(s: &str) -> RawHandle {
s.parse().expect("Failed to parse fd")
}
pub(crate) fn disable_cloexec(fd: RawHandle) -> std::io::Result<()> {
nix::fcntl::fcntl(
fd,
nix::fcntl::FcntlArg::F_SETFD(nix::fcntl::FdFlag::empty()),
)?;
Ok(())
}
pub(crate) fn enable_cloexec(fd: RawHandle) -> std::io::Result<()> {
nix::fcntl::fcntl(
fd,
nix::fcntl::FcntlArg::F_SETFD(nix::fcntl::FdFlag::FD_CLOEXEC),
)?;
Ok(())
}