Repository: uutils/procps (rust)

Issue:
pidof: When multiple program names are specified, `-s` should return multiple PIDs
The original `pidof` returns a PID for each specified program name whereas our `pidof` returns a single PID.
```
$ pidof -s bash bash bash
9024 9024 9024

$ cargo run pidof -s bash bash bash
9024
```

Pull request:
pidof: Return multiple PIDs while multiple program
fix #118

This commit fixed `-s` flag only output one result.

Before this commit:

```shell
❯ cargo run pidof -s zsh zsh zsh
218159
```

After:

```shell
❯ cargo run pidof -s zsh zsh zsh
218159 218159 218159
```

The behavior of uutils' implementation are as same as GNU's implementation now.

```shell
❯ cargo run pidof -s zsh zsh zsh
218159 218159 218159

❯ pidof -s zsh zsh zsh
218159 218159 218159
```

Patch:
diff --git a/src/uu/pidof/src/pidof.rs b/src/uu/pidof/src/pidof.rs
index dd71936..70d2d76 100644
--- a/src/uu/pidof/src/pidof.rs
+++ b/src/uu/pidof/src/pidof.rs
@@ -75,27 +75,32 @@ fn collect_matched_pids(matches: &ArgMatches) -> Vec<ProcessInformation> {
         .copied()
         .collect::<Vec<_>>();
 
-    let mut processed = Vec::new();
-    for mut process in collected {
-        let contains = program_names.contains(&get_executable_name(&mut process));
-        let should_omit = arg_omit_pid.contains(&process.pid);
-
-        if contains && !should_omit {
-            processed.push(process)
-        }
-    }
-
-    processed.sort_by(|a, b| b.pid.cmp(&a.pid));
-
-    let flag_s = matches.get_flag("s");
-    if flag_s {
-        match processed.first() {
-            Some(first) => vec![first.clone()],
-            None => Vec::new(),
-        }
-    } else {
-        processed
-    }
+    program_names
+        .into_iter()
+        .flat_map(|program| {
+            let mut processed = Vec::new();
+            for mut process in collected.clone() {
+                let contains = program == get_executable_name(&mut process);
+                let should_omit = arg_omit_pid.contains(&process.pid);
+
+                if contains && !should_omit {
+                    processed.push(process)
+                }
+            }
+
+            processed.sort_by(|a, b| b.pid.cmp(&a.pid));
+
+            let flag_s = matches.get_flag("s");
+            if flag_s {
+                match processed.first() {
+                    Some(first) => vec![first.clone()],
+                    None => Vec::new(),
+                }
+            } else {
+                processed
+            }
+        })
+        .collect()
 }
 
 #[allow(clippy::cognitive_complexity)]


Test patch:
diff --git a/tests/by-util/test_pidof.rs b/tests/by-util/test_pidof.rs
index c06c4bc..94f6e5f 100644
--- a/tests/by-util/test_pidof.rs
+++ b/tests/by-util/test_pidof.rs
@@ -39,3 +39,20 @@ fn test_no_pid_found() {
 fn test_quiet() {
     new_ucmd!().arg("kthreadd").arg("-q").succeeds().no_output();
 }
+
+#[test]
+#[cfg(target_os = "linux")]
+fn test_s_flag() {
+    let binding = new_ucmd!()
+        .args(&["-s", "kthreadd", "kthreadd", "kthreadd"])
+        .succeeds();
+    let output = binding.stdout_str().trim_end();
+
+    let pids = output.split(' ').collect::<Vec<_>>();
+    let first = pids[0];
+
+    let result = pids.iter().all(|it| *it == first);
+
+    assert!(result);
+    assert_eq!(pids.len(), 3);
+}