X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/b94a50ef4e4b58db7a7a3b1a6974c0d475d1ca4e..1c15e88899094343f75aeba04122cd96a96b428e:/usr/src/usr.sbin/pstat/pstat.c diff --git a/usr/src/usr.sbin/pstat/pstat.c b/usr/src/usr.sbin/pstat/pstat.c index 8d1a09eba8..78789cbe84 100644 --- a/usr/src/usr.sbin/pstat/pstat.c +++ b/usr/src/usr.sbin/pstat/pstat.c @@ -1,88 +1,133 @@ -#ifndef lint -static char *sccsid = "@(#)pstat.c 4.24 (Berkeley) %G%"; -#endif /* - * Print system stuff + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. */ -#define mask(x) (x&0377) -#define clear(x) ((int)x&0x7fffffff) +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ +#ifndef lint +static char sccsid[] = "@(#)pstat.c 5.26 (Berkeley) 6/29/90"; +#endif /* not lint */ + +/* + * Print system stuff + */ #include -#include -#define KERNEL -#include -#undef KERNEL #include #include #include -#include +#include +#include #include +#define KERNEL +#define NFS +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#undef KERNEL #include #include -#include #include -char *fcore = "/dev/kmem"; -char *fnlist = "/vmunix"; -int fc; +#include +#include +#include +#include "pathnames.h" + +#define mask(x) (x&0377) +#define clear(x) ((int)x &~ KERNBASE) + +char *fnlist = NULL; +char *fcore = NULL; struct nlist nl[] = { -#define SINODE 0 - { "_inode" }, -#define STEXT 1 +#define STEXT 0 { "_text" }, +#define SCONS 1 + { "_cons" }, #define SPROC 2 { "_proc" }, -#define SDZ 3 - { "_dz_tty" }, -#define SNDZ 4 - { "_dz_cnt" }, -#define SKL 5 - { "_cons" }, -#define SFIL 6 +#define SFIL 3 { "_file" }, -#define USRPTMA 7 - { "_Usrptmap" }, -#define USRPT 8 - { "_usrpt" }, -#define SWAPMAP 9 +#define SWAPMAP 4 { "_swapmap" }, -#define SDH 10 - { "_dh11" }, -#define SNDH 11 - { "_ndh11" }, -#define SNPROC 12 +#define SNPROC 5 { "_nproc" }, -#define SNTEXT 13 +#define SNTEXT 6 { "_ntext" }, -#define SNFILE 14 +#define SNFILE 7 { "_nfile" }, -#define SNINODE 15 - { "_ninode" }, -#define SNSWAPMAP 16 +#define SNSWAPMAP 8 { "_nswapmap" }, -#define SPTY 17 +#define SPTY 9 { "_pt_tty" }, -#define SDMMIN 18 +#define SDMMIN 10 { "_dmmin" }, -#define SDMMAX 19 +#define SDMMAX 11 { "_dmmax" }, -#define SNSWDEV 20 +#define SNSWDEV 12 { "_nswdev" }, -#define SSWDEVT 21 +#define SSWDEVT 13 { "_swdevt" }, +#define SNPTY 14 + { "_npty" }, +#ifdef vax +#define SDZ (SNPTY+1) + { "_dz_tty" }, +#define SNDZ (SNPTY+2) + { "_dz_cnt" }, +#define SDMF (SNPTY+3) + { "_dmf_tty" }, +#define SNDMF (SNPTY+4) + { "_ndmf" }, +#define SDH (SNPTY+5) + { "_dh11" }, +#define SNDH (SNPTY+6) + { "_ndh11" }, +#define SDHU (SNPTY+7) + { "_dhu_tty" }, +#define SNDHU (SNPTY+8) + { "_ndhu" }, +#define SDMZ (SNPTY+9) + { "_dmz_tty" }, +#define SNDMZ (SNPTY+10) + { "_ndmz" }, +#define SQD (SNPTY+11) + { "_qd_tty" }, +#define SNQD (SNPTY+12) + { "_nNQD" }, +#endif +#ifdef tahoe +#define SVX (SNPTY+1) + { "_vx_tty" }, +#define SNVX (SNPTY+2) + { "_nvx" }, +#define SMP (SNPTY+3) + { "_mp_tty" }, +#define SNMP (SNPTY+4) + { "_nmp" }, +#endif { "" } }; -int inof; +int vnof; int txtf; int prcf; int ttyf; int usrf; -long ubase; +int upid; int filf; int swpf; int totflg; @@ -90,96 +135,83 @@ char partab[1]; struct cdevsw cdevsw[1]; struct bdevsw bdevsw[1]; int allflg; -int kflg; -struct pte *Usrptma; -struct pte *usrpt; +int nflg; +u_long getword(); +off_t mkphys(); + +char *Program; main(argc, argv) -char **argv; + int argc; + char **argv; { - register char *argp; - int allflags; - - argc--, argv++; - while (argc > 0 && **argv == '-') { - argp = *argv++; - argp++; - argc--; - while (*argp++) - switch (argp[-1]) { + extern char *optarg; + extern int optind; + int ch; + Program = argv[0]; + while ((ch = getopt(argc, argv, "Tafvikptu:sxn")) != EOF) + switch((char)ch) { case 'T': totflg++; break; - case 'a': allflg++; - break; - - case 'i': - inof++; - break; - - case 'k': - kflg++; - fcore = "/vmcore"; - break; - - case 'x': - txtf++; - break; - + /*FALLTHROUGH*/ case 'p': prcf++; break; - + case 'f': + filf++; + break; + case 'v': + case 'i': + vnof++; + break; case 't': ttyf++; break; - case 'u': - if (argc == 0) - break; - argc--; usrf++; - sscanf( *argv++, "%x", &ubase); - break; - - case 'f': - filf++; + sscanf(optarg, "%d", &upid); break; case 's': swpf++; break; + case 'x': + txtf++; + break; + case 'n': + nflg++; + break; + case '?': default: - usage(); + printf("usage: pstat -[Tafiptsx] [-u [pid]] [system] [core]\n"); exit(1); } - } - if (argc>1) + argc -= optind; + argv += optind; + + if (argc > 1) fcore = argv[1]; - if ((fc = open(fcore, 0)) < 0) { - printf("Can't find %s\n", fcore); + if (argc > 0) + fnlist = argv[0]; + if (kvm_openfiles(fnlist, fcore, NULL) == -1) { + syserror("kvm_openfiles: %s", kvm_geterr()); exit(1); } - if (argc>0) - fnlist = argv[0]; - nlist(fnlist, nl); - usrpt = (struct pte *)nl[USRPT].n_value; - Usrptma = (struct pte *)nl[USRPTMA].n_value; - if (nl[0].n_type == 0) { - printf("no namelist\n"); + if (kvm_nlist(nl) != 0) { + syserror("kvm_nlist: %s", kvm_geterr()); exit(1); } - allflags = filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf; - if (allflags == 0) { - printf("pstat: one or more of -[aixptfsu] is required\n"); + if (!(filf | totflg | vnof | prcf | txtf | ttyf | usrf | swpf)) { + printf("pstat: one or more of -[aivxptfsu] is required\n"); exit(1); } if (filf||totflg) dofile(); - if (inof||totflg) - doinode(); + if (vnof||totflg) + dovnode(); if (prcf||totflg) doproc(); if (txtf||totflg) @@ -192,75 +224,429 @@ char **argv; doswap(); } -usage() -{ - - printf("usage: pstat -[aixptfs] [-u [ubase]] [system] [core]\n"); -} +struct e_vnode { + struct vnode *avnode; + struct vnode vnode; +}; -doinode() +dovnode() { + register struct e_vnode *e_vnodebase, *endvnode, *evp; + register struct vnode *vp; + register struct mount *maddr = NULL, *mp; register struct inode *ip; - struct inode *xinode, *ainode; - register int nin; - int ninode; - - nin = 0; - ninode = getw(nl[SNINODE].n_value); - xinode = (struct inode *)calloc(ninode, sizeof (struct inode)); - lseek(fc, (int)(ainode = (struct inode *)getw(nl[SINODE].n_value)), 0); - read(fc, xinode, ninode * sizeof(struct inode)); - for (ip = xinode; ip < &xinode[ninode]; ip++) - if (ip->i_count) - nin++; + int numvnodes; + struct e_vnode *loadvnodes(); + struct mount *getmnt(); + + e_vnodebase = loadvnodes(&numvnodes); if (totflg) { - printf("%3d/%3d inodes\n", nin, ninode); + printf("%7d vnodes\n", numvnodes); return; } - printf("%d/%d active inodes\n", nin, ninode); -printf(" LOC FLAGS CNT DEVICE RDC WRC INO MODE NLK UID SIZE/DEV\n"); - for (ip = xinode; ip < &xinode[ninode]; ip++) { - if (ip->i_count == 0) - continue; - printf("%8.1x ", ainode + (ip - xinode)); - putf(ip->i_flag&ILOCKED, 'L'); - putf(ip->i_flag&IUPD, 'U'); - putf(ip->i_flag&IACC, 'A'); - putf(ip->i_flag&IMOUNT, 'M'); - putf(ip->i_flag&IWANT, 'W'); - putf(ip->i_flag&ITEXT, 'T'); - putf(ip->i_flag&ICHG, 'C'); - putf(ip->i_flag&ISHLOCK, 'S'); - putf(ip->i_flag&IEXLOCK, 'E'); - putf(ip->i_flag&ILWAIT, 'Z'); - printf("%4d", ip->i_count&0377); - printf("%4d,%3d", major(ip->i_dev), minor(ip->i_dev)); - printf("%4d", ip->i_shlockc&0377); - printf("%4d", ip->i_exlockc&0377); - printf("%6d", ip->i_number); - printf("%6x", ip->i_mode & 0xffff); - printf("%4d", ip->i_nlink); - printf("%4d", ip->i_uid); - if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR) - printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev)); - else - printf("%10ld", ip->i_size); + endvnode = e_vnodebase + numvnodes; + printf("%d active vnodes\n", numvnodes); + + +#define ST mp->mnt_stat + for (evp = e_vnodebase; evp < endvnode; evp++) { + vp = &evp->vnode; + if (vp->v_mount != maddr) { + /* + * New filesystem + */ + if ((mp = getmnt(vp->v_mount)) == NULL) + continue; + maddr = vp->v_mount; + mount_print(mp); + vnode_header(); + switch(ST.f_type) { + case MOUNT_UFS: + case MOUNT_MFS: + ufs_header(); + break; + case MOUNT_NFS: + nfs_header(); + break; + case MOUNT_NONE: + case MOUNT_PC: + default: + break; + } + printf("\n"); + } + vnode_print(evp->avnode, vp); + switch(ST.f_type) { + case MOUNT_UFS: + case MOUNT_MFS: + ufs_print(vp); + break; + case MOUNT_NFS: + nfs_print(vp); + break; + case MOUNT_NONE: + case MOUNT_PC: + default: + break; + } printf("\n"); } - free(xinode); + free(e_vnodebase); } -getw(loc) +vnode_header() +{ + printf("ADDR TYP VFLAG USE REF"); +} + +vnode_print(avnode, vp) + struct vnode *avnode; + struct vnode *vp; +{ + char *type, flags[16]; + char *fp = flags; + register flag; + + /* + * set type + */ + switch(vp->v_type) { + case VNON: + type = "non"; break; + case VREG: + type = "reg"; break; + case VDIR: + type = "dir"; break; + case VBLK: + type = "blk"; break; + case VCHR: + type = "chr"; break; + case VLNK: + type = "lnk"; break; + case VSOCK: + type = "soc"; break; + case VFIFO: + type = "fif"; break; + case VBAD: + type = "bad"; break; + default: + type = "unk"; break; + } + /* + * gather flags + */ + flag = vp->v_flag; + if (flag & VROOT) + *fp++ = 'R'; + if (flag & VTEXT) + *fp++ = 'T'; + if (flag & VXLOCK) + *fp++ = 'L'; + if (flag & VXWANT) + *fp++ = 'W'; + if (flag & VEXLOCK) + *fp++ = 'E'; + if (flag & VSHLOCK) + *fp++ = 'S'; + if (flag & VLWAIT) + *fp++ = 'T'; + if (flag & VALIASED) + *fp++ = 'A'; + if (flag & VBWAIT) + *fp++ = 'B'; + if (flag == 0) + *fp++ = '-'; + *fp = '\0'; + /* + * print it + */ + printf("%8x %s %5s %4d %4d", + avnode, type, flags, vp->v_usecount, vp->v_holdcnt); +} + +ufs_header() +{ + printf(" FILEID IFLAG RDEV|SZ"); +} + +ufs_print(vp) + struct vnode *vp; +{ + struct inode *ip = VTOI(vp); + char flagbuf[16], *flags = flagbuf; + register flag; + char *name; + mode_t type; + extern char *devname(); + + flag = ip->i_flag; + if (flag & ILOCKED) + *flags++ = 'L'; + if (flag & IWANT) + *flags++ = 'W'; + if (flag & IRENAME) + *flags++ = 'R'; + if (flag & IUPD) + *flags++ = 'U'; + if (flag & IACC) + *flags++ = 'A'; + if (flag & ICHG) + *flags++ = 'C'; + if (flag & IMOD) + *flags++ = 'M'; + if (flag & ISHLOCK) + *flags++ = 'S'; + if (flag & IEXLOCK) + *flags++ = 'E'; + if (flag & ILWAIT) + *flags++ = 'Z'; + if (flag == 0) + *flags++ = '-'; + *flags = '\0'; + + 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)) + printf(" %2d,%-2d", + major(ip->i_rdev), minor(ip->i_rdev)); + else + printf(" %7s", name); + else + printf(" %7d", ip->i_size); +} + +nfs_header() +{ + printf(" FILEID NFLAG RDEV|SZ"); +} + +nfs_print(vp) + struct vnode *vp; +{ + struct nfsnode *np = VTONFS(vp); + char flagbuf[16], *flags = flagbuf; + register flag; + char *name; + mode_t type; + extern char *devname(); + + flag = np->n_flag; + if (flag & NLOCKED) + *flags++ = 'L'; + if (flag & NWANT) + *flags++ = 'W'; + if (flag & NMODIFIED) + *flags++ = 'M'; + if (flag & NWRITEERR) + *flags++ = 'E'; + if (flag == 0) + *flags++ = '-'; + *flags = '\0'; + +#define VT np->n_vattr + 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)) + printf(" %2d,%-2d", + major(VT.va_rdev), minor(VT.va_rdev)); + else + printf(" %7s", name); + else + printf(" %7d", np->n_size); +} + +/* + * Given a pointer to a mount structure in kernel space, + * read it in and return a usable pointer to it. + */ +struct mount * +getmnt(maddr) + struct mount *maddr; +{ + static struct mtab { + struct mtab *next; + struct mount *maddr; + struct mount mount; + } *mhead = NULL; + register struct mtab *mt; + + for (mt = mhead; mt != NULL; mt = mt->next) + if (maddr == mt->maddr) + return (&mt->mount); + if ((mt = (struct mtab *)malloc(sizeof (struct mtab))) == NULL) { + error("out of memory"); + exit(1); + } + if (kvm_read((off_t)maddr, &mt->mount, sizeof(struct mount)) != + sizeof(struct mount)) { + error("can't read mount table at %x", maddr); + return (NULL); + } + mt->maddr = maddr; + mt->next = mhead; + mhead = mt; + return (&mt->mount); +} + +mount_print(mp) + struct mount *mp; +{ + char *type = "unknown"; + register flags; + +#define ST mp->mnt_stat + printf("*** MOUNT "); + switch (ST.f_type) { + case MOUNT_NONE: + type = "none"; + break; + case MOUNT_UFS: + type = "ufs"; + break; + case MOUNT_NFS: + type = "nfs"; + break; + case MOUNT_MFS: + type = "mfs"; + break; + case MOUNT_PC: + type = "pc"; + break; + } + printf("%s %s on %s", type, ST.f_mntfromname, ST.f_mntonname); + if (flags = mp->mnt_flag) { + char *comma = "("; + + putchar(' '); + /* user visable flags */ + if (flags & MNT_RDONLY) { + printf("%srdonly", comma); + flags &= ~MNT_RDONLY; + comma = ","; + } + if (flags & MNT_SYNCHRONOUS) { + printf("%ssynchronous", comma); + flags &= ~MNT_SYNCHRONOUS; + comma = ","; + } + if (flags & MNT_NOEXEC) { + printf("%snoexec", comma); + flags &= ~MNT_NOEXEC; + comma = ","; + } + if (flags & MNT_NOSUID) { + printf("%snosuid", comma); + flags &= ~MNT_NOSUID; + comma = ","; + } + if (flags & MNT_NODEV) { + printf("%snodev", comma); + flags &= ~MNT_NODEV; + comma = ","; + } + if (flags & MNT_EXPORTED) { + printf("%sexport", comma); + flags &= ~MNT_EXPORTED; + comma = ","; + } + if (flags & MNT_EXRDONLY) { + printf("%sexrdonly", comma); + flags &= ~MNT_EXRDONLY; + comma = ","; + } + if (flags & MNT_LOCAL) { + printf("%slocal", comma); + flags &= ~MNT_LOCAL; + comma = ","; + } + if (flags & MNT_QUOTA) { + printf("%squota", comma); + flags &= ~MNT_QUOTA; + comma = ","; + } + /* filesystem control flags */ + if (flags & MNT_UPDATE) { + printf("%supdate", comma); + flags &= ~MNT_UPDATE; + comma = ","; + } + if (flags & MNT_MLOCK) { + printf("%slock", comma); + flags &= ~MNT_MLOCK; + comma = ","; + } + if (flags & MNT_MWAIT) { + printf("%swait", comma); + flags &= ~MNT_MWAIT; + comma = ","; + } + if (flags & MNT_MPBUSY) { + printf("%sbusy", comma); + flags &= ~MNT_MPBUSY; + comma = ","; + } + if (flags & MNT_MPWANT) { + printf("%swant", comma); + flags &= ~MNT_MPWANT; + comma = ","; + } + if (flags & MNT_UNMOUNT) { + printf("%sunmount", comma); + flags &= ~MNT_UNMOUNT; + comma = ","; + } + if (flags) + printf("%sunknown_flags:%x", flags); + printf(")"); + } + printf("\n"); +#undef ST +} + +struct e_vnode * +loadvnodes(avnodes) + int *avnodes; +{ + int ret, copysize, i; + struct e_vnode *vnodebase; + + if (fcore != NULL) { + error("vnodes on dead kernel, not impl yet\n"); + exit(1); + } + if ((ret = getkerninfo(KINFO_VNODE, NULL, NULL, 0)) == -1) { + syserror("can't get estimate for kerninfo"); + exit(1); + } + copysize = ret; + if ((vnodebase = (struct e_vnode *)malloc(copysize)) + == NULL) { + error("out of memory"); + exit(1); + } + if ((ret = getkerninfo(KINFO_VNODE, vnodebase, ©size, 0)) + == -1) { + syserror("can't get vnode list"); + exit(1); + } + if (copysize % sizeof (struct e_vnode)) { + error("vnode size mismatch"); + error(1); + } + *avnodes = copysize / sizeof (struct e_vnode); + + return (vnodebase); +} + +u_long +getword(loc) off_t loc; { - int word; - - if (kflg) - loc &= 0x7fffffff; - lseek(fc, loc, 0); - read(fc, &word, sizeof (word)); - if (kflg) - word &= 0x7fffffff; + u_long word; + + kvm_read(loc, &word, sizeof (word)); return (word); } @@ -277,40 +663,55 @@ dotext() register struct text *xp; int ntext; struct text *xtext, *atext; - int ntx; + int ntx, ntxca; - ntx = 0; - ntext = getw(nl[SNTEXT].n_value); + ntx = ntxca = 0; + ntext = getword(nl[SNTEXT].n_value); xtext = (struct text *)calloc(ntext, sizeof (struct text)); - lseek(fc, (int)(atext = (struct text *)getw(nl[STEXT].n_value)), 0); - read(fc, xtext, ntext * sizeof (struct text)); - for (xp = xtext; xp < &xtext[ntext]; xp++) - if (xp->x_iptr!=NULL) + atext = (struct text *)getword(nl[STEXT].n_value); + if (ntext < 0 || ntext > 10000) { + fprintf(stderr, "number of texts is preposterous (%d)\n", + ntext); + return; + } + if (xtext == NULL) { + fprintf(stderr, "can't allocate memory for text table\n"); + return; + } + kvm_read(atext, xtext, ntext * sizeof (struct text)); + for (xp = xtext; xp < &xtext[ntext]; xp++) { + if (xp->x_vptr != NULL) + ntxca++; + if (xp->x_count != 0) ntx++; + } if (totflg) { - printf("%3d/%3d texts\n", ntx, ntext); + printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca); return; } - printf("%d/%d active texts\n", ntx, ntext); - printf(" LOC FLAGS DADDR CADDR RSS SIZE IPTR CNT CCNT\n"); + printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca); + printf("\ + LOC FLAGS DADDR CADDR RSS SIZE VPTR CNT CCNT FORW BACK\n"); for (xp = xtext; xp < &xtext[ntext]; xp++) { - if (xp->x_iptr == NULL) + if (xp->x_vptr == NULL) continue; printf("%8.1x", atext + (xp - xtext)); printf(" "); - putf(xp->x_flag&XPAGI, 'P'); + putf(xp->x_flag&XPAGV, 'P'); putf(xp->x_flag&XTRC, 'T'); putf(xp->x_flag&XWRIT, 'W'); putf(xp->x_flag&XLOAD, 'L'); putf(xp->x_flag&XLOCK, 'K'); putf(xp->x_flag&XWANT, 'w'); printf("%5x", xp->x_daddr[0]); - printf("%11x", xp->x_caddr); + printf("%10x", xp->x_caddr); printf("%5d", xp->x_rssize); printf("%5d", xp->x_size); - printf("%10.1x", xp->x_iptr); + printf("%10.1x", xp->x_vptr); printf("%5d", xp->x_count&0377); printf("%5d", xp->x_ccount); + printf("%10x", xp->x_forw); + printf("%9x", xp->x_back); printf("\n"); } free(xtext); @@ -324,10 +725,19 @@ doproc() register loc, np; struct pte apte; - nproc = getw(nl[SNPROC].n_value); + nproc = getword(nl[SNPROC].n_value); xproc = (struct proc *)calloc(nproc, sizeof (struct proc)); - lseek(fc, (int)(aproc = (struct proc *)getw(nl[SPROC].n_value)), 0); - read(fc, xproc, nproc * sizeof (struct proc)); + aproc = (struct proc *)getword(nl[SPROC].n_value); + if (nproc < 0 || nproc > 10000) { + fprintf(stderr, "number of procs is preposterous (%d)\n", + nproc); + return; + } + if (xproc == NULL) { + fprintf(stderr, "can't allocate memory for proc table\n"); + return; + } + kvm_read(aproc, xproc, nproc * sizeof (struct proc)); np = 0; for (pp=xproc; pp < &xproc[nproc]; pp++) if (pp->p_stat) @@ -337,13 +747,13 @@ doproc() return; } printf("%d/%d processes\n", np, nproc); - printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PGRP PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP CLKT\n"); + printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n"); for (pp=xproc; pp<&xproc[nproc]; pp++) { if (pp->p_stat==0 && allflg==0) continue; printf("%8x", aproc + (pp - xproc)); printf(" %2d", pp->p_stat); - printf(" %4x", pp->p_flag & 0xffff); + printf(" %8x", pp->p_flag); printf(" %4d", pp->p_poip); printf(" %3d", pp->p_pri); printf(" %8x", pp->p_sig); @@ -352,14 +762,15 @@ doproc() printf(" %3d", pp->p_time); printf(" %4d", pp->p_cpu&0377); printf(" %3d", pp->p_nice); - printf(" %6d", pp->p_pgrp); printf(" %6d", pp->p_pid); printf(" %6d", pp->p_ppid); - if (kflg) - pp->p_addr = (struct pte *)clear((int)pp->p_addr); - lseek(fc, (long)(Usrptma+btokmx(pp->p_addr)), 0); - read(fc, &apte, sizeof(apte)); - printf(" %8x", ctob(apte.pg_pfnum+1) - sizeof(struct pte) * UPAGES); + /* + if (pp->p_flag & SLOAD) { + kvm_read(pp->p_addr, &apte, sizeof(apte)); + printf(" %8x", apte.pg_pfnum); + } else + printf(" %8x", pp->p_swaddr); + */ printf(" %4x", pp->p_rssize); printf(" %4x", pp->p_swrss); printf(" %5x", pp->p_dsize+pp->p_ssize); @@ -368,212 +779,279 @@ doproc() printf(" %7x", clear(pp->p_textp)); printf("\n"); } + free(xproc); } +char mesg[] = "LINE RAW CAN OUT RCC CCC OCC HWT LWT ADDR COL STATE PGID DISC\n"; +int ttyspace = 128; +struct tty *tty; + dotty() { - struct tty dz_tty[128]; - int ndz; - register struct tty *tp; - register char *mesg; + if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) { + printf("pstat: out of memory\n"); + return; + } printf("1 cons\n"); - if (kflg) - nl[SKL].n_value = clear(nl[SKL].n_value); - lseek(fc, (long)nl[SKL].n_value, 0); - read(fc, dz_tty, sizeof(dz_tty[0])); - mesg = " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP DISC\n"; + kvm_read((long)nl[SCONS].n_value, tty, sizeof(*tty)); + printf(mesg); + ttyprt(&tty[0], 0); +#ifdef vax + if (nl[SNQD].n_type != 0) + doqdss(); + 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); +#endif +#ifdef tahoe + if (nl[SNVX].n_type != 0) + dottytype("vx", SVX, SNVX); + if (nl[SNMP].n_type != 0) + dottytype("mp", SMP, SNMP); +#endif + 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. + */ +#ifdef vax +doqdss() +{ + int nqd; + register struct tty *tp; + + kvm_read((long)nl[SNQD].n_value, &nqd, sizeof(nqd)); + printf("%d qd\n", nqd); + kvm_read((long)nl[SQD].n_value, tty, nqd * sizeof(struct tty) * 4); + printf(mesg); + for (tp = tty; tp < &tty[nqd * 4]; tp += 4) + ttyprt(tp, tp - tty); +} +#endif + +dottytype(name, type, number) +char *name; +{ + int ntty; + register struct tty *tp; + extern char *realloc(); + + if (tty == (struct tty *)0) + return; + kvm_read((long)nl[number].n_value, &ntty, sizeof(ntty)); + printf("%d %s lines\n", ntty, name); + if (ntty > ttyspace) { + ttyspace = ntty; + if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { + printf("pstat: out of memory\n"); + return; + } + } + kvm_read((long)nl[type].n_value, tty, ntty * sizeof(struct tty)); printf(mesg); - ttyprt(&dz_tty[0], 0); - if (nl[SNDZ].n_type == 0) - goto dh; - if (kflg) { - nl[SNDZ].n_value = clear(nl[SNDZ].n_value); - nl[SDZ].n_value = clear(nl[SDZ].n_value); - } - lseek(fc, (long)nl[SNDZ].n_value, 0); - read(fc, &ndz, sizeof(ndz)); - printf("%d dz lines\n", ndz); - lseek(fc, (long)nl[SDZ].n_value, 0); - read(fc, dz_tty, ndz * sizeof (struct tty)); - for (tp = dz_tty; tp < &dz_tty[ndz]; tp++) - ttyprt(tp, tp - dz_tty); -dh: - if (nl[SNDH].n_type == 0) - goto pty; - if (kflg) { - nl[SNDH].n_value = clear(nl[SNDH].n_value); - nl[SDH].n_value = clear(nl[SDH].n_value); - } - lseek(fc, (long)nl[SNDH].n_value, 0); - read(fc, &ndz, sizeof(ndz)); - printf("%d dh lines\n", ndz); - lseek(fc, (long)nl[SDH].n_value, 0); - read(fc, dz_tty, ndz * sizeof(struct tty)); - for (tp = dz_tty; tp < &dz_tty[ndz]; tp++) - ttyprt(tp, tp - dz_tty); -pty: - if (nl[SPTY].n_type == 0) - goto pty; - if (kflg) { - nl[SPTY].n_value = clear(nl[SPTY].n_value); - } - printf("32 pty lines\n"); - lseek(fc, (long)nl[SPTY].n_value, 0); - read(fc, dz_tty, 32*sizeof(struct tty)); - for (tp = dz_tty; tp < &dz_tty[32]; tp++) - ttyprt(tp, tp - dz_tty); + for (tp = tty; tp < &tty[ntty]; tp++) + ttyprt(tp, tp - tty); } +struct { + int flag; + char val; +} ttystates[] = { + TS_WOPEN, 'W', + TS_ISOPEN, 'O', + TS_CARR_ON, 'C', + TS_TIMEOUT, 'T', + TS_FLUSH, 'F', + TS_BUSY, 'B', + TS_ASLEEP, 'A', + TS_XCLUDE, 'X', + TS_TTSTOP, 'S', + TS_HUPCLS, 'H', + TS_TBLOCK, 'K', + TS_RCOLL, 'R', + TS_WCOLL, 'I', /* running short on letters ! */ + TS_ASYNC, 'Y', + TS_BKSL, 'D', + TS_ERASE, 'E', + TS_LNCH, 'L', + TS_TYPEN, 'P', + TS_CNTTB, 'N', + 0, 0 +}; + ttyprt(atp, line) struct tty *atp; { register struct tty *tp; + char state[20]; + register i, j; + char *name; + extern char *devname(); + pid_t pgid; - printf("%2d", line); tp = atp; + if (nflg || tp->t_dev == 0 || /* XXX */ + (name = devname(tp->t_dev, S_IFCHR)) == NULL) + printf("%7d ", line); + else + printf("%7s ", name); + printf("%2d %3d ", tp->t_rawq.c_cc, tp->t_canq.c_cc); + printf("%3d %6d %6d %6d %4d %3d %8x %3d ", tp->t_outq.c_cc, + tp->t_rawcc, tp->t_cancc, tp->t_outcc, + 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; + state[j] = '\0'; + printf("%-4s ", state); + if (tp->t_pgrp == NULL || kvm_read(&tp->t_pgrp->pg_id, &pgid, + sizeof (pid_t)) != sizeof (pid_t)) + pgid = 0; + printf("%6d ", pgid); switch (tp->t_line) { -/* - case NETLDISC: - if (tp->t_rec) - printf("%4d%4d", 0, tp->t_inbuf); - else - printf("%4d%4d", tp->t_inbuf, 0); + case 0: + printf("term\n"); break; -*/ - - default: - printf("%4d", tp->t_rawq.c_cc); - printf("%4d", tp->t_canq.c_cc); - } - printf("%4d", tp->t_outq.c_cc); - printf("%8.1x", tp->t_flags); - printf(" %8.1x", tp->t_addr); - printf("%3d", tp->t_delct); - printf("%4d ", tp->t_col); - putf(tp->t_state&TS_TIMEOUT, 'T'); - putf(tp->t_state&TS_WOPEN, 'W'); - putf(tp->t_state&TS_ISOPEN, 'O'); - putf(tp->t_state&TS_CARR_ON, 'C'); - putf(tp->t_state&TS_BUSY, 'B'); - putf(tp->t_state&TS_ASLEEP, 'A'); - putf(tp->t_state&TS_XCLUDE, 'X'); - putf(tp->t_state&TS_HUPCLS, 'H'); - printf("%6d", tp->t_pgrp); - switch (tp->t_line) { - case NTTYDISC: - printf(" ntty"); + case TABLDISC: + printf("tab\n"); break; - case NETLDISC: - printf(" net"); + case SLIPDISC: + printf("slip\n"); break; + + default: + printf("%d\n", tp->t_line); } - printf("\n"); } dousr() { - struct user U; +#ifdef notyet + register struct user *up; register i, j, *ip; + register struct nameidata *nd = &U.u_nd; + struct proc *p; - /* This wins only if PAGSIZ > sizeof (struct user) */ - lseek(fc, ubase * NBPG, 0); - read(fc, &U, sizeof(U)); + /* This wins only if CLBYTES >= sizeof (struct user) */ + /* (WHICH IT ISN'T, but u. is going away - so who cares */ + if (kvm_getprocs(KINFO_PROC_PID, upid) != 0) { + error("kvm_getproc: %s", kvm_geterr()); + return (1); + } + if ((p = kvm_nextproc()); == NULL) { + error("kvm_nextproc: %s", kvm_geterr()); + return (1); + } + if (up = kvm_getu(p)) == NULL) { + error("kvm_getu: %s", kvm_geterr()); + return (1); + } printf("pcb"); - ip = (int *)&U.u_pcb; - while (ip < &U.u_arg[0]) { - if ((ip - (int *)&U.u_pcb) % 4 == 0) + ip = (int *)&up->u_pcb; + while (ip < &up->u_arg[0]) { + if ((ip - (int *)&up->u_pcb) % 4 == 0) printf("\t"); printf("%x ", *ip++); - if ((ip - (int *)&U.u_pcb) % 4 == 0) + if ((ip - (int *)&up->u_pcb) % 4 == 0) printf("\n"); } - if ((ip - (int *)&U.u_pcb) % 4 != 0) + if ((ip - (int *)&up->u_pcb) % 4 != 0) printf("\n"); - printf("arg\t"); - for (i=0; i<5; i++) - printf(" %.1x", U.u_arg[i]); - printf("\n"); - for (i=0; iu_arg)/sizeof(up->u_arg[0]); i++) { if (i%5==0) printf("\t"); - printf("%9.1x", U.u_ssave.val[i]); + printf(" %.1x", up->u_arg[i]); if (i%5==4) printf("\n"); } if (i%5) printf("\n"); - printf("segflg\t%d\nerror %d\n", U.u_segflg, U.u_error); - printf("uids\t%d,%d,%d,%d\n", U.u_uid,U.u_gid,U.u_ruid,U.u_rgid); - printf("procp\t%.1x\n", U.u_procp); - printf("ap\t%.1x\n", U.u_ap); - printf("r_val?\t%.1x %.1x\n", U.u_r.r_val1, U.u_r.r_val2); - printf("base, count, offset %.1x %.1x %ld\n", U.u_base, - U.u_count, U.u_offset); - printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir); - printf("dirp %.1x\n", U.u_dirp); - printf("dent %d %.14s\n", U.u_dent.d_ino, U.u_dent.d_name); - printf("pdir %.1o\n", U.u_pdir); - printf("file\t"); - for (i=0; i<10; i++) - printf("%9.1x", U.u_ofile[i]); - printf("\n\t"); - for (i=10; ini_segflg, up->u_error); + printf("uids\t%d,%d,%d,%d\n", up->u_uid,up->u_gid,up->u_ruid,up->u_rgid); + printf("procp\t%.1x\n", up->u_procp); + printf("ap\t%.1x\n", up->u_ap); + printf("r_val?\t%.1x %.1x\n", up->u_r.r_val1, up->u_r.r_val2); + printf("base, count, offset %.1x %.1x %ld\n", nd->ni_base, + nd->ni_count, nd->ni_offset); + printf("cdir rdir %.1x %.1x\n", up->u_cdir, up->u_rdir); + printf("dirp %.1x\n", nd->ni_dirp); + printf("dent %d %.14s\n", nd->ni_dent.d_ino, nd->ni_dent.d_name); + printf("dvp vp %.1x %.1x\n", nd->ni_dvp, nd->ni_vp); + printf("file"); + for (i=0; iu_ofile[i]); + if (i % 8 == 7) + printf("\n"); + } + if (i % 8) + printf("\n"); + printf("pofile"); + for (i=0; iu_pofile[i]); + if (i % 8 == 7) + printf("\n"); + } + if (i % 8) + printf("\n"); printf("ssave"); for (i=0; iu_ssave.val[i]); if (i%5==4) printf("\n"); } if (i%5) printf("\n"); - printf("sigs\t"); - for (i=0; iu_signal[i]); + if (i % 8 == 7) + printf("\n"); + } + if (i % 8) + printf("\n"); + printf("code\t%.1x\n", up->u_code); + printf("ar0\t%.1x\n", up->u_ar0); + printf("prof\t%x %x %x %x\n", up->u_prof.pr_base, up->u_prof.pr_size, + up->u_prof.pr_off, up->u_prof.pr_scale); + printf("start\t%ld\n", up->u_start.tv_sec); + printf("acflag\t%ld\n", up->u_acflag); + printf("cmask\t%ld\n", up->u_cmask); + printf("sizes\t%.1x %.1x %.1x\n", up->u_tsize, up->u_dsize, up->u_ssize); printf("ru\t"); - ip = (int *)&U.u_ru; - for (i = 0; i < sizeof(U.u_ru)/sizeof(int); i++) - printf("%D ", ip[i]); + ip = (int *)&up->u_ru; + for (i = 0; i < sizeof(up->u_ru)/sizeof(int); i++) + printf("%ld ", ip[i]); printf("\n"); - ip = (int *)&U.u_cru; + ip = (int *)&up->u_cru; printf("cru\t"); - for (i = 0; i < sizeof(U.u_cru)/sizeof(int); i++) - printf("%D ", ip[i]); + for (i = 0; i < sizeof(up->u_cru)/sizeof(int); i++) + printf("%ld ", ip[i]); printf("\n"); -/* - i = U.u_stack - &U; +#ifdef notdef + i = up->u_stack - &U; while (U[++i] == 0); i &= ~07; while (i < 512) { @@ -582,7 +1060,8 @@ dousr() printf("%9x", U[i++]); printf("\n"); } -*/ +#endif +#endif } oatoi(s) @@ -606,10 +1085,19 @@ dofile() static char *dtypes[] = { "???", "inode", "socket" }; nf = 0; - nfile = getw(nl[SNFILE].n_value); + nfile = getword(nl[SNFILE].n_value); xfile = (struct file *)calloc(nfile, sizeof (struct file)); - lseek(fc, (int)(afile = (struct file *)getw(nl[SFIL].n_value)), 0); - read(fc, xfile, nfile * sizeof (struct file)); + afile = (struct file *)getword(nl[SFIL].n_value); + if (nfile < 0 || nfile > 10000) { + fprintf(stderr, "number of files is preposterous (%d)\n", + nfile); + return; + } + if (xfile == NULL) { + fprintf(stderr, "can't allocate memory for file table\n"); + return; + } + kvm_read(afile, xfile, nfile * sizeof (struct file)); for (fp=xfile; fp < &xfile[nfile]; fp++) if (fp->f_count) nf++; @@ -626,7 +1114,7 @@ dofile() if (fp->f_type <= DTYPE_SOCKET) printf("%-8.8s", dtypes[fp->f_type]); else - printf("8d", fp->f_type); + printf("%8d", fp->f_type); putf(fp->f_flag&FREAD, 'R'); putf(fp->f_flag&FWRITE, 'W'); putf(fp->f_flag&FAPPEND, 'A'); @@ -641,6 +1129,7 @@ dofile() else printf(" %ld\n", fp->f_offset); } + free(xfile); } int dmmin, dmmax, nswdev; @@ -660,40 +1149,60 @@ doswap() register struct mapent *me; register struct text *xp; int i, j; + long rmalloc(); - nproc = getw(nl[SNPROC].n_value); + nproc = getword(nl[SNPROC].n_value); + ntext = getword(nl[SNTEXT].n_value); + if (nproc < 0 || nproc > 10000 || ntext < 0 || ntext > 10000) { + fprintf(stderr, "number of procs/texts is preposterous (%d, %d)\n", + nproc, ntext); + return; + } proc = (struct proc *)calloc(nproc, sizeof (struct proc)); - ntext = getw(nl[SNTEXT].n_value); + if (proc == NULL) { + fprintf(stderr, "can't allocate memory for proc table\n"); + exit(1); + } xtext = (struct text *)calloc(ntext, sizeof (struct text)); - nswapmap = getw(nl[SNSWAPMAP].n_value); + if (xtext == NULL) { + fprintf(stderr, "can't allocate memory for text table\n"); + exit(1); + } + nswapmap = getword(nl[SNSWAPMAP].n_value); swapmap = (struct map *)calloc(nswapmap, sizeof (struct map)); - nswdev = getw(nl[SNSWDEV].n_value); + if (swapmap == NULL) { + fprintf(stderr, "can't allocate memory for swapmap\n"); + exit(1); + } + nswdev = getword(nl[SNSWDEV].n_value); swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); - lseek(fc, nl[SSWDEVT].n_value, L_SET); - read(fc, swdevt, nswdev * sizeof (struct swdevt)); - lseek(fc, getw(nl[SPROC].n_value), 0); - read(fc, proc, nproc * sizeof (struct proc)); - lseek(fc, getw(nl[STEXT].n_value), 0); - read(fc, xtext, ntext * sizeof (struct text)); - lseek(fc, getw(nl[SWAPMAP].n_value), 0); - read(fc, swapmap, nswapmap * sizeof (struct map)); + if (swdevt == NULL) { + fprintf(stderr, "can't allocate memory for swdevt table\n"); + exit(1); + } + kvm_read(nl[SSWDEVT].n_value, swdevt, nswdev * sizeof (struct swdevt)); + kvm_read(nl[SPROC].n_value, proc, nproc * sizeof (struct proc)); + kvm_read(nl[STEXT].n_value, xtext, ntext * sizeof (struct text)); + kvm_read(nl[SWAPMAP].n_value, swapmap, nswapmap * sizeof (struct map)); + swapmap->m_name = "swap"; swapmap->m_limit = (struct mapent *)&swapmap[nswapmap]; - dmmin = getw(nl[SDMMIN].n_value); - dmmax = getw(nl[SDMMAX].n_value); + dmmin = getword(nl[SDMMIN].n_value); + dmmax = getword(nl[SDMMAX].n_value); nswap = 0; for (sw = swdevt; sw < &swdevt[nswdev]; sw++) - nswap += sw->sw_nblks, + if (sw->sw_freed) + nswap += sw->sw_nblks; free = 0; for (me = (struct mapent *)(swapmap+1); me < (struct mapent *)&swapmap[nswapmap]; me++) free += me->m_size; tused = 0; for (xp = xtext; xp < &xtext[ntext]; xp++) - if (xp->x_iptr!=NULL) { - tused += ctod(xp->x_size); - if (xp->x_flag & XPAGI) - tused += ctod(ctopt(xp->x_size)); + if (xp->x_vptr!=NULL) { + tused += ctod(clrnd(xp->x_size)); + if (xp->x_flag & XPAGV) + tused += ctod(clrnd(ctopt(xp->x_size))); } used = tused; waste = 0; @@ -709,7 +1218,7 @@ doswap() used += sb; waste += sb - db; if ((pp->p_flag&SLOAD) == 0) - used += vusize(pp); + used += ctod(vusize(pp)); } if (totflg) { #define btok(x) ((x) / (1024 / DEV_BSIZE)) @@ -942,3 +1451,35 @@ done: badrmfree: printf("bad rmfree\n"); } + +#include + +error(va_alist) + va_dcl +{ + char *fmt; + va_list ap; + extern errno; + + fprintf(stderr, "%s: ", Program); + va_start(ap); + fmt = va_arg(ap, char *); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +syserror(va_alist) + va_dcl +{ + char *fmt; + va_list ap; + extern errno; + + fprintf(stderr, "%s: ", Program); + va_start(ap); + fmt = va_arg(ap, char *); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, ": %s\n", strerror(errno)); +}