zinit 0.3.8

Process supervisor with dependency management
Documentation
//! Signal name and number conversion utilities.

/// Parse a signal name to its number.
///
/// Accepts formats like "SIGTERM", "TERM", "sigterm", "term", or "15".
pub fn parse(name: &str) -> Option<i32> {
    let name = name.trim().to_uppercase();
    let name = name.strip_prefix("SIG").unwrap_or(&name);

    match name {
        "HUP" => Some(1),
        "INT" => Some(2),
        "QUIT" => Some(3),
        "ILL" => Some(4),
        "TRAP" => Some(5),
        "ABRT" | "IOT" => Some(6),
        "BUS" => Some(7),
        "FPE" => Some(8),
        "KILL" => Some(9),
        "USR1" => Some(10),
        "SEGV" => Some(11),
        "USR2" => Some(12),
        "PIPE" => Some(13),
        "ALRM" => Some(14),
        "TERM" => Some(15),
        "STKFLT" => Some(16),
        "CHLD" => Some(17),
        "CONT" => Some(18),
        "STOP" => Some(19),
        "TSTP" => Some(20),
        "TTIN" => Some(21),
        "TTOU" => Some(22),
        "URG" => Some(23),
        "XCPU" => Some(24),
        "XFSZ" => Some(25),
        "VTALRM" => Some(26),
        "PROF" => Some(27),
        "WINCH" => Some(28),
        "IO" | "POLL" => Some(29),
        "PWR" => Some(30),
        "SYS" => Some(31),
        _ => name.parse().ok(),
    }
}

/// Convert a signal number to its name.
pub fn name(sig: i32) -> &'static str {
    match sig {
        1 => "SIGHUP",
        2 => "SIGINT",
        3 => "SIGQUIT",
        4 => "SIGILL",
        5 => "SIGTRAP",
        6 => "SIGABRT",
        7 => "SIGBUS",
        8 => "SIGFPE",
        9 => "SIGKILL",
        10 => "SIGUSR1",
        11 => "SIGSEGV",
        12 => "SIGUSR2",
        13 => "SIGPIPE",
        14 => "SIGALRM",
        15 => "SIGTERM",
        16 => "SIGSTKFLT",
        17 => "SIGCHLD",
        18 => "SIGCONT",
        19 => "SIGSTOP",
        20 => "SIGTSTP",
        21 => "SIGTTIN",
        22 => "SIGTTOU",
        23 => "SIGURG",
        24 => "SIGXCPU",
        25 => "SIGXFSZ",
        26 => "SIGVTALRM",
        27 => "SIGPROF",
        28 => "SIGWINCH",
        29 => "SIGIO",
        30 => "SIGPWR",
        31 => "SIGSYS",
        _ => "UNKNOWN",
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_with_sig_prefix() {
        assert_eq!(parse("SIGTERM"), Some(15));
        assert_eq!(parse("SIGKILL"), Some(9));
        assert_eq!(parse("SIGHUP"), Some(1));
    }

    #[test]
    fn test_parse_without_prefix() {
        assert_eq!(parse("TERM"), Some(15));
        assert_eq!(parse("KILL"), Some(9));
        assert_eq!(parse("HUP"), Some(1));
    }

    #[test]
    fn test_parse_lowercase() {
        assert_eq!(parse("sigterm"), Some(15));
        assert_eq!(parse("term"), Some(15));
    }

    #[test]
    fn test_parse_numeric() {
        assert_eq!(parse("15"), Some(15));
        assert_eq!(parse("9"), Some(9));
    }

    #[test]
    fn test_parse_invalid() {
        assert_eq!(parse("INVALID"), None);
        assert_eq!(parse(""), None);
    }

    #[test]
    fn test_name() {
        assert_eq!(name(15), "SIGTERM");
        assert_eq!(name(9), "SIGKILL");
        assert_eq!(name(1), "SIGHUP");
        assert_eq!(name(999), "UNKNOWN");
    }

    #[test]
    fn test_roundtrip() {
        for sig in 1..=31 {
            let sig_name = name(sig);
            if sig_name != "UNKNOWN" {
                assert_eq!(parse(sig_name), Some(sig));
            }
        }
    }
}