use rustix::process::Signal;
pub const SIGNALS: &[(i32, &str)] = &[
(1, "HUP"),
(2, "INT"),
(3, "QUIT"),
(4, "ILL"),
(5, "TRAP"),
(6, "ABRT"),
(7, "BUS"),
(8, "FPE"),
(9, "KILL"),
(10, "USR1"),
(11, "SEGV"),
(12, "USR2"),
(13, "PIPE"),
(14, "ALRM"),
(15, "TERM"),
(16, "STKFLT"),
(17, "CHLD"),
(18, "CONT"),
(19, "STOP"),
(20, "TSTP"),
(21, "TTIN"),
(22, "TTOU"),
(23, "URG"),
(24, "XCPU"),
(25, "XFSZ"),
(26, "VTALRM"),
(27, "PROF"),
(28, "WINCH"),
(29, "IO"),
(30, "PWR"),
(31, "SYS"),
];
pub fn parse_signal(name: &str) -> Option<Signal> {
if let Ok(n) = name.parse::<i32>() {
return Signal::from_named_raw(n);
}
let name = name
.strip_prefix("SIG")
.unwrap_or(name)
.to_ascii_uppercase();
match name.as_str() {
"HUP" => Some(Signal::HUP),
"INT" => Some(Signal::INT),
"QUIT" => Some(Signal::QUIT),
"ILL" => Some(Signal::ILL),
"TRAP" => Some(Signal::TRAP),
"ABRT" | "IOT" => Some(Signal::ABORT),
"BUS" => Some(Signal::BUS),
"FPE" => Some(Signal::FPE),
"KILL" => Some(Signal::KILL),
"USR1" => Some(Signal::USR1),
"SEGV" => Some(Signal::SEGV),
"USR2" => Some(Signal::USR2),
"PIPE" => Some(Signal::PIPE),
"ALRM" => Some(Signal::ALARM),
"TERM" => Some(Signal::TERM),
"STKFLT" => Some(Signal::STKFLT),
"CHLD" | "CLD" => Some(Signal::CHILD),
"CONT" => Some(Signal::CONT),
"STOP" => Some(Signal::STOP),
"TSTP" => Some(Signal::TSTP),
"TTIN" => Some(Signal::TTIN),
"TTOU" => Some(Signal::TTOU),
"URG" => Some(Signal::URG),
"XCPU" => Some(Signal::XCPU),
"XFSZ" => Some(Signal::XFSZ),
"VTALRM" => Some(Signal::VTALARM),
"PROF" => Some(Signal::PROF),
"WINCH" => Some(Signal::WINCH),
"IO" | "POLL" => Some(Signal::IO),
"PWR" => Some(Signal::POWER),
"SYS" => Some(Signal::SYS),
_ => None,
}
}
pub fn name_for_number(n: i32) -> Option<&'static str> {
SIGNALS
.iter()
.find(|(num, _)| *num == n)
.map(|(_, name)| *name)
}
pub fn number_for_name(name: &str) -> Option<i32> {
let name = name
.strip_prefix("SIG")
.unwrap_or(name)
.to_ascii_uppercase();
SIGNALS
.iter()
.find(|(_, n)| *n == name)
.map(|(num, _)| *num)
}
pub fn rt_min() -> i32 {
libc::SIGRTMIN()
}
pub fn rt_max() -> i32 {
libc::SIGRTMAX()
}
pub fn parse_rt_name(name: &str) -> Option<i32> {
let s = name
.strip_prefix("SIG")
.unwrap_or(name)
.to_ascii_uppercase();
let min = rt_min();
let max = rt_max();
let in_range = |n: i32| -> Option<i32> {
if (min..=max).contains(&n) {
Some(n)
} else {
None
}
};
if s == "RTMIN" {
return Some(min);
}
if s == "RTMAX" {
return Some(max);
}
if let Some(rest) = s.strip_prefix("RTMIN+") {
let off: i32 = rest.parse().ok()?;
if off < 0 {
return None;
}
return in_range(min + off);
}
if let Some(rest) = s.strip_prefix("RTMAX-") {
let off: i32 = rest.parse().ok()?;
if off < 0 {
return None;
}
return in_range(max - off);
}
None
}
pub fn rt_name_for_number(n: i32) -> Option<String> {
let min = rt_min();
let max = rt_max();
if !(min..=max).contains(&n) {
return None;
}
if n == min {
Some("RTMIN".into())
} else {
Some(format!("RTMIN+{}", n - min))
}
}
pub fn all_signals() -> impl Iterator<Item = (i32, String)> {
let standard = SIGNALS.iter().map(|(n, name)| (*n, (*name).to_string()));
let rt = (rt_min()..=rt_max())
.filter_map(|n| rt_name_for_number(n).map(|s| (n, s)));
standard.chain(rt)
}
pub fn parse_signum_any(s: &str) -> Option<i32> {
if let Ok(n) = s.parse::<i32>() {
if (1..=31).contains(&n) || (rt_min()..=rt_max()).contains(&n) {
return Some(n);
}
return None;
}
if let Some(sig) = parse_signal(s) {
return Some(sig.as_raw());
}
parse_rt_name(s)
}
pub fn name_for_number_any(n: i32) -> Option<String> {
if let Some(name) = name_for_number(n) {
return Some(name.to_string());
}
rt_name_for_number(n)
}