[PATCH] ps: add basic -p <pid> option
Sertonix
sertonix at posteo.net
Thu Jul 4 10:57:08 UTC 2024
This implementation only supports specifying a single pid.
function old new delta
format_process - 176 +176
.rodata 100714 100751 +37
packed_usage 34927 34959 +32
procps_scan 1193 1205 +12
top_main 1115 1117 +2
pstree_main 375 377 +2
process_action 1204 1206 +2
pgrep_main 781 783 +2
lsof_main 279 281 +2
kill_main 1035 1037 +2
find_pid_by_name 262 264 +2
ps_main 692 634 -58
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 10/1 up/down: 271/-58) Total: 213 bytes
text data bss dec hex filename
1040876 16443 1840 1059159 102957 busybox_old
1041089 16443 1840 1059372 102a2c busybox_unstripped
Signed-off-by: Sertonix <sertonix at posteo.net>
---
include/libbb.h | 3 ++-
libbb/find_pid_by_name.c | 2 +-
libbb/procps.c | 11 +++++++----
procps/kill.c | 2 +-
procps/lsof.c | 2 +-
procps/pgrep.c | 2 +-
procps/ps.c | 28 ++++++++++++++++++++--------
procps/pstree.c | 2 +-
procps/top.c | 2 +-
util-linux/mdev.c | 2 +-
10 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/include/libbb.h b/include/libbb.h
index 01cdb1bdc..64572ff56 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2132,10 +2132,11 @@ enum {
PSSCAN_NICE = (1 << 20) * ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS,
PSSCAN_RUIDGID = (1 << 21) * ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS,
PSSCAN_TASKS = (1 << 22) * ENABLE_FEATURE_SHOW_THREADS,
+ PSSCAN_FILTER = (1 << 23),
};
//procps_status_t* alloc_procps_scan(void) FAST_FUNC;
void free_procps_scan(procps_status_t* sp) FAST_FUNC;
-procps_status_t* procps_scan(procps_status_t* sp, int flags) FAST_FUNC;
+procps_status_t* procps_scan(procps_status_t* sp, int flags, unsigned pid) FAST_FUNC;
/* Format cmdline (up to col chars) into char buf[size] */
/* Puts [comm] if cmdline is empty (-> process is a kernel thread) */
void read_cmdline(char *buf, int size, unsigned pid, const char *comm) FAST_FUNC;
diff --git a/libbb/find_pid_by_name.c b/libbb/find_pid_by_name.c
index fe13f7211..021b132ab 100644
--- a/libbb/find_pid_by_name.c
+++ b/libbb/find_pid_by_name.c
@@ -85,7 +85,7 @@ pid_t* FAST_FUNC find_pid_by_name(const char *procName)
procps_status_t* p = NULL;
pidList = xzalloc(sizeof(*pidList));
- while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN|PSSCAN_EXE))) {
+ while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN|PSSCAN_EXE, 0))) {
if (comm_match(p, procName)
/* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/
|| (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0)
diff --git a/libbb/procps.c b/libbb/procps.c
index f56b71b21..fe1798cf6 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -92,6 +92,7 @@ static procps_status_t* FAST_FUNC alloc_procps_scan(void)
}
sp->shift_pages_to_kb = sp->shift_pages_to_bytes - 10;
sp->dir = xopendir("/proc");
+ sp->pid = 0;
return sp;
}
@@ -279,16 +280,18 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
}
#endif
-procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
+procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags, unsigned pid)
{
if (!sp)
sp = alloc_procps_scan();
+ if (pid)
+ goto got_pid;
+
for (;;) {
struct dirent *entry;
char buf[PROCPS_BUFSIZE];
long tasknice;
- unsigned pid;
int n;
char filename[sizeof("/proc/%u/task/%u/cmdline") + sizeof(int)*3 * 2];
char *filename_tail;
@@ -302,8 +305,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
sp->task_dir = NULL;
}
#endif
- entry = readdir(sp->dir);
- if (entry == NULL) {
+ if ((flags & PSSCAN_FILTER) || (entry = readdir(sp->dir)) == NULL) {
free_procps_scan(sp);
return NULL;
}
@@ -311,6 +313,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
pid = bb_strtou(entry->d_name, NULL, 10);
if (errno)
continue;
+ got_pid:
#if ENABLE_FEATURE_SHOW_THREADS
if ((flags & PSSCAN_TASKS) && !sp->task_dir) {
/* We found another /proc/PID. Do not use it,
diff --git a/procps/kill.c b/procps/kill.c
index d4be18dd8..9be7350f4 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -219,7 +219,7 @@ int kill_main(int argc UNUSED_PARAM, char **argv)
if (signo != SIGSTOP && signo != SIGCONT)
kill(-1, SIGSTOP);
/* Signal all processes except those in our session */
- while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID)) != NULL) {
+ while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID, 0)) != NULL) {
char **args;
if (p->sid == (unsigned)sid
diff --git a/procps/lsof.c b/procps/lsof.c
index 57e385c3f..28f804fae 100644
--- a/procps/lsof.c
+++ b/procps/lsof.c
@@ -46,7 +46,7 @@ int lsof_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
{
procps_status_t *proc = NULL;
- while ((proc = procps_scan(proc, PSSCAN_PID|PSSCAN_EXE)) != NULL) {
+ while ((proc = procps_scan(proc, PSSCAN_PID|PSSCAN_EXE, 0)) != NULL) {
char name[sizeof("/proc/%u/fd/0123456789") + sizeof(int)*3];
unsigned baseofs;
DIR *d_fd;
diff --git a/procps/pgrep.c b/procps/pgrep.c
index 04ae92a67..587ca4db6 100644
--- a/procps/pgrep.c
+++ b/procps/pgrep.c
@@ -164,7 +164,7 @@ int pgrep_main(int argc UNUSED_PARAM, char **argv)
matched_pid = 0;
cmd_last = NULL;
proc = NULL;
- while ((proc = procps_scan(proc, scan_mask)) != NULL) {
+ while ((proc = procps_scan(proc, scan_mask, 0)) != NULL) {
char *cmd;
int cmdlen, match;
diff --git a/procps/ps.c b/procps/ps.c
index 5b521aebd..337a13cd0 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -59,10 +59,11 @@
//usage:#if ENABLE_DESKTOP
//usage:
//usage:#define ps_trivial_usage
-//usage: "[-o COL1,COL2=HEADER]" IF_FEATURE_SHOW_THREADS(" [-T]")
+//usage: "[-o COL1,COL2=HEADER] [-p PID]" IF_FEATURE_SHOW_THREADS(" [-T]")
//usage:#define ps_full_usage "\n\n"
//usage: "Show list of processes\n"
//usage: "\n -o COL1,COL2=HEADER Select columns for display"
+//usage: "\n -p PID Select pid to show"
//usage: IF_FEATURE_SHOW_THREADS(
//usage: "\n -T Show threads"
//usage: )
@@ -553,10 +554,9 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
{
procps_status_t *p;
llist_t* opt_o = NULL;
+ unsigned opt_p = 0;
char default_o[sizeof(DEFAULT_O_STR)];
-#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS
int opt;
-#endif
enum {
OPT_Z = (1 << 0),
OPT_o = (1 << 1),
@@ -566,7 +566,8 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
OPT_e = (1 << 5),
OPT_f = (1 << 6),
OPT_l = (1 << 7),
- OPT_T = (1 << 8) * ENABLE_FEATURE_SHOW_THREADS,
+ OPT_p = (1 << 8),
+ OPT_T = (1 << 9) * ENABLE_FEATURE_SHOW_THREADS,
};
INIT_G();
@@ -592,10 +593,8 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
* procps v3.2.7 supports -T and shows tids as SPID column,
* it also supports -L where it shows tids as LWP column.
*/
-#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS
opt =
-#endif
- getopt32(argv, "Zo:*aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o);
+ getopt32(argv, "Zo:*aAdeflp:+"IF_FEATURE_SHOW_THREADS("T"), &opt_o, &opt_p);
if (opt_o) {
do {
@@ -633,7 +632,20 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
format_header();
p = NULL;
- while ((p = procps_scan(p, need_flags)) != NULL) {
+ if (opt & OPT_p) {
+ if (!opt_p)
+ bb_error_msg_and_die("bad -p argument, pid out of range");
+ need_flags |= PSSCAN_FILTER;
+ if ((p = procps_scan(p, need_flags, opt_p)) == NULL)
+ return EXIT_FAILURE;
+ format_process(p);
+#if ENABLE_FEATURE_SHOW_THREADS
+ if (!(opt & OPT_T))
+#endif
+ return EXIT_SUCCESS;
+ }
+
+ while ((p = procps_scan(p, need_flags, 0)) != NULL) {
format_process(p);
}
diff --git a/procps/pstree.c b/procps/pstree.c
index bf6ceed5a..9d3da9446 100644
--- a/procps/pstree.c
+++ b/procps/pstree.c
@@ -361,7 +361,7 @@ static void mread_proc(void)
#endif
int flags = PSSCAN_COMM | PSSCAN_PID | PSSCAN_PPID | PSSCAN_UIDGID | PSSCAN_TASKS;
- while ((p = procps_scan(p, flags)) != NULL) {
+ while ((p = procps_scan(p, flags, 0)) != NULL) {
#if ENABLE_FEATURE_SHOW_THREADS
if (p->pid != p->main_thread_pid)
handle_thread(p->comm, p->pid, parent, p->uid);
diff --git a/procps/top.c b/procps/top.c
index 09d31c673..87c392a12 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -1247,7 +1247,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
/* read process IDs & status for all the processes */
ntop = 0;
- while ((p = procps_scan(p, scan_mask)) != NULL) {
+ while ((p = procps_scan(p, scan_mask, 0)) != NULL) {
int n;
IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) {
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index e98d46743..7ab7a191d 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -1058,7 +1058,7 @@ wait_for_seqfile(unsigned expected_seq)
static void signal_mdevs(unsigned my_pid)
{
procps_status_t* p = NULL;
- while ((p = procps_scan(p, PSSCAN_ARGV0)) != NULL) {
+ while ((p = procps_scan(p, PSSCAN_ARGV0, 0)) != NULL) {
if (p->pid != my_pid
&& p->argv0
&& strcmp(bb_basename(p->argv0), "mdev") == 0
--
2.45.2
More information about the busybox
mailing list