use core::fmt;
use bun_core::output;
#[repr(transparent)]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct SignalCode(pub u8);
macro_rules! __sys_signal_consts {
($($name:ident = $n:literal),* $(,)?) => { $(pub const $name: Self = Self($n);)* };
}
impl SignalCode {
bun_core::for_each_signal!(__sys_signal_consts);
pub const DEFAULT: Self = Self::SIGTERM;
pub fn name(self) -> Option<&'static str> {
match self.0 {
1..=31 => Some(bun_core::SIGNAL_NAMES[self.0 as usize]),
_ => None,
}
}
pub fn valid(self) -> bool {
self.0 <= Self::SIGSYS.0 && self.0 >= Self::SIGHUP.0
}
pub fn to_exit_code(self) -> Option<u8> {
match self.0 {
1..=31 => Some(128u8.wrapping_add(self.0)),
_ => None,
}
}
pub fn description(self) -> Option<&'static str> {
match self {
Self::SIGHUP => Some("Terminal hung up"),
Self::SIGINT => Some("Quit request"),
Self::SIGQUIT => Some("Quit request"),
Self::SIGILL => Some("Illegal instruction"),
Self::SIGTRAP => Some("Trace or breakpoint trap"),
Self::SIGABRT => Some("Abort"),
Self::SIGBUS => Some("Misaligned address error"),
Self::SIGFPE => Some("Floating point exception"),
Self::SIGKILL => Some("Forced quit"),
Self::SIGUSR1 => Some("User defined signal 1"),
Self::SIGUSR2 => Some("User defined signal 2"),
Self::SIGSEGV => Some("Address boundary error"),
Self::SIGPIPE => Some("Broken pipe"),
Self::SIGALRM => Some("Timer expired"),
Self::SIGTERM => Some("Polite quit request"),
Self::SIGCHLD => Some("Child process status changed"),
Self::SIGCONT => Some("Continue previously stopped process"),
Self::SIGSTOP => Some("Forced stop"),
Self::SIGTSTP => Some("Stop request from job control (^Z)"),
Self::SIGTTIN => Some("Stop from terminal input"),
Self::SIGTTOU => Some("Stop from terminal output"),
Self::SIGURG => Some("Urgent socket condition"),
Self::SIGXCPU => Some("CPU time limit exceeded"),
Self::SIGXFSZ => Some("File size limit exceeded"),
Self::SIGVTALRM => Some("Virtual timefr expired"),
Self::SIGPROF => Some("Profiling timer expired"),
Self::SIGWINCH => Some("Window size change"),
Self::SIGIO => Some("I/O on asynchronous file descriptor is possible"),
Self::SIGSYS => Some("Bad system call"),
Self::SIGPWR => Some("Power failure"),
_ => None,
}
}
pub fn from<T: bytemuck::NoUninit>(value: T) -> SignalCode {
SignalCode(bytemuck::bytes_of(&value)[0])
}
pub fn fmt(self, enable_ansi_colors: bool) -> Fmt {
Fmt {
signal: self,
enable_ansi_colors,
}
}
}
#[inline]
pub fn from_name(s: &[u8]) -> Option<SignalCode> {
bun_core::SignalCode::from_name(s).map(|c| SignalCode(c as u8))
}
pub struct Fmt {
signal: SignalCode,
enable_ansi_colors: bool,
}
impl fmt::Display for Fmt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let signal = self.signal;
if let Some(str_) = signal.name() {
if let Some(desc) = signal.description() {
if self.enable_ansi_colors {
return write!(f, "{} {}({}){}", str_, output::DIM, desc, output::RESET);
} else {
return write!(f, "{} ({})", str_, desc);
}
}
}
write!(f, "code {}", signal.0)
}
}