* Copyright (c) 1980, 1991 The Regents of the University of California.
* %sccs.include.proprietary.c%
"@(#) Copyright (c) 1980, 1991 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)pstat.c 5.39 (Berkeley) %G%";
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
/* #include <nfs/nfsv2.h> */
/* #include <nfs/nfs.h> */
#define clear(x) ((int)x &~ KERNBASE)
#define NLMANDATORY SSWDEVT /* names up to here are mandatory */
#define SCONS NLMANDATORY + 1
#define SPTY NLMANDATORY + 2
#define SNPTY NLMANDATORY + 3
char buf
[_POSIX2_LINE_MAX
];
while ((ch
= getopt(argc
, argv
, "TafvikptU:sxnu")) != EOF
)
sscanf(optarg
, "%d", &upid
);
fprintf(stderr
, "pstat: use [ -U pid ] for -u\n");
* Discard setgid privileges if not the running kernel so that bad
* guys can't print interesting stuff from kernel memory.
if (nlistf
!= NULL
|| memf
!= NULL
)
if ((kd
= kvm_openfiles(nlistf
, memf
, NULL
, O_RDONLY
, buf
)) == 0) {
error("kvm_openfiles: %s", buf
);
if ((ret
= kvm_nlist(kd
, nl
)) != 0) {
error("kvm_nlist: %s", kvm_geterr(kd
));
for (i
= 0; i
<= NLMANDATORY
; i
++) {
error("undefined symbol: %s\n",
if (!(filf
| totflg
| vnof
| prcf
| txtf
| ttyf
| usrf
| swpf
))
"usage: pstat -[Tafiptsx] [-U [pid]] [system] [core]\n");
register struct e_vnode
*e_vnodebase
, *endvnode
, *evp
;
register struct vnode
*vp
;
register struct mount
*maddr
= NULL
, *mp
;
struct e_vnode
*loadvnodes();
e_vnodebase
= loadvnodes(&numvnodes
);
printf("%7d vnodes\n", numvnodes
);
endvnode
= e_vnodebase
+ numvnodes
;
printf("%d active vnodes\n", numvnodes
);
for (evp
= e_vnodebase
; evp
< endvnode
; evp
++) {
if (vp
->v_mount
!= maddr
) {
if ((mp
= getmnt(vp
->v_mount
)) == NULL
)
vnode_print(evp
->avnode
, vp
);
printf("ADDR TYP VFLAG USE HOLD");
printf("%8x %s %5s %4d %4d",
avnode
, type
, flags
, vp
->v_usecount
, vp
->v_holdcnt
);
printf(" FILEID IFLAG RDEV|SZ");
struct inode inode
, *ip
= &inode
;
char flagbuf
[16], *flags
= flagbuf
;
if (kvm_read(kd
, V(VTOI(vp
)), &inode
, sizeof(struct inode
)) !=
error("can't read inode for %x", vp
);
printf(" %6d %5s", ip
->i_number
, flagbuf
);
type
= ip
->i_mode
& S_IFMT
;
if (type
== S_IFCHR
|| type
== S_IFBLK
)
if (nflg
|| ((name
= devname(ip
->i_rdev
, type
)) == NULL
))
major(ip
->i_rdev
), minor(ip
->i_rdev
));
printf(" %7qd", ip
->i_size
);
printf(" FILEID NFLAG RDEV|SZ");
struct nfsnode nfsnode
, *np
= &nfsnode
;
char flagbuf
[16], *flags
= flagbuf
;
if (kvm_read(kd
, V(VTONFS(vp
)), &nfsnode
, sizeof(struct nfsnode
)) !=
sizeof(struct nfsnode
)) {
error("can't read nfsnode for %x", vp
);
if (flag
& NQNFSNONCACHE
)
printf(" %6d %5s", VT
.va_fileid
, flagbuf
);
type
= VT
.va_mode
& S_IFMT
;
if (type
== S_IFCHR
|| type
== S_IFBLK
)
if (nflg
|| ((name
= devname(VT
.va_rdev
, type
)) == NULL
))
major(VT
.va_rdev
), minor(VT
.va_rdev
));
printf(" %7qd", np
->n_size
);
* Given a pointer to a mount structure in kernel space,
* read it in and return a usable pointer to it.
register struct mtab
*mt
;
for (mt
= mhead
; mt
!= NULL
; mt
= mt
->next
)
if ((mt
= (struct mtab
*)malloc(sizeof (struct mtab
))) == NULL
) {
if (kvm_read(kd
, V(maddr
), &mt
->mount
, sizeof(struct mount
)) !=
error("can't read mount table at %x", maddr
);
printf("%s %s on %s", type
, ST
.f_mntfromname
, ST
.f_mntonname
);
if (flags
= mp
->mnt_flag
) {
if (flags
& MNT_RDONLY
) {
printf("%srdonly", comma
);
if (flags
& MNT_SYNCHRONOUS
) {
printf("%ssynchronous", comma
);
flags
&= ~MNT_SYNCHRONOUS
;
if (flags
& MNT_NOEXEC
) {
printf("%snoexec", comma
);
if (flags
& MNT_NOSUID
) {
printf("%snosuid", comma
);
printf("%snodev", comma
);
if (flags
& MNT_EXPORTED
) {
printf("%sexport", comma
);
if (flags
& MNT_EXRDONLY
) {
printf("%sexrdonly", comma
);
printf("%slocal", comma
);
printf("%squota", comma
);
/* filesystem control flags */
if (flags
& MNT_UPDATE
) {
printf("%supdate", comma
);
if (flags
& MNT_MPBUSY
) {
if (flags
& MNT_MPWANT
) {
if (flags
& MNT_UNMOUNT
) {
printf("%sunmount", comma
);
printf("%sunknown_flags:%x", flags
);
struct e_vnode
*vnodebase
;
struct e_vnode
*kinfo_vnodes();
return (kinfo_vnodes(avnodes
));
if (sysctl(mib
, 2, NULL
, ©size
, NULL
, 0) == -1) {
syserror("can't get estimate from sysctl");
if ((vnodebase
= (struct e_vnode
*)malloc(copysize
)) == NULL
) {
if (sysctl(mib
, 2, vnodebase
, ©size
, NULL
, 0) == -1) {
syserror("can't get vnode list");
if (copysize
% sizeof (struct e_vnode
)) {
error("vnode size mismatch");
*avnodes
= copysize
/ sizeof (struct e_vnode
);
* simulate what a running kernel does in in kinfo_vnode
struct mount
*rootfs
, *mp
, mount
;
#define VPTRSZ sizeof (struct vnode *)
#define VNODESZ sizeof (struct vnode)
#define NVAL(indx) vnl[(indx)].n_value
if (kvm_nlist(kd
, vnl
) != 0) {
error("nlist vnl: %s", kvm_geterr(kd
));
numvnodes
= getword(NVAL(V_NUMV
));
if ((vbuf
= (char *)malloc((numvnodes
+ 20) * (VPTRSZ
+ VNODESZ
)))
evbuf
= vbuf
+ (numvnodes
+ 20) * (VPTRSZ
+ VNODESZ
);
mp
= rootfs
= (struct mount
*)getword(NVAL(V_ROOTFS
));
kvm_read(kd
, V(mp
), &mount
, sizeof(mount
));
for (vp
= mount
.mnt_mounth
; vp
; vp
= vnode
.v_mountf
) {
kvm_read(kd
, V(vp
), &vnode
, sizeof (vnode
));
if ((bp
+ VPTRSZ
+ VNODESZ
) > evbuf
) {
/* XXX - should realloc */
fprintf(stderr
, "pstat: ran out of room for vnodes\n");
bcopy(&vnode
, bp
, VNODESZ
);
return ((struct e_vnode
*)vbuf
);
kvm_read(kd
, V(loc
), &word
, sizeof (word
));
printf("no text table in this system\n");
printf("pstat: -p no longer supported (use ps)\n");
char mesg
[] = " LINE RAW CAN OUT HWT LWT ADDR COL STATE SESS PGID DISC\n";
if ((tty
= (struct tty
*)malloc(ttyspace
* sizeof(*tty
))) == 0) {
printf("pstat: out of memory\n");
kvm_read(kd
, V(nl
[SCONS
].n_value
), tty
, sizeof(*tty
));
if (nl
[SNQD
].n_type
!= 0)
if (nl
[SNDZ
].n_type
!= 0)
dottytype("dz", SDZ
, SNDZ
);
if (nl
[SNDH
].n_type
!= 0)
dottytype("dh", SDH
, SNDH
);
if (nl
[SNDMF
].n_type
!= 0)
dottytype("dmf", SDMF
, SNDMF
);
if (nl
[SNDHU
].n_type
!= 0)
dottytype("dhu", SDHU
, SNDHU
);
if (nl
[SNDMZ
].n_type
!= 0)
dottytype("dmz", SDMZ
, SNDMZ
);
if (nl
[SNVX
].n_type
!= 0)
dottytype("vx", SVX
, SNVX
);
if (nl
[SNMP
].n_type
!= 0)
dottytype("mp", SMP
, SNMP
);
if (nl
[SNITE
].n_type
!= 0)
dottytype("ite", SITE
, SNITE
);
if (nl
[SNDCA
].n_type
!= 0)
dottytype("dca", SDCA
, SNDCA
);
if (nl
[SNDCM
].n_type
!= 0)
dottytype("dcm", SDCM
, SNDCM
);
if (nl
[SNDCL
].n_type
!= 0)
dottytype("dcl", SDCL
, SNDCL
);
if (nl
[SNPTY
].n_type
!= 0)
dottytype("pty", SPTY
, SNPTY
);
* Special case the qdss: there are 4 ttys per qdss,
* but only the first of each is used as a tty.
kvm_read(kd
, V(nl
[SNQD
].n_value
), &nqd
, sizeof(nqd
));
kvm_read(kd
, V(nl
[SQD
].n_value
), tty
, nqd
* sizeof(struct tty
) * 4);
for (tp
= tty
; tp
< &tty
[nqd
* 4]; tp
+= 4)
dottytype(name
, type
, number
)
if (tty
== (struct tty
*)0)
kvm_read(kd
, V(nl
[number
].n_value
), &ntty
, sizeof(ntty
));
printf("%d %s %s\n", ntty
, name
, (ntty
== 1) ? "line" :
if ((tty
= (struct tty
*)realloc(tty
, ttyspace
* sizeof(*tty
))) == 0) {
printf("pstat: out of memory\n");
kvm_read(kd
, V(nl
[type
].n_value
), tty
, ntty
* sizeof(struct tty
));
for (tp
= tty
; tp
< &tty
[ntty
]; tp
++)
if (nflg
|| tp
->t_dev
== 0 ||
(name
= devname(tp
->t_dev
, S_IFCHR
)) == NULL
)
printf("%2d %3d ", tp
->t_rawq
.c_cc
, tp
->t_canq
.c_cc
);
printf("%3d %4d %3d %8x %3d ", tp
->t_outq
.c_cc
,
tp
->t_hiwat
, tp
->t_lowat
, tp
->t_addr
, tp
->t_col
);
for (i
= j
= 0; ttystates
[i
].flag
; i
++)
if (tp
->t_state
&ttystates
[i
].flag
)
state
[j
++] = ttystates
[i
].val
;
printf("%-4s %6x", state
, (u_long
)tp
->t_session
& ~KERNBASE
);
if (tp
->t_pgrp
== NULL
|| kvm_read(kd
, V(&tp
->t_pgrp
->pg_id
), &pgid
,
sizeof (pid_t
)) != sizeof (pid_t
))
printf("%d\n", tp
->t_line
);
* The user structure is going away. What's left here won't
printf("nothing left in user structure in this system\n");
register struct file
*fp
;
static char *dtypes
[] = { "???", "inode", "socket" };
if (kvm_nlist(kd
, fnl
) != 0) {
error("kvm_nlist: no _nfiles or _maxfiles: %s",
kvm_read(kd
, V(fnl
[FNL_MAXFILE
].n_value
), &maxfile
,
kvm_read(kd
, V(fnl
[FNL_NFILE
].n_value
), &nfile
, sizeof (nfile
));
printf("%3d/%3d files\n", nfile
, maxfile
);
if (getfiles(&buf
, &len
) == -1)
* getfiles returns in malloc'd buf a pointer to the first file
* structure, and then an array of file structs (whose
* addresses are derivable from the previous entry)
addr
= *((struct file
**)buf
);
fp
= (struct file
*)(buf
+ sizeof (struct file
*));
nfile
= (len
- sizeof (struct file
*)) / sizeof (struct file
);
printf("%d/%d open files\n", nfile
, maxfile
);
printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n");
for (; (char *)fp
< buf
+ len
; addr
= fp
->f_filef
, fp
++) {
if ((unsigned)fp
->f_type
> DTYPE_SOCKET
)
printf("%-8.8s", dtypes
[fp
->f_type
]);
putf(fp
->f_flag
&FREAD
, 'R');
putf(fp
->f_flag
&FWRITE
, 'W');
putf(fp
->f_flag
&FAPPEND
, 'A');
#ifdef FSHLOCK /* currently gone */
putf(fp
->f_flag
&FSHLOCK
, 'S');
putf(fp
->f_flag
&FEXLOCK
, 'X');
putf(fp
->f_flag
&FASYNC
, 'I');
printf(" %3d", fp
->f_count
);
printf(" %3d", fp
->f_msgcount
);
printf(" %8.1x", fp
->f_data
);
printf(" %x\n", fp
->f_offset
);
printf(" %ld\n", fp
->f_offset
);
* add emulation of KINFO_FILE here
error("files on dead kernel, not impl\n");
if (sysctl(mib
, 2, NULL
, &len
, NULL
, 0) == -1) {
syserror("sysctl size estimate");
if ((buf
= (char *)malloc(len
)) == NULL
) {
if (sysctl(mib
, 2, buf
, &len
, NULL
, 0) == -1) {
printf("swap statistics not yet supported in this system\n");
fprintf(stderr
, "pstat: ");
fmt
= va_arg(ap
, char *);
(void) vfprintf(stderr
, fmt
, ap
);
fprintf(stderr
, "pstat: ");
fmt
= va_arg(ap
, char *);
(void) vfprintf(stderr
, fmt
, ap
);
fprintf(stderr
, ": %s\n", strerror(errno
));