Skip to content

Commit

Permalink
pgrep: Support --signal and --require-handler
Browse files Browse the repository at this point in the history
This is not listed in pgrep --help, but is documented in the man page
and does work. Unlike pkill the -SIGNAL short option is not supported by
pgrep.
  • Loading branch information
dezgeg committed Feb 11, 2025
1 parent 2d0b842 commit 5ba8e29
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
29 changes: 28 additions & 1 deletion src/uu/pgrep/src/pgrep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use clap::{arg, crate_version, Arg, ArgAction, ArgGroup, ArgMatches, Command};
use process::{walk_process, ProcessInformation, Teletype};
use regex::Regex;
use std::{collections::HashSet, sync::OnceLock};
#[cfg(unix)]
use uucore::{display::Quotable, signals::signal_by_name_or_value};
use uucore::{
error::{UResult, USimpleError},
format_usage, help_about, help_usage,
Expand Down Expand Up @@ -87,9 +89,21 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
));
}

// Parse signal
#[cfg(unix)]
let sig_num = parse_signal_value(matches.get_one::<String>("signal").unwrap())?;

// Collect pids
let pids = {
let mut pids = collect_matched_pids(&settings);
#[cfg(unix)]
if matches.get_flag("require-handler") {
pids.retain(|pid| {
let mask =
u64::from_str_radix(pid.clone().status().get("SigCgt").unwrap(), 16).unwrap();
mask & (1 << sig_num) != 0
});
}
if pids.is_empty() {
uucore::error::set_exit_code(1);
pids
Expand Down Expand Up @@ -275,6 +289,17 @@ fn process_flag_o_n(
}
}

#[cfg(unix)]
fn parse_signal_value(signal_name: &str) -> UResult<usize> {
let optional_signal_value = signal_by_name_or_value(signal_name);
match optional_signal_value {
Some(x) => Ok(x),
None => Err(USimpleError::new(
1,
format!("Unknown signal {}", signal_name.quote()),
)),
}
}
#[allow(clippy::cognitive_complexity)]
pub fn uu_app() -> Command {
Command::new(uucore::util_name())
Expand All @@ -289,6 +314,7 @@ pub fn uu_app() -> Command {
.hide_default_value(true),
arg!(-l --"list-name" "list PID and process name"),
arg!(-a --"list-full" "list PID and full command line"),
arg!(-H --"require-handler" "match only if signal handler is present"),
arg!(-v --inverse "negates the matching"),
// arg!(-w --lightweight "list all TID"),
arg!(-c --count "count of matching processes"),
Expand All @@ -310,7 +336,8 @@ pub fn uu_app() -> Command {
// arg!(-s --session <SID> "match session IDs")
// .value_delimiter(',')
// .value_parser(clap::value_parser!(u64)),
// arg!(--signal <sig> "signal to send (either number or name)"),
arg!(--signal <sig> "signal to send (either number or name)")
.default_value("SIGTERM"),
arg!(-t --terminal <tty> "match by controlling terminal")
.value_delimiter(','),
// arg!(-u --euid <ID> ... "match by effective IDs")
Expand Down
20 changes: 20 additions & 0 deletions tests/by-util/test_pgrep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,23 @@ fn test_parent_non_matching_parent() {
.code_is(1)
.no_output();
}

#[test]
#[cfg(target_os = "linux")]
fn test_require_handler() {
new_ucmd!()
.arg("--require-handler")
.arg("--signal=INT")
.arg("NONEXISTENT")
.fails();
}

#[test]
#[cfg(target_os = "linux")]
fn test_invalid_signal() {
new_ucmd!()
.arg("--signal=foo")
.arg("NONEXISTENT")
.fails()
.stderr_contains("Unknown signal 'foo'");
}

0 comments on commit 5ba8e29

Please sign in to comment.