static char *sccsid
= "@(#)ps.c 4.5 (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
[8]; /* 8 = a few, for less syscalls */
char upages
[UPAGES
][NBPG
];
#define clear(x) ((int)x & 0x7fffffff)
int aflg
, cflg
, eflg
, gflg
, kflg
, lflg
, sflg
, uflg
, vflg
, xflg
;
char *gettty(), *getcmd(), *getname(), *savestr(), *alloc(), *state();
struct pte
*Usrptma
, *usrpt
;
struct savcom savcom
[NPROC
];
char *kmemf
, *memf
, *swapf
, *nlistf
;
while (*ap
) switch (*ap
++) {
procp
= nl
[X_PROC
].n_value
;
for (i
=0; i
<NPROC
; i
+= 8) {
lseek(kmem
, (char *)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 &&
mproc
->p_ppid
== 1 && (mproc
->p_flag
&SDETACH
) == 0)
if (uid
!= mproc
->p_uid
&& aflg
==0 ||
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
||
qsort(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)
printf(" %.*s", twidth
- cmdstart
- 2, sp
->ap
->a_cmdp
);
kmemf
= argc
> 1 ? argv
[1] : "/vmcore";
swapf
= argc
>2 ? argv
[2]: "drum";
register struct nlist
*nlp
;
nlistf
= argc
> 3 ? argv
[3] : "/vmunix";
fprintf(stderr
, "%s: No namelist\n", nlistf
);
for (nlp
= nl
; nlp
< &nl
[sizeof (nl
)/sizeof (nl
[0])]; nlp
++)
nlp
->n_value
= clear(nlp
->n_value
);
Usrptma
= (struct pte
*)nl
[X_USRPTMA
].n_value
;
usrpt
= (struct pte
*)nl
[X_USRPT
].n_value
;
lseek(kmem
, (long)nl
[X_NSWAP
].n_value
, 0);
if (read(kmem
, &nswap
, sizeof (nswap
)) != sizeof (nswap
)) {
cantread("nswap", kmemf
);
lseek(kmem
, (long)nl
[X_MAXSLP
].n_value
, 0);
if (read(kmem
, &maxslp
, sizeof (maxslp
)) != sizeof (maxslp
)) {
cantread("maxslp", kmemf
);
lseek(kmem
, (long)nl
[X_CCPU
].n_value
, 0);
if (read(kmem
, &ccpu
, sizeof (ccpu
)) != sizeof (ccpu
)) {
lseek(kmem
, (long)nl
[X_ECMX
].n_value
, 0);
if (read(kmem
, &ecmx
, sizeof (ecmx
)) != sizeof (ecmx
)) {
text
= (struct text
*)alloc(NTEXT
* sizeof (struct text
));
fprintf(stderr
, "no room for text table\n");
lseek(kmem
, (long)nl
[X_TEXT
].n_value
, 0);
if (read(kmem
, (char *)text
, NTEXT
* sizeof (struct text
))
!= NTEXT
* sizeof (struct text
)) {
cantread("text table", kmemf
);
if (sflg
+lflg
+vflg
+uflg
> 1) {
fprintf(stderr
, "ps: specify only one of s,l,v and u\n");
hdr
= lflg
? lhdr
: (vflg
? vhdr
: (uflg
? uhdr
: shdr
));
if (lflg
+vflg
+uflg
+sflg
== 0)
printf("%s COMMAND\n", hdr
);
fprintf(stderr
, "ps: error reading %s from %s", what
, fromwhat
);
register struct ttys
*dp
;
if ((df
= fopen(".", "r")) == NULL
) {
fprintf(stderr
, "Can't open . in /dev\n");
while (fread((char *)&dbuf
, sizeof(dbuf
), 1, df
) == 1) {
* 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"))
if (*cp
== 'r' || *cp
== 'u' || *cp
== 'h')
#define is(a,b) cp[0] == 'a' && cp[1] == 'b'
if (is(r
,p
) || is(u
,p
) || is(r
,k
) || is(r
,m
) || is(m
,t
)) {
if (isdigit(*cp
) && cp
[2] == 0)
if (cp
[0] == 'm' && cp
[1] == 'e' && cp
[2] == 'm' && cp
[3] == 0)
if ((cp
[1] == 'a' || cp
[1] == 'p') && isdigit(cp
[2]) &&
while (cp
< &dbuf
.d_name
[DIRSIZ
] && *cp
)
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')
dp
= (struct ttys
*)alloc(sizeof (struct ttys
));
strncpy(dp
->name
, dbuf
.d_name
, DIRSIZ
);
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
; dp
= dp
->next
) {
if (stat(dp
->name
, &stb
) == 0)
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
&& strcmpn(tptr
, ttyp
, 2))
sp
->ap
= ap
= (struct asav
*)alloc(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
) {
register struct xproc
*xp
= (struct xproc
*)mproc
;
ap
->a_cpu
= xp
->xp_vm
.vm_utime
+ xp
->xp_vm
.vm_stime
;
ap
->a_size
= mproc
->p_dsize
+ mproc
->p_ssize
;
ap
->a_cpu
= u
.u_vm
.vm_utime
+ u
.u_vm
.vm_stime
;
ap
->a_cpu
+= u
.u_cvm
.vm_utime
+ u
.u_cvm
.vm_stime
;
xp
= &text
[mproc
->p_textp
-
(struct text
*)nl
[X_TEXT
].n_value
];
ap
->a_txtrss
= xp
->x_rssize
;
ap
->a_xccount
= xp
->x_ccount
;
register struct lsav
*lp
;
sp
->sun
.lp
= lp
= (struct lsav
*)alloc(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
->sun
.vp
= vp
= (struct vsav
*)alloc(sizeof (struct vsav
));
#define e(a,b) vp->a = mproc->b
if (ap
->a_stat
!= SZOMB
) {
vp
->v_majflt
= u
.u_vm
.vm_majflt
;
vp
->v_txtswrss
= xp
->x_swrss
;
sp
->sun
.u_pctcpu
= pcpu();
if (ap
->a_stat
!= SZOMB
) {
for (cp
= (char *)u
.u_stack
;
cp
< &user
.upages
[UPAGES
][NBPG
]; )
sp
->sun
.s_ssiz
= (&user
.upages
[UPAGES
][NBPG
] - 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
, arguutl
[UPAGES
+CLSIZE
];
size
= sflg
? ctob(UPAGES
) : sizeof (struct user
);
if ((mproc
->p_flag
& SLOAD
) == 0) {
lseek(swap
, ctob(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
= &Usrptma
[btokmx(mproc
->p_p0br
) + mproc
->p_szpt
- 1];
lseek(kmem
, kflg
? clear(pteaddr
) : (int)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",
ctob(apte
.pg_pfnum
+1) - (UPAGES
+CLSIZE
) * sizeof (struct pte
), 0);
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
, 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
);
int argi
[CLSIZE
*NBPG
/sizeof (int)];
if (mproc
->p_stat
== SZOMB
|| mproc
->p_flag
&(SSYS
|SWEXIT
))
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);
lseek(swap
, ctob(db
.db_base
), 0);
if (read(swap
, (char *)&argspac
, sizeof(argspac
))
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
== '=') {
strncpy(cmdbuf
, cp
, &argspac
.argc
[CLSIZE
*NBPG
] - cp
);
if (cp
[0] == '-' || cp
[0] == '?' || cp
[0] <= ' ') {
strncat(cmdbuf
, u
.u_comm
, sizeof(u
.u_comm
));
if (xflg == 0 && gflg == 0 && tptr == 0 && cp[0] == '-')
return (savestr(cmdbuf
));
fprintf(stderr
, "ps: error locating command name for pid %d\n",
strncat(cmdbuf
, u
.u_comm
, sizeof (u
.u_comm
));
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
->sun
.lp
;
printf("%6x%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
, ap
->a_size
/2, ap
->a_rss
/2);
printf(lp
->l_wchan
? " %5x" : " ", (int)lp
->l_wchan
&0xfffff);
printf(" %4.4s ", state(ap
));
printf("%3ld:%02ld", ap
->a_cpu
/ HZ
, ap
->a_cpu
% HZ
);
"USER PID %CPU %MEM SZ RSS TT STAT TIME";
register struct asav
*ap
= sp
->ap
;
vmsize
= (ap
->a_size
+ ap
->a_tsiz
)/2;
rmsize
+= ap
->a_txtrss
/ap
->a_xccount
/2;
printf("%-8.8s %5d%5.1f%5.1f%5d%5d",
getname(ap
->a_uid
), ap
->a_pid
, sp
->sun
.u_pctcpu
, pmem(ap
),
printf(" %4.4s", state(ap
));
" PID TT STAT TIME SL RE PAGEIN SIZE RSS SRS TSIZ TRS %CPU %MEM";
register struct vsav
*vp
= sp
->sun
.vp
;
register struct asav
*ap
= sp
->ap
;
printf("%5u ", ap
->a_pid
);
printf(" %4.4s", state(ap
));
printf("%3d%3d%7d%5d%5d%5d%5d%4d%5.1f%5.1f",
ap
->a_slptime
, ap
->a_time
> 99 ? 99 : ap
->a_time
, vp
->v_majflt
,
ap
->a_size
/2, ap
->a_rss
/2, vp
->v_swrss
/2,
ap
->a_tsiz
/2, ap
->a_txtrss
/2, vp
->v_pctcpu
, pmem(ap
));
register struct asav
*ap
= sp
->ap
;
printf("%4d ", sp
->sun
.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
? ' ' : 'W';
else if (ap
->a_nice
> NZERO
)
anom
= ap
->a_flag
& (SANOM
|SUANOM
) ? 'A' : ' ';
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
->sun
.u_pctcpu
> s1
->sun
.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
->sun
.vp
;
ap
->a_txtrss
/ (ap
->a_xccount
? ap
->a_xccount
: 1));
return (vp
->v_swrss
+ (ap
->a_xccount
? 0 : vp
->v_txtswrss
));
char names
[NUID
][NMAX
+1];
register struct passwd
*pw
;
struct passwd
*getpwent();
if (uid
>= 0 && uid
< NUID
&& names
[uid
][0])
while (pw
= getpwent()) {
if (names
[pw
->pw_uid
][0])
strncpy(names
[pw
->pw_uid
], pw
->pw_name
, NMAX
);
freebase
= (char *)sbrk(i
= size
> 2048 ? size
: 2048);
fprintf(stderr
, "ps: ran out of memory\n");
for (i
= size
; --i
>= 0; )
dp
= (char *)alloc(len
+1);