diff --git a/Cargo.lock b/Cargo.lock index 0ef4ca84..f46f521b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -623,12 +623,6 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9feedaea5a9f602932e78b512b2fde69aaefd2ef4fd5fd744238f7424b246186" -[[package]] -name = "exitcode" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" - [[package]] name = "fake-simd" version = "0.1.2" @@ -2092,7 +2086,6 @@ dependencies = [ "daemonize", "directories", "env_logger", - "exitcode", "futures", "ipnet", "jemallocator", @@ -2108,6 +2101,7 @@ dependencies = [ "serde", "shadowsocks-service", "snmalloc-rs", + "sysexits", "tcmalloc", "thiserror", "tokio", @@ -2285,6 +2279,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sysexits" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c24dea646d0a2a4209a2d960275fd4416be9ab32c77927f51279a621e2b629" + [[package]] name = "tcmalloc" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index cc19e55f..72c7cabd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -153,7 +153,7 @@ thiserror = "1.0" clap = { version = "3.1", features = ["wrap_help", "suggestions"] } cfg-if = "1" qrcode = { version = "0.12", default-features = false, optional = true } -exitcode = "1" +sysexits = "0.3" build-time = "0.1" directories = "4.0" xdg = "2.4" diff --git a/bin/sslocal.rs b/bin/sslocal.rs index b2625ae1..8efad7af 100644 --- a/bin/sslocal.rs +++ b/bin/sslocal.rs @@ -4,15 +4,17 @@ //! or you could specify a configuration file. The format of configuration file is defined //! in mod `config`. +use std::process::ExitCode; + use clap::Command; use shadowsocks_rust::service::local; -fn main() { +fn main() -> ExitCode { let mut app = Command::new("shadowsocks") .version(shadowsocks_rust::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); app = local::define_command_line_options(app); let matches = app.get_matches(); - local::main(&matches); + local::main(&matches) } diff --git a/bin/ssmanager.rs b/bin/ssmanager.rs index b30ba0ff..515929cd 100644 --- a/bin/ssmanager.rs +++ b/bin/ssmanager.rs @@ -7,15 +7,17 @@ //! *It should be notice that the extended configuration file is not suitable for the server //! side.* +use std::process::ExitCode; + use clap::Command; use shadowsocks_rust::service::manager; -fn main() { +fn main() -> ExitCode { let mut app = Command::new("shadowsocks") .version(shadowsocks_rust::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); app = manager::define_command_line_options(app); let matches = app.get_matches(); - manager::main(&matches); + manager::main(&matches) } diff --git a/bin/ssserver.rs b/bin/ssserver.rs index 5c784fb4..5ba89038 100644 --- a/bin/ssserver.rs +++ b/bin/ssserver.rs @@ -7,15 +7,17 @@ //! *It should be notice that the extended configuration file is not suitable for the server //! side.* +use std::process::ExitCode; + use clap::Command; use shadowsocks_rust::service::server; -fn main() { +fn main() -> ExitCode { let mut app = Command::new("shadowsocks") .version(shadowsocks_rust::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); app = server::define_command_line_options(app); let matches = app.get_matches(); - server::main(&matches); + server::main(&matches) } diff --git a/bin/ssservice.rs b/bin/ssservice.rs index a00b8536..b85088c9 100644 --- a/bin/ssservice.rs +++ b/bin/ssservice.rs @@ -7,12 +7,12 @@ //! *It should be notice that the extended configuration file is not suitable for the server //! side.* -use std::{env, path::Path}; +use std::{env, path::Path, process::ExitCode}; use clap::Command; use shadowsocks_rust::service::{local, manager, server}; -fn main() { +fn main() -> ExitCode { let app = Command::new("shadowsocks") .version(shadowsocks_rust::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); diff --git a/src/lib.rs b/src/lib.rs index e2b04606..fd6590dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,13 +13,13 @@ pub mod sys; pub mod validator; /// Exit code when server exits unexpectly -pub const EXIT_CODE_SERVER_EXIT_UNEXPECTEDLY: i32 = exitcode::SOFTWARE; +pub const EXIT_CODE_SERVER_EXIT_UNEXPECTEDLY: sysexits::ExitCode = sysexits::ExitCode::Software; /// Exit code when server aborted -pub const EXIT_CODE_SERVER_ABORTED: i32 = exitcode::SOFTWARE; +pub const EXIT_CODE_SERVER_ABORTED: sysexits::ExitCode = sysexits::ExitCode::Software; /// Exit code when loading configuration from file fails -pub const EXIT_CODE_LOAD_CONFIG_FAILURE: i32 = exitcode::CONFIG; +pub const EXIT_CODE_LOAD_CONFIG_FAILURE: sysexits::ExitCode = sysexits::ExitCode::Config; /// Exit code when loading ACL from file fails -pub const EXIT_CODE_LOAD_ACL_FAILURE: i32 = exitcode::CONFIG; +pub const EXIT_CODE_LOAD_ACL_FAILURE: sysexits::ExitCode = sysexits::ExitCode::Config; /// Build timestamp in UTC pub const BUILD_TIME: &str = build_time::build_time_utc!(); diff --git a/src/service/local.rs b/src/service/local.rs index 62e3ef7f..e016cc7a 100644 --- a/src/service/local.rs +++ b/src/service/local.rs @@ -1,6 +1,6 @@ //! Local server launchers -use std::{net::IpAddr, path::PathBuf, process, time::Duration}; +use std::{net::IpAddr, path::PathBuf, process::ExitCode, time::Duration}; use clap::{Arg, ArgGroup, ArgMatches, Command, ErrorKind as ClapErrorKind}; use futures::future::{self, Either}; @@ -376,7 +376,7 @@ pub fn define_command_line_options(mut app: Command<'_>) -> Command<'_> { } /// Program entrance `main` -pub fn main(matches: &ArgMatches) { +pub fn main(matches: &ArgMatches) -> ExitCode { let (config, runtime) = { let config_path_opt = matches.value_of("CONFIG").map(PathBuf::from).or_else(|| { if !matches.is_present("SERVER_CONFIG") { @@ -397,7 +397,7 @@ pub fn main(matches: &ArgMatches) { Ok(c) => c, Err(err) => { eprintln!("loading config {:?}, {}", config_path, err); - process::exit(crate::EXIT_CODE_LOAD_CONFIG_FAILURE); + return crate::EXIT_CODE_LOAD_CONFIG_FAILURE.into(); } }, None => ServiceConfig::default(), @@ -421,7 +421,7 @@ pub fn main(matches: &ArgMatches) { Ok(cfg) => cfg, Err(err) => { eprintln!("loading config {:?}, {}", cpath, err); - process::exit(crate::EXIT_CODE_LOAD_CONFIG_FAILURE); + return crate::EXIT_CODE_LOAD_CONFIG_FAILURE.into(); } }, None => Config::new(ConfigType::Local), @@ -703,7 +703,7 @@ pub fn main(matches: &ArgMatches) { Ok(acl) => acl, Err(err) => { eprintln!("loading ACL \"{}\", {}", acl_file, err); - process::exit(crate::EXIT_CODE_LOAD_ACL_FAILURE); + return crate::EXIT_CODE_LOAD_ACL_FAILURE.into(); } }; config.acl = Some(acl); @@ -763,12 +763,12 @@ pub fn main(matches: &ArgMatches) { "missing `local_address`, consider specifying it by --local-addr command line option, \ or \"local_address\" and \"local_port\" in configuration file" ); - return; + return ExitCode::SUCCESS; } if let Err(err) = config.check_integrity() { eprintln!("config integrity check failed, {}", err); - return; + return ExitCode::SUCCESS; } #[cfg(unix)] @@ -816,17 +816,17 @@ pub fn main(matches: &ArgMatches) { // Server future resolved without an error. This should never happen. Either::Left((Ok(..), ..)) => { eprintln!("server exited unexpectedly"); - process::exit(crate::EXIT_CODE_SERVER_EXIT_UNEXPECTEDLY); + crate::EXIT_CODE_SERVER_EXIT_UNEXPECTEDLY.into() } // Server future resolved with error, which are listener errors in most cases Either::Left((Err(err), ..)) => { eprintln!("server aborted with {}", err); - process::exit(crate::EXIT_CODE_SERVER_ABORTED); + crate::EXIT_CODE_SERVER_ABORTED.into() } // The abort signal future resolved. Means we should just exit. - Either::Right(_) => (), + Either::Right(_) => ExitCode::SUCCESS, } - }); + }) } #[cfg(unix)] diff --git a/src/service/manager.rs b/src/service/manager.rs index 525f1a94..dd0973e9 100644 --- a/src/service/manager.rs +++ b/src/service/manager.rs @@ -1,6 +1,6 @@ //! Server Manager launchers -use std::{net::IpAddr, path::PathBuf, process, time::Duration}; +use std::{net::IpAddr, path::PathBuf, process::ExitCode, time::Duration}; use clap::{Arg, ArgGroup, ArgMatches, Command, ErrorKind as ClapErrorKind}; use futures::future::{self, Either}; @@ -209,7 +209,7 @@ pub fn define_command_line_options(mut app: Command<'_>) -> Command<'_> { } /// Program entrance `main` -pub fn main(matches: &ArgMatches) { +pub fn main(matches: &ArgMatches) -> ExitCode { let (config, runtime) = { let config_path_opt = matches.value_of("CONFIG").map(PathBuf::from).or_else(|| { if !matches.is_present("SERVER_CONFIG") { @@ -230,7 +230,7 @@ pub fn main(matches: &ArgMatches) { Ok(c) => c, Err(err) => { eprintln!("loading config {:?}, {}", config_path, err); - process::exit(crate::EXIT_CODE_LOAD_CONFIG_FAILURE); + return crate::EXIT_CODE_LOAD_CONFIG_FAILURE.into(); } }, None => ServiceConfig::default(), @@ -254,7 +254,7 @@ pub fn main(matches: &ArgMatches) { Ok(cfg) => cfg, Err(err) => { eprintln!("loading config {:?}, {}", cpath, err); - process::exit(crate::EXIT_CODE_LOAD_CONFIG_FAILURE); + return crate::EXIT_CODE_LOAD_CONFIG_FAILURE.into(); } }, None => Config::new(ConfigType::Manager), @@ -375,7 +375,7 @@ pub fn main(matches: &ArgMatches) { Ok(acl) => acl, Err(err) => { eprintln!("loading ACL \"{}\", {}", acl_file, err); - process::exit(crate::EXIT_CODE_LOAD_ACL_FAILURE); + return crate::EXIT_CODE_LOAD_ACL_FAILURE.into(); } }; config.acl = Some(acl); @@ -435,12 +435,12 @@ pub fn main(matches: &ArgMatches) { "missing `manager_address`, consider specifying it by --manager-address command line option, \ or \"manager_address\" and \"manager_port\" keys in configuration file" ); - return; + return ExitCode::SUCCESS; } if let Err(err) = config.check_integrity() { eprintln!("config integrity check failed, {}", err); - return; + return ExitCode::SUCCESS; } #[cfg(unix)] @@ -485,15 +485,15 @@ pub fn main(matches: &ArgMatches) { // Server future resolved without an error. This should never happen. Either::Left((Ok(..), ..)) => { eprintln!("server exited unexpectedly"); - process::exit(crate::EXIT_CODE_SERVER_EXIT_UNEXPECTEDLY); + crate::EXIT_CODE_SERVER_EXIT_UNEXPECTEDLY.into() } // Server future resolved with error, which are listener errors in most cases Either::Left((Err(err), ..)) => { eprintln!("server aborted with {}", err); - process::exit(crate::EXIT_CODE_SERVER_ABORTED); + crate::EXIT_CODE_SERVER_ABORTED.into() } // The abort signal future resolved. Means we should just exit. - Either::Right(_) => (), + Either::Right(_) => ExitCode::SUCCESS, } - }); + }) } diff --git a/src/service/server.rs b/src/service/server.rs index 69f3bf44..4f939eb1 100644 --- a/src/service/server.rs +++ b/src/service/server.rs @@ -1,6 +1,6 @@ //! Server launchers -use std::{net::IpAddr, path::PathBuf, process, time::Duration}; +use std::{net::IpAddr, path::PathBuf, process::ExitCode, time::Duration}; use clap::{Arg, ArgGroup, ArgMatches, Command, ErrorKind as ClapErrorKind}; use futures::future::{self, Either}; @@ -221,7 +221,7 @@ pub fn define_command_line_options(mut app: Command<'_>) -> Command<'_> { } /// Program entrance `main` -pub fn main(matches: &ArgMatches) { +pub fn main(matches: &ArgMatches) -> ExitCode { let (config, runtime) = { let config_path_opt = matches.value_of("CONFIG").map(PathBuf::from).or_else(|| { if !matches.is_present("SERVER_CONFIG") { @@ -242,7 +242,7 @@ pub fn main(matches: &ArgMatches) { Ok(c) => c, Err(err) => { eprintln!("loading config {:?}, {}", config_path, err); - process::exit(crate::EXIT_CODE_LOAD_CONFIG_FAILURE); + return crate::EXIT_CODE_LOAD_CONFIG_FAILURE.into(); } }, None => ServiceConfig::default(), @@ -266,7 +266,7 @@ pub fn main(matches: &ArgMatches) { Ok(cfg) => cfg, Err(err) => { eprintln!("loading config {:?}, {}", cpath, err); - process::exit(crate::EXIT_CODE_LOAD_CONFIG_FAILURE); + return crate::EXIT_CODE_LOAD_CONFIG_FAILURE.into(); } }, None => Config::new(ConfigType::Server), @@ -387,7 +387,7 @@ pub fn main(matches: &ArgMatches) { Ok(acl) => acl, Err(err) => { eprintln!("loading ACL \"{}\", {}", acl_file, err); - process::exit(crate::EXIT_CODE_LOAD_ACL_FAILURE); + return crate::EXIT_CODE_LOAD_ACL_FAILURE.into(); } }; config.acl = Some(acl); @@ -448,12 +448,12 @@ pub fn main(matches: &ArgMatches) { --server-addr, --encrypt-method, --password command line option, \ or configuration file, check more details in https://shadowsocks.org/en/config/quick-guide.html" ); - return; + return ExitCode::SUCCESS; } if let Err(err) = config.check_integrity() { eprintln!("config integrity check failed, {}", err); - return; + return ExitCode::SUCCESS; } #[cfg(unix)] @@ -498,15 +498,15 @@ pub fn main(matches: &ArgMatches) { // Server future resolved without an error. This should never happen. Either::Left((Ok(..), ..)) => { eprintln!("server exited unexpectedly"); - process::exit(crate::EXIT_CODE_SERVER_EXIT_UNEXPECTEDLY); + crate::EXIT_CODE_SERVER_EXIT_UNEXPECTEDLY.into() } // Server future resolved with error, which are listener errors in most cases Either::Left((Err(err), ..)) => { eprintln!("server aborted with {}", err); - process::exit(crate::EXIT_CODE_SERVER_ABORTED); + crate::EXIT_CODE_SERVER_ABORTED.into() } // The abort signal future resolved. Means we should just exit. - Either::Right(_) => (), + Either::Right(_) => ExitCode::SUCCESS, } - }); + }) }