From f206e2c28a77b74264703042e14fa281ed3fc789 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 6 Sep 2022 10:53:54 +0200 Subject: [PATCH 1/2] Make ExitCode a struct Signed-off-by: Matthias Beyer --- examples/basic.rs | 4 ++-- src/lib.rs | 47 ++++++++++++++++++++++++++++++----------------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/examples/basic.rs b/examples/basic.rs index ab0a4ca..ee5e57e 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -14,11 +14,11 @@ pub fn main() { match parse_int_or_return_error_exitcode("foo") { Ok(i) => { println!("Parsed: {}", i); - process::exit(exitcode::OK); + process::exit(exitcode::OK.into()); }, Err(code) => { writeln!(stderr(), "Parse error. Exiting with code: {}", code).unwrap(); - process::exit(code); + process::exit(code.into()); } } } diff --git a/src/lib.rs b/src/lib.rs index f170546..ef1632a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,82 +11,95 @@ //! ``` /// Alias for the numeric type that holds system exit codes. -pub type ExitCode = i32; +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct ExitCode(i32); + +impl From for i32 { + fn from(ec: ExitCode) -> i32 { + ec.0 + } +} + +impl std::fmt::Display for ExitCode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} /// Successful exit -pub const OK: ExitCode = 0; +pub const OK: ExitCode = ExitCode(0); /// The command was used incorrectly, e.g., with the /// wrong number of arguments, a bad flag, a bad syntax /// in a parameter, etc. -pub const USAGE: ExitCode = 64; +pub const USAGE: ExitCode = ExitCode(64); /// The input data was incorrect in some way. This /// should only be used for user's data and not system /// files. -pub const DATAERR: ExitCode = 65; +pub const DATAERR: ExitCode = ExitCode(65); /// An input file (not a system file) did not exist or /// was not readable. This could also include errors /// like "No message" to a mailer (if it cared to /// catch it). -pub const NOINPUT: ExitCode = 66; +pub const NOINPUT: ExitCode = ExitCode(66); /// The user specified did not exist. This might be /// used for mail addresses or remote logins. -pub const NOUSER: ExitCode = 67; +pub const NOUSER: ExitCode = ExitCode(67); /// The host specified did not exist. This is used in /// mail addresses or network requests. -pub const NOHOST: ExitCode = 68; +pub const NOHOST: ExitCode = ExitCode(68); /// A service is unavailable. This can occur if a /// support program or file does not exist. This can also /// be used as a catchall message when something you /// wanted to do doesn't work, but you don't know why. -pub const UNAVAILABLE: ExitCode = 69; +pub const UNAVAILABLE: ExitCode = ExitCode(69); /// An internal software error has been detected. This /// should be limited to non-operating system related /// errors as possible. -pub const SOFTWARE: ExitCode = 70; +pub const SOFTWARE: ExitCode = ExitCode(70); /// An operating system error has been detected. This /// is intended to be used for such things as "cannot /// fork", "cannot create pipe", or the like. It /// includes things like getuid returning a user that /// does not exist in the passwd file. -pub const OSERR: ExitCode = 71; +pub const OSERR: ExitCode = ExitCode(71); /// Some system file (e.g., /etc/passwd, /var/run/utmp, /// etc.) does not exist, cannot be opened, or has some /// sort of error (e.g., syntax error). -pub const OSFILE: ExitCode = 72; +pub const OSFILE: ExitCode = ExitCode(72); /// A (user specified) output file cannot be created. -pub const CANTCREAT: ExitCode = 73; +pub const CANTCREAT: ExitCode = ExitCode(73); /// An error occurred while doing I/O on some file. -pub const IOERR: ExitCode = 74; +pub const IOERR: ExitCode = ExitCode(74); /// Temporary failure, indicating something that is not /// really an error. In sendmail, this means that a /// mailer (e.g.) could not create a connection, and /// the request should be reattempted later. -pub const TEMPFAIL: ExitCode = 75; +pub const TEMPFAIL: ExitCode = ExitCode(75); /// The remote system returned something that was /// "not possible" during a protocol exchange. -pub const PROTOCOL: ExitCode = 76; +pub const PROTOCOL: ExitCode = ExitCode(76); /// You did not have sufficient permission to perform /// the operation. This is not intended for file system /// problems, which should use `NOINPUT` or `CANTCREAT`, /// but rather for higher level permissions. -pub const NOPERM: ExitCode = 77; +pub const NOPERM: ExitCode = ExitCode(77); /// Something was found in an unconfigured or misconfigured state. -pub const CONFIG: ExitCode = 78; +pub const CONFIG: ExitCode = ExitCode(78); /// Check if exit code given by `code` is successful /// From 39fca283702330db5bfb8e7e137fbe3b3ecb4190 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Tue, 6 Sep 2022 10:57:12 +0200 Subject: [PATCH 2/2] Implement Termination for ExitCode Signed-off-by: Matthias Beyer --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index ef1632a..ec9134c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,6 +26,12 @@ impl std::fmt::Display for ExitCode { } } +impl std::process::Termination for ExitCode { + fn report(self) -> std::process::ExitCode { + std::process::ExitCode::from(self.0 as u8) // safe because our highest exit code fits in u8 + } +} + /// Successful exit pub const OK: ExitCode = ExitCode(0);