#![allow(unsafe_code)]
use core::mem::MaybeUninit;
use crate::backend::c::{c_int, c_uint, c_void};
use crate::backend::process::syscalls;
use crate::backend::process::types::{RawId, Signal};
use crate::io;
use crate::process::{Pid, RawPid};
#[repr(i32)]
pub enum IdType {
Pid = 0,
Pgid = 2,
}
pub type ProcSelector = Option<(IdType, Pid)>;
fn proc_selector_to_raw(selector: ProcSelector) -> (IdType, RawPid) {
match selector {
Some((idtype, id)) => (idtype, id.as_raw_nonzero().get()),
None => (IdType::Pid, 0),
}
}
#[inline]
pub(crate) unsafe fn procctl(
option: c_int,
process: ProcSelector,
data: *mut c_void,
) -> io::Result<()> {
let (idtype, id) = proc_selector_to_raw(process);
syscalls::procctl(idtype as c_uint, id as RawId, option, data)
}
#[inline]
pub(crate) unsafe fn procctl_set<P>(
option: c_int,
process: ProcSelector,
data: &P,
) -> io::Result<()> {
procctl(option, process, (data as *const P as *mut P).cast())
}
#[inline]
pub(crate) unsafe fn procctl_get_optional<P>(
option: c_int,
process: ProcSelector,
) -> io::Result<P> {
let mut value: MaybeUninit<P> = MaybeUninit::uninit();
procctl(option, process, value.as_mut_ptr().cast())?;
Ok(value.assume_init())
}
const PROC_PDEATHSIG_STATUS: c_int = 12;
#[inline]
pub fn parent_process_death_signal() -> io::Result<Option<Signal>> {
unsafe { procctl_get_optional::<c_int>(PROC_PDEATHSIG_STATUS, None) }.map(Signal::from_raw)
}
const PROC_PDEATHSIG_CTL: c_int = 11;
#[inline]
pub fn set_parent_process_death_signal(signal: Option<Signal>) -> io::Result<()> {
let signal = signal.map_or(0, |signal| signal as c_int);
unsafe { procctl_set::<c_int>(PROC_PDEATHSIG_CTL, None, &signal) }
}
const PROC_TRACE_CTL: c_int = 7;
const PROC_TRACE_CTL_ENABLE: i32 = 1;
const PROC_TRACE_CTL_DISABLE: i32 = 2;
const PROC_TRACE_CTL_DISABLE_EXEC: i32 = 3;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(i32)]
pub enum DumpableBehavior {
NotDumpable = PROC_TRACE_CTL_DISABLE,
Dumpable = PROC_TRACE_CTL_ENABLE,
NotDumpableExecPreserved = PROC_TRACE_CTL_DISABLE_EXEC,
}
#[inline]
pub fn set_dumpable_behavior(process: ProcSelector, config: DumpableBehavior) -> io::Result<()> {
unsafe { procctl(PROC_TRACE_CTL, process, config as usize as *mut _) }
}
const PROC_TRACE_STATUS: c_int = 8;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum TracingStatus {
NotTraceble,
Tracable,
BeingTraced(Pid),
}
#[inline]
pub fn trace_status(process: ProcSelector) -> io::Result<TracingStatus> {
let val = unsafe { procctl_get_optional::<c_int>(PROC_TRACE_STATUS, process) }?;
match val {
-1 => Ok(TracingStatus::NotTraceble),
0 => Ok(TracingStatus::Tracable),
pid => {
let pid = unsafe { Pid::from_raw(pid as RawPid) }.ok_or(io::Errno::RANGE)?;
Ok(TracingStatus::BeingTraced(pid))
}
}
}