Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Aug 2023 16:37:10 GMT
From:      Piotr Pawel Stefaniak <pstef@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 5c0a1c15ff8c - main - ps: add a new option -D to reimplement tree traversal
Message-ID:  <202308241637.37OGbAfl011165@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by pstef:

URL: https://cgit.FreeBSD.org/src/commit/?id=5c0a1c15ff8cb66128f4826ace8ba91e0a31486d

commit 5c0a1c15ff8cb66128f4826ace8ba91e0a31486d
Author:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
AuthorDate: 2023-08-24 16:29:46 +0000
Commit:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
CommitDate: 2023-08-24 16:35:56 +0000

    ps: add a new option -D to reimplement tree traversal
    
    It takes a non-optional parameter string, one of "up", "down", or "both"
    that can request tree traversal in the chosen directions. This adds PIDs
    from the paths to the selection of PIDs and can be used together with -d
    to draw a subset of the process tree.
    
    Differential Revision:  https://reviews.freebsd.org/D41231
---
 bin/ps/ps.1 | 15 ++++++++++++++-
 bin/ps/ps.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/bin/ps/ps.1 b/bin/ps/ps.1
index 5fdecc4a3d4c..23868d8b3009 100644
--- a/bin/ps/ps.1
+++ b/bin/ps/ps.1
@@ -28,7 +28,7 @@
 .\"
 .\"     @(#)ps.1	8.3 (Berkeley) 4/18/94
 .\"
-.Dd April 25, 2023
+.Dd August 24, 2023
 .Dt PS 1
 .Os
 .Sh NAME
@@ -39,6 +39,7 @@
 .Op Fl -libxo
 .Op Fl aCcdefHhjlmrSTuvwXxZ
 .Op Fl O Ar fmt | Fl o Ar fmt
+.Op Fl D Ar up | down | both
 .Op Fl G Ar gid Ns Op , Ns Ar gid Ns Ar ...
 .Op Fl J Ar jid Ns Op , Ns Ar jid Ns Ar ...
 .Op Fl M Ar core
@@ -146,6 +147,18 @@ relative to each other.
 Note that this option has no effect if the
 .Dq command
 column is not the last column displayed.
+.It Fl D
+Expand the list of selected processes based on the process tree.
+.Dq UP
+will add the ancestor processes,
+.Dq DOWN
+will add the descendant processes, and
+.Dq BOTH
+will add both the ancestor and the descendant processes.
+.Fl D
+does not imply
+.Fl d ,
+but works well with it.
 .It Fl e
 Display the environment as well.
 .It Fl f
diff --git a/bin/ps/ps.c b/bin/ps/ps.c
index 8554a2eaa0a2..3a7a0f54cca0 100644
--- a/bin/ps/ps.c
+++ b/bin/ps/ps.c
@@ -168,7 +168,7 @@ static char vfmt[] = "pid,state,time,sl,re,pagein,vsz,rss,lim,tsiz,"
 			"%cpu,%mem,command";
 static char Zfmt[] = "label";
 
-#define	PS_ARGS	"AaCcde" OPT_LAZY_f "G:gHhjJ:LlM:mN:O:o:p:rSTt:U:uvwXxZ"
+#define	PS_ARGS	"AaCcD:de" OPT_LAZY_f "G:gHhjJ:LlM:mN:O:o:p:rSTt:U:uvwXxZ"
 
 int
 main(int argc, char *argv[])
@@ -188,6 +188,8 @@ main(int argc, char *argv[])
 	int fwidthmin, fwidthmax;
 	char errbuf[_POSIX2_LINE_MAX];
 	char fmtbuf[_POSIX2_LINE_MAX];
+	enum { NONE = 0, UP = 1, DOWN = 2, BOTH = 1 | 2 } directions = NONE;
+	struct { int traversed; int initial; } pid_count;
 
 	(void) setlocale(LC_ALL, "");
 	time(&now);			/* Used by routines in print.c. */
@@ -262,6 +264,20 @@ main(int argc, char *argv[])
 		case 'c':
 			cflag = 1;
 			break;
+		case 'D': {
+				size_t len = strlen(optarg);
+
+				if (len <= 2 &&
+					strncasecmp(optarg, "up", len) == 0)
+					directions |= UP;
+				else if (len <= 4 &&
+					strncasecmp(optarg, "down", len) == 0)
+					directions |= DOWN;
+				else if (len <= 4 &&
+					strncasecmp(optarg, "both", len) == 0)
+					directions |= BOTH;
+				break;
+			}
 		case 'd':
 			descendancy = 1;
 			break;
@@ -502,7 +518,7 @@ main(int argc, char *argv[])
 			what = KERN_PROC_PGRP | showthreads;
 			flag = *pgrplist.l.pids;
 			nselectors = 0;
-		} else if (pidlist.count == 1) {
+		} else if (pidlist.count == 1 && directions == NONE) {
 			what = KERN_PROC_PID | showthreads;
 			flag = *pidlist.l.pids;
 			nselectors = 0;
@@ -537,6 +553,33 @@ main(int argc, char *argv[])
 	if ((kp == NULL && errno != ESRCH) || (kp != NULL && nentries < 0))
 		xo_errx(1, "%s", kvm_geterr(kd));
 	nkept = 0;
+	pid_count.initial = pidlist.count;
+	if (directions & DOWN)
+		for (elem = 0; elem < pidlist.count; elem++)
+			for (i = 0; i < nentries; i++) {
+				if (kp[i].ki_ppid == kp[i].ki_pid)
+					continue;
+				if (kp[i].ki_ppid == pidlist.l.pids[elem]) {
+					if (pidlist.count >= pidlist.maxcount)
+						expand_list(&pidlist);
+					pidlist.l.pids[pidlist.count++] = kp[i].ki_pid;
+				}
+			}
+	pid_count.traversed = pidlist.count;
+	if (directions & UP)
+		for (elem = 0; elem < pidlist.count; elem++) {
+			if (elem >= pid_count.initial && elem < pid_count.traversed)
+				continue;
+			for (i = 0; i < nentries; i++) {
+				if (kp[i].ki_ppid == kp[i].ki_pid)
+					continue;
+				if (kp[i].ki_pid == pidlist.l.pids[elem]) {
+					if (pidlist.count >= pidlist.maxcount)
+						expand_list(&pidlist);
+					pidlist.l.pids[pidlist.count++] = kp[i].ki_ppid;
+				}
+			}
+		}
 	if (nentries > 0) {
 		if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL)
 			xo_errx(1, "malloc failed");
@@ -1448,10 +1491,11 @@ usage(void)
 {
 #define	SINGLE_OPTS	"[-aCcde" OPT_LAZY_f "HhjlmrSTuvwXxZ]"
 
-	(void)xo_error("%s\n%s\n%s\n%s\n",
+	(void)xo_error("%s\n%s\n%s\n%s\n%s\n",
 	    "usage: ps [--libxo] " SINGLE_OPTS " [-O fmt | -o fmt]",
 	    "          [-G gid[,gid...]] [-J jid[,jid...]] [-M core] [-N system]",
 	    "          [-p pid[,pid...]] [-t tty[,tty...]] [-U user[,user...]]",
+	    "          [-D up | down | both]",
 	    "       ps [--libxo] -L");
 	exit(1);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202308241637.37OGbAfl011165>