Dear all,
Some ps(1) implementations have an '-d' ('descendancy') option. Through
ASCII art parent/child process relationships are grouped and displayed.
Here is an example:
$ ps ad -O ppid,user
PID PPID USER TT STAT TIME COMMAND
18180 12529 job pb I+p 0:00.01 `-- -sh (sh)
26689 56460 job p3 Ip 0:00.01 `-- -ksh (ksh)
5153 26689 job p3 I+p 0:40.18 `-- mutt
62046 25272 job p4 Sp 0:00.25 `-- -ksh (ksh)
61156 62046 job p4 R+/0 0:00.00 `-- ps -ad -O ppid
26816 2565 job p5 Ip 0:00.01 `-- -ksh (ksh)
79431 26816 root p5 Ip 0:00.16 `-- /bin/ksh
43915 79431 _rpki-cl p5 S+pU 0:06.97 `-- rpki-client
70511 43915 _rpki-cl p5 I+pU 0:01.26 |-- rpki-client: parser
(rpki-client)
96992 43915 _rpki-cl p5 I+pU 0:00.00 |-- rpki-client: rsync
(rpki-client)
49160 43915 _rpki-cl p5 S+p 0:01.52 |-- rpki-client: http
(rpki-client)
99329 43915 _rpki-cl p5 S+p 0:03.20 `-- rpki-client: rrdp
(rpki-client)
The functionality is similar to pstree(1) in the ports collection.
The below changeset borrows heavily from the following two
implementations:
https://github.com/freebsd/freebsd-src/commit/044fce530f89a819827d351de364d208a30e9645.patch
https://github.com/NetBSD/src/commit/b82f6d00d93d880d3976c4f1e88c33d88a8054ad.patch
Thoughts?
Kind regards,
Job
Index: extern.h
===================================================================
RCS file: /cvs/src/bin/ps/extern.h,v
retrieving revision 1.23
diff -u -p -r1.23 extern.h
--- extern.h 5 Jan 2022 04:10:36 -0000 1.23
+++ extern.h 1 Sep 2022 03:31:36 -0000
@@ -44,44 +44,44 @@ extern VAR var[];
extern VARENT *vhead;
__BEGIN_DECLS
-void command(const struct kinfo_proc *, VARENT *);
-void cputime(const struct kinfo_proc *, VARENT *);
+void command(const struct pinfo *, VARENT *);
+void cputime(const struct pinfo *, VARENT *);
int donlist(void);
-void elapsed(const struct kinfo_proc *, VARENT *);
+void elapsed(const struct pinfo *, VARENT *);
double getpcpu(const struct kinfo_proc *);
-double getpmem(const struct kinfo_proc *);
-void gname(const struct kinfo_proc *, VARENT *);
-void supgid(const struct kinfo_proc *, VARENT *);
-void supgrp(const struct kinfo_proc *, VARENT *);
-void logname(const struct kinfo_proc *, VARENT *);
-void longtname(const struct kinfo_proc *, VARENT *);
-void lstarted(const struct kinfo_proc *, VARENT *);
-void maxrss(const struct kinfo_proc *, VARENT *);
+double getpmem(const struct pinfo *);
+void gname(const struct pinfo *, VARENT *);
+void supgid(const struct pinfo *, VARENT *);
+void supgrp(const struct pinfo *, VARENT *);
+void logname(const struct pinfo *, VARENT *);
+void longtname(const struct pinfo *, VARENT *);
+void lstarted(const struct pinfo *, VARENT *);
+void maxrss(const struct pinfo *, VARENT *);
void nlisterr(struct nlist *);
-void p_rssize(const struct kinfo_proc *, VARENT *);
-void pagein(const struct kinfo_proc *, VARENT *);
+void p_rssize(const struct pinfo *, VARENT *);
+void pagein(const struct pinfo *, VARENT *);
void parsefmt(char *);
-void pcpu(const struct kinfo_proc *, VARENT *);
-void pmem(const struct kinfo_proc *, VARENT *);
-void pri(const struct kinfo_proc *, VARENT *);
+void pcpu(const struct pinfo *, VARENT *);
+void pmem(const struct pinfo *, VARENT *);
+void pri(const struct pinfo *, VARENT *);
void printheader(void);
-void pvar(const struct kinfo_proc *kp, VARENT *);
-void pnice(const struct kinfo_proc *kp, VARENT *);
-void rgname(const struct kinfo_proc *, VARENT *);
-void rssize(const struct kinfo_proc *, VARENT *);
-void runame(const struct kinfo_proc *, VARENT *);
+void pvar(const struct pinfo *, VARENT *);
+void pnice(const struct pinfo *, VARENT *);
+void rgname(const struct pinfo *, VARENT *);
+void rssize(const struct pinfo *, VARENT *);
+void runame(const struct pinfo *, VARENT *);
void showkey(void);
-void started(const struct kinfo_proc *, VARENT *);
-void printstate(const struct kinfo_proc *, VARENT *);
-void printpledge(const struct kinfo_proc *, VARENT *);
-void tdev(const struct kinfo_proc *, VARENT *);
-void tname(const struct kinfo_proc *, VARENT *);
-void tsize(const struct kinfo_proc *, VARENT *);
-void dsize(const struct kinfo_proc *, VARENT *);
-void ssize(const struct kinfo_proc *, VARENT *);
-void ucomm(const struct kinfo_proc *, VARENT *);
-void curwd(const struct kinfo_proc *, VARENT *);
-void euname(const struct kinfo_proc *, VARENT *);
-void vsize(const struct kinfo_proc *, VARENT *);
-void wchan(const struct kinfo_proc *, VARENT *);
+void started(const struct pinfo *, VARENT *);
+void printstate(const struct pinfo *, VARENT *);
+void printpledge(const struct pinfo *, VARENT *);
+void tdev(const struct pinfo *, VARENT *);
+void tname(const struct pinfo *, VARENT *);
+void tsize(const struct pinfo *, VARENT *);
+void dsize(const struct pinfo *, VARENT *);
+void ssize(const struct pinfo *, VARENT *);
+void ucomm(const struct pinfo *, VARENT *);
+void curwd(const struct pinfo *, VARENT *);
+void euname(const struct pinfo *, VARENT *);
+void vsize(const struct pinfo *, VARENT *);
+void wchan(const struct pinfo *, VARENT *);
__END_DECLS
Index: print.c
===================================================================
RCS file: /cvs/src/bin/ps/print.c,v
retrieving revision 1.82
diff -u -p -r1.82 print.c
--- print.c 15 Feb 2022 23:16:00 -0000 1.82
+++ print.c 1 Sep 2022 03:31:36 -0000
@@ -96,8 +96,9 @@ printheader(void)
}
void
-command(const struct kinfo_proc *kp, VARENT *ve)
+command(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
int left, wantspace = 0;
char **p;
@@ -138,6 +139,8 @@ command(const struct kinfo_proc *kp, VAR
}
if (needcomm) {
+ if (pi->prefix)
+ mbswprint(pi->prefix, left, 0);
if (!commandonly) {
char **argv = NULL;
@@ -186,14 +189,16 @@ command(const struct kinfo_proc *kp, VAR
}
void
-ucomm(const struct kinfo_proc *kp, VARENT *ve)
+ucomm(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
mbswprint(kp->p_comm, ve->var->width, ve->next != NULL);
}
void
-curwd(const struct kinfo_proc *kp, VARENT *ve)
+curwd(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
int name[] = { CTL_KERN, KERN_PROC_CWD, kp->p_pid };
char path[PATH_MAX];
size_t pathlen = sizeof path;
@@ -205,8 +210,9 @@ curwd(const struct kinfo_proc *kp, VAREN
}
void
-logname(const struct kinfo_proc *kp, VARENT *ve)
+logname(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -223,8 +229,9 @@ logname(const struct kinfo_proc *kp, VAR
#define pgtok(a) (((unsigned long long)(a)*getpagesize())/1024)
void
-printstate(const struct kinfo_proc *kp, VARENT *ve)
+printstate(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
int flag;
char *cp, state = '\0';
VAR *v;
@@ -306,8 +313,9 @@ printstate(const struct kinfo_proc *kp,
}
void
-printpledge(const struct kinfo_proc *kp, VARENT *ve)
+printpledge(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
int i;
VAR *v;
char buf[1024];
@@ -327,8 +335,9 @@ printpledge(const struct kinfo_proc *kp,
}
void
-pri(const struct kinfo_proc *kp, VARENT *ve)
+pri(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -336,44 +345,55 @@ pri(const struct kinfo_proc *kp, VARENT
}
void
-pnice(const struct kinfo_proc *kp, VARENT *ve)
+pnice(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
+
v = ve->var;
(void)printf("%*d", v->width, kp->p_nice - NZERO);
}
void
-euname(const struct kinfo_proc *kp, VARENT *ve)
+euname(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
+
mbswprint(user_from_uid(kp->p_uid, 0), ve->var->width,
ve->next != NULL);
}
void
-runame(const struct kinfo_proc *kp, VARENT *ve)
+runame(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
+
mbswprint(user_from_uid(kp->p_ruid, 0), ve->var->width,
ve->next != NULL);
}
void
-gname(const struct kinfo_proc *kp, VARENT *ve)
+gname(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
+
mbswprint(group_from_gid(kp->p_gid, 0), ve->var->width,
ve->next != NULL);
}
void
-rgname(const struct kinfo_proc *kp, VARENT *ve)
+rgname(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
+
mbswprint(group_from_gid(kp->p_rgid, 0), ve->var->width,
ve->next != NULL);
}
void
-supgid(const struct kinfo_proc *kp, VARENT *ve)
+supgid(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
char buf[1024];
char *p = buf;
ssize_t size = sizeof(buf);
@@ -393,8 +413,9 @@ supgid(const struct kinfo_proc *kp, VARE
}
void
-supgrp(const struct kinfo_proc *kp, VARENT *ve)
+supgrp(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
char buf[1024];
char *p = buf;
ssize_t size = sizeof(buf);
@@ -414,8 +435,9 @@ supgrp(const struct kinfo_proc *kp, VARE
}
void
-tdev(const struct kinfo_proc *kp, VARENT *ve)
+tdev(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
dev_t dev;
@@ -433,8 +455,9 @@ tdev(const struct kinfo_proc *kp, VARENT
}
void
-tname(const struct kinfo_proc *kp, VARENT *ve)
+tname(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
dev_t dev;
char *ttname;
@@ -452,8 +475,9 @@ tname(const struct kinfo_proc *kp, VAREN
}
void
-longtname(const struct kinfo_proc *kp, VARENT *ve)
+longtname(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
dev_t dev;
char *ttname;
@@ -467,8 +491,9 @@ longtname(const struct kinfo_proc *kp, V
}
void
-started(const struct kinfo_proc *kp, VARENT *ve)
+started(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
static time_t now;
time_t startt;
@@ -498,8 +523,9 @@ started(const struct kinfo_proc *kp, VAR
}
void
-lstarted(const struct kinfo_proc *kp, VARENT *ve)
+lstarted(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
time_t startt;
char buf[100];
@@ -515,8 +541,9 @@ lstarted(const struct kinfo_proc *kp, VA
(void)printf("%-*s", v->width, buf);
}
-void elapsed(const struct kinfo_proc *kp, VARENT *ve)
+void elapsed(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
static time_t now;
time_t secs;
@@ -560,8 +587,9 @@ void elapsed(const struct kinfo_proc *kp
}
void
-wchan(const struct kinfo_proc *kp, VARENT *ve)
+wchan(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -572,8 +600,9 @@ wchan(const struct kinfo_proc *kp, VAREN
}
void
-vsize(const struct kinfo_proc *kp, VARENT *ve)
+vsize(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -582,8 +611,9 @@ vsize(const struct kinfo_proc *kp, VAREN
}
void
-rssize(const struct kinfo_proc *kp, VARENT *ve)
+rssize(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -593,8 +623,9 @@ rssize(const struct kinfo_proc *kp, VARE
}
void
-p_rssize(const struct kinfo_proc *kp, VARENT *ve)
+p_rssize(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -603,8 +634,9 @@ p_rssize(const struct kinfo_proc *kp, VA
}
void
-cputime(const struct kinfo_proc *kp, VARENT *ve)
+cputime(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
long secs;
long psecs; /* "parts" of a second. first micro, then centi */
@@ -648,17 +680,18 @@ getpcpu(const struct kinfo_proc *kp)
}
void
-pcpu(const struct kinfo_proc *kp, VARENT *ve)
+pcpu(const struct pinfo *pi, VARENT *ve)
{
VAR *v;
v = ve->var;
- (void)printf("%*.1f", v->width, getpcpu(kp));
+ (void)printf("%*.1f", v->width, getpcpu(pi->ki));
}
double
-getpmem(const struct kinfo_proc *kp)
+getpmem(const struct pinfo *pi)
{
+ const struct kinfo_proc *kp = pi->ki;
double fracmem;
if (mempages == 0)
@@ -672,17 +705,18 @@ getpmem(const struct kinfo_proc *kp)
}
void
-pmem(const struct kinfo_proc *kp, VARENT *ve)
+pmem(const struct pinfo *pi, VARENT *ve)
{
VAR *v;
v = ve->var;
- (void)printf("%*.1f", v->width, getpmem(kp));
+ (void)printf("%*.1f", v->width, getpmem(pi));
}
void
-pagein(const struct kinfo_proc *kp, VARENT *ve)
+pagein(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -691,8 +725,9 @@ pagein(const struct kinfo_proc *kp, VARE
}
void
-maxrss(const struct kinfo_proc *kp, VARENT *ve)
+maxrss(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -700,8 +735,9 @@ maxrss(const struct kinfo_proc *kp, VARE
}
void
-tsize(const struct kinfo_proc *kp, VARENT *ve)
+tsize(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -709,8 +745,9 @@ tsize(const struct kinfo_proc *kp, VAREN
}
void
-dsize(const struct kinfo_proc *kp, VARENT *ve)
+dsize(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -718,8 +755,9 @@ dsize(const struct kinfo_proc *kp, VAREN
}
void
-ssize(const struct kinfo_proc *kp, VARENT *ve)
+ssize(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
@@ -778,8 +816,9 @@ printval(char *bp, VAR *v)
}
void
-pvar(const struct kinfo_proc *kp, VARENT *ve)
+pvar(const struct pinfo *pi, VARENT *ve)
{
+ const struct kinfo_proc *kp = pi->ki;
VAR *v;
v = ve->var;
Index: ps.1
===================================================================
RCS file: /cvs/src/bin/ps/ps.1,v
retrieving revision 1.126
diff -u -p -r1.126 ps.1
--- ps.1 5 Jul 2022 15:06:16 -0000 1.126
+++ ps.1 1 Sep 2022 03:31:37 -0000
@@ -39,7 +39,7 @@
.Sh SYNOPSIS
.Nm ps
.Sm off
-.Op Oo Fl Oc Cm AaceHhjkLlmrSTuvwx
+.Op Oo Fl Oc Cm AacdeHhjkLlmrSTuvwx
.Sm on
.Op Fl M Ar core
.Op Fl N Ar system
@@ -83,6 +83,15 @@ This may be somewhat confusing; for exam
.Xr sh 1
scripts will show as
.Dq sh .
+.It Fl d
+Arrange processes into descendancy order and prefix each command with
+indentation text showing sibling and parent/child relationships.
+If either of the
+.Fl m
+and
+.Fl r
+options are also used, they control how sibling processes are sorted relative
+to each other.
.It Fl e
Display the environment as well.
.It Fl H
@@ -652,7 +661,7 @@ X/Open System Interfaces option of
.St -p1003.1-2008 .
.Pp
The flags
-.Op Fl cHhjkLMmNOrSTvWwx
+.Op Fl cdHhjkLMmNOrSTvWwx
are extensions to
.St -p1003.1-2008 .
.Pp
Index: ps.c
===================================================================
RCS file: /cvs/src/bin/ps/ps.c,v
retrieving revision 1.78
diff -u -p -r1.78 ps.c
--- ps.c 1 Dec 2021 18:21:23 -0000 1.78
+++ ps.c 1 Sep 2022 03:31:37 -0000
@@ -73,6 +73,7 @@ enum sort { DEFAULT, SORTMEM, SORTCPU }
static char *kludge_oldps_options(char *);
static int pscomp(const void *, const void *);
static void scanvars(void);
+static void descendant_sort(struct pinfo *, int);
static void usage(void);
char dfmt[] = "pid tt state time command";
@@ -90,7 +91,8 @@ int kvm_sysctl_only;
int
main(int argc, char *argv[])
{
- struct kinfo_proc *kp, **kinfo;
+ struct kinfo_proc *kp;
+ struct pinfo *pinfo;
struct varent *vent;
struct winsize ws;
dev_t ttydev;
@@ -98,6 +100,7 @@ main(int argc, char *argv[])
uid_t uid;
int all, ch, flag, i, fmt, lineno, nentries;
int prtheader, showthreads, wflag, kflag, what, Uflag, xflg;
+ int descendancy;
char *nlistf, *memf, *swapf, *cols, errbuf[_POSIX2_LINE_MAX];
setlocale(LC_CTYPE, "");
@@ -120,10 +123,11 @@ main(int argc, char *argv[])
all = fmt = prtheader = showthreads = wflag = kflag = Uflag = xflg = 0;
pid = -1;
uid = 0;
+ descendancy = 0;
ttydev = NODEV;
memf = nlistf = swapf = NULL;
while ((ch = getopt(argc, argv,
- "AaCcegHhjkLlM:mN:O:o:p:rSTt:U:uvW:wx")) != -1)
+ "AaCcdegHhjkLlM:mN:O:o:p:rSTt:U:uvW:wx")) != -1)
switch (ch) {
case 'A':
all = 1;
@@ -137,6 +141,9 @@ main(int argc, char *argv[])
case 'c':
commandonly = 1;
break;
+ case 'd':
+ descendancy = 1;
+ break;
case 'e': /* XXX set ufmt */
needenv = 1;
break;
@@ -349,26 +356,27 @@ main(int argc, char *argv[])
printheader();
if (nentries == 0)
exit(1);
- /*
- * sort proc list, we convert from an array of structs to an array
- * of pointers to make the sort cheaper.
- */
- if ((kinfo = reallocarray(NULL, nentries, sizeof(*kinfo))) == NULL)
- err(1, "failed to allocate memory for proc pointers");
+
+ if ((pinfo = calloc(nentries, sizeof(struct pinfo))) == NULL)
+ err(1, NULL);
for (i = 0; i < nentries; i++)
- kinfo[i] = &kp[i];
- qsort(kinfo, nentries, sizeof(*kinfo), pscomp);
+ pinfo[i].ki = &kp[i];
+ qsort(pinfo, nentries, sizeof(struct pinfo), pscomp);
+
+ if (descendancy)
+ descendant_sort(pinfo, nentries);
+
/*
* for each proc, call each variable output function.
*/
for (i = lineno = 0; i < nentries; i++) {
- if (xflg == 0 && ((int)kinfo[i]->p_tdev == NODEV ||
- (kinfo[i]->p_psflags & PS_CONTROLT ) == 0))
+ if (xflg == 0 && ((int)pinfo[i].ki->p_tdev == NODEV ||
+ (pinfo[i].ki->p_psflags & PS_CONTROLT ) == 0))
continue;
- if (showthreads && kinfo[i]->p_tid == -1)
+ if (showthreads && pinfo[i].ki->p_tid == -1)
continue;
for (vent = vhead; vent; vent = vent->next) {
- (vent->var->oproc)(kinfo[i], vent);
+ (vent->var->oproc)(&pinfo[i], vent);
if (vent->next != NULL)
(void)putchar(' ');
}
@@ -406,8 +414,10 @@ scanvars(void)
static int
pscomp(const void *v1, const void *v2)
{
- const struct kinfo_proc *kp1 = *(const struct kinfo_proc **)v1;
- const struct kinfo_proc *kp2 = *(const struct kinfo_proc **)v2;
+ const struct pinfo *p1 = (const struct pinfo *)v1;
+ const struct pinfo *p2 = (const struct pinfo *)v2;
+ const struct kinfo_proc *kp1 = p1->ki;
+ const struct kinfo_proc *kp2 = p2->ki;
int i;
#define VSIZE(k) ((k)->p_vm_dsize + (k)->p_vm_ssize + (k)->p_vm_tsize)
@@ -484,12 +494,120 @@ kludge_oldps_options(char *s)
}
static void
+descendant_sort(struct pinfo *ki, int items)
+{
+ int dst, lvl, maxlvl, n, ndst, nsrc, siblings, src;
+ unsigned char *path;
+ struct pinfo kn;
+
+ /*
+ * First, sort the entries by descendancy, tracking the descendancy
+ * depth in the level field.
+ */
+ src = 0;
+ maxlvl = 0;
+ while (src < items) {
+ if (ki[src].level) {
+ src++;
+ continue;
+ }
+ for (nsrc = 1; src + nsrc < items; nsrc++)
+ if (!ki[src + nsrc].level)
+ break;
+
+ for (dst = 0; dst < items; dst++) {
+ if (ki[dst].ki->p_pid == ki[src].ki->p_pid)
+ continue;
+ if (ki[dst].ki->p_pid == ki[src].ki->p_ppid)
+ break;
+ }
+
+ if (dst == items) {
+ src += nsrc;
+ continue;
+ }
+
+ for (ndst = 1; dst + ndst < items; ndst++)
+ if (ki[dst + ndst].level <= ki[dst].level)
+ break;
+
+ for (n = src; n < src + nsrc; n++) {
+ ki[n].level += ki[dst].level + 1;
+ if (maxlvl < ki[n].level)
+ maxlvl = ki[n].level;
+ }
+
+ while (nsrc) {
+ if (src < dst) {
+ kn = ki[src];
+ memmove(ki + src, ki + src + 1,
+ (dst - src + ndst - 1) * sizeof *ki);
+ ki[dst + ndst - 1] = kn;
+ nsrc--;
+ dst--;
+ ndst++;
+ } else if (src != dst + ndst) {
+ kn = ki[src];
+ memmove(ki + dst + ndst + 1, ki + dst + ndst,
+ (src - dst - ndst) * sizeof *ki);
+ ki[dst + ndst] = kn;
+ ndst++;
+ nsrc--;
+ src++;
+ } else {
+ ndst += nsrc;
+ src += nsrc;
+ nsrc = 0;
+ }
+ }
+ }
+ /*
+ * Now populate prefix (instead of level) with the command
+ * prefix used to show descendancies.
+ */
+ path = malloc((maxlvl + 7) / 8);
+ memset(path, '\0', (maxlvl + 7) / 8);
+ for (src = 0; src < items; src++) {
+ if ((lvl = ki[src].level) == 0) {
+ ki[src].prefix = NULL;
+ continue;
+ }
+ if ((ki[src].prefix = malloc(lvl * 2 + 1)) == NULL)
+ errx(1, "malloc failed");
+ for (n = 0; n < lvl - 2; n++) {
+ ki[src].prefix[n * 2] =
+ path[n / 8] & 1 << (n % 8) ? '|' : ' ';
+ ki[src].prefix[n * 2 + 1] = ' ';
+
+ }
+ if (n == lvl - 2) {
+ /* Have I any more siblings? */
+ for (siblings = 0, dst = src + 1; dst < items; dst++) {
+ if (ki[dst].level > lvl)
+ continue;
+ if (ki[dst].level == lvl)
+ siblings = 1;
+ break;
+ }
+ if (siblings)
+ path[n / 8] |= 1 << (n % 8);
+ else
+ path[n / 8] &= ~(1 << (n % 8));
+ ki[src].prefix[n * 2] = siblings ? '|' : '`';
+ ki[src].prefix[n * 2 + 1] = '-';
+ n++;
+ }
+ strcpy(ki[src].prefix + n * 2, "- ");
+ }
+ free(path);
+}
+
+static void
usage(void)
{
- (void)fprintf(stderr,
- "usage: %s [-AaceHhjkLlmrSTuvwx] [-M core] [-N system] [-O fmt] [-o
fmt] [-p pid]\n",
- __progname);
- (void)fprintf(stderr,
- "%-*s[-t tty] [-U username] [-W swap]\n", (int)strlen(__progname) +
8, "");
+ fprintf(stderr, "usage: %s [-AacdeHhjkLlmrSTuvwx] [-M core] [-N system]"
+ " [-O fmt] [-o fmt] [-p pid]\n", __progname);
+ fprintf(stderr, "%-*s[-t tty] [-U username] [-W swap]\n",
+ (int)strlen(__progname) + 8, "");
exit(1);
}
Index: ps.h
===================================================================
RCS file: /cvs/src/bin/ps/ps.h,v
retrieving revision 1.10
diff -u -p -r1.10 ps.h
--- ps.h 3 May 2015 06:23:28 -0000 1.10
+++ ps.h 1 Sep 2022 03:31:37 -0000
@@ -44,6 +44,11 @@ typedef struct varent {
} VARENT;
struct kinfo_proc;
+struct pinfo {
+ struct kinfo_proc *ki;
+ char *prefix;
+ int level;
+};
typedef struct var {
char *name; /* name(s) of variable */
char *header; /* default header */
@@ -55,7 +60,7 @@ typedef struct var {
#define NLIST 0x10 /* needs nlist info from kernel */
u_int flag;
/* output routine */
- void (*oproc)(const struct kinfo_proc *, struct varent *);
+ void (*oproc)(const struct pinfo *, struct varent *);
short width; /* printing width */
char parsed; /* have we been parsed yet? (avoid dupes) */
/*