devela/sys/os/linux/structs/
sigaction.rs

1// devela::sys::os::linux::structs::sigaction
2
3#![cfg_attr(not(feature = "unsafe_syscall"), allow(dead_code))]
4
5/// Represents the [`sigaction`] structure from libc.
6/// Examine and change a signal action.
7///
8/// [`sigaction`]: https://man7.org/linux/man-pages/man2/sigaction.2.html
9#[derive(Debug)]
10#[repr(C)]
11pub struct LinuxSigaction {
12    /// A pointer to a signal handling function.
13    ///
14    /// This function receives the signal number as its only argument.
15    pub sa_handler: extern "C" fn(i32),
16
17    /// A set of flags which modify the behavior of the signal.
18    pub sa_flags: usize,
19
20    /// A legacy field that is not used on modern Linux systems, but must be
21    /// filled in for compatibility
22    pub sa_restorer: Option<extern "C" fn()>,
23
24    /// A mask of signals that should be blocked.
25    pub sa_mask: LinuxSigset,
26}
27
28impl LinuxSigaction {
29    /// Retuns a new `LinuxSigation`.
30    #[must_use]
31    pub fn new(handler: extern "C" fn(i32), flags: usize, mask: LinuxSigset) -> Self {
32        Self {
33            sa_handler: handler,
34            sa_flags: flags,
35            sa_restorer: None,
36            sa_mask: mask,
37        }
38    }
39}
40
41/// [`sa_handler`][Self::sa_handler] field constants.
42impl LinuxSigaction {
43    /// The default signal handling.
44    pub const SIG_DFL: isize = 0;
45
46    /// Ignore this signal.
47    pub const SIG_IGN: isize = 1;
48
49    // /// Error return from signal.
50    // pub const SIG_ERR: isize = -1;
51}
52
53/// A set of signals.
54#[repr(C)]
55#[derive(Debug, Default, Clone, Copy)]
56pub struct LinuxSigset {
57    /// An array of signals.
58    ///
59    /// Its lenght is calculated from the number of signals divided by the bits of a usize.
60    pub sig: [usize; Self::LEN],
61}
62impl LinuxSigset {
63    const BITS_PER_USIZE: usize = usize::BITS as usize;
64    // The hardcoded number of system signals defined in `LINUX_SIGNAL`.
65    const NSIG: usize = 36;
66    // The size of the array is the number of signals divided by the bits of an usize.
67    const LEN: usize = { Self::NSIG.div_ceil(Self::BITS_PER_USIZE) };
68
69    /// Returns the size in bytes of `LinuxSigset`.
70    #[must_use]
71    pub const fn size() -> usize {
72        core::mem::size_of::<Self>()
73    }
74}
75impl LinuxSigset {
76    /// Sets the bit corresponding to a `signal` in the `sig` array.
77    ///
78    /// # Arguments
79    /// * `signum` - The number of the signal. This should be between 1 and `NSIG`.
80    ///
81    /// # Panics
82    /// Panics if `signum` < 1 or > 36.
83    pub fn set_signal(&mut self, signal: i32) {
84        let signal = signal as usize;
85        assert![(1..=Self::NSIG).contains(&signal)];
86
87        // Subtract 1 from the signal number because signal numbers start from 1
88        // but array indices start from 0
89        let signal_index = (signal - 1) / Self::BITS_PER_USIZE;
90        let bit_position = (signal - 1) % Self::BITS_PER_USIZE;
91        self.sig[signal_index] |= 1 << bit_position;
92    }
93}