Skip to content

Commit 6dd29c5

Browse files
committed
process_matcher: Add support for --pgroup and --session
1 parent cb6a977 commit 6dd29c5

File tree

2 files changed

+100
-6
lines changed

2 files changed

+100
-6
lines changed

src/uu/pgrep/src/process_matcher.rs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use std::{collections::HashSet, io};
1111
use clap::{arg, Arg, ArgAction, ArgMatches};
1212
use regex::Regex;
1313
#[cfg(unix)]
14+
use uucore::libc::{getpgrp, getsid};
15+
#[cfg(unix)]
1416
use uucore::{
1517
display::Quotable,
1618
entries::{grp2gid, usr2uid},
@@ -40,6 +42,8 @@ pub struct Settings {
4042
pub uid: Option<HashSet<u32>>,
4143
pub euid: Option<HashSet<u32>>,
4244
pub gid: Option<HashSet<u32>>,
45+
pub pgroup: Option<HashSet<u64>>,
46+
pub session: Option<HashSet<u64>>,
4347
}
4448

4549
pub fn get_match_settings(matches: &ArgMatches) -> UResult<Settings> {
@@ -76,6 +80,26 @@ pub fn get_match_settings(matches: &ArgMatches) -> UResult<Settings> {
7680
gid: matches
7781
.get_many::<u32>("group")
7882
.map(|ids| ids.cloned().collect()),
83+
pgroup: matches.get_many::<u64>("pgroup").map(|xs| {
84+
xs.map(|pg| {
85+
if *pg == 0 {
86+
unsafe { getpgrp() as u64 }
87+
} else {
88+
*pg
89+
}
90+
})
91+
.collect()
92+
}),
93+
session: matches.get_many::<u64>("session").map(|xs| {
94+
xs.map(|sid| {
95+
if *sid == 0 {
96+
unsafe { getsid(0) as u64 }
97+
} else {
98+
*sid
99+
}
100+
})
101+
.collect()
102+
}),
79103
};
80104

81105
if !settings.newest
@@ -87,6 +111,8 @@ pub fn get_match_settings(matches: &ArgMatches) -> UResult<Settings> {
87111
&& settings.uid.is_none()
88112
&& settings.euid.is_none()
89113
&& settings.gid.is_none()
114+
&& settings.pgroup.is_none()
115+
&& settings.session.is_none()
90116
&& pattern.is_empty()
91117
{
92118
return Err(USimpleError::new(
@@ -207,6 +233,8 @@ fn collect_matched_pids(settings: &Settings) -> Vec<ProcessInformation> {
207233
let older_matched = pid.start_time().unwrap() >= arg_older;
208234

209235
let parent_matched = any_matches(&settings.parent, pid.ppid().unwrap());
236+
let pgroup_matched = any_matches(&settings.pgroup, pid.pgid().unwrap());
237+
let session_matched = any_matches(&settings.session, pid.sid().unwrap());
210238

211239
let ids_matched = any_matches(&settings.uid, pid.uid().unwrap())
212240
&& any_matches(&settings.euid, pid.euid().unwrap())
@@ -217,6 +245,8 @@ fn collect_matched_pids(settings: &Settings) -> Vec<ProcessInformation> {
217245
&& tty_matched
218246
&& older_matched
219247
&& parent_matched
248+
&& pgroup_matched
249+
&& session_matched
220250
&& ids_matched)
221251
^ settings.inverse
222252
{
@@ -290,6 +320,22 @@ pub fn grp2gid(_name: &str) -> io::Result<u32> {
290320
))
291321
}
292322

323+
/// # Safety
324+
///
325+
/// Dummy implementation for unsupported platforms.
326+
#[cfg(not(unix))]
327+
pub unsafe fn getpgrp() -> u32 {
328+
panic!("unsupported on this platform");
329+
}
330+
331+
/// # Safety
332+
///
333+
/// Dummy implementation for unsupported platforms.
334+
#[cfg(not(unix))]
335+
pub unsafe fn getsid(_pid: u32) -> u32 {
336+
panic!("unsupported on this platform");
337+
}
338+
293339
fn parse_uid_or_username(uid_or_username: &str) -> io::Result<u32> {
294340
uid_or_username
295341
.parse::<u32>()
@@ -315,9 +361,9 @@ pub fn clap_args(pattern_help: &'static str, enable_v_flag: bool) -> Vec<Arg> {
315361
arg!(-H --"require-handler" "match only if signal handler is present"),
316362
arg!(-c --count "count of matching processes"),
317363
arg!(-f --full "use full process name to match"),
318-
// arg!(-g --pgroup <PGID> "match listed process group IDs")
319-
// .value_delimiter(',')
320-
// .value_parser(clap::value_parser!(u64)),
364+
arg!(-g --pgroup <PGID> "match listed process group IDs")
365+
.value_delimiter(',')
366+
.value_parser(clap::value_parser!(u64)),
321367
arg!(-G --group <GID> "match real group IDs")
322368
.value_delimiter(',')
323369
.value_parser(parse_gid_or_group_name),
@@ -331,9 +377,9 @@ pub fn clap_args(pattern_help: &'static str, enable_v_flag: bool) -> Vec<Arg> {
331377
arg!(-P --parent <PPID> "match only child processes of the given parent")
332378
.value_delimiter(',')
333379
.value_parser(clap::value_parser!(u64)),
334-
// arg!(-s --session <SID> "match session IDs")
335-
// .value_delimiter(',')
336-
// .value_parser(clap::value_parser!(u64)),
380+
arg!(-s --session <SID> "match session IDs")
381+
.value_delimiter(',')
382+
.value_parser(clap::value_parser!(u64)),
337383
arg!(--signal <sig> "signal to send (either number or name)")
338384
.default_value("SIGTERM"),
339385
arg!(-t --terminal <tty> "match by controlling terminal").value_delimiter(','),

tests/by-util/test_pgrep.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,51 @@ fn test_does_not_match_current_process() {
430430
.fails()
431431
.no_output();
432432
}
433+
434+
#[test]
435+
#[cfg(target_os = "linux")]
436+
fn test_pgroup() {
437+
let our_pid = std::process::id();
438+
let our_pgroup = unsafe { uucore::libc::getpgid(0) };
439+
new_ucmd!()
440+
.arg("--pgroup")
441+
.arg(our_pgroup.to_string())
442+
.succeeds()
443+
.stdout_contains(our_pid.to_string());
444+
445+
new_ucmd!()
446+
.arg("--pgroup")
447+
.arg("0")
448+
.succeeds()
449+
.stdout_contains(our_pid.to_string());
450+
}
451+
452+
#[test]
453+
#[cfg(target_os = "linux")]
454+
fn test_nonexisting_pgroup() {
455+
new_ucmd!().arg("--pgroup=9999999999").fails();
456+
}
457+
458+
#[test]
459+
#[cfg(target_os = "linux")]
460+
fn test_session() {
461+
let our_pid = std::process::id();
462+
let our_sid = unsafe { uucore::libc::getsid(0) };
463+
new_ucmd!()
464+
.arg("--session")
465+
.arg(our_sid.to_string())
466+
.succeeds()
467+
.stdout_contains(our_pid.to_string());
468+
469+
new_ucmd!()
470+
.arg("--session")
471+
.arg("0")
472+
.succeeds()
473+
.stdout_contains(our_pid.to_string());
474+
}
475+
476+
#[test]
477+
#[cfg(target_os = "linux")]
478+
fn test_nonexisting_session() {
479+
new_ucmd!().arg("--session=9999999999").fails();
480+
}

0 commit comments

Comments
 (0)