use getopt; fix usage statement; -a should imply -p; minor cleanups
[unix-history] / usr / src / usr.sbin / pstat / pstat.c
index 2feeb99..b784c59 100644 (file)
@@ -1,31 +1,48 @@
-static char *sccsid = "@(#)pstat.c     4.11 (Berkeley) %G%";
 /*
 /*
- * 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.17 (Berkeley) %G%";
+#endif /* not lint */
+
+/*
+ * Print system stuff
+ */
 
 #include <sys/param.h>
 #include <sys/dir.h>
 
 #include <sys/param.h>
 #include <sys/dir.h>
+#define        KERNEL
 #include <sys/file.h>
 #include <sys/file.h>
+#undef KERNEL
 #include <sys/user.h>
 #include <sys/proc.h>
 #include <sys/text.h>
 #include <sys/inode.h>
 #include <sys/map.h>
 #include <sys/user.h>
 #include <sys/proc.h>
 #include <sys/text.h>
 #include <sys/inode.h>
 #include <sys/map.h>
+#include <sys/ioctl.h>
 #include <sys/tty.h>
 #include <sys/conf.h>
 #include <sys/vm.h>
 #include <nlist.h>
 #include <sys/tty.h>
 #include <sys/conf.h>
 #include <sys/vm.h>
 #include <nlist.h>
-#include <sys/pte.h>
-#define        KERNEL
-#include <sys/mx.h>
-#undef KERNEL
+#include <machine/pte.h>
+#include <stdio.h>
+
+#define mask(x)                (x&0377)
+#define        clear(x)        ((int)x &~ KERNBASE)
 
 char   *fcore  = "/dev/kmem";
 
 char   *fcore  = "/dev/kmem";
+char   *fmem   = "/dev/mem";
 char   *fnlist = "/vmunix";
 char   *fnlist = "/vmunix";
-int    fc;
+int    fc, fm;
 
 struct nlist nl[] = {
 #define        SINODE  0
 
 struct nlist nl[] = {
 #define        SINODE  0
@@ -34,43 +51,73 @@ struct nlist nl[] = {
        { "_text" },
 #define        SPROC   2
        { "_proc" },
        { "_text" },
 #define        SPROC   2
        { "_proc" },
-#define        SDZ     3
-       { "_dz_tty" },
-#define        SNDZ    4
-       { "_dz_cnt" },
-#define        SKL     5
+#define        SCONS   3
        { "_cons" },
        { "_cons" },
-#define        SFIL    6
+#define        SFIL    4
        { "_file" },
        { "_file" },
-#define        USRPTMA 7
+#define        USRPTMA 5
        { "_Usrptmap" },
        { "_Usrptmap" },
-#define        USRPT   8
+#define        USRPT   6
        { "_usrpt" },
        { "_usrpt" },
-#define        SNSWAP  9
-       { "_nswap" },
-#define        SWAPMAP 10
+#define        SWAPMAP 7
        { "_swapmap" },
        { "_swapmap" },
-#define        SDH     11
-       { "_dh11" },
-#define        SNDH    12
-       { "_ndh11" },
-#define        SGROUP  13
-       { "_groups" },
-#define        SCHANS  14
-       { "_chans" },
-#define        SSCHANS 15
-       { "_schans" },
-#define        SNPROC  16
+#define        SNPROC  8
        { "_nproc" },
        { "_nproc" },
-#define        SNTEXT  17
+#define        SNTEXT  9
        { "_ntext" },
        { "_ntext" },
-#define        SNFILE  18
+#define        SNFILE  10
        { "_nfile" },
        { "_nfile" },
-#define        SNINODE 19
+#define        SNINODE 11
        { "_ninode" },
        { "_ninode" },
-#define        SNSWAPMAP 20
+#define        SNSWAPMAP 12
        { "_nswapmap" },
        { "_nswapmap" },
-       0,
+#define        SPTY    13
+       { "_pt_tty" },
+#define        SDMMIN  14
+       { "_dmmin" },
+#define        SDMMAX  15
+       { "_dmmax" },
+#define        SNSWDEV 16
+       { "_nswdev" },
+#define        SSWDEVT 17
+       { "_swdevt" },
+#define        SYSMAP  18
+       { "_Sysmap" },
+#define        SNPTY   19
+       { "_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" },
+#endif
+       { "" }
 };
 
 int    inof;
 };
 
 int    inof;
@@ -78,8 +125,6 @@ int  txtf;
 int    prcf;
 int    ttyf;
 int    usrf;
 int    prcf;
 int    ttyf;
 int    usrf;
-int    mpxf;
-int    groupf;
 long   ubase;
 int    filf;
 int    swpf;
 long   ubase;
 int    filf;
 int    swpf;
@@ -91,84 +136,82 @@ int        allflg;
 int    kflg;
 struct pte *Usrptma;
 struct pte *usrpt;
 int    kflg;
 struct pte *Usrptma;
 struct pte *usrpt;
+u_long getword();
+off_t  mkphys();
 
 main(argc, argv)
 
 main(argc, argv)
-char **argv;
+       int argc;
+       char **argv;
 {
 {
-       register char *argp;
-
-       argc--, argv++;
-       while (argc > 0 && **argv == '-') {
-               argp = *argv++;
-               argp++;
-               argc--;
-               while (*argp++)
-               switch (argp[-1]) {
+       extern char *optarg;
+       extern int optind;
+       int ch;
 
 
+       while ((ch = getopt(argc, argv, "Tafikptu:sx")) != EOF)
+               switch((char)ch) {
                case 'T':
                        totflg++;
                        break;
                case 'T':
                        totflg++;
                        break;
-
                case 'a':
                        allflg++;
                case 'a':
                        allflg++;
+                       /*FALLTHROUGH*/
+               case 'p':
+                       prcf++;
+                       break;
+               case 'f':
+                       filf++;
                        break;
                        break;
-
                case 'i':
                        inof++;
                        break;
                case 'i':
                        inof++;
                        break;
-
-               case 'k':
+               case 'k':                       /* undocumented */
                        kflg++;
                        kflg++;
-                       fcore = "/vmcore";
-                       break;
-
-               case 'x':
-                       txtf++;
-                       break;
-
-               case 'p':
-                       prcf++;
+                       fcore = fmem = "/vmcore";
                        break;
                        break;
-
                case 't':
                        ttyf++;
                        break;
                case 't':
                        ttyf++;
                        break;
-
                case 'u':
                case 'u':
-                       if (argc == 0)
-                               break;
-                       argc--;
                        usrf++;
                        usrf++;
-                       sscanf( *argv++, "%x", &ubase);
-                       break;
-
-               case 'f':
-                       filf++;
+                       sscanf(optarg, "%x", &ubase);
                        break;
                case 's':
                        swpf++;
                        break;
                        break;
                case 's':
                        swpf++;
                        break;
-               case 'm':
-                       mpxf++;
-                       break;
-               case 'g':
-                       groupf++;
+               case 'x':
+                       txtf++;
                        break;
                        break;
+               case '?':
+               default:
+                       printf("usage: pstat -[Tafiptsx] [-u [ubase]] [system] [core]\n");
+                       exit(1);
                }
                }
+       argc -= optind;
+       argv += optind;
+
+       if (argc>1) {
+               fcore = fmem = argv[1];
+               kflg++;
        }
        }
-       if (argc>0)
-               fcore = argv[0];
-       if ((fc = open(fcore, 0)) < 0) {
-               printf("Can't find %s\n", fcore);
+       if ((fc = open(fcore, O_RDONLY, 0)) < 0) {
+               perror(fcore);
                exit(1);
        }
                exit(1);
        }
-       if (argc>1)
-               fnlist = argv[1];
+       if ((fm = open(fmem, O_RDONLY, 0)) < 0) {
+               perror(fmem);
+               exit(1);
+       }
+       if (argc>0)
+               fnlist = argv[0];
        nlist(fnlist, nl);
        nlist(fnlist, nl);
+       if (nl[0].n_type == 0) {
+               printf("pstat: no namelist.\n");
+               exit(1);
+       }
        usrpt = (struct pte *)nl[USRPT].n_value;
        Usrptma = (struct pte *)nl[USRPTMA].n_value;
        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 (!(filf | totflg | inof | prcf | txtf | ttyf | usrf | swpf)) {
+               printf("pstat: one or more of -[aixptfsu] is required\n");
                exit(1);
        }
        if (filf||totflg)
                exit(1);
        }
        if (filf||totflg)
@@ -185,10 +228,6 @@ char **argv;
                dousr();
        if (swpf||totflg)
                doswap();
                dousr();
        if (swpf||totflg)
                doswap();
-       if (mpxf)
-               dompx();
-       if (groupf)
-               dogroup();
 }
 
 doinode()
 }
 
 doinode()
@@ -199,9 +238,19 @@ doinode()
        int ninode;
 
        nin = 0;
        int ninode;
 
        nin = 0;
-       ninode = getw(nl[SNINODE].n_value);
+       ninode = getword(nl[SNINODE].n_value);
        xinode = (struct inode *)calloc(ninode, sizeof (struct inode));
        xinode = (struct inode *)calloc(ninode, sizeof (struct inode));
-       lseek(fc, (int)(ainode = (struct inode *)getw(nl[SINODE].n_value)), 0);
+       ainode = (struct inode *)getword(nl[SINODE].n_value);
+       if (ninode < 0 || ninode > 10000) {
+               fprintf(stderr, "number of inodes is preposterous (%d)\n",
+                       ninode);
+               return;
+       }
+       if (xinode == NULL) {
+               fprintf(stderr, "can't allocate memory for inode table\n");
+               return;
+       }
+       lseek(fc, mkphys((off_t)ainode), 0);
        read(fc, xinode, ninode * sizeof(struct inode));
        for (ip = xinode; ip < &xinode[ninode]; ip++)
                if (ip->i_count)
        read(fc, xinode, ninode * sizeof(struct inode));
        for (ip = xinode; ip < &xinode[ninode]; ip++)
                if (ip->i_count)
@@ -211,25 +260,31 @@ doinode()
                return;
        }
        printf("%d/%d active inodes\n", nin, ninode);
                return;
        }
        printf("%d/%d active inodes\n", nin, ninode);
-       printf("   LOC    FLAGS  CNT DEVICE   INO  MODE  NLK UID   SIZE/DEV\n");
+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));
        for (ip = xinode; ip < &xinode[ninode]; ip++) {
                if (ip->i_count == 0)
                        continue;
                printf("%8.1x ", ainode + (ip - xinode));
-               putf(ip->i_flag&ILOCK, 'L');
+               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&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_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", 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_un.i_rdev), minor(ip->i_un.i_rdev));
+                       printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev));
                else
                        printf("%10ld", ip->i_size);
                printf("\n");
                else
                        printf("%10ld", ip->i_size);
                printf("\n");
@@ -237,17 +292,16 @@ doinode()
        free(xinode);
 }
 
        free(xinode);
 }
 
-getw(loc)
+u_long
+getword(loc)
        off_t loc;
 {
        off_t loc;
 {
-       int word;
+       u_long word;
 
        if (kflg)
 
        if (kflg)
-               loc &= 0x7fffffff;
+               loc = clear(loc);
        lseek(fc, loc, 0);
        read(fc, &word, sizeof (word));
        lseek(fc, loc, 0);
        read(fc, &word, sizeof (word));
-       if (kflg)
-               word &= 0x7fffffff;
        return (word);
 }
 
        return (word);
 }
 
@@ -264,22 +318,36 @@ dotext()
        register struct text *xp;
        int ntext;
        struct text *xtext, *atext;
        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));
        xtext = (struct text *)calloc(ntext, sizeof (struct text));
-       lseek(fc, (int)(atext = (struct text *)getw(nl[STEXT].n_value)), 0);
+       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;
+       }
+       lseek(fc, mkphys((off_t)atext), 0);
        read(fc, xtext, ntext * sizeof (struct text));
        read(fc, xtext, ntext * sizeof (struct text));
-       for (xp = xtext; xp < &xtext[ntext]; xp++)
-               if (xp->x_iptr!=NULL)
+       for (xp = xtext; xp < &xtext[ntext]; xp++) {
+               if (xp->x_iptr != NULL)
+                       ntxca++;
+               if (xp->x_count != 0)
                        ntx++;
                        ntx++;
+       }
        if (totflg) {
        if (totflg) {
-               printf("%3d/%3d texts\n", ntx, ntext);
+               printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca);
                return;
        }
                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     IPTR   CNT CCNT      FORW     BACK\n");
        for (xp = xtext; xp < &xtext[ntext]; xp++) {
                if (xp->x_iptr == NULL)
                        continue;
        for (xp = xtext; xp < &xtext[ntext]; xp++) {
                if (xp->x_iptr == NULL)
                        continue;
@@ -292,12 +360,14 @@ dotext()
                putf(xp->x_flag&XLOCK, 'K');
                putf(xp->x_flag&XWANT, 'w');
                printf("%5x", xp->x_daddr[0]);
                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("%5d", xp->x_count&0377);
                printf("%5d", xp->x_ccount);
                printf("%5d", xp->x_rssize);
                printf("%5d", xp->x_size);
                printf("%10.1x", xp->x_iptr);
                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);
                printf("\n");
        }
        free(xtext);
@@ -311,9 +381,19 @@ doproc()
        register loc, np;
        struct pte apte;
 
        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));
        xproc = (struct proc *)calloc(nproc, sizeof (struct proc));
-       lseek(fc, (int)(aproc = (struct proc *)getw(nl[SPROC].n_value)), 0);
+       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;
+       }
+       lseek(fc, mkphys((off_t)aproc), 0);
        read(fc, xproc, nproc * sizeof (struct proc));
        np = 0;
        for (pp=xproc; pp < &xproc[nproc]; pp++)
        read(fc, xproc, nproc * sizeof (struct proc));
        np = 0;
        for (pp=xproc; pp < &xproc[nproc]; pp++)
@@ -324,7 +404,7 @@ doproc()
                return;
        }
        printf("%d/%d processes\n", np, nproc);
                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   PGRP    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;
        for (pp=xproc; pp<&xproc[nproc]; pp++) {
                if (pp->p_stat==0 && allflg==0)
                        continue;
@@ -344,62 +424,118 @@ doproc()
                printf(" %6d", pp->p_ppid);
                if (kflg)
                        pp->p_addr = (struct pte *)clear((int)pp->p_addr);
                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) {
+                       lseek(fc, (long)pp->p_addr, 0);
+                       read(fc, &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);
                printf(" %7x", clear(pp->p_wchan));
                printf(" %7x", clear(pp->p_link));
                printf(" %7x", clear(pp->p_textp));
                printf(" %4x", pp->p_rssize);
                printf(" %4x", pp->p_swrss);
                printf(" %5x", pp->p_dsize+pp->p_ssize);
                printf(" %7x", clear(pp->p_wchan));
                printf(" %7x", clear(pp->p_link));
                printf(" %7x", clear(pp->p_textp));
-               printf("    %u", pp->p_clktim);
                printf("\n");
        }
                printf("\n");
        }
+       free(xproc);
 }
 
 }
 
+static char mesg[] =
+" # RAW CAN OUT     MODE     ADDR DEL COL     STATE  PGRP DISC\n";
+static int ttyspace = 128;
+static struct tty *tty;
+
 dotty()
 {
 dotty()
 {
-       struct tty dz_tty[64];
-       int ndz;
-       register struct tty *tp;
-       register char *mesg;
+       extern char *malloc();
 
 
+       if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) {
+               printf("pstat: out of memory\n");
+               return;
+       }
        printf("1 cons\n");
        if (kflg)
        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";
+               nl[SCONS].n_value = clear(nl[SCONS].n_value);
+       lseek(fc, (long)nl[SCONS].n_value, 0);
+       read(fc, tty, sizeof(*tty));
        printf(mesg);
        printf(mesg);
-       ttyprt(&dz_tty[0], 0);
-       if (nl[SNDZ].n_type == 0)
-               goto dh;
+       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);
+#endif
+       if (nl[SNPTY].n_type != 0)
+               dottytype("pty", SPTY, SNPTY);
+}
+
+/* 
+ * Special case the qdss because there are 4 tty structs per qdss 
+ * and only the first of each is used as a tty.  
+ */
+#ifdef vax
+doqdss()
+{
+       int nqd;
+       register struct tty *tp;
+
        if (kflg) {
        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, sizeof(dz_tty));
-       for (tp = dz_tty; tp < &dz_tty[ndz]; tp++)
-               ttyprt(tp, tp - dz_tty);
-dh:
-       if (nl[SNDH].n_type == 0)
+               nl[SNQD].n_value = clear(nl[SNQD].n_value);
+               nl[SQD].n_value = clear(nl[SQD].n_value);
+       }
+       lseek(fc, (long)nl[SNQD].n_value, 0);
+       read(fc, &nqd, sizeof(nqd));
+       printf("%d qd\n", nqd);
+       lseek(fc, (long)nl[SQD].n_value, 0);
+       read(fc, 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;
        if (kflg) {
                return;
        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, sizeof(dz_tty));
-       for (tp = dz_tty; tp < &dz_tty[ndz]; tp++)
-               ttyprt(tp, tp - dz_tty);
+               nl[number].n_value = clear(nl[number].n_value);
+               nl[type].n_value = clear(nl[type].n_value);
+       }
+       lseek(fc, (long)nl[number].n_value, 0);
+       read(fc, &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;
+               }
+       }
+       lseek(fc, (long)nl[type].n_value, 0);
+       read(fc, tty, ntty * sizeof(struct tty));
+       printf(mesg);
+       for (tp = tty; tp < &tty[ntty]; tp++)
+               ttyprt(tp, tp - tty);
 }
 
 ttyprt(atp, line)
 }
 
 ttyprt(atp, line)
@@ -411,54 +547,67 @@ struct tty *atp;
        tp = atp;
        switch (tp->t_line) {
 
        tp = atp;
        switch (tp->t_line) {
 
+#ifdef notdef
        case NETLDISC:
                if (tp->t_rec)
                        printf("%4d%4d", 0, tp->t_inbuf);
                else
                        printf("%4d%4d", tp->t_inbuf, 0);
                break;
        case NETLDISC:
                if (tp->t_rec)
                        printf("%4d%4d", 0, tp->t_inbuf);
                else
                        printf("%4d%4d", tp->t_inbuf, 0);
                break;
+#endif
 
        default:
 
        default:
-               printf("%4d", tp->t_rawq.c_cc);
-               printf("%4d", tp->t_canq.c_cc);
-       }
-       printf("%4d", tp->t_outq.c_cc);
-       printf("%8.1o", tp->t_flags);
-       printf(" %8.1x", tp->t_addr);
-       printf("%3d", tp->t_delct);
-       printf("%4d ", tp->t_col);
-       putf(tp->t_state&TIMEOUT, 'T');
-       putf(tp->t_state&WOPEN, 'W');
-       putf(tp->t_state&ISOPEN, 'O');
-       putf(tp->t_state&CARR_ON, 'C');
-       putf(tp->t_state&BUSY, 'B');
-       putf(tp->t_state&ASLEEP, 'A');
-       putf(tp->t_state&XCLUDE, 'X');
-/*
-       putf(tp->t_state&HUPCLS, 'H');
- */
+               printf("%4d%4d", tp->t_rawq.c_cc, tp->t_canq.c_cc);
+       }
+       printf("%4d %8x %8x%4d%4d", tp->t_outq.c_cc, tp->t_flags,
+               tp->t_addr, tp->t_delct, 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_FLUSH, 'F');
+       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_TTSTOP, 'S');
+       putf(tp->t_state&TS_HUPCLS, 'H');
        printf("%6d", tp->t_pgrp);
        switch (tp->t_line) {
 
        printf("%6d", tp->t_pgrp);
        switch (tp->t_line) {
 
+       case OTTYDISC:
+               printf("\n");
+               break;
+
        case NTTYDISC:
        case NTTYDISC:
-               printf(" ntty");
+               printf(" ntty\n");
                break;
 
        case NETLDISC:
                break;
 
        case NETLDISC:
-               printf(" net");
+               printf(" berknet\n");
+               break;
+
+       case TABLDISC:
+               printf(" tab\n");
+               break;
+
+       case SLIPDISC:
+               printf(" slip\n");
                break;
                break;
+
+       default:
+               printf(" %d\n", tp->t_line);
        }
        }
-       printf("\n");
 }
 
 dousr()
 {
        struct user U;
        register i, j, *ip;
 }
 
 dousr()
 {
        struct user U;
        register i, j, *ip;
+       register struct nameidata *nd = &U.u_nd;
 
 
-       /* 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) */
+       lseek(fm, ubase * NBPG, 0);
+       read(fm, &U, sizeof(U));
        printf("pcb");
        ip = (int *)&U.u_pcb;
        while (ip < &U.u_arg[0]) {
        printf("pcb");
        ip = (int *)&U.u_pcb;
        while (ip < &U.u_arg[0]) {
@@ -470,89 +619,90 @@ dousr()
        }
        if ((ip - (int *)&U.u_pcb) % 4 != 0)
                printf("\n");
        }
        if ((ip - (int *)&U.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; i<sizeof(label_t)/sizeof(int); i++) {
+       printf("arg");
+       for (i=0; i<sizeof(U.u_arg)/sizeof(U.u_arg[0]); i++) {
                if (i%5==0)
                        printf("\t");
                if (i%5==0)
                        printf("\t");
-               printf("%9.1x", U.u_ssav[i]);
+               printf(" %.1x", U.u_arg[i]);
                if (i%5==4)
                        printf("\n");
        }
        if (i%5)
                printf("\n");
                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("segflg\t%d\nerror %d\n", nd->ni_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("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("base, count, offset %.1x %.1x %ld\n", nd->ni_base,
+               nd->ni_count, nd->ni_offset);
        printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir);
        printf("cdir rdir %.1x %.1x\n", U.u_cdir, U.u_rdir);
-       printf("dbuf %.14s\n", U.u_dbuf);
-       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; i<NOFILE; i++)
+       printf("dirp %.1x\n", nd->ni_dirp);
+       printf("dent %d %.14s\n", nd->ni_dent.d_ino, nd->ni_dent.d_name);
+       printf("pdir %.1o\n", nd->ni_pdir);
+       printf("file");
+       for (i=0; i<NOFILE; i++) {
+               if (i % 8 == 0)
+                       printf("\t");
                printf("%9.1x", U.u_ofile[i]);
                printf("%9.1x", U.u_ofile[i]);
-       printf("\n");
-       printf("pofile\t");
-       for (i=0; i<10; i++)
-               printf("%9.1x", U.u_pofile[i]);
-       printf("\n\t");
-       for (i=10; i<NOFILE; i++)
+               if (i % 8 == 7)
+                       printf("\n");
+       }
+       if (i % 8)
+               printf("\n");
+       printf("pofile");
+       for (i=0; i<NOFILE; i++) {
+               if (i % 8 == 0)
+                       printf("\t");
                printf("%9.1x", U.u_pofile[i]);
                printf("%9.1x", U.u_pofile[i]);
-       printf("\n");
-       printf("ssav");
+               if (i % 8 == 7)
+                       printf("\n");
+       }
+       if (i % 8)
+               printf("\n");
+       printf("ssave");
        for (i=0; i<sizeof(label_t)/sizeof(int); i++) {
                if (i%5==0)
                        printf("\t");
        for (i=0; i<sizeof(label_t)/sizeof(int); i++) {
                if (i%5==0)
                        printf("\t");
-               printf("%9.1x", U.u_ssav[i]);
+               printf("%9.1x", U.u_ssave.val[i]);
                if (i%5==4)
                        printf("\n");
        }
        if (i%5)
                printf("\n");
                if (i%5==4)
                        printf("\n");
        }
        if (i%5)
                printf("\n");
-       printf("sigs\t");
-       for (i=0; i<NSIG; i++)
+       printf("sigs");
+       for (i=0; i<NSIG; i++) {
+               if (i % 8 == 0)
+                       printf("\t");
                printf("%.1x ", U.u_signal[i]);
                printf("%.1x ", U.u_signal[i]);
-       printf("\n");
+               if (i % 8 == 7)
+                       printf("\n");
+       }
+       if (i % 8)
+               printf("\n");
        printf("code\t%.1x\n", U.u_code);
        printf("ar0\t%.1x\n", U.u_ar0);
        printf("code\t%.1x\n", U.u_code);
        printf("ar0\t%.1x\n", U.u_ar0);
-       printf("prof\t%X %X %X %X\n", U.u_prof.pr_base, U.u_prof.pr_size,
+       printf("prof\t%x %x %x %x\n", U.u_prof.pr_base, U.u_prof.pr_size,
            U.u_prof.pr_off, U.u_prof.pr_scale);
        printf("\neosys\t%d\n", U.u_eosys);
            U.u_prof.pr_off, U.u_prof.pr_scale);
        printf("\neosys\t%d\n", U.u_eosys);
-       printf("sep\t%d\n", U.u_sep);
        printf("ttyp\t%.1x\n", U.u_ttyp);
        printf("ttyd\t%d,%d\n", major(U.u_ttyd), minor(U.u_ttyd));
        printf("ttyp\t%.1x\n", U.u_ttyp);
        printf("ttyd\t%d,%d\n", major(U.u_ttyd), minor(U.u_ttyd));
-       printf("exdata\t");
-       ip = (int *)&U.u_exdata;
-       for (i = 0; i < 8; i++)
-               printf("%.1D ", *ip++);
-       printf("\n");
        printf("comm %.14s\n", U.u_comm);
        printf("comm %.14s\n", U.u_comm);
-       printf("start\t%D\n", U.u_start);
-       printf("acflag\t%D\n", U.u_acflag);
-       printf("fpflag\t%D\n", U.u_fpflag);
-       printf("cmask\t%D\n", U.u_cmask);
+       printf("start\t%ld\n", U.u_start.tv_sec);
+       printf("acflag\t%ld\n", U.u_acflag);
+       printf("cmask\t%ld\n", U.u_cmask);
        printf("sizes\t%.1x %.1x %.1x\n", U.u_tsize, U.u_dsize, U.u_ssize);
        printf("sizes\t%.1x %.1x %.1x\n", U.u_tsize, U.u_dsize, U.u_ssize);
-       printf("vm\t");
-       ip = (int *)&U.u_vm;
-       for (i = 0; i < sizeof(U.u_vm)/sizeof(int); i++)
-               printf("%D ", ip[i]);
+       printf("ru\t");
+       ip = (int *)&U.u_ru;
+       for (i = 0; i < sizeof(U.u_ru)/sizeof(int); i++)
+               printf("%ld ", ip[i]);
        printf("\n");
        printf("\n");
-       ip = (int *)&U.u_cvm;
-       printf("cvm\t");
-       for (i = 0; i < sizeof(U.u_vm)/sizeof(int); i++)
-               printf("%D ", ip[i]);
+       ip = (int *)&U.u_cru;
+       printf("cru\t");
+       for (i = 0; i < sizeof(U.u_cru)/sizeof(int); i++)
+               printf("%ld ", ip[i]);
        printf("\n");
        printf("\n");
-/*
+#ifdef notdef
        i =  U.u_stack - &U;
        while (U[++i] == 0);
        i &= ~07;
        i =  U.u_stack - &U;
        while (U[++i] == 0);
        i &= ~07;
@@ -562,7 +712,7 @@ dousr()
                        printf("%9x", U[i++]);
                printf("\n");
        }
                        printf("%9x", U[i++]);
                printf("\n");
        }
-*/
+#endif
 }
 
 oatoi(s)
 }
 
 oatoi(s)
@@ -583,11 +733,22 @@ dofile()
        register struct file *fp;
        register nf;
        int loc;
        register struct file *fp;
        register nf;
        int loc;
+       static char *dtypes[] = { "???", "inode", "socket" };
 
        nf = 0;
 
        nf = 0;
-       nfile = getw(nl[SNFILE].n_value);
+       nfile = getword(nl[SNFILE].n_value);
        xfile = (struct file *)calloc(nfile, sizeof (struct file));
        xfile = (struct file *)calloc(nfile, sizeof (struct file));
-       lseek(fc, (int)(afile = (struct file *)getw(nl[SFIL].n_value)), 0);
+       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;
+       }
+       lseek(fc, mkphys((off_t)afile), 0);
        read(fc, xfile, nfile * sizeof (struct file));
        for (fp=xfile; fp < &xfile[nfile]; fp++)
                if (fp->f_count)
        read(fc, xfile, nfile * sizeof (struct file));
        for (fp=xfile; fp < &xfile[nfile]; fp++)
                if (fp->f_count)
@@ -597,20 +758,34 @@ dofile()
                return;
        }
        printf("%d/%d open files\n", nf, nfile);
                return;
        }
        printf("%d/%d open files\n", nf, nfile);
-       printf("   LOC   FLG  CNT   INO    OFFS\n");
-       for (fp=xfile,loc=nl[SFIL].n_value; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) {
+       printf("   LOC   TYPE    FLG     CNT  MSG    DATA    OFFSET\n");
+       for (fp=xfile,loc=(int)afile; fp < &xfile[nfile]; fp++,loc+=sizeof(xfile[0])) {
                if (fp->f_count==0)
                        continue;
                printf("%8x ", loc);
                if (fp->f_count==0)
                        continue;
                printf("%8x ", loc);
+               if (fp->f_type <= DTYPE_SOCKET)
+                       printf("%-8.8s", dtypes[fp->f_type]);
+               else
+                       printf("%8d", fp->f_type);
                putf(fp->f_flag&FREAD, 'R');
                putf(fp->f_flag&FWRITE, 'W');
                putf(fp->f_flag&FREAD, 'R');
                putf(fp->f_flag&FWRITE, 'W');
-               putf(fp->f_flag&FPIPE, 'P');
-               printf("%4d", mask(fp->f_count));
-               printf("%9.1x", fp->f_inode);
-               printf("  %ld\n", fp->f_un.f_offset);
+               putf(fp->f_flag&FAPPEND, 'A');
+               putf(fp->f_flag&FSHLOCK, 'S');
+               putf(fp->f_flag&FEXLOCK, 'X');
+               putf(fp->f_flag&FASYNC, 'I');
+               printf("  %3d", mask(fp->f_count));
+               printf("  %3d", mask(fp->f_msgcount));
+               printf("  %8.1x", fp->f_data);
+               if (fp->f_offset < 0)
+                       printf("  %x\n", fp->f_offset);
+               else
+                       printf("  %ld\n", fp->f_offset);
        }
        }
+       free(xfile);
 }
 
 }
 
+int dmmin, dmmax, nswdev;
+
 doswap()
 {
        struct proc *proc;
 doswap()
 {
        struct proc *proc;
@@ -619,49 +794,109 @@ doswap()
        int ntext;
        struct map *swapmap;
        int nswapmap;
        int ntext;
        struct map *swapmap;
        int nswapmap;
+       struct swdevt *swdevt, *sw;
        register struct proc *pp;
        register struct proc *pp;
-       int nswap, used, tused, free;
+       int nswap, used, tused, free, waste;
+       int db, sb;
        register struct mapent *me;
        register struct text *xp;
        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));
        proc = (struct proc *)calloc(nproc, sizeof (struct proc));
-       lseek(fc, getw(nl[SPROC].n_value), 0);
-       read(fc, proc, nproc * sizeof (struct proc));
-       nswapmap = getw(nl[SNSWAPMAP].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));
+       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));
        swapmap = (struct map *)calloc(nswapmap, sizeof (struct map));
-       lseek(fc, getw(nl[SWAPMAP].n_value), 0);
+       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));
+       if (swdevt == NULL) {
+               fprintf(stderr, "can't allocate memory for swdevt table\n");
+               exit(1);
+       }
+       lseek(fc, mkphys((off_t)nl[SSWDEVT].n_value), L_SET);
+       read(fc, swdevt, nswdev * sizeof (struct swdevt));
+       lseek(fc, mkphys((off_t)getword(nl[SPROC].n_value)), 0);
+       read(fc, proc, nproc * sizeof (struct proc));
+       lseek(fc, mkphys((off_t)getword(nl[STEXT].n_value)), 0);
+       read(fc, xtext, ntext * sizeof (struct text));
+       lseek(fc, mkphys((off_t)getword(nl[SWAPMAP].n_value)), 0);
        read(fc, swapmap, nswapmap * sizeof (struct map));
        read(fc, swapmap, nswapmap * sizeof (struct map));
-       nswap = getw(nl[SNSWAP].n_value);
+       swapmap->m_name = "swap";
+       swapmap->m_limit = (struct mapent *)&swapmap[nswapmap];
+       dmmin = getword(nl[SDMMIN].n_value);
+       dmmax = getword(nl[SDMMAX].n_value);
+       nswap = 0;
+       for (sw = swdevt; sw < &swdevt[nswdev]; sw++)
+               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;
        free = 0;
        for (me = (struct mapent *)(swapmap+1);
            me < (struct mapent *)&swapmap[nswapmap]; me++)
                free += me->m_size;
-       ntext = getw(nl[SNTEXT].n_value);
-       xtext = (struct text *)calloc(ntext, sizeof (struct text));
-       lseek(fc, getw(nl[STEXT].n_value), 0);
-       read(fc, xtext, ntext * sizeof (struct text));
        tused = 0;
        for (xp = xtext; xp < &xtext[ntext]; xp++)
        tused = 0;
        for (xp = xtext; xp < &xtext[ntext]; xp++)
-               if (xp->x_iptr!=NULL)
-                       tused += xdsize(xp);
+               if (xp->x_iptr!=NULL) {
+                       tused += ctod(clrnd(xp->x_size));
+                       if (xp->x_flag & XPAGI)
+                               tused += ctod(clrnd(ctopt(xp->x_size)));
+               }
        used = tused;
        used = tused;
+       waste = 0;
        for (pp = proc; pp < &proc[nproc]; pp++) {
                if (pp->p_stat == 0 || pp->p_stat == SZOMB)
                        continue;
                if (pp->p_flag & SSYS)
                        continue;
        for (pp = proc; pp < &proc[nproc]; pp++) {
                if (pp->p_stat == 0 || pp->p_stat == SZOMB)
                        continue;
                if (pp->p_flag & SSYS)
                        continue;
-               used += up(pp->p_dsize) + up(pp->p_ssize);
+               db = ctod(pp->p_dsize), sb = up(db);
+               used += sb;
+               waste += sb - db;
+               db = ctod(pp->p_ssize), sb = up(db);
+               used += sb;
+               waste += sb - db;
                if ((pp->p_flag&SLOAD) == 0)
                if ((pp->p_flag&SLOAD) == 0)
-                       used += vusize(pp);
+                       used += ctod(vusize(pp));
        }
        }
-       /* a DMMAX/2 block goes to argmap */
        if (totflg) {
        if (totflg) {
-               printf("%3d/%3d 00k swap\n", used/2/100, (used+free)/2/100);
+#define        btok(x) ((x) / (1024 / DEV_BSIZE))
+               printf("%3d/%3d 00k swap\n",
+                   btok(used/100), btok((used+free)/100));
                return;
        }
                return;
        }
-       printf("%d used (%d text), %d free, %d missing\n",
-           used/2, tused/2, free/2, (nswap - DMMAX/2 - (used + free))/2);
+       printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n",
+           btok(used), btok(tused), btok(free), btok(waste),
+/* a dmmax/2 block goes to argmap */
+           btok(nswap - dmmax/2 - (used + free)));
+       printf("avail: ");
+       for (i = dmmax; i >= dmmin; i /= 2) {
+               j = 0;
+               while (rmalloc(swapmap, i) != 0)
+                       j++;
+               if (j) printf("%d*%dk ", j, btok(i));
+       }
+       free = 0;
+       for (me = (struct mapent *)(swapmap+1);
+           me < (struct mapent *)&swapmap[nswapmap]; me++)
+               free += me->m_size;
+       printf("%d*1k\n", btok(free));
 }
 
 up(size)
 }
 
 up(size)
@@ -670,126 +905,229 @@ up(size)
        register int i, block;
 
        i = 0;
        register int i, block;
 
        i = 0;
-       block = DMMIN;
+       block = dmmin;
        while (i < size) {
                i += block;
        while (i < size) {
                i += block;
-               if (block < DMMAX)
+               if (block < dmmax)
                        block *= 2;
        }
        return (i);
 }
 
                        block *= 2;
        }
        return (i);
 }
 
+/*
+ * Compute number of pages to be allocated to the u. area
+ * and data and stack area page tables, which are stored on the
+ * disk immediately after the u. area.
+ */
 vusize(p)
 vusize(p)
-struct proc *p;
+       register struct proc *p;
 {
        register int tsz = p->p_tsize / NPTEPG;
 
 {
        register int tsz = p->p_tsize / NPTEPG;
 
-       return (clrnd(UPAGES + clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
+       /*
+        * We do not need page table space on the disk for page
+        * table pages wholly containing text. 
+        */
+       return (clrnd(UPAGES +
+           clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
 }
 
 }
 
-xdsize(xp)
-struct text *xp;
+/*
+ * Allocate 'size' units from the given
+ * map. Return the base of the allocated space.
+ * In a map, the addresses are increasing and the
+ * list is terminated by a 0 size.
+ *
+ * Algorithm is first-fit.
+ *
+ * This routine knows about the interleaving of the swapmap
+ * and handles that.
+ */
+long
+rmalloc(mp, size)
+       register struct map *mp;
+       long size;
 {
 {
+       register struct mapent *ep = (struct mapent *)(mp+1);
+       register int addr;
+       register struct mapent *bp;
+       swblk_t first, rest;
 
 
-       if (xp->x_flag & XPAGI)
-               return (clrnd(xp->x_size + ctopt(xp->x_size)));
-       return (xp->x_size);
+       if (size <= 0 || size > dmmax)
+               return (0);
+       /*
+        * Search for a piece of the resource map which has enough
+        * free space to accomodate the request.
+        */
+       for (bp = ep; bp->m_size; bp++) {
+               if (bp->m_size >= size) {
+                       /*
+                        * If allocating from swapmap,
+                        * then have to respect interleaving
+                        * boundaries.
+                        */
+                       if (nswdev > 1 &&
+                           (first = dmmax - bp->m_addr%dmmax) < bp->m_size) {
+                               if (bp->m_size - first < size)
+                                       continue;
+                               addr = bp->m_addr + first;
+                               rest = bp->m_size - first - size;
+                               bp->m_size = first;
+                               if (rest)
+                                       rmfree(mp, rest, addr+size);
+                               return (addr);
+                       }
+                       /*
+                        * Allocate from the map.
+                        * If there is no space left of the piece
+                        * we allocated from, move the rest of
+                        * the pieces to the left.
+                        */
+                       addr = bp->m_addr;
+                       bp->m_addr += size;
+                       if ((bp->m_size -= size) == 0) {
+                               do {
+                                       bp++;
+                                       (bp-1)->m_addr = bp->m_addr;
+                               } while ((bp-1)->m_size = bp->m_size);
+                       }
+                       if (addr % CLSIZE)
+                               return (0);
+                       return (addr);
+               }
+       }
+       return (0);
 }
 
 }
 
-dompx()
+/*
+ * Free the previously allocated space at addr
+ * of size units into the specified map.
+ * Sort addr into map and combine on
+ * one or both ends if possible.
+ */
+rmfree(mp, size, addr)
+       struct map *mp;
+       long size, addr;
 {
 {
-       register int i;
-       struct chan chans[NCHANS];
-       struct schan schans[NPORTS];
-
-       lseek(fc, (long)nl[SCHANS].n_value, 0);
-       read(fc, chans, sizeof chans);
-       lseek(fc, (long)nl[SSCHANS].n_value, 0);
-       read(fc, schans, sizeof schans);
-
-       printf("CHAN  FLAGS            INDEX     LINE  GROUP     FILE      TTYP      CTLX      PGRP    OTTYP     OLINE  DATQ      CTLY\n");
-       for (i = 0; i < NCHANS; i++) {
-               printf("%3d   ", i);
-               putf(chans[i].c_flags&INUSE, 'I');
-               putf(chans[i].c_flags&SIOCTL, 'S');
-               putf(chans[i].c_flags&XGRP, 'X');
-               putf(chans[i].c_flags&YGRP, 'Y');
-               putf(chans[i].c_flags&WCLOSE, 'W');
-               putf(chans[i].c_flags&ISGRP, 'i');
-               putf(chans[i].c_flags&BLOCK, 'B');
-               putf(chans[i].c_flags&EOTMARK, 'E');
-               putf(chans[i].c_flags&SIGBLK, 's');
-               putf(chans[i].c_flags&BLKMSG, 'b');
-               putf(chans[i].c_flags&ENAMSG, 'e');
-               putf(chans[i].c_flags&WFLUSH, 'w');
-               putf(chans[i].c_flags&NMBUF, 'N');
-               putf(chans[i].c_flags&PORT, 'P');
-               putf(chans[i].c_flags&ALT, 'A');
-               putf(chans[i].c_flags&FBLOCK, 'F');
-               printf("%8x  ", chans[i].c_index);
-               printf("%3d   ", chans[i].c_line);
-               printf("%8x  ", chans[i].c_group);
-               printf("%8x  ", chans[i].c_fy);
-               printf("%8x  ", chans[i].c_ttyp);
-               printf("%8x  ", chans[i].c_ctlx);
-               printf("%6d  ", chans[i].c_pgrp);
-               printf("%8x  ", chans[i].c_ottyp);
-               printf("%3d   ", chans[i].c_oline);
-               printf("%8x  ", chans[i].cx.datq);
-               printf("%8x\n", chans[i].c_ctly);
-       }
-
-       printf("\nCHAN  FLAGS            INDEX     LINE  GROUP     FILE      TTYP      CTLX      PGRP\n");
-       for (i = 0; i < NPORTS; i++) {
-               printf("%3d  ", i);
-               putf(schans[i].c_flags&INUSE, 'I');
-               putf(schans[i].c_flags&SIOCTL, 'S');
-               putf(schans[i].c_flags&XGRP, 'X');
-               putf(schans[i].c_flags&YGRP, 'Y');
-               putf(schans[i].c_flags&WCLOSE, 'W');
-               putf(schans[i].c_flags&ISGRP, 'i');
-               putf(schans[i].c_flags&BLOCK, 'B');
-               putf(schans[i].c_flags&EOTMARK, 'E');
-               putf(schans[i].c_flags&SIGBLK, 's');
-               putf(schans[i].c_flags&BLKMSG, 'b');
-               putf(schans[i].c_flags&ENAMSG, 'e');
-               putf(schans[i].c_flags&WFLUSH, 'w');
-               putf(schans[i].c_flags&NMBUF, 'N');
-               putf(schans[i].c_flags&PORT, 'P');
-               putf(schans[i].c_flags&ALT, 'A');
-               putf(schans[i].c_flags&FBLOCK, 'F');
-               printf("%8x  ", schans[i].c_index);
-               printf("%3d   ", schans[i].c_line);
-               printf("%8x  ", schans[i].c_group);
-               printf("%8x  ", schans[i].c_fy);
-               printf("%8x  ", schans[i].c_ttyp);
-               printf("%8x  ", schans[i].c_ctlx);
-               printf("%6d\n", schans[i].c_pgrp);
+       struct mapent *firstbp;
+       register struct mapent *bp;
+       register int t;
+
+       /*
+        * Both address and size must be
+        * positive, or the protocol has broken down.
+        */
+       if (addr <= 0 || size <= 0)
+               goto badrmfree;
+       /*
+        * Locate the piece of the map which starts after the
+        * returned space (or the end of the map).
+        */
+       firstbp = bp = (struct mapent *)(mp + 1);
+       for (; bp->m_addr <= addr && bp->m_size != 0; bp++)
+               continue;
+       /*
+        * If the piece on the left abuts us,
+        * then we should combine with it.
+        */
+       if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) {
+               /*
+                * Check no overlap (internal error).
+                */
+               if ((bp-1)->m_addr+(bp-1)->m_size > addr)
+                       goto badrmfree;
+               /*
+                * Add into piece on the left by increasing its size.
+                */
+               (bp-1)->m_size += size;
+               /*
+                * If the combined piece abuts the piece on
+                * the right now, compress it in also,
+                * by shifting the remaining pieces of the map over.
+                */
+               if (bp->m_addr && addr+size >= bp->m_addr) {
+                       if (addr+size > bp->m_addr)
+                               goto badrmfree;
+                       (bp-1)->m_size += bp->m_size;
+                       while (bp->m_size) {
+                               bp++;
+                               (bp-1)->m_addr = bp->m_addr;
+                               (bp-1)->m_size = bp->m_size;
+                       }
+               }
+               goto done;
+       }
+       /*
+        * Don't abut on the left, check for abutting on
+        * the right.
+        */
+       if (addr+size >= bp->m_addr && bp->m_size) {
+               if (addr+size > bp->m_addr)
+                       goto badrmfree;
+               bp->m_addr -= size;
+               bp->m_size += size;
+               goto done;
        }
        }
+       /*
+        * Don't abut at all.  Make a new entry
+        * and check for map overflow.
+        */
+       do {
+               t = bp->m_addr;
+               bp->m_addr = addr;
+               addr = t;
+               t = bp->m_size;
+               bp->m_size = size;
+               bp++;
+       } while (size = t);
+       /*
+        * Segment at bp is to be the delimiter;
+        * If there is not room for it 
+        * then the table is too full
+        * and we must discard something.
+        */
+       if (bp+1 > mp->m_limit) {
+               /*
+                * Back bp up to last available segment.
+                * which contains a segment already and must
+                * be made into the delimiter.
+                * Discard second to last entry,
+                * since it is presumably smaller than the last
+                * and move the last entry back one.
+                */
+               bp--;
+               printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name,
+                   (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size);
+               bp[-1] = bp[0];
+               bp[0].m_size = bp[0].m_addr = 0;
+       }
+done:
+       return;
+badrmfree:
+       printf("bad rmfree\n");
 }
 }
-
-dogroup()
+/*
+ * "addr"  is a kern virt addr and does not correspond
+ * To a phys addr after zipping out the high bit..
+ * since it was valloc'd in the kernel.
+ *
+ * We return the phys addr by simulating kernel vm (/dev/kmem)
+ * when we are reading a crash dump.
+ */
+off_t
+mkphys(addr)
+       off_t addr;
 {
 {
-       register int i, j;
-       struct group *groups[NGROUPS];
-       struct group g;
-
-       lseek(fc, (long)nl[SGROUP].n_value, 0);
-       read(fc, groups, sizeof groups);
-       printf("GROUP STATE      INDEX     ROT  *GROUP    *INODE    *FILE     ROTM  DATQ\n");
-       for (i = 0; i < NGROUPS; i++) {
-               if (groups[i] == 0)
-                       continue;
-               lseek(fc, (long) groups[i], 0);
-               read(fc, &g, sizeof g);
-               printf("%3d   ", i);
-               printf("%8x  ", g.g_state);
-               printf("%8x  ", g.g_index);
-               printf("%3d  ", g.g_rot);
-               printf("%8x  ", g.g_group);
-               printf("%8x  ", g.g_inode);
-               printf("%8x  ", g.g_file);
-               printf("%3d   ", g.g_rotmask);
-               printf("%3d\n", g.g_datq);
-       }
+       register off_t o;
+
+       if (!kflg)
+               return(addr);
+       addr = clear(addr);
+       o = addr & PGOFSET;
+       addr >>= PGSHIFT;
+       addr &= PG_PFNUM;
+       addr *=  NBPW;
+       addr = getword(nl[SYSMAP].n_value + addr);
+       addr = ((addr & PG_PFNUM) << PGSHIFT) | o;
+       return(addr);
 }
 }