use abort::abort;
use core::mem::MaybeUninit as MU;
pub use libc::id_t as Id;
use Error;
#[inline]
pub fn fork() -> Result<Id, Error> { unsafe { esyscall!(FORK).map(|pid| pid as _) } }
#[inline]
pub fn quit(code: isize) -> ! { unsafe {
#[cfg(target_os = "linux")]
syscall!(EXIT_GROUP, code);
syscall!(EXIT, code);
abort()
} }
#[inline]
pub fn pid() -> Id { unsafe { syscall!(GETPID) as _ } }
#[inline]
pub fn ppid() -> Id { unsafe { syscall!(GETPPID) as _ } }
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum WaitSpec {
Pid(Id),
Gid(Id),
All,
}
impl WaitSpec {
#[inline]
pub fn wait(self, flags: WaitFlags) -> Result<(WaitInfo, ::libc::rusage), Error> {
unsafe {
let (id_type, id) = self.to_wait_args();
let mut si = siginfo_ { u: () };
let mut ru = MU::<::libc::rusage>::uninit();
si.si.si_pid = 0;
#[cfg(target_os = "linux")]
esyscall!(WAITID, id_type, id, &mut si as *mut _, flags.bits(), ru.as_mut_ptr())?;
#[cfg(target_os = "freebsd")]
esyscall!(WAIT6, id_type, id, &mut 0usize as *mut _, flags.bits(), ru.as_mut_ptr(), &mut si as *mut _)?;
if 0 == si.si.si_pid { return Err(Error::EWOULDBLOCK) }
Ok((WaitInfo::from_c(si.si), ru.assume_init()))
}
}
#[inline]
unsafe fn to_wait_args(self) -> (::libc::idtype_t, Id) {
use self::WaitSpec::*;
match self {
Pid(pid) => (::libc::P_PID, pid),
Gid(gid) => (::libc::P_PGID, gid),
All => (::libc::P_ALL, MU::uninit().assume_init()),
}
}
}
#[allow(missing_docs)]
mod wait_flags { bitflags! {
pub struct WaitFlags: usize {
const Exit = ::libc::WEXITED as usize;
const Stop = ::libc::WSTOPPED as usize;
const Cont = ::libc::WCONTINUED as usize;
const NoHang = ::libc::WNOHANG as usize;
const NoWait = ::libc::WNOWAIT as usize;
}
} } pub use self::wait_flags::WaitFlags;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct WaitInfo {
pub pid: Id,
pub code: WaitCode,
pub status: isize,
}
impl WaitInfo {
#[inline]
unsafe fn from_c(si: siginfo) -> Self {
WaitInfo {
pid: si.si_pid as _,
code: WaitCode(si.si_code),
status: si.si_status as _,
}
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct WaitCode(::libc::c_int);
#[allow(missing_docs)]
impl WaitCode {
pub const Exit: Self = WaitCode(1);
pub const Kill: Self = WaitCode(2);
pub const Dump: Self = WaitCode(3);
pub const Trap: Self = WaitCode(4);
pub const Stop: Self = WaitCode(5);
pub const Cont: Self = WaitCode(6);
}
#[cfg(target_os = "linux")]
#[repr(C)]
#[derive(Clone, Copy)]
struct siginfo {
si_signo: ::libc::c_int,
si_errno: ::libc::c_int,
si_code: ::libc::c_int,
si_pid: ::libc::pid_t,
si_uid: ::libc::uid_t,
si_value: ::libc::sigval,
si_status: ::libc::c_int,
}
#[cfg(target_os = "freebsd")]
type siginfo = ::libc::siginfo_t;
#[repr(C)]
union siginfo_ {
si: siginfo,
pad: [u8; 0x80],
u: (),
}