Job Snijders(j...@openbsd.org) on 2022.09.01 03:37:59 +0000:
> 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?

i like it. found some little things below, with those fixed and some
agreement on the option letter (which i dont care about) it has my ok.

> 
> 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);

check the result of malloc

> +     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");

why not just 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++;
> +             }
> +             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) */
>       /*
> 

Reply via email to