From: job Date: Thu, 1 Sep 2022 21:15:54 +0000 (+0000) Subject: Add forest (-f) mode X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=24ca0f25af7a8162d84e3e77f54ee3b4d2dcf56a;p=openbsd Add forest (-f) mode In -f mode group & display parent/child process relationships using ASCII art. Borrows heavily from Brian Somers' work on FreeBSD ps(1). With input from deraadt@ and tb@ OK benno@ claudio@ --- diff --git a/bin/ps/extern.h b/bin/ps/extern.h index 385229fcc00..64649027a26 100644 --- a/bin/ps/extern.h +++ b/bin/ps/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.23 2022/01/05 04:10:36 guenther Exp $ */ +/* $OpenBSD: extern.h,v 1.24 2022/09/01 21:15:54 job Exp $ */ /* $NetBSD: extern.h,v 1.10 1995/05/21 13:38:27 mycroft Exp $ */ /*- @@ -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 *); +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 diff --git a/bin/ps/print.c b/bin/ps/print.c index 4afa30f70fc..de3f47722f8 100644 --- a/bin/ps/print.c +++ b/bin/ps/print.c @@ -1,4 +1,4 @@ -/* $OpenBSD: print.c,v 1.82 2022/02/15 23:16:00 rob Exp $ */ +/* $OpenBSD: print.c,v 1.83 2022/09/01 21:15:54 job Exp $ */ /* $NetBSD: print.c,v 1.27 1995/09/29 21:58:12 cgd Exp $ */ /*- @@ -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, VARENT *ve) } 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, VARENT *ve) } 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, VARENT *ve) } 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, VARENT *ve) #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, VARENT *ve) } 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, VARENT *ve) } 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 *ve) } 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, VARENT *ve) } 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, VARENT *ve) } 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 *ve) } 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, VARENT *ve) } 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, VARENT *ve) } 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, VARENT *ve) } 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, VARENT *ve) (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, VARENT *ve) } 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, VARENT *ve) } 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, VARENT *ve) } 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, VARENT *ve) } 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, VARENT *ve) } 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,12 +680,12 @@ 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 @@ -672,17 +704,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->ki)); } 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 +724,9 @@ pagein(const struct kinfo_proc *kp, VARENT *ve) } 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 +734,9 @@ maxrss(const struct kinfo_proc *kp, VARENT *ve) } 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 +744,9 @@ tsize(const struct kinfo_proc *kp, VARENT *ve) } 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 +754,9 @@ dsize(const struct kinfo_proc *kp, VARENT *ve) } 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 +815,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; diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index d70cb4db6ce..33cced379b6 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ps.1,v 1.126 2022/07/05 15:06:16 visa Exp $ +.\" $OpenBSD: ps.1,v 1.127 2022/09/01 21:15:54 job Exp $ .\" $NetBSD: ps.1,v 1.16 1996/03/21 01:36:28 jtc Exp $ .\" .\" Copyright (c) 1980, 1990, 1991, 1993, 1994 @@ -30,7 +30,7 @@ .\" .\" @(#)ps.1 8.3 (Berkeley) 4/18/94 .\" -.Dd $Mdocdate: July 5 2022 $ +.Dd $Mdocdate: September 1 2022 $ .Dt PS 1 .Os .Sh NAME @@ -39,7 +39,7 @@ .Sh SYNOPSIS .Nm ps .Sm off -.Op Oo Fl Oc Cm AaceHhjkLlmrSTuvwx +.Op Oo Fl Oc Cm AacefHhjkLlmrSTuvwx .Sm on .Op Fl M Ar core .Op Fl N Ar system @@ -85,6 +85,15 @@ scripts will show as .Dq sh . .It Fl e Display the environment as well. +.It Fl f +Arrange processes into a tree, 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 H Also display information about kernel visible threads. .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 cfHhjkLMmNOrSTvWwx are extensions to .St -p1003.1-2008 . .Pp diff --git a/bin/ps/ps.c b/bin/ps/ps.c index 6c7c68ba81b..4cf9bfd066b 100644 --- a/bin/ps/ps.c +++ b/bin/ps/ps.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ps.c,v 1.78 2021/12/01 18:21:23 deraadt Exp $ */ +/* $OpenBSD: ps.c,v 1.79 2022/09/01 21:15:54 job Exp $ */ /* $NetBSD: ps.c,v 1.15 1995/05/18 20:33:25 mycroft Exp $ */ /*- @@ -73,6 +73,7 @@ enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT; static char *kludge_oldps_options(char *); static int pscomp(const void *, const void *); static void scanvars(void); +static void forest_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 forest; 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; + forest = 0; ttydev = NODEV; memf = nlistf = swapf = NULL; while ((ch = getopt(argc, argv, - "AaCcegHhjkLlM:mN:O:o:p:rSTt:U:uvW:wx")) != -1) + "AaCcefgHhjkLlM:mN:O:o:p:rSTt:U:uvW:wx")) != -1) switch (ch) { case 'A': all = 1; @@ -140,6 +144,9 @@ main(int argc, char *argv[]) case 'e': /* XXX set ufmt */ needenv = 1; break; + case 'f': + forest = 1; + break; case 'g': break; /* no-op */ case 'H': @@ -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 (forest) + forest_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) @@ -483,13 +493,125 @@ kludge_oldps_options(char *s) return (newopts); } +static void +forest_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 forest, tracking the forest + * 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 = calloc(1, (maxlvl + 7) / 8); + if (path == NULL) + err(1, NULL); + + 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) + err(1, NULL); + + 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++; + } + strlcpy(ki[src].prefix + n * 2, "- ", (lvl - n) * 2 + 1); + } + 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 [-AacefHhjkLlmrSTuvwx] [-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); } diff --git a/bin/ps/ps.h b/bin/ps/ps.h index 689b1283543..65df50924e7 100644 --- a/bin/ps/ps.h +++ b/bin/ps/ps.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ps.h,v 1.10 2015/05/03 06:23:28 guenther Exp $ */ +/* $OpenBSD: ps.h,v 1.11 2022/09/01 21:15:54 job Exp $ */ /* $NetBSD: ps.h,v 1.11 1995/09/29 21:57:03 cgd Exp $ */ /*- @@ -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) */ /*