diff --git a/Cargo.lock b/Cargo.lock index 31787e626..05040dff1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2041,6 +2041,7 @@ dependencies = [ name = "uu_kill" version = "0.0.6" dependencies = [ + "clap", "libc", "uucore", "uucore_procs", diff --git a/src/uu/kill/Cargo.toml b/src/uu/kill/Cargo.toml index 6b66806bc..e33411c70 100644 --- a/src/uu/kill/Cargo.toml +++ b/src/uu/kill/Cargo.toml @@ -15,6 +15,7 @@ edition = "2018" path = "src/kill.rs" [dependencies] +clap = "2.33" libc = "0.2.42" uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features=["signals"] } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } diff --git a/src/uu/kill/src/kill.rs b/src/uu/kill/src/kill.rs index fe925ce37..362f13f18 100644 --- a/src/uu/kill/src/kill.rs +++ b/src/uu/kill/src/kill.rs @@ -10,18 +10,26 @@ #[macro_use] extern crate uucore; +use clap::{App, Arg}; use libc::{c_int, pid_t}; use std::io::Error; use uucore::signals::ALL_SIGNALS; use uucore::InvalidEncodingHandling; -static SYNTAX: &str = "[options] [...]"; -static SUMMARY: &str = ""; -static LONG_HELP: &str = ""; +static VERSION: &str = env!("CARGO_PKG_VERSION"); +static ABOUT: &str = "Send signal to processes or list information about signals."; static EXIT_OK: i32 = 0; static EXIT_ERR: i32 = 1; +pub mod options { + pub static PIDS_OR_SIGNALS: &str = "pids_of_signals"; + pub static LIST: &str = "list"; + pub static TABLE: &str = "table"; + pub static TABLE_OLD: &str = "table_old"; + pub static SIGNAL: &str = "signal"; +} + #[derive(Clone, Copy)] pub enum Mode { Kill, @@ -33,41 +41,70 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let args = args .collect_str(InvalidEncodingHandling::Ignore) .accept_any(); - let (args, obs_signal) = handle_obsolete(args); - let matches = app!(SYNTAX, SUMMARY, LONG_HELP) - .optopt("s", "signal", "specify the to be sent", "SIGNAL") - .optflagopt( - "l", - "list", - "list all signal names, or convert one to a name", - "LIST", - ) - .optflag("L", "table", "list all signal names in a nice table") - .parse(args); - let mode = if matches.opt_present("table") { + let usage = format!("{} [OPTIONS]... PID...", executable!()); + let matches = App::new(executable!()) + .version(VERSION) + .about(ABOUT) + .usage(&usage[..]) + .arg( + Arg::with_name(options::LIST) + .short("l") + .long(options::LIST) + .help("Lists signals") + .conflicts_with(options::TABLE) + .conflicts_with(options::TABLE_OLD), + ) + .arg( + Arg::with_name(options::TABLE) + .short("t") + .long(options::TABLE) + .help("Lists table of signals"), + ) + .arg(Arg::with_name(options::TABLE_OLD).short("L").hidden(true)) + .arg( + Arg::with_name(options::SIGNAL) + .short("s") + .long(options::SIGNAL) + .help("Sends given signal") + .takes_value(true), + ) + .arg( + Arg::with_name(options::PIDS_OR_SIGNALS) + .hidden(true) + .multiple(true), + ) + .get_matches_from(args); + + let mode = if matches.is_present(options::TABLE) || matches.is_present(options::TABLE_OLD) { Mode::Table - } else if matches.opt_present("list") { + } else if matches.is_present(options::LIST) { Mode::List } else { Mode::Kill }; + let pids_or_signals: Vec = matches + .values_of(options::PIDS_OR_SIGNALS) + .map(|v| v.map(ToString::to_string).collect()) + .unwrap_or_default(); + match mode { Mode::Kill => { - return kill( - &matches - .opt_str("signal") - .unwrap_or_else(|| obs_signal.unwrap_or_else(|| "TERM".to_owned())), - matches.free, - ) + let sig = match (obs_signal, matches.value_of(options::SIGNAL)) { + (Some(s), Some(_)) => s, // -s takes precedence + (Some(s), None) => s, + (None, Some(s)) => s.to_owned(), + (None, None) => "TERM".to_owned(), + }; + return kill(&sig, &pids_or_signals); } Mode::Table => table(), - Mode::List => list(matches.opt_str("list")), + Mode::List => list(pids_or_signals.get(0).cloned()), } - 0 + EXIT_OK } fn handle_obsolete(mut args: Vec) -> (Vec, Option) { @@ -148,14 +185,14 @@ fn list(arg: Option) { }; } -fn kill(signalname: &str, pids: std::vec::Vec) -> i32 { +fn kill(signalname: &str, pids: &[String]) -> i32 { let mut status = 0; let optional_signal_value = uucore::signals::signal_by_name_or_value(signalname); let signal_value = match optional_signal_value { Some(x) => x, None => crash!(EXIT_ERR, "unknown signal name {}", signalname), }; - for pid in &pids { + for pid in pids { match pid.parse::() { Ok(x) => { if unsafe { libc::kill(x as pid_t, signal_value as c_int) } != 0 {