1
0
mirror of https://github.com/openbsd/src.git synced 2024-12-22 07:27:59 -08:00

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@
This commit is contained in:
job 2022-09-01 21:15:54 +00:00
parent 716e1627c1
commit 24ca0f25af
5 changed files with 272 additions and 98 deletions

View File

@ -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

View File

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

View File

@ -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

View File

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

View File

@ -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) */
/*