1 //! Bindings for the FreeBSD `procctl` system call.
3 //! There are similarities (but also differences) with Linux's `prctl` system call, whose interface
4 //! is located in the `prctl.rs` file.
8 use core
::mem
::MaybeUninit
;
10 use crate::backend
::c
::{c_int, c_uint, c_void}
;
11 use crate::backend
::process
::syscalls
;
12 use crate::backend
::process
::types
::{RawId, Signal}
;
14 use crate::process
::{Pid, RawPid}
;
20 /// Subset of `idtype_t` C enum, with only the values allowed by `procctl`.
29 /// A process selector for use with the `procctl` interface.
31 /// `None` represents the current process. `Some((IdType::Pid, pid))` represents the process
32 /// with pid `pid`. `Some((IdType::Pgid, pgid))` represents the control processes belonging to
33 /// the process group with id `pgid`.
34 pub type ProcSelector
= Option
<(IdType
, Pid
)>;
35 fn proc_selector_to_raw(selector
: ProcSelector
) -> (IdType
, RawPid
) {
37 Some((idtype
, id
)) => (idtype
, id
.as_raw_nonzero().get()),
38 None
=> (IdType
::Pid
, 0),
43 pub(crate) unsafe fn procctl(
45 process
: ProcSelector
,
48 let (idtype
, id
) = proc_selector_to_raw(process
);
49 syscalls
::procctl(idtype
as c_uint
, id
as RawId
, option
, data
)
53 pub(crate) unsafe fn procctl_set
<P
>(
55 process
: ProcSelector
,
58 procctl(option
, process
, (data
as *const P
as *mut P
).cast())
62 pub(crate) unsafe fn procctl_get_optional
<P
>(
64 process
: ProcSelector
,
66 let mut value
: MaybeUninit
<P
> = MaybeUninit
::uninit();
67 procctl(option
, process
, value
.as_mut_ptr().cast())?
;
68 Ok(value
.assume_init())
72 // PROC_PDEATHSIG_STATUS/PROC_PDEATHSIG_CTL
75 const PROC_PDEATHSIG_STATUS
: c_int
= 12;
77 /// Get the current value of the parent process death signal.
80 /// - [Linux: `prctl(PR_GET_PDEATHSIG,...)`]
81 /// - [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`]
83 /// [Linux: `prctl(PR_GET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
84 /// [FreeBSD: `procctl(PROC_PDEATHSIG_STATUS,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
86 pub fn parent_process_death_signal() -> io
::Result
<Option
<Signal
>> {
87 unsafe { procctl_get_optional::<c_int>(PROC_PDEATHSIG_STATUS, None) }
.map(Signal
::from_raw
)
90 const PROC_PDEATHSIG_CTL
: c_int
= 11;
92 /// Set the parent-death signal of the calling process.
95 /// - [Linux: `prctl(PR_SET_PDEATHSIG,...)`]
96 /// - [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`]
98 /// [Linux: `prctl(PR_SET_PDEATHSIG,...)`]: https://man7.org/linux/man-pages/man2/prctl.2.html
99 /// [FreeBSD: `procctl(PROC_PDEATHSIG_CTL,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
101 pub fn set_parent_process_death_signal(signal
: Option
<Signal
>) -> io
::Result
<()> {
102 let signal
= signal
.map_or(0, |signal
| signal
as c_int
);
103 unsafe { procctl_set::<c_int>(PROC_PDEATHSIG_CTL, None, &signal) }
110 const PROC_TRACE_CTL
: c_int
= 7;
112 const PROC_TRACE_CTL_ENABLE
: i32 = 1;
113 const PROC_TRACE_CTL_DISABLE
: i32 = 2;
114 const PROC_TRACE_CTL_DISABLE_EXEC
: i32 = 3;
116 /// `PROC_TRACE_CTL_*`.
117 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
119 pub enum DumpableBehavior
{
121 NotDumpable
= PROC_TRACE_CTL_DISABLE
,
123 Dumpable
= PROC_TRACE_CTL_ENABLE
,
124 /// Not dumpable, and this behaviour is preserved across `execve` calls.
125 NotDumpableExecPreserved
= PROC_TRACE_CTL_DISABLE_EXEC
,
128 /// Set the state of the `dumpable` attribute for the process indicated by `idtype` and `id`.
129 /// This determines whether the process can be traced and whether core dumps are produced for
130 /// the process upon delivery of a signal whose default behavior is to produce a core dump.
132 /// This is similar to `set_dumpable_behavior` on Linux, with the exception that on FreeBSD
133 /// there is an extra argument `process`. When `process` is set to `None`, the operation is
134 /// performed for the current process, like on Linux.
137 /// - [`procctl(PROC_TRACE_CTL,...)`]
139 /// [`procctl(PROC_TRACE_CTL,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
141 pub fn set_dumpable_behavior(process
: ProcSelector
, config
: DumpableBehavior
) -> io
::Result
<()> {
142 unsafe { procctl(PROC_TRACE_CTL, process, config as usize as *mut _) }
149 const PROC_TRACE_STATUS
: c_int
= 8;
151 /// Tracing status as returned by [`trace_status`].
152 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
153 pub enum TracingStatus
{
154 /// Tracing is disabled for the process.
156 /// Tracing is not disabled for the process, but not debugger/tracer is attached.
158 /// The process is being traced by the process whose pid is stored in the first
159 /// component of this variant.
163 /// Get the tracing status of the process indicated by `idtype` and `id`.
166 /// - [`procctl(PROC_TRACE_STATUS,...)`]
168 /// [`procctl(PROC_TRACE_STATUS,...)`]: https://www.freebsd.org/cgi/man.cgi?query=procctl&sektion=2
170 pub fn trace_status(process
: ProcSelector
) -> io
::Result
<TracingStatus
> {
171 let val
= unsafe { procctl_get_optional::<c_int>(PROC_TRACE_STATUS, process) }?
;
173 -1 => Ok(TracingStatus
::NotTraceble
),
174 0 => Ok(TracingStatus
::Tracable
),
176 let pid
= unsafe { Pid::from_raw(pid as RawPid) }
.ok_or(io
::Errno
::RANGE
)?
;
177 Ok(TracingStatus
::BeingTraced(pid
))