static char *sccsid
= "@(#)ps.c 4.30 (Berkeley) %G%";
short a_stat
, a_uid
, a_pid
, a_nice
, a_pri
, a_slptime
, a_time
;
size_t a_size
, a_rss
, a_tsiz
, a_txtrss
;
size_t v_swrss
, v_txtswrss
;
struct proc proc
[NPROC
]; /* a few, for less syscalls */
char upages
[UPAGES
][NBPG
];
char *psdb
= "/etc/psdatabase";
int aflg
, cflg
, eflg
, gflg
, kflg
, lflg
, sflg
,
char *gettty(), *getcmd(), *getname(), *savestr(), *state();
char *rindex(), *calloc(), *sbrk(), *strcpy(), *strcat(), *strncat();
char *strncpy(), *index(), *ttyname(), mytty
[16];
struct pte
*Usrptmap
, *usrpt
;
} allttys
[MAXTTYS
], *cand
[16];
char *kmemf
, *memf
, *swapf
, *nlistf
;
int kmem
, mem
, swap
= -1;
#define pgtok(a) ((a)/(1024/NBPG))
if (ioctl(0, TIOCGWINSZ
, &win
) == -1)
twidth
= (win
.ws_col
== 0 ? 80 : win
.ws_col
);
while (*ap
) switch (*ap
++) {
else if ((tptr
= ttyname(2)) != 0) {
if ((tptr
= index(mytty
,'y')) != 0)
if (tptr
&& *tptr
== '?')
procp
= getw(nl
[X_PROC
].n_value
);
nproc
= getw(nl
[X_NPROC
].n_value
);
savcom
= (struct savcom
*)calloc((unsigned) nproc
, sizeof (*savcom
));
for (i
=0; i
<nproc
; i
+= NPROC
) {
klseek(kmem
, (long)procp
, 0);
j
*= sizeof (struct proc
);
if (read(kmem
, (char *)proc
, j
) != j
) {
cantread("proc table", kmemf
);
for (j
= j
/ sizeof (struct proc
) - 1; j
>= 0; j
--) {
if (mproc
->p_stat
== 0 ||
mproc
->p_pgrp
== 0 && xflg
== 0)
if (tptr
== 0 && gflg
== 0 && xflg
== 0 &&
if (uid
!= mproc
->p_uid
&& aflg
==0)
if (chkpid
!= 0 && chkpid
!= mproc
->p_pid
)
if (vflg
&& gflg
== 0 && xflg
== 0) {
if (mproc
->p_stat
== SZOMB
||
if (mproc
->p_slptime
> MAXSLP
&&
(mproc
->p_stat
== SSLEEP
||
width
= twidth
- cmdstart
- 2;
qsort((char *) savcom
, npr
, sizeof(savcom
[0]), pscomp
);
register struct savcom
*sp
= &savcom
[i
];
if (sp
->ap
->a_flag
& SWEXIT
)
else if (sp
->ap
->a_stat
== SZOMB
)
else if (sp
->ap
->a_pid
== 0)
else if (sp
->ap
->a_pid
== 2)
else if (sp
->ap
->a_pid
== 3 && sp
->ap
->a_flag
& SSYS
)
printf(" %.*s", twidth
- cmdstart
- 2, sp
->ap
->a_cmdp
);
klseek(kmem
, (long)loc
, 0);
if (read(kmem
, (char *)&word
, sizeof (word
)) != sizeof (word
))
printf("error reading kmem at %x\n", loc
);
if ((loc
= vtophys(loc
)) == -1)
(void) lseek(fd
, (long)loc
, off
);
if ((fp
= fopen(psdb
, "w")) == NULL
) {
fchmod(fileno(fp
), 0644);
nllen
= sizeof nl
/ sizeof (struct nlist
);
fwrite((char *) &nllen
, sizeof nllen
, 1, fp
);
fwrite((char *) nl
, sizeof (struct nlist
), nllen
, fp
);
fwrite((char *) &nttys
, sizeof nttys
, 1, fp
);
fwrite((char *) allttys
, sizeof (struct ttys
), nttys
, fp
);
fwrite(unixname
, strlen(unixname
) + 1, 1, fp
);
if ((fp
= fopen(psdb
, "r")) == NULL
) {
fread((char *) &nllen
, sizeof nllen
, 1, fp
);
fread((char *) nl
, sizeof (struct nlist
), nllen
, fp
);
fread((char *) &nttys
, sizeof nttys
, 1, fp
);
fread((char *) allttys
, sizeof (struct ttys
), nttys
, fp
);
while ((*p
= getc(fp
)) != '\0')
return (strcmp(unixname
, unamebuf
) == 0);
kmemf
= argc
> 2 ? argv
[2] : "/vmcore";
if (kflg
== 0 || argc
> 3) {
swapf
= argc
>3 ? argv
[3]: "/dev/drum";
nlistf
= argc
> 1 ? argv
[1] : "/vmunix";
} else if (!readpsdb(nlistf
)) {
nl
[X_SYSMAP
].n_name
= "";
fprintf(stderr
, "%s: No namelist\n", nlistf
);
/* We must do the sys map first because klseek uses it */
Syssize
= nl
[X_SYSSIZE
].n_value
;
calloc((unsigned) Syssize
, sizeof (struct pte
));
fprintf(stderr
, "Out of space for Sysmap\n");
addr
= (long) nl
[X_SYSMAP
].n_value
;
(void) lseek(kmem
, addr
, 0);
read(kmem
, (char *) Sysmap
, Syssize
* sizeof (struct pte
));
usrpt
= (struct pte
*)nl
[X_USRPT
].n_value
;
Usrptmap
= (struct pte
*)nl
[X_USRPTMAP
].n_value
;
klseek(kmem
, (long)nl
[X_NSWAP
].n_value
, 0);
if (read(kmem
, (char *)&nswap
, sizeof (nswap
)) != sizeof (nswap
)) {
cantread("nswap", kmemf
);
klseek(kmem
, (long)nl
[X_MAXSLP
].n_value
, 0);
if (read(kmem
, (char *)&maxslp
, sizeof (maxslp
)) != sizeof (maxslp
)) {
cantread("maxslp", kmemf
);
klseek(kmem
, (long)nl
[X_CCPU
].n_value
, 0);
if (read(kmem
, (char *)&ccpu
, sizeof (ccpu
)) != sizeof (ccpu
)) {
klseek(kmem
, (long)nl
[X_ECMX
].n_value
, 0);
if (read(kmem
, (char *)&ecmx
, sizeof (ecmx
)) != sizeof (ecmx
)) {
ntext
= getw(nl
[X_NTEXT
].n_value
);
calloc((unsigned) ntext
, sizeof (struct text
));
fprintf(stderr
, "no room for text table\n");
atext
= (struct text
*)getw(nl
[X_TEXT
].n_value
);
klseek(kmem
, (long)atext
, 0);
if (read(kmem
, (char *)text
, ntext
* sizeof (struct text
))
!= ntext
* sizeof (struct text
)) {
cantread("text table", kmemf
);
dmmin
= getw(nl
[X_DMMIN
].n_value
);
dmmax
= getw(nl
[X_DMMAX
].n_value
);
if (sflg
+lflg
+vflg
+uflg
> 1) {
fprintf(stderr
, "ps: specify only one of s,l,v and u\n");
if (lflg
+vflg
+uflg
+sflg
== 0)
printf("%s COMMAND\n", hdr
);
fprintf(stderr
, "ps: error reading %s from %s\n", what
, fromwhat
);
if ((df
= opendir(".")) == NULL
) {
fprintf(stderr
, "Can't open . in /dev\n");
while ((dbuf
= readdir(df
)) != NULL
)
* Attempt to avoid stats by guessing minor device
* numbers from tty names. Console is known,
* know that r(hp|up|mt) are unlikely as are different mem's,
* floppy, null, tty, etc.
register char *cp
= dbuf
->d_name
;
register struct ttys
*dp
;
if (!strcmp(cp
, "console")) {
/* cu[la]? are possible!?! don't rule them out */
if (!strcmp(cp
, "floppy"))
#define is(a,b) cp[0] == 'a' && cp[1] == 'b'
if (is(h
,p
) || is(r
,a
) || is(u
,p
) || is(r
,k
)
if (isdigit(*cp
) && cp
[2] == 0)
if (cp
[0] == 'm' && cp
[1] == 'e' && cp
[2] == 'm' && cp
[3] == 0)
if (cp
[0] == 'm' && cp
[1] == 't')
if ((cp
[1] == 'a' || cp
[1] == 'p') && isdigit(cp
[2]) &&
cp
= dbuf
->d_name
+ dbuf
->d_namlen
- 1;
if (stat("ttyd0", &stb
) == 0)
dialbase
= stb
.st_rdev
& 017;
if (cp
> dbuf
->d_name
&& isdigit(cp
[-1]) && isdigit(*cp
))
x
+= 10 * (cp
[-1] - ' ') + cp
[0] - '0';
else if (*cp
>= 'a' && *cp
<= 'f')
fprintf(stderr
, "ps: tty table overflow\n");
(void) strcpy(dp
->name
, dbuf
->d_name
);
if (stat(dp
->name
, &stb
) == 0 &&
(stb
.st_mode
&S_IFMT
)==S_IFCHR
)
dp
->ttyd
= x
= stb
.st_rdev
;
register struct ttys
*dp
;
for (dp
= cand
[x
]; dp
; dp
= dp
->cand
) {
if (stat(dp
->name
, &stb
) == 0 &&
(stb
.st_mode
&S_IFMT
)==S_IFCHR
)
if (dp
->ttyd
== u
.u_ttyd
)
for (dp
= allttys
; dp
< &allttys
[nttys
]; dp
++) {
if (stat(dp
->name
, &stb
) == 0 &&
(stb
.st_mode
&S_IFMT
)==S_IFCHR
)
if (dp
->ttyd
== u
.u_ttyd
)
if (p
[0]=='t' && p
[1]=='t' && p
[2]=='y')
register struct savcom
*sp
;
register struct asav
*ap
;
register struct text
*xp
;
if (mproc
->p_stat
!= SZOMB
&& getu() == 0)
if (xflg
== 0 && ttyp
[0] == '?' || tptr
&& strncmp(tptr
, ttyp
, 2))
sp
->ap
= ap
= (struct asav
*)calloc(1, sizeof (struct asav
));
#define e(a,b) ap->a = mproc->b
e(a_flag
, p_flag
); e(a_stat
, p_stat
); e(a_nice
, p_nice
);
e(a_uid
, p_uid
); e(a_pid
, p_pid
); e(a_pri
, p_pri
);
e(a_slptime
, p_slptime
); e(a_time
, p_time
);
ap
->a_tty
[1] = ttyp
[1] ? ttyp
[1] : ' ';
if (ap
->a_stat
== SZOMB
) {
ap
->a_size
= mproc
->p_dsize
+ mproc
->p_ssize
;
ap
->a_cpu
= u
.u_ru
.ru_utime
.tv_sec
+ u
.u_ru
.ru_stime
.tv_sec
;
ap
->a_cpu
+= u
.u_cru
.ru_utime
.tv_sec
+ u
.u_cru
.ru_stime
.tv_sec
;
if (mproc
->p_textp
&& text
) {
xp
= &text
[mproc
->p_textp
- atext
];
ap
->a_txtrss
= xp
->x_rssize
;
ap
->a_xccount
= xp
->x_ccount
;
ap
->a_maxrss
= mproc
->p_maxrss
;
register struct lsav
*lp
;
sp
->s_un
.lp
= lp
= (struct lsav
*)
calloc(1, sizeof (struct lsav
));
#define e(a,b) lp->a = mproc->b
e(l_ppid
, p_ppid
); e(l_cpu
, p_cpu
);
register struct vsav
*vp
;
sp
->s_un
.vp
= vp
= (struct vsav
*)
calloc(1, sizeof (struct vsav
));
#define e(a,b) vp->a = mproc->b
if (ap
->a_stat
!= SZOMB
) {
vp
->v_majflt
= u
.u_ru
.ru_majflt
;
vp
->v_txtswrss
= xp
->x_swrss
;
sp
->s_un
.u_pctcpu
= pcpu();
if (ap
->a_stat
!= SZOMB
) {
for (cp
= (char *)u
.u_stack
;
cp
< &user
.upages
[UPAGES
][0]; )
sp
->s_un
.s_ssiz
= (&user
.upages
[UPAGES
][0] - cp
);
register struct asav
*ap
;
if ((ap
->a_flag
&SLOAD
) == 0)
szptudot
= UPAGES
+ clrnd(ctopt(ap
->a_size
+ap
->a_tsiz
));
fracmem
= ((float)ap
->a_rss
+szptudot
)/CLSIZE
/ecmx
;
fracmem
+= ((float)ap
->a_txtrss
)/CLSIZE
/
return (100.0 * fracmem
);
if (time
== 0 || (mproc
->p_flag
&SLOAD
) == 0)
return (100.0 * mproc
->p_pctcpu
);
return (100.0 * mproc
->p_pctcpu
/ (1.0 - exp(time
* log(ccpu
))));
struct pte
*pteaddr
, apte
;
struct pte arguutl
[UPAGES
+CLSIZE
];
size
= sflg
? ctob(UPAGES
) : sizeof (struct user
);
if ((mproc
->p_flag
& SLOAD
) == 0) {
(void) lseek(swap
, (long)dtob(mproc
->p_swaddr
), 0);
if (read(swap
, (char *)&user
.user
, size
) != size
) {
fprintf(stderr
, "ps: cant read u for pid %d from %s\n",
pteaddr
= &Usrptmap
[btokmx(mproc
->p_p0br
) + mproc
->p_szpt
- 1];
klseek(kmem
, (long)pteaddr
, 0);
if (read(kmem
, (char *)&apte
, sizeof(apte
)) != sizeof(apte
)) {
printf("ps: cant read indir pte to get u for pid %d from %s\n",
(long)ctob(apte
.pg_pfnum
+1) - (UPAGES
+CLSIZE
) * sizeof (struct pte
),
if (read(mem
, (char *)arguutl
, sizeof(arguutl
)) != sizeof(arguutl
)) {
printf("ps: cant read page table for u of pid %d from %s\n",
if (arguutl
[0].pg_fod
== 0 && arguutl
[0].pg_pfnum
)
argaddr
= ctob(arguutl
[0].pg_pfnum
);
pcbpf
= arguutl
[CLSIZE
].pg_pfnum
;
ncl
= (size
+ NBPG
*CLSIZE
- 1) / (NBPG
*CLSIZE
);
lseek(mem
, (long)ctob(arguutl
[CLSIZE
+i
].pg_pfnum
), 0);
if (read(mem
, user
.upages
[i
], CLSIZE
*NBPG
) != CLSIZE
*NBPG
) {
printf("ps: cant read page %d of u of pid %d from %s\n",
arguutl
[CLSIZE
+i
].pg_pfnum
, mproc
->p_pid
, memf
);
char cmdbuf
[CLSIZE
*NBPG
];
int argi
[CLSIZE
*NBPG
/sizeof (int)];
if (mproc
->p_stat
== SZOMB
|| mproc
->p_flag
&(SSYS
|SWEXIT
))
(void) strncpy(cmdbuf
, u
.u_comm
, sizeof (u
.u_comm
));
return (savestr(cmdbuf
));
if ((mproc
->p_flag
& SLOAD
) == 0 || argaddr
== 0) {
vstodb(0, CLSIZE
, &u
.u_smap
, &db
, 1);
(void) lseek(swap
, (long)dtob(db
.db_base
), 0);
if (read(swap
, (char *)&argspac
, sizeof(argspac
))
lseek(mem
, (long)argaddr
, 0);
if (read(mem
, (char *)&argspac
, sizeof (argspac
))
ip
= &argspac
.argi
[CLSIZE
*NBPG
/sizeof (int)];
ip
-= 2; /* last arg word and .long 0 */
for (cp
= (char *)ip
; cp
< &argspac
.argc
[CLSIZE
*NBPG
]; cp
++) {
else if (c
< ' ' || c
> 0176) {
if (++nbad
>= 5*(eflg
+1)) {
} else if (eflg
== 0 && c
== '=') {
(void) strncpy(cmdbuf
, cp
, &argspac
.argc
[CLSIZE
*NBPG
] - cp
);
if (cp
[0] == '-' || cp
[0] == '?' || cp
[0] <= ' ') {
(void) strcat(cmdbuf
, " (");
(void) strncat(cmdbuf
, u
.u_comm
, sizeof(u
.u_comm
));
(void) strcat(cmdbuf
, ")");
return (savestr(cmdbuf
));
fprintf(stderr
, "ps: error locating command name for pid %d from %s\n",
(void) strcpy(cmdbuf
, " (");
(void) strncat(cmdbuf
, u
.u_comm
, sizeof (u
.u_comm
));
(void) strcat(cmdbuf
, ")");
return (savestr(cmdbuf
));
" F UID PID PPID CP PRI NI ADDR SZ RSS WCHAN STAT TT TIME";
register struct asav
*ap
= sp
->ap
;
register struct lsav
*lp
= sp
->s_un
.lp
;
printf("%7x%4d%6u%6u%3d%4d%3d%5x%4d%5d",
ap
->a_pid
, lp
->l_ppid
, lp
->l_cpu
&0377, ap
->a_pri
-PZERO
,
ap
->a_nice
-NZERO
, lp
->l_addr
, pgtok(ap
->a_size
), pgtok(ap
->a_rss
));
printf(lp
->l_wchan
? " %6x" : " ", (int)lp
->l_wchan
&0xffffff);
printf(" %4.4s ", state(ap
));
printf("%3ld:%02ld", ap
->a_cpu
/ 60, ap
->a_cpu
% 60);
"USER PID %CPU %MEM SZ RSS TT STAT TIME";
register struct asav
*ap
= sp
->ap
;
vmsize
= pgtok((ap
->a_size
+ ap
->a_tsiz
));
rmsize
= pgtok(ap
->a_rss
);
rmsize
+= pgtok(ap
->a_txtrss
/ap
->a_xccount
);
printf("%-8.8s %5d%5.1f%5.1f%5d%5d",
getname(ap
->a_uid
), ap
->a_pid
, sp
->s_un
.u_pctcpu
, pmem(ap
),
printf(" %4.4s", state(ap
));
" SIZE PID TT STAT TIME SL RE PAGEIN SIZE RSS LIM TSIZ TRS %CPU %MEM"+5;
register struct vsav
*vp
= sp
->s_un
.vp
;
register struct asav
*ap
= sp
->ap
;
printf("%5u ", ap
->a_pid
);
printf(" %4.4s", state(ap
));
printf("%3d%3d%7d%5d%5d",
ap
->a_slptime
> 99 ? 99 : ap
-> a_slptime
,
ap
->a_time
> 99 ? 99 : ap
->a_time
, vp
->v_majflt
,
pgtok(ap
->a_size
), pgtok(ap
->a_rss
));
if (ap
->a_maxrss
== (RLIM_INFINITY
/NBPG
))
printf("%5d", pgtok(ap
->a_maxrss
));
printf("%5d%4d%5.1f%5.1f",
pgtok(ap
->a_tsiz
), pgtok(ap
->a_txtrss
), vp
->v_pctcpu
, pmem(ap
));
register struct asav
*ap
= sp
->ap
;
printf("%4d ", sp
->s_un
.s_ssiz
);
printf("%5u", ap
->a_pid
);
printf(" %4.4s", state(ap
));
register struct asav
*ap
;
char stat
, load
, nice
, anom
;
if (ap
->a_slptime
>= MAXSLP
)
else if (ap
->a_flag
& SPAGE
)
load
= ap
->a_flag
& SLOAD
? (ap
->a_rss
>ap
->a_maxrss
? '>' : ' ') : 'W';
else if (ap
->a_nice
> NZERO
)
anom
= (ap
->a_flag
&SUANOM
) ? 'A' : ((ap
->a_flag
&SSEQL
) ? 'S' : ' ');
res
[0] = stat
; res
[1] = load
; res
[2] = nice
; res
[3] = anom
;
* Given a base/size pair in virtual swap area,
* return a physical base/size pair which is the
* (largest) initial, physically contiguous block.
vstodb(vsbase
, vssize
, dmp
, dbp
, rev
)
register struct dblock
*dbp
;
register int blk
= dmmin
;
register swblk_t
*ip
= dmp
->dm_map
;
if (vsbase
< 0 || vsbase
+ vssize
> dmp
->dm_size
)
if (*ip
<= 0 || *ip
+ blk
> nswap
)
dbp
->db_size
= min(vssize
, blk
- vsbase
);
dbp
->db_base
= *ip
+ (rev
? blk
- (vsbase
+ dbp
->db_size
) : vsbase
);
return (s2
->s_un
.u_pctcpu
> s1
->s_un
.u_pctcpu
? 1 : -1);
return (vsize(s2
) - vsize(s1
));
i
= s1
->ap
->a_ttyd
- s2
->ap
->a_ttyd
;
i
= s1
->ap
->a_pid
- s2
->ap
->a_pid
;
register struct asav
*ap
= sp
->ap
;
register struct vsav
*vp
= sp
->s_un
.vp
;
ap
->a_txtrss
/ (ap
->a_xccount
? ap
->a_xccount
: 1));
return (vp
->v_swrss
+ (ap
->a_xccount
? 0 : vp
->v_txtswrss
));
#define NMAX 8 /* sizeof loginname (should be sizeof (utmp.ut_name)) */
#define NUID 2048 /* must not be a multiple of 5 */
register struct nametable
*n
, *start
;
* find the uid or an empty slot.
* return NULL if neither found.
n
= start
= nametable
+ (uid
% (NUID
- 20));
while (n
->nt_name
[0] && n
->nt_uid
!= uid
) {
if ((n
+= 5) >= &nametable
[NUID
])
return((struct nametable
*)NULL
);
register struct passwd
*pw
;
struct passwd
*getpwent();
register struct nametable
*n
;
* find uid in hashed table; add it if not found.
* return pointer to name.
if ((n
= findslot(uid
)) == NULL
)
if (n
->nt_name
[0]) /* occupied? */
/* intentional fall-thru */
while (pw
= getpwent()) {
if ((n
= findslot(pw
->pw_uid
)) == NULL
) {
continue; /* duplicate, not uid */
strncpy(n
->nt_name
, pw
->pw_name
, NMAX
);
/* intentional fall-thru */
dp
= (char *)calloc(len
+1, sizeof (char));
* This routine was stolen from adb to simulate memory management
newloc
= loc
& ~0xc0000000;
if ((loc
& 0xc0000000) == 0) {
fprintf(stderr
, "Vtophys: translating non-kernel address\n");
fprintf(stderr
, "Vtophys: page out of bound (%d>=%d)\n",
&& (Sysmap
[p
].pg_fod
|| Sysmap
[p
].pg_pfnum
== 0)) {
fprintf(stderr
, "Vtophys: page not valid\n");
loc
= (long) (ptob(Sysmap
[p
].pg_pfnum
) + (loc
& PGOFSET
));