#[cfg(feature = "std")]
use std::{env, process::Command};
#[cfg(any(unix, all(windows, feature = "std")))]
use crate::Error;
#[cfg(all(unix, feature = "std"))]
pub mod unix_shmem_server;
#[cfg(unix)]
pub mod unix_signals;
#[cfg(all(unix, feature = "std"))]
pub mod pipes;
#[cfg(all(unix, feature = "std"))]
use std::ffi::CString;
#[cfg(all(windows, feature = "std"))]
#[allow(missing_docs, overflowing_literals)]
pub mod windows_exceptions;
#[cfg(unix)]
use libc::pid_t;
#[cfg(unix)]
#[derive(Debug)]
pub struct ChildHandle {
pub pid: pid_t,
}
#[cfg(unix)]
impl ChildHandle {
#[must_use]
pub fn status(&self) -> i32 {
let mut status = -1;
unsafe {
libc::waitpid(self.pid, &mut status, 0);
}
status
}
}
#[cfg(unix)]
#[derive(Debug)]
pub enum ForkResult {
Parent(ChildHandle),
Child,
}
#[cfg(unix)]
pub unsafe fn fork() -> Result<ForkResult, Error> {
match libc::fork() {
pid if pid > 0 => Ok(ForkResult::Parent(ChildHandle { pid })),
pid if pid < 0 => {
#[cfg(feature = "std")]
{
let err_str = CString::new("Fork failed").unwrap();
libc::perror(err_str.as_ptr());
}
Err(Error::unknown(format!("Fork failed ({pid})")))
}
_ => Ok(ForkResult::Child),
}
}
#[cfg(feature = "std")]
pub fn startable_self() -> Result<Command, Error> {
let mut startable = Command::new(env::current_exe()?);
startable
.current_dir(env::current_dir()?)
.args(env::args().skip(1));
Ok(startable)
}
#[cfg(all(unix, feature = "std"))]
pub fn dup2(fd: i32, device: i32) -> Result<(), Error> {
match unsafe { libc::dup2(fd, device) } {
-1 => Err(Error::file(std::io::Error::last_os_error())),
_ => Ok(()),
}
}