Skip to content

Commit c4f18be

Browse files
authored
Merge pull request #457 from Bluemangoo/feature/pkill-queue
pkill: implement `--queue`
2 parents 353a2a6 + 3d5bcda commit c4f18be

File tree

2 files changed

+49
-15
lines changed

2 files changed

+49
-15
lines changed

src/uu/pkill/src/pkill.rs

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// file that was distributed with this source code.
55

66
// Pid utils
7-
use clap::{arg, crate_version, Command};
7+
use clap::{arg, crate_version, value_parser, Command};
88
#[cfg(unix)]
99
use nix::{
1010
sys::signal::{self, Signal},
@@ -48,19 +48,21 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
4848
} else {
4949
let sig = (settings.signal as i32)
5050
.try_into()
51-
.map_err(|e| std::io::Error::from_raw_os_error(e as i32))?;
51+
.map_err(|e| Error::from_raw_os_error(e as i32))?;
5252
Some(sig)
5353
};
5454

5555
// Collect pids
5656
let pids = process_matcher::find_matching_pids(&settings)?;
5757

5858
// Send signal
59-
// TODO: Implement -q
6059
#[cfg(unix)]
61-
let echo = matches.get_flag("echo");
62-
#[cfg(unix)]
63-
kill(&pids, sig, echo);
60+
{
61+
let echo = matches.get_flag("echo");
62+
let queue = matches.get_one::<u32>("queue").cloned();
63+
64+
kill(&pids, sig, queue, echo);
65+
}
6466

6567
if matches.get_flag("count") {
6668
println!("{}", pids.len());
@@ -71,25 +73,50 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
7173

7274
#[cfg(unix)]
7375
fn handle_obsolete(args: &mut [String]) {
74-
// Sanity check
75-
if args.len() > 2 {
76-
// Old signal can only be in the first argument position
77-
let slice = args[1].as_str();
78-
if let Some(signal) = slice.strip_prefix('-') {
76+
for arg in &mut args[1..] {
77+
if let Some(signal) = arg.strip_prefix('-') {
7978
// Check if it is a valid signal
8079
let opt_signal = signal_by_name_or_value(signal);
8180
if opt_signal.is_some() {
8281
// Replace with long option that clap can parse
83-
args[1] = format!("--signal={signal}");
82+
*arg = format!("--signal={signal}");
8483
}
8584
}
8685
}
8786
}
8887

88+
// Not contains in libc
89+
#[cfg(target_os = "linux")]
90+
extern "C" {
91+
fn sigqueue(
92+
pid: uucore::libc::pid_t,
93+
sig: uucore::libc::c_int,
94+
val: uucore::libc::sigval,
95+
) -> uucore::libc::c_int;
96+
}
97+
8998
#[cfg(unix)]
90-
fn kill(pids: &Vec<ProcessInformation>, sig: Option<Signal>, echo: bool) {
99+
#[allow(unused_variables)]
100+
fn kill(pids: &Vec<ProcessInformation>, sig: Option<Signal>, queue: Option<u32>, echo: bool) {
91101
for pid in pids {
92-
if let Err(e) = signal::kill(Pid::from_raw(pid.pid as i32), sig) {
102+
#[cfg(target_os = "linux")]
103+
let result = if let Some(queue) = queue {
104+
let v = unsafe {
105+
sigqueue(
106+
pid.pid as i32,
107+
sig.map_or(0, |s| s as uucore::libc::c_int),
108+
uucore::libc::sigval {
109+
sival_ptr: queue as usize as *mut uucore::libc::c_void,
110+
},
111+
)
112+
};
113+
nix::errno::Errno::result(v).map(drop)
114+
} else {
115+
signal::kill(Pid::from_raw(pid.pid as i32), sig)
116+
};
117+
#[cfg(not(target_os = "linux"))]
118+
let result = signal::kill(Pid::from_raw(pid.pid as i32), sig);
119+
if let Err(e) = result {
93120
show!(Error::from_raw_os_error(e as i32)
94121
.map_err_context(|| format!("killing pid {} failed", pid.pid)));
95122
} else if echo {
@@ -111,7 +138,8 @@ pub fn uu_app() -> Command {
111138
.args_override_self(true)
112139
.args([
113140
// arg!(-<sig> "signal to send (either number or name)"),
114-
// arg!(-q --queue <value> "integer value to be sent with the signal"),
141+
arg!(-q --queue <value> "integer value to be sent with the signal")
142+
.value_parser(value_parser!(u32)),
115143
arg!(-e --echo "display what is killed"),
116144
])
117145
.args(process_matcher::clap_args(

tests/by-util/test_pkill.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,9 @@ fn test_too_long_pattern() {
7474
.code_is(1)
7575
.stderr_contains("pattern that searches for process name longer than 15 characters will result in zero matches");
7676
}
77+
78+
#[test]
79+
#[cfg(target_os = "linux")]
80+
fn test_invalid_queue() {
81+
new_ucmd!().args(&["-q"]).fails().code_is(1);
82+
}

0 commit comments

Comments
 (0)