#![cfg_attr(not(feature = "unsafe_syscall"), allow(dead_code))]
use crate::{Debug, FmtResult, Formatter, c_void};
#[cfg(feature = "unsafe_syscall")]
use crate::{LINUX_SIGACTION, impl_trait};
#[doc = crate::_tags!(linux)]
#[doc = crate::_doc_location!("sys/os/linux")]
#[repr(C)]
#[must_use]
pub struct LinuxSigaction {
sa_handler: LinuxSigactionHandler,
sa_flags: usize,
sa_restorer: Option<extern "C" fn()>,
sa_mask: LinuxSigset,
}
#[rustfmt::skip]
impl Debug for LinuxSigaction {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult<()> {
write!(f, "LinuxSigaction {{ ")?;
#[cfg(feature = "unsafe_syscall")]
if self.sa_flags & LINUX_SIGACTION::SA_SIGINFO == 0 {
write!(f, "sa_handler: {:p}, ", unsafe { self.sa_handler.sa_handler })?;
} else {
write!(f, "sa_sigaction: {:p}, ", unsafe { self.sa_handler.sa_sigaction })?;
}
write!(f, "sa_flags: {:#x}, ", self.sa_flags)?;
match self.sa_restorer {
Some(ptr) => write!(f, "sa_restorer: {ptr:p}, ")?,
None => write!(f, "sa_restorer: None, ")?,
}
write!(f, "sa_mask: {:?}", self.sa_mask)?;
write!(f, " }}")
}
}
impl LinuxSigaction {
pub const fn new(
handler: extern "C" fn(i32),
flags: usize,
mask: LinuxSigset,
restorer: Option<extern "C" fn()>,
) -> Self {
Self {
sa_handler: LinuxSigactionHandler { sa_handler: handler },
sa_flags: flags,
sa_restorer: restorer,
sa_mask: mask,
}
}
pub const fn new_siginfo(
handler: extern "C" fn(i32, LinuxSiginfo, *mut c_void),
flags: usize,
mask: LinuxSigset,
restorer: Option<extern "C" fn()>,
) -> Self {
Self {
sa_handler: LinuxSigactionHandler { sa_sigaction: handler },
sa_flags: flags,
sa_restorer: restorer,
sa_mask: mask,
}
}
#[cfg(feature = "unsafe_syscall")]
#[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_syscall")))]
pub const fn sa_handler(&self) -> Option<extern "C" fn(i32)> {
if self.sa_flags & LINUX_SIGACTION::SA_SIGINFO == 0 {
Some(unsafe { self.sa_handler.sa_handler })
} else {
None
}
}
#[must_use]
#[cfg(feature = "unsafe_syscall")]
#[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_syscall")))]
pub const fn sa_sigaction(&self) -> Option<extern "C" fn(i32, LinuxSiginfo, *mut c_void)> {
if self.sa_flags & LINUX_SIGACTION::SA_SIGINFO != 0 {
Some(unsafe { self.sa_handler.sa_sigaction })
} else {
None
}
}
}
impl LinuxSigaction {
pub const SIG_DFL: isize = 0;
pub const SIG_IGN: isize = 1;
}
#[doc = crate::_tags!(linux)]
#[doc = crate::_doc_location!("sys/os/linux")]
#[repr(C)]
#[must_use]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LinuxSigset {
pub sig: [usize; Self::LEN],
}
#[rustfmt::skip]
impl LinuxSigset {
const BITS_PER_USIZE: usize = usize::BITS as usize;
const NSIG: usize = 31;
const LEN: usize = { Self::NSIG.div_ceil(Self::BITS_PER_USIZE) };
pub const fn empty() -> Self { Self { sig: [0; Self::LEN] } }
#[must_use]
pub const fn size() -> usize { size_of::<Self>() }
}
impl LinuxSigset {
pub fn set_signal(&mut self, signal: i32) {
let signal = signal as usize;
assert![(1..=Self::NSIG).contains(&signal)];
let signal_index = (signal - 1) / Self::BITS_PER_USIZE;
let bit_position = (signal - 1) % Self::BITS_PER_USIZE;
self.sig[signal_index] |= 1 << bit_position;
}
}
#[doc = crate::_tags!(linux)]
#[doc = crate::_doc_location!("sys/os/linux")]
#[repr(C)]
#[must_use]
pub struct LinuxSiginfo {
si_signo: i32,
si_errno: i32,
si_code: i32,
si_pid: i32,
si_uid: u32,
si_status: i32,
si_addr: *mut c_void,
si_band: i64,
si_value: LinuxSigval,
}
#[rustfmt::skip]
impl LinuxSiginfo {
pub fn signo(&self) -> i32 { self.si_signo }
pub fn errno(&self) -> i32 { self.si_errno }
pub fn code(&self) -> i32 { self.si_code } pub fn pid(&self) -> i32 { self.si_pid }
pub fn uid(&self) -> u32 { self.si_uid }
pub fn status(&self) -> i32 { self.si_status }
pub fn addr(&self) -> *mut c_void { self.si_addr }
pub fn band(&self) -> i64 { self.si_band }
#[cfg(feature = "unsafe_syscall")]
#[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_syscall")))]
pub fn value_int(&self) -> i32 { unsafe { self.si_value.int } }
#[cfg(feature = "unsafe_syscall")]
#[cfg_attr(nightly_doc, doc(cfg(feature = "unsafe_syscall")))]
pub fn value_ptr(&self) -> *mut c_void { unsafe { self.si_value.ptr } }
}
#[rustfmt::skip]
impl Debug for LinuxSiginfo {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult<()> {
write!(f, "LinuxSiginfo {{ ")?;
write!(f, "si_signo: {}, ", self.si_signo)?;
write!(f, "si_errno: {}, ", self.si_errno)?;
write!(f, "si_code: {}, ", self.si_code)?;
write!(f, "si_pid: {}, ", self.si_pid)?;
write!(f, "si_uid: {}, ", self.si_uid)?;
write!(f, "si_status: {}, ", self.si_status)?;
write!(f, "si_addr: {:?}, ", self.si_addr)?;
write!(f, "si_band: {}, ", self.si_band)?;
#[cfg(feature = "unsafe_syscall")]
write!(f, "si_value: LinuxSigval {{ sival_int: {}, sival_ptr: {:?} }}",
unsafe { self.si_value.int }, unsafe { self.si_value.ptr })?;
write!(f, " }}")
}
}
#[repr(C)]
union LinuxSigactionHandler {
sa_handler: extern "C" fn(i32),
sa_sigaction: extern "C" fn(i32, LinuxSiginfo, *mut c_void),
}
#[repr(C)]
union LinuxSigval {
int: i32,
ptr: *mut c_void,
}
#[cfg(feature = "unsafe_syscall")]
impl_trait![fmt::Debug for LinuxSigval |self, f|
write!(f, "LinuxSigval {{ int: {}, ptr: {:?} }}", unsafe { self.int }, unsafe { self.ptr })
];