1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 03:57:44 +00:00

Merge pull request #3501 from tertsdiepraam/kill-group-id

`kill`: kill process group with negative id
This commit is contained in:
Sylvestre Ledru 2022-05-20 11:53:45 +02:00 committed by GitHub
commit 27ccb3df2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 18 deletions

3
Cargo.lock generated
View file

@ -1158,6 +1158,7 @@ dependencies = [
"bitflags", "bitflags",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"memoffset",
] ]
[[package]] [[package]]
@ -2452,7 +2453,7 @@ name = "uu_kill"
version = "0.0.13" version = "0.0.13"
dependencies = [ dependencies = [
"clap 3.1.18", "clap 3.1.18",
"libc", "nix",
"uucore", "uucore",
] ]

View file

@ -16,7 +16,7 @@ path = "src/kill.rs"
[dependencies] [dependencies]
clap = { version = "3.1", features = ["wrap_help", "cargo"] } clap = { version = "3.1", features = ["wrap_help", "cargo"] }
libc = "0.2.126" nix = { version = "0.24.1", features = ["signal"] }
uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["signals"] } uucore = { version=">=0.0.11", package="uucore", path="../../uucore", features=["signals"] }
[[bin]] [[bin]]

View file

@ -5,16 +5,17 @@
// * For the full copyright and license information, please view the LICENSE file // * For the full copyright and license information, please view the LICENSE file
// * that was distributed with this source code. // * that was distributed with this source code.
// spell-checker:ignore (ToDO) signalname pids // spell-checker:ignore (ToDO) signalname pids killpg
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use clap::{crate_version, Arg, Command}; use clap::{crate_version, Arg, Command};
use libc::{c_int, pid_t}; use nix::sys::signal::{self, Signal};
use nix::unistd::Pid;
use std::io::Error; use std::io::Error;
use uucore::display::Quotable; use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError}; use uucore::error::{FromIo, UError, UResult, USimpleError};
use uucore::signals::{signal_by_name_or_value, ALL_SIGNALS}; use uucore::signals::{signal_by_name_or_value, ALL_SIGNALS};
use uucore::{format_usage, InvalidEncodingHandling}; use uucore::{format_usage, InvalidEncodingHandling};
@ -22,10 +23,9 @@ static ABOUT: &str = "Send signal to processes or list information about signals
const USAGE: &str = "{} [OPTIONS]... PID..."; const USAGE: &str = "{} [OPTIONS]... PID...";
pub mod options { pub mod options {
pub static PIDS_OR_SIGNALS: &str = "pids_of_signals"; pub static PIDS_OR_SIGNALS: &str = "pids_or_signals";
pub static LIST: &str = "list"; pub static LIST: &str = "list";
pub static TABLE: &str = "table"; pub static TABLE: &str = "table";
pub static TABLE_OLD: &str = "table_old";
pub static SIGNAL: &str = "signal"; pub static SIGNAL: &str = "signal";
} }
@ -45,7 +45,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().get_matches_from(args); let matches = uu_app().get_matches_from(args);
let mode = if matches.is_present(options::TABLE) || matches.is_present(options::TABLE_OLD) { let mode = if matches.is_present(options::TABLE) {
Mode::Table Mode::Table
} else if matches.is_present(options::LIST) { } else if matches.is_present(options::LIST) {
Mode::List Mode::List
@ -67,8 +67,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
} else { } else {
15_usize //SIGTERM 15_usize //SIGTERM
}; };
let sig: Signal = (sig as i32)
.try_into()
.map_err(|e| std::io::Error::from_raw_os_error(e as i32))?;
let pids = parse_pids(&pids_or_signals)?; let pids = parse_pids(&pids_or_signals)?;
kill(sig, &pids) kill(sig, &pids);
Ok(())
} }
Mode::Table => { Mode::Table => {
table(); table();
@ -84,21 +88,21 @@ pub fn uu_app<'a>() -> Command<'a> {
.about(ABOUT) .about(ABOUT)
.override_usage(format_usage(USAGE)) .override_usage(format_usage(USAGE))
.infer_long_args(true) .infer_long_args(true)
.allow_negative_numbers(true)
.arg( .arg(
Arg::new(options::LIST) Arg::new(options::LIST)
.short('l') .short('l')
.long(options::LIST) .long(options::LIST)
.help("Lists signals") .help("Lists signals")
.conflicts_with(options::TABLE) .conflicts_with(options::TABLE),
.conflicts_with(options::TABLE_OLD),
) )
.arg( .arg(
Arg::new(options::TABLE) Arg::new(options::TABLE)
.short('t') .short('t')
.short_alias('L')
.long(options::TABLE) .long(options::TABLE)
.help("Lists table of signals"), .help("Lists table of signals"),
) )
.arg(Arg::new(options::TABLE_OLD).short('L').hide(true))
.arg( .arg(
Arg::new(options::SIGNAL) Arg::new(options::SIGNAL)
.short('s') .short('s')
@ -190,21 +194,21 @@ fn parse_signal_value(signal_name: &str) -> UResult<usize> {
} }
} }
fn parse_pids(pids: &[String]) -> UResult<Vec<usize>> { fn parse_pids(pids: &[String]) -> UResult<Vec<i32>> {
pids.iter() pids.iter()
.map(|x| { .map(|x| {
x.parse::<usize>().map_err(|e| { x.parse::<i32>().map_err(|e| {
USimpleError::new(1, format!("failed to parse argument {}: {}", x.quote(), e)) USimpleError::new(1, format!("failed to parse argument {}: {}", x.quote(), e))
}) })
}) })
.collect() .collect()
} }
fn kill(signal_value: usize, pids: &[usize]) -> UResult<()> { fn kill(sig: Signal, pids: &[i32]) {
for &pid in pids { for &pid in pids {
if unsafe { libc::kill(pid as pid_t, signal_value as c_int) } != 0 { if let Err(e) = signal::kill(Pid::from_raw(pid), sig) {
show!(USimpleError::new(1, format!("{}", Error::last_os_error()))); show!(Error::from_raw_os_error(e as i32)
.map_err_context(|| format!("sending signal to {} failed", pid)));
} }
} }
Ok(())
} }