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:
parent
716e1627c1
commit
24ca0f25af
@ -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
|
||||
|
110
bin/ps/print.c
110
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;
|
||||
|
17
bin/ps/ps.1
17
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
|
||||
|
166
bin/ps/ps.c
166
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);
|
||||
}
|
||||
|
@ -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) */
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user