Skip to content

Commit d302e8d

Browse files
Merge #884
884: impl FromStr for sys::Signal r=Susurrus a=quodlibetor This implements both ALLCAPS and lowercase full name (including SIG) and short name. This matches what `kill` accepts in many shells, and it also allows the `Debug` representation of `Signal`, which means it can be round-tripped, if desired. Co-authored-by: Brandon W Maister <[email protected]>
2 parents 11dad16 + 8de86cc commit d302e8d

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
6161
([#857](https://github.com/nix-rust/nix/pull/857))
6262
- Added `request_code_write_int!` on FreeBSD/DragonFlyBSD
6363
([#833](https://github.com/nix-rust/nix/pull/833))
64+
- Added `FromStr` and `Display` impls for `nix::sys::Signal`
65+
([#884](https://github.com/nix-rust/nix/pull/884))
6466

6567
### Changed
6668
- `Display` and `Debug` for `SysControlAddr` now includes all fields.

src/sys/signal.rs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use libc;
77
use {Error, Result};
88
use errno::Errno;
99
use std::mem;
10+
use std::fmt;
11+
use std::str::FromStr;
1012
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
1113
use std::os::unix::io::RawFd;
1214
use std::ptr;
@@ -62,6 +64,104 @@ libc_enum!{
6264
}
6365
}
6466

67+
impl FromStr for Signal {
68+
type Err = Error;
69+
fn from_str(s: &str) -> Result<Signal> {
70+
Ok(match s {
71+
"SIGHUP" => Signal::SIGHUP,
72+
"SIGINT" => Signal::SIGINT,
73+
"SIGQUIT" => Signal::SIGQUIT,
74+
"SIGILL" => Signal::SIGILL,
75+
"SIGTRAP" => Signal::SIGTRAP,
76+
"SIGABRT" => Signal::SIGABRT,
77+
"SIGBUS" => Signal::SIGBUS,
78+
"SIGFPE" => Signal::SIGFPE,
79+
"SIGKILL" => Signal::SIGKILL,
80+
"SIGUSR1" => Signal::SIGUSR1,
81+
"SIGSEGV" => Signal::SIGSEGV,
82+
"SIGUSR2" => Signal::SIGUSR2,
83+
"SIGPIPE" => Signal::SIGPIPE,
84+
"SIGALRM" => Signal::SIGALRM,
85+
"SIGTERM" => Signal::SIGTERM,
86+
#[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
87+
not(any(target_arch = "mips", target_arch = "mips64"))))]
88+
"SIGSTKFLT" => Signal::SIGSTKFLT,
89+
"SIGCHLD" => Signal::SIGCHLD,
90+
"SIGCONT" => Signal::SIGCONT,
91+
"SIGSTOP" => Signal::SIGSTOP,
92+
"SIGTSTP" => Signal::SIGTSTP,
93+
"SIGTTIN" => Signal::SIGTTIN,
94+
"SIGTTOU" => Signal::SIGTTOU,
95+
"SIGURG" => Signal::SIGURG,
96+
"SIGXCPU" => Signal::SIGXCPU,
97+
"SIGXFSZ" => Signal::SIGXFSZ,
98+
"SIGVTALRM" => Signal::SIGVTALRM,
99+
"SIGPROF" => Signal::SIGPROF,
100+
"SIGWINCH" => Signal::SIGWINCH,
101+
"SIGIO" => Signal::SIGIO,
102+
#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
103+
"SIGPWR" => Signal::SIGPWR,
104+
"SIGSYS" => Signal::SIGSYS,
105+
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
106+
"SIGEMT" => Signal::SIGEMT,
107+
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
108+
"SIGINFO" => Signal::SIGINFO,
109+
_ => return Err(Error::invalid_argument()),
110+
})
111+
}
112+
}
113+
114+
impl AsRef<str> for Signal {
115+
fn as_ref(&self) -> &str {
116+
match *self {
117+
Signal::SIGHUP => "SIGHUP",
118+
Signal::SIGINT => "SIGINT",
119+
Signal::SIGQUIT => "SIGQUIT",
120+
Signal::SIGILL => "SIGILL",
121+
Signal::SIGTRAP => "SIGTRAP",
122+
Signal::SIGABRT => "SIGABRT",
123+
Signal::SIGBUS => "SIGBUS",
124+
Signal::SIGFPE => "SIGFPE",
125+
Signal::SIGKILL => "SIGKILL",
126+
Signal::SIGUSR1 => "SIGUSR1",
127+
Signal::SIGSEGV => "SIGSEGV",
128+
Signal::SIGUSR2 => "SIGUSR2",
129+
Signal::SIGPIPE => "SIGPIPE",
130+
Signal::SIGALRM => "SIGALRM",
131+
Signal::SIGTERM => "SIGTERM",
132+
#[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
133+
not(any(target_arch = "mips", target_arch = "mips64"))))]
134+
Signal::SIGSTKFLT => "SIGSTKFLT",
135+
Signal::SIGCHLD => "SIGCHLD",
136+
Signal::SIGCONT => "SIGCONT",
137+
Signal::SIGSTOP => "SIGSTOP",
138+
Signal::SIGTSTP => "SIGTSTP",
139+
Signal::SIGTTIN => "SIGTTIN",
140+
Signal::SIGTTOU => "SIGTTOU",
141+
Signal::SIGURG => "SIGURG",
142+
Signal::SIGXCPU => "SIGXCPU",
143+
Signal::SIGXFSZ => "SIGXFSZ",
144+
Signal::SIGVTALRM => "SIGVTALRM",
145+
Signal::SIGPROF => "SIGPROF",
146+
Signal::SIGWINCH => "SIGWINCH",
147+
Signal::SIGIO => "SIGIO",
148+
#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
149+
Signal::SIGPWR => "SIGPWR",
150+
Signal::SIGSYS => "SIGSYS",
151+
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
152+
Signal::SIGEMT => "SIGEMT",
153+
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
154+
Signal::SIGINFO => "SIGINFO",
155+
}
156+
}
157+
}
158+
159+
impl fmt::Display for Signal {
160+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
161+
f.write_str(self.as_ref())
162+
}
163+
}
164+
65165
pub use self::Signal::*;
66166

67167
#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), not(any(target_arch = "mips", target_arch = "mips64"))))]
@@ -684,6 +784,22 @@ mod tests {
684784
}
685785
}
686786

787+
#[test]
788+
fn test_from_str_round_trips() {
789+
for signal in Signal::iterator() {
790+
assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
791+
assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
792+
}
793+
}
794+
795+
#[test]
796+
fn test_from_str_invalid_value() {
797+
let errval = Err(Error::Sys(Errno::EINVAL));
798+
assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
799+
assert_eq!("kill".parse::<Signal>(), errval);
800+
assert_eq!("9".parse::<Signal>(), errval);
801+
}
802+
687803
#[test]
688804
fn test_extend() {
689805
let mut one_signal = SigSet::empty();

0 commit comments

Comments
 (0)