use super::Disposition;
pub use crate::signal::*;
use std::ffi::c_int;
use std::mem::MaybeUninit;
use std::num::NonZero;
use std::ops::RangeInclusive;
#[must_use]
pub fn rt_range() -> RangeInclusive<RawNumber> {
#[cfg(target_os = "aix")]
return libc::SIGRTMIN..=libc::SIGRTMAX;
#[cfg(any(
target_os = "android",
target_os = "emscripten",
target_os = "l4re",
target_os = "linux",
))]
return libc::SIGRTMIN()..=libc::SIGRTMAX();
#[allow(unreachable_code)]
{
#[allow(clippy::reversed_empty_ranges)]
return 0..=-1;
}
}
impl Name {
pub(super) fn to_raw_real(self) -> Option<Number> {
#[inline]
fn wrap(number: RawNumber) -> Option<Number> {
NonZero::new(number).map(Number::from_raw_unchecked)
}
match self {
Self::Abrt => wrap(libc::SIGABRT),
Self::Alrm => wrap(libc::SIGALRM),
Self::Bus => wrap(libc::SIGBUS),
Self::Chld => wrap(libc::SIGCHLD),
#[cfg(any(
target_os = "aix",
target_os = "horizon",
target_os = "illumos",
target_os = "solaris",
))]
Self::Cld => wrap(libc::SIGCLD),
#[cfg(not(any(
target_os = "aix",
target_os = "horizon",
target_os = "illumos",
target_os = "solaris",
)))]
Self::Cld => None,
Self::Cont => wrap(libc::SIGCONT),
#[cfg(not(any(
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "haiku",
target_os = "linux",
target_os = "redox",
)))]
Self::Emt => wrap(libc::SIGEMT),
#[cfg(any(
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "haiku",
target_os = "linux",
target_os = "redox",
))]
Self::Emt => None,
Self::Fpe => wrap(libc::SIGFPE),
Self::Hup => wrap(libc::SIGHUP),
Self::Ill => wrap(libc::SIGILL),
#[cfg(not(any(
target_os = "aix",
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "haiku",
target_os = "linux",
target_os = "redox",
)))]
Self::Info => wrap(libc::SIGINFO),
#[cfg(any(
target_os = "aix",
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "haiku",
target_os = "linux",
target_os = "redox",
))]
Self::Info => None,
Self::Int => wrap(libc::SIGINT),
#[cfg(any(
target_os = "aix",
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon",
target_os = "illumos",
target_os = "linux",
target_os = "nto",
target_os = "solaris",
))]
Self::Io => wrap(libc::SIGIO),
#[cfg(not(any(
target_os = "aix",
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon",
target_os = "illumos",
target_os = "linux",
target_os = "nto",
target_os = "solaris",
)))]
Self::Io => None,
Self::Iot => wrap(libc::SIGIOT),
Self::Kill => wrap(libc::SIGKILL),
#[cfg(target_os = "horizon")]
Self::Lost => wrap(libc::SIGLOST),
#[cfg(not(target_os = "horizon"))]
Self::Lost => None,
Self::Pipe => wrap(libc::SIGPIPE),
#[cfg(any(
target_os = "aix",
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "haiku",
target_os = "horizon",
target_os = "illumos",
target_os = "linux",
target_os = "nto",
target_os = "solaris",
))]
Self::Poll => wrap(libc::SIGPOLL),
#[cfg(not(any(
target_os = "aix",
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "haiku",
target_os = "horizon",
target_os = "illumos",
target_os = "linux",
target_os = "nto",
target_os = "solaris",
)))]
Self::Poll => None,
Self::Prof => wrap(libc::SIGPROF),
#[cfg(any(
target_os = "aix",
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "illumos",
target_os = "linux",
target_os = "nto",
target_os = "redox",
target_os = "solaris",
))]
Self::Pwr => wrap(libc::SIGPWR),
#[cfg(not(any(
target_os = "aix",
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "illumos",
target_os = "linux",
target_os = "nto",
target_os = "redox",
target_os = "solaris",
)))]
Self::Pwr => None,
Self::Quit => wrap(libc::SIGQUIT),
Self::Segv => wrap(libc::SIGSEGV),
#[cfg(all(
any(
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "linux"
),
not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))
))]
Self::Stkflt => wrap(libc::SIGSTKFLT),
#[cfg(not(all(
any(
target_os = "android",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "linux"
),
not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))
)))]
Self::Stkflt => None,
Self::Stop => wrap(libc::SIGSTOP),
Self::Sys => wrap(libc::SIGSYS),
Self::Term => wrap(libc::SIGTERM),
#[cfg(target_os = "freebsd")]
Self::Thr => wrap(libc::SIGTHR),
#[cfg(not(target_os = "freebsd"))]
Self::Thr => None,
Self::Trap => wrap(libc::SIGTRAP),
Self::Tstp => wrap(libc::SIGTSTP),
Self::Ttin => wrap(libc::SIGTTIN),
Self::Ttou => wrap(libc::SIGTTOU),
Self::Urg => wrap(libc::SIGURG),
Self::Usr1 => wrap(libc::SIGUSR1),
Self::Usr2 => wrap(libc::SIGUSR2),
Self::Vtalrm => wrap(libc::SIGVTALRM),
Self::Winch => wrap(libc::SIGWINCH),
Self::Xcpu => wrap(libc::SIGXCPU),
Self::Xfsz => wrap(libc::SIGXFSZ),
Self::Rtmin(n) => {
let range = rt_range();
if let Some(number) = range.start().checked_add(n) {
if range.contains(&number) {
return wrap(number);
}
}
None
}
Self::Rtmax(n) => {
let range = rt_range();
if let Some(number) = range.end().checked_add(n) {
if range.contains(&number) {
return wrap(number);
}
}
None
}
}
}
}
fn all_signals() -> impl Iterator<Item = Number> {
let non_real_time = Name::iter()
.filter(|name| !matches!(name, Name::Rtmin(_) | Name::Rtmax(_)))
.filter_map(Name::to_raw_real);
let real_time = rt_range()
.filter_map(NonZero::new)
.map(Number::from_raw_unchecked);
non_real_time.chain(real_time)
}
pub(super) fn sigset_to_vec(set: *const libc::sigset_t, vec: &mut Vec<Number>) {
vec.extend(
all_signals().filter(|number| unsafe { libc::sigismember(set, number.as_raw()) == 1 }),
);
}
impl Disposition {
pub(super) fn to_sigaction(self) -> MaybeUninit<libc::sigaction> {
let handler = match self {
Disposition::Default => libc::SIG_DFL,
Disposition::Ignore => libc::SIG_IGN,
Disposition::Catch => super::catch_signal as *const extern "C" fn(c_int) as _,
};
let mut sa = MaybeUninit::<libc::sigaction>::uninit();
let sa_ptr = sa.as_mut_ptr();
unsafe {
(&raw mut (*sa_ptr).sa_flags).write(0);
libc::sigemptyset(&raw mut (*sa_ptr).sa_mask);
#[cfg(not(target_os = "aix"))]
#[allow(clippy::useless_transmute)] (&raw mut (*sa_ptr).sa_sigaction).write(std::mem::transmute(handler));
#[cfg(target_os = "aix")]
#[allow(clippy::useless_transmute)] (&raw mut (*sa_ptr).sa_union.__su_sigaction).write(std::mem::transmute(handler));
}
sa
}
pub(super) unsafe fn from_sigaction(sa: &MaybeUninit<libc::sigaction>) -> Self {
unsafe {
#[cfg(not(target_os = "aix"))]
let handler = (*sa.as_ptr()).sa_sigaction;
#[cfg(target_os = "aix")]
let handler = (*sa.as_ptr()).sa_union.__su_sigaction;
#[allow(clippy::useless_transmute)]
match std::mem::transmute(handler) {
libc::SIG_DFL => Self::Default,
libc::SIG_IGN => Self::Ignore,
_ => Self::Catch,
}
}
}
}