allow limited 8-bit support; allow [TCP] as an alias for [IPC], even
[unix-history] / usr / src / usr.sbin / pstat / pstat.c
CommitLineData
5ff67f98
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
ae1f9014 7#ifndef lint
5ff67f98
DF
8char copyright[] =
9"@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
0dc27808 11#endif /* not lint */
5ff67f98
DF
12
13#ifndef lint
1bbe0c66 14static char sccsid[] = "@(#)pstat.c 5.35 (Berkeley) %G%";
0dc27808 15#endif /* not lint */
5ff67f98 16
ceb84881
BJ
17/*
18 * Print system stuff
19 */
ceb84881 20#include <sys/param.h>
ceb84881
BJ
21#include <sys/user.h>
22#include <sys/proc.h>
9eecf21c
KM
23#include <sys/time.h>
24#include <sys/vnode.h>
ceb84881 25#include <sys/map.h>
844d8384 26#define KERNEL
6102031f
MT
27#define NFS
28#include <sys/file.h>
29#include <sys/mount.h>
551215f4 30#include <ufs/quota.h>
6102031f
MT
31#include <ufs/inode.h>
32#include <sys/stat.h>
33#include <nfs/nfsv2.h>
34#include <nfs/nfs.h>
35#include <nfs/nfsnode.h>
88a58f27 36#include <sys/ioctl.h>
ceb84881 37#include <sys/tty.h>
844d8384 38#undef KERNEL
ceb84881 39#include <sys/conf.h>
d7985207
MK
40
41#ifdef SPPWAIT
42#define NEWVM
43#endif
44
45#ifndef NEWVM
ceb84881 46#include <sys/vm.h>
0bc29a7d 47#include <machine/pte.h>
7e7bb114 48#include <sys/text.h>
d7985207 49#endif
1d47dec3 50#include <sys/kinfo.h>
9eecf21c
KM
51
52#include <nlist.h>
1d47dec3 53#include <kvm.h>
9ed2dfb9 54#include <stdio.h>
12f0ac74 55#include "pathnames.h"
ceb84881 56
f20270fc
MK
57#define mask(x) (x&0377)
58#define clear(x) ((int)x &~ KERNBASE)
59
6102031f
MT
60char *fnlist = NULL;
61char *fcore = NULL;
ceb84881
BJ
62
63struct nlist nl[] = {
d7985207 64#define SWAPMAP 0
ceb84881 65 { "_swapmap" },
d7985207 66#define SNSWAPMAP 1
69d3d166 67 { "_nswapmap" },
d7985207 68#define SDMMIN 2
e79dc02e 69 { "_dmmin" },
d7985207 70#define SDMMAX 3
e79dc02e 71 { "_dmmax" },
d7985207 72#define SNSWDEV 4
e79dc02e 73 { "_nswdev" },
d7985207 74#define SSWDEVT 5
b94a50ef 75 { "_swdevt" },
d7985207 76#ifdef NEWVM
1bbe0c66 77#define NLMANDATORY SSWDEVT /* names up to here are mandatory */
d7985207
MK
78#else
79#define STEXT 8
80 { "_text" },
81#define SNTEXT 9
82 { "_ntext" },
83#define SPROC 10
84 { "_proc" },
85#define SNPROC 11
86 { "_nproc" },
87#define NLMANDATORY SNPROC /* names up to here are mandatory */
88#endif
89
90#define SCONS NLMANDATORY + 1
1d47dec3 91 { "_cons" },
d7985207 92#define SPTY NLMANDATORY + 2
1d47dec3 93 { "_pt_tty" },
d7985207 94#define SNPTY NLMANDATORY + 3
4242be26
SL
95 { "_npty" },
96#ifdef vax
97#define SDZ (SNPTY+1)
98 { "_dz_tty" },
99#define SNDZ (SNPTY+2)
100 { "_dz_cnt" },
101#define SDMF (SNPTY+3)
890571d1 102 { "_dmf_tty" },
4242be26 103#define SNDMF (SNPTY+4)
890571d1 104 { "_ndmf" },
4242be26
SL
105#define SDH (SNPTY+5)
106 { "_dh11" },
107#define SNDH (SNPTY+6)
108 { "_ndh11" },
109#define SDHU (SNPTY+7)
5cf6fff2 110 { "_dhu_tty" },
4242be26 111#define SNDHU (SNPTY+8)
5cf6fff2 112 { "_ndhu" },
4242be26 113#define SDMZ (SNPTY+9)
35d0530f 114 { "_dmz_tty" },
4242be26 115#define SNDMZ (SNPTY+10)
35d0530f 116 { "_ndmz" },
bac975ad
MT
117#define SQD (SNPTY+11)
118 { "_qd_tty" },
119#define SNQD (SNPTY+12)
120 { "_nNQD" },
4242be26 121#endif
b98ff689 122
4242be26
SL
123#ifdef tahoe
124#define SVX (SNPTY+1)
125 { "_vx_tty" },
126#define SNVX (SNPTY+2)
127 { "_nvx" },
844d8384 128#define SMP (SNPTY+3)
c6864ab6 129 { "_mp_tty" },
844d8384 130#define SNMP (SNPTY+4)
c6864ab6 131 { "_nmp" },
4242be26 132#endif
b98ff689
MK
133
134#ifdef hp300
135#define SDCA (SNPTY+1)
136 { "_dca_tty" },
137#define SNDCA (SNPTY+2)
138 { "_ndca" },
139#define SDCM (SNPTY+3)
140 { "_dcm_tty" },
141#define SNDCM (SNPTY+4)
1d47dec3 142 { "_ndcm" },
b98ff689
MK
143#define SDCL (SNPTY+5)
144 { "_dcl_tty" },
145#define SNDCL (SNPTY+6)
146 { "_ndcl" },
147#define SITE (SNPTY+7)
148 { "_ite_tty" },
149#define SNITE (SNPTY+8)
150 { "_nite" },
151#endif
b94a50ef 152 { "" }
ceb84881
BJ
153};
154
6102031f 155int vnof;
ceb84881
BJ
156int txtf;
157int prcf;
158int ttyf;
159int usrf;
8a5d2599 160int upid;
ceb84881
BJ
161int filf;
162int swpf;
163int totflg;
164char partab[1];
165struct cdevsw cdevsw[1];
166struct bdevsw bdevsw[1];
167int allflg;
6102031f 168int nflg;
dc2a22f1 169u_long getword();
9ed2dfb9 170off_t mkphys();
ceb84881 171
6102031f
MT
172char *Program;
173
1d47dec3
MT
174#define V(x) (void *)(x)
175
ceb84881 176main(argc, argv)
0dc27808
KB
177 int argc;
178 char **argv;
ceb84881 179{
0dc27808
KB
180 extern char *optarg;
181 extern int optind;
1d47dec3 182 int ch, ret;
ceb84881 183
6102031f 184 Program = argv[0];
2e924960 185 while ((ch = getopt(argc, argv, "TafvikptU:sxnu")) != EOF)
b98ff689 186 switch (ch) {
ceb84881
BJ
187 case 'T':
188 totflg++;
189 break;
ceb84881
BJ
190 case 'a':
191 allflg++;
0dc27808
KB
192 /*FALLTHROUGH*/
193 case 'p':
194 prcf++;
195 break;
196 case 'f':
197 filf++;
ceb84881 198 break;
6102031f 199 case 'v':
ceb84881 200 case 'i':
6102031f 201 vnof++;
ceb84881 202 break;
ceb84881
BJ
203 case 't':
204 ttyf++;
205 break;
2e924960 206 case 'U':
ceb84881 207 usrf++;
8a5d2599 208 sscanf(optarg, "%d", &upid);
ceb84881
BJ
209 break;
210 case 's':
211 swpf++;
212 break;
0dc27808
KB
213 case 'x':
214 txtf++;
215 break;
6102031f
MT
216 case 'n':
217 nflg++;
218 break;
2e924960
MT
219 case 'u':
220 fprintf(stderr, "pstat: use [ -U pid ] for -u\n");
221 exit(1);
0dc27808 222 case '?':
ae1f9014 223 default:
2e924960 224 fprintf(stderr, "usage: pstat -[Tafiptsx] [-U [pid]] [system] [core]\n");
ae1f9014 225 exit(1);
ceb84881 226 }
0dc27808
KB
227 argc -= optind;
228 argv += optind;
229
6102031f
MT
230 if (argc > 1)
231 fcore = argv[1];
232 if (argc > 0)
233 fnlist = argv[0];
234 if (kvm_openfiles(fnlist, fcore, NULL) == -1) {
1d47dec3 235 error("kvm_openfiles: %s", kvm_geterr());
aadf0902
MK
236 exit(1);
237 }
1d47dec3
MT
238 if ((ret = kvm_nlist(nl)) != 0) {
239 int i, quit = 0;
240
241 if (ret == -1) {
242 error("kvm_nlist: %s", kvm_geterr());
243 exit(1);
244 }
245 for (i = 0; i <= NLMANDATORY; i++) {
246 if (!nl[i].n_value) {
247 quit = 1;
248 error("undefined symbol: %s\n",
249 nl[i].n_name);
250 }
251 }
252 if (quit)
253 exit(1);
ceb84881 254 }
6102031f 255 if (!(filf | totflg | vnof | prcf | txtf | ttyf | usrf | swpf)) {
2e924960 256 printf("pstat: one or more of -[aivxptfsU] is required\n");
ae1f9014
SL
257 exit(1);
258 }
ceb84881 259 if (filf||totflg)
69d3d166 260 dofile();
6102031f
MT
261 if (vnof||totflg)
262 dovnode();
ceb84881
BJ
263 if (prcf||totflg)
264 doproc();
265 if (txtf||totflg)
266 dotext();
267 if (ttyf)
268 dotty();
269 if (usrf)
270 dousr();
271 if (swpf||totflg)
272 doswap();
273}
274
551215f4
MT
275struct e_vnode {
276 struct vnode *avnode;
277 struct vnode vnode;
278};
279
6102031f 280dovnode()
ceb84881 281{
551215f4
MT
282 register struct e_vnode *e_vnodebase, *endvnode, *evp;
283 register struct vnode *vp;
6102031f 284 register struct mount *maddr = NULL, *mp;
6102031f 285 int numvnodes;
551215f4 286 struct e_vnode *loadvnodes();
6102031f
MT
287 struct mount *getmnt();
288
551215f4 289 e_vnodebase = loadvnodes(&numvnodes);
ceb84881 290 if (totflg) {
6102031f 291 printf("%7d vnodes\n", numvnodes);
ceb84881
BJ
292 return;
293 }
551215f4 294 endvnode = e_vnodebase + numvnodes;
6102031f
MT
295 printf("%d active vnodes\n", numvnodes);
296
297
551215f4
MT
298#define ST mp->mnt_stat
299 for (evp = e_vnodebase; evp < endvnode; evp++) {
300 vp = &evp->vnode;
6102031f
MT
301 if (vp->v_mount != maddr) {
302 /*
303 * New filesystem
304 */
305 if ((mp = getmnt(vp->v_mount)) == NULL)
306 continue;
307 maddr = vp->v_mount;
308 mount_print(mp);
309 vnode_header();
310 switch(ST.f_type) {
311 case MOUNT_UFS:
312 case MOUNT_MFS:
313 ufs_header();
314 break;
315 case MOUNT_NFS:
316 nfs_header();
317 break;
318 case MOUNT_NONE:
319 case MOUNT_PC:
320 default:
321 break;
322 }
323 printf("\n");
324 }
551215f4 325 vnode_print(evp->avnode, vp);
6102031f
MT
326 switch(ST.f_type) {
327 case MOUNT_UFS:
328 case MOUNT_MFS:
329 ufs_print(vp);
330 break;
331 case MOUNT_NFS:
332 nfs_print(vp);
333 break;
334 case MOUNT_NONE:
335 case MOUNT_PC:
336 default:
337 break;
338 }
339 printf("\n");
6102031f 340 }
551215f4 341 free(e_vnodebase);
6102031f
MT
342}
343
344vnode_header()
345{
b98ff689 346 printf("ADDR TYP VFLAG USE HOLD");
6102031f
MT
347}
348
551215f4
MT
349vnode_print(avnode, vp)
350 struct vnode *avnode;
6102031f
MT
351 struct vnode *vp;
352{
353 char *type, flags[16];
354 char *fp = flags;
355 register flag;
356
357 /*
358 * set type
359 */
360 switch(vp->v_type) {
361 case VNON:
362 type = "non"; break;
363 case VREG:
364 type = "reg"; break;
365 case VDIR:
366 type = "dir"; break;
367 case VBLK:
368 type = "blk"; break;
369 case VCHR:
370 type = "chr"; break;
371 case VLNK:
372 type = "lnk"; break;
373 case VSOCK:
374 type = "soc"; break;
375 case VFIFO:
376 type = "fif"; break;
377 case VBAD:
378 type = "bad"; break;
379 default:
380 type = "unk"; break;
381 }
382 /*
383 * gather flags
384 */
385 flag = vp->v_flag;
386 if (flag & VROOT)
387 *fp++ = 'R';
388 if (flag & VTEXT)
389 *fp++ = 'T';
1d47dec3
MT
390 if (flag & VSYSTEM)
391 *fp++ = 'S';
6102031f
MT
392 if (flag & VXLOCK)
393 *fp++ = 'L';
394 if (flag & VXWANT)
395 *fp++ = 'W';
6102031f
MT
396 if (flag & VBWAIT)
397 *fp++ = 'B';
1d47dec3
MT
398 if (flag & VALIASED)
399 *fp++ = 'A';
6102031f
MT
400 if (flag == 0)
401 *fp++ = '-';
402 *fp = '\0';
403 /*
404 * print it
405 */
551215f4
MT
406 printf("%8x %s %5s %4d %4d",
407 avnode, type, flags, vp->v_usecount, vp->v_holdcnt);
6102031f
MT
408}
409
410ufs_header()
411{
551215f4 412 printf(" FILEID IFLAG RDEV|SZ");
6102031f
MT
413}
414
415ufs_print(vp)
416 struct vnode *vp;
417{
418 struct inode *ip = VTOI(vp);
419 char flagbuf[16], *flags = flagbuf;
420 register flag;
421 char *name;
422 mode_t type;
423 extern char *devname();
424
425 flag = ip->i_flag;
426 if (flag & ILOCKED)
427 *flags++ = 'L';
428 if (flag & IWANT)
429 *flags++ = 'W';
430 if (flag & IRENAME)
431 *flags++ = 'R';
432 if (flag & IUPD)
433 *flags++ = 'U';
434 if (flag & IACC)
435 *flags++ = 'A';
436 if (flag & ICHG)
437 *flags++ = 'C';
438 if (flag & IMOD)
439 *flags++ = 'M';
440 if (flag & ISHLOCK)
441 *flags++ = 'S';
442 if (flag & IEXLOCK)
443 *flags++ = 'E';
444 if (flag & ILWAIT)
445 *flags++ = 'Z';
446 if (flag == 0)
447 *flags++ = '-';
448 *flags = '\0';
449
551215f4 450 printf(" %6d %5s", ip->i_number, flagbuf);
6102031f
MT
451 type = ip->i_mode & S_IFMT;
452 if (type == S_IFCHR || type == S_IFBLK)
ff337c25 453 if (nflg || ((name = devname(ip->i_rdev, type)) == NULL))
6102031f
MT
454 printf(" %2d,%-2d",
455 major(ip->i_rdev), minor(ip->i_rdev));
456 else
457 printf(" %7s", name);
458 else
459 printf(" %7d", ip->i_size);
460}
461
462nfs_header()
463{
551215f4 464 printf(" FILEID NFLAG RDEV|SZ");
6102031f
MT
465}
466
467nfs_print(vp)
468 struct vnode *vp;
469{
551215f4 470 struct nfsnode *np = VTONFS(vp);
6102031f
MT
471 char flagbuf[16], *flags = flagbuf;
472 register flag;
473 char *name;
474 mode_t type;
475 extern char *devname();
476
477 flag = np->n_flag;
478 if (flag & NLOCKED)
479 *flags++ = 'L';
480 if (flag & NWANT)
481 *flags++ = 'W';
482 if (flag & NMODIFIED)
483 *flags++ = 'M';
6102031f
MT
484 if (flag & NWRITEERR)
485 *flags++ = 'E';
486 if (flag == 0)
487 *flags++ = '-';
488 *flags = '\0';
489
490#define VT np->n_vattr
551215f4 491 printf(" %6d %5s", VT.va_fileid, flagbuf);
6102031f
MT
492 type = VT.va_mode & S_IFMT;
493 if (type == S_IFCHR || type == S_IFBLK)
ff337c25 494 if (nflg || ((name = devname(VT.va_rdev, type)) == NULL))
6102031f
MT
495 printf(" %2d,%-2d",
496 major(VT.va_rdev), minor(VT.va_rdev));
497 else
498 printf(" %7s", name);
499 else
500 printf(" %7d", np->n_size);
501}
502
503/*
504 * Given a pointer to a mount structure in kernel space,
505 * read it in and return a usable pointer to it.
506 */
507struct mount *
508getmnt(maddr)
509 struct mount *maddr;
510{
511 static struct mtab {
512 struct mtab *next;
513 struct mount *maddr;
514 struct mount mount;
515 } *mhead = NULL;
516 register struct mtab *mt;
517
518 for (mt = mhead; mt != NULL; mt = mt->next)
519 if (maddr == mt->maddr)
520 return (&mt->mount);
521 if ((mt = (struct mtab *)malloc(sizeof (struct mtab))) == NULL) {
522 error("out of memory");
523 exit(1);
524 }
1d47dec3 525 if (kvm_read(V(maddr), &mt->mount, sizeof(struct mount)) !=
6102031f
MT
526 sizeof(struct mount)) {
527 error("can't read mount table at %x", maddr);
528 return (NULL);
529 }
530 mt->maddr = maddr;
531 mt->next = mhead;
532 mhead = mt;
533 return (&mt->mount);
534}
535
536mount_print(mp)
537 struct mount *mp;
538{
539 char *type = "unknown";
540 register flags;
541
551215f4 542#define ST mp->mnt_stat
6102031f
MT
543 printf("*** MOUNT ");
544 switch (ST.f_type) {
545 case MOUNT_NONE:
546 type = "none";
547 break;
548 case MOUNT_UFS:
549 type = "ufs";
550 break;
551 case MOUNT_NFS:
552 type = "nfs";
553 break;
554 case MOUNT_MFS:
555 type = "mfs";
556 break;
557 case MOUNT_PC:
558 type = "pc";
559 break;
560 }
561 printf("%s %s on %s", type, ST.f_mntfromname, ST.f_mntonname);
551215f4 562 if (flags = mp->mnt_flag) {
6102031f
MT
563 char *comma = "(";
564
565 putchar(' ');
551215f4
MT
566 /* user visable flags */
567 if (flags & MNT_RDONLY) {
6102031f 568 printf("%srdonly", comma);
551215f4 569 flags &= ~MNT_RDONLY;
6102031f
MT
570 comma = ",";
571 }
551215f4 572 if (flags & MNT_SYNCHRONOUS) {
6102031f 573 printf("%ssynchronous", comma);
551215f4 574 flags &= ~MNT_SYNCHRONOUS;
6102031f
MT
575 comma = ",";
576 }
551215f4 577 if (flags & MNT_NOEXEC) {
6102031f 578 printf("%snoexec", comma);
551215f4 579 flags &= ~MNT_NOEXEC;
6102031f
MT
580 comma = ",";
581 }
551215f4 582 if (flags & MNT_NOSUID) {
6102031f 583 printf("%snosuid", comma);
551215f4 584 flags &= ~MNT_NOSUID;
6102031f
MT
585 comma = ",";
586 }
551215f4 587 if (flags & MNT_NODEV) {
6102031f 588 printf("%snodev", comma);
551215f4 589 flags &= ~MNT_NODEV;
6102031f
MT
590 comma = ",";
591 }
551215f4 592 if (flags & MNT_EXPORTED) {
6102031f 593 printf("%sexport", comma);
551215f4 594 flags &= ~MNT_EXPORTED;
6102031f
MT
595 comma = ",";
596 }
551215f4 597 if (flags & MNT_EXRDONLY) {
6102031f 598 printf("%sexrdonly", comma);
551215f4
MT
599 flags &= ~MNT_EXRDONLY;
600 comma = ",";
601 }
602 if (flags & MNT_LOCAL) {
603 printf("%slocal", comma);
604 flags &= ~MNT_LOCAL;
6102031f
MT
605 comma = ",";
606 }
551215f4
MT
607 if (flags & MNT_QUOTA) {
608 printf("%squota", comma);
609 flags &= ~MNT_QUOTA;
610 comma = ",";
611 }
612 /* filesystem control flags */
613 if (flags & MNT_UPDATE) {
614 printf("%supdate", comma);
615 flags &= ~MNT_UPDATE;
616 comma = ",";
617 }
618 if (flags & MNT_MLOCK) {
6102031f 619 printf("%slock", comma);
551215f4 620 flags &= ~MNT_MLOCK;
6102031f
MT
621 comma = ",";
622 }
551215f4 623 if (flags & MNT_MWAIT) {
6102031f 624 printf("%swait", comma);
551215f4
MT
625 flags &= ~MNT_MWAIT;
626 comma = ",";
627 }
628 if (flags & MNT_MPBUSY) {
629 printf("%sbusy", comma);
630 flags &= ~MNT_MPBUSY;
631 comma = ",";
632 }
633 if (flags & MNT_MPWANT) {
634 printf("%swant", comma);
635 flags &= ~MNT_MPWANT;
6102031f
MT
636 comma = ",";
637 }
551215f4
MT
638 if (flags & MNT_UNMOUNT) {
639 printf("%sunmount", comma);
640 flags &= ~MNT_UNMOUNT;
6102031f
MT
641 comma = ",";
642 }
551215f4
MT
643 if (flags)
644 printf("%sunknown_flags:%x", flags);
6102031f
MT
645 printf(")");
646 }
647 printf("\n");
648#undef ST
649}
650
551215f4 651struct e_vnode *
6102031f
MT
652loadvnodes(avnodes)
653 int *avnodes;
654{
caa05a92 655 int ret, copysize;
551215f4 656 struct e_vnode *vnodebase;
6102031f
MT
657
658 if (fcore != NULL) {
1bbe0c66
MT
659 /*
660 * add emulation of KINFO_VNODE here
661 */
662 error("vnodes on dead kernel, not impl\n");
6102031f
MT
663 exit(1);
664 }
665 if ((ret = getkerninfo(KINFO_VNODE, NULL, NULL, 0)) == -1) {
666 syserror("can't get estimate for kerninfo");
667 exit(1);
668 }
669 copysize = ret;
551215f4 670 if ((vnodebase = (struct e_vnode *)malloc(copysize))
6102031f
MT
671 == NULL) {
672 error("out of memory");
673 exit(1);
674 }
675 if ((ret = getkerninfo(KINFO_VNODE, vnodebase, &copysize, 0))
676 == -1) {
677 syserror("can't get vnode list");
678 exit(1);
679 }
551215f4 680 if (copysize % sizeof (struct e_vnode)) {
6102031f 681 error("vnode size mismatch");
1d47dec3 682 exit(1);
ceb84881 683 }
551215f4 684 *avnodes = copysize / sizeof (struct e_vnode);
6102031f
MT
685
686 return (vnodebase);
69d3d166
BJ
687}
688
9ed2dfb9 689u_long
dc2a22f1 690getword(loc)
1d47dec3 691 int loc;
69d3d166 692{
9ed2dfb9 693 u_long word;
69d3d166 694
1d47dec3 695 kvm_read(V(loc), &word, sizeof (word));
69d3d166 696 return (word);
ceb84881
BJ
697}
698
699putf(v, n)
700{
701 if (v)
702 printf("%c", n);
703 else
69d3d166 704 printf(" ");
ceb84881
BJ
705}
706
707dotext()
708{
d7985207
MK
709#ifdef NEWVM
710 printf("no text table in this system\n");
711#else
ceb84881 712 register struct text *xp;
69d3d166
BJ
713 int ntext;
714 struct text *xtext, *atext;
9ed2dfb9 715 int ntx, ntxca;
ceb84881 716
9ed2dfb9 717 ntx = ntxca = 0;
dc2a22f1 718 ntext = getword(nl[SNTEXT].n_value);
69d3d166 719 xtext = (struct text *)calloc(ntext, sizeof (struct text));
dc2a22f1 720 atext = (struct text *)getword(nl[STEXT].n_value);
9ed2dfb9
MK
721 if (ntext < 0 || ntext > 10000) {
722 fprintf(stderr, "number of texts is preposterous (%d)\n",
723 ntext);
724 return;
725 }
726 if (xtext == NULL) {
727 fprintf(stderr, "can't allocate memory for text table\n");
728 return;
729 }
6102031f 730 kvm_read(atext, xtext, ntext * sizeof (struct text));
9ed2dfb9 731 for (xp = xtext; xp < &xtext[ntext]; xp++) {
9eecf21c 732 if (xp->x_vptr != NULL)
9ed2dfb9
MK
733 ntxca++;
734 if (xp->x_count != 0)
ceb84881 735 ntx++;
9ed2dfb9 736 }
ceb84881 737 if (totflg) {
9ed2dfb9 738 printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca);
ceb84881
BJ
739 return;
740 }
9ed2dfb9
MK
741 printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca);
742 printf("\
9eecf21c 743 LOC FLAGS DADDR CADDR RSS SIZE VPTR CNT CCNT FORW BACK\n");
69d3d166 744 for (xp = xtext; xp < &xtext[ntext]; xp++) {
9eecf21c 745 if (xp->x_vptr == NULL)
ceb84881 746 continue;
69d3d166 747 printf("%8.1x", atext + (xp - xtext));
ceb84881 748 printf(" ");
9eecf21c 749 putf(xp->x_flag&XPAGV, 'P');
ceb84881
BJ
750 putf(xp->x_flag&XTRC, 'T');
751 putf(xp->x_flag&XWRIT, 'W');
752 putf(xp->x_flag&XLOAD, 'L');
753 putf(xp->x_flag&XLOCK, 'K');
754 putf(xp->x_flag&XWANT, 'w');
ceb84881 755 printf("%5x", xp->x_daddr[0]);
9ed2dfb9 756 printf("%10x", xp->x_caddr);
ceb84881
BJ
757 printf("%5d", xp->x_rssize);
758 printf("%5d", xp->x_size);
9eecf21c 759 printf("%10.1x", xp->x_vptr);
ceb84881 760 printf("%5d", xp->x_count&0377);
54298f71 761 printf("%5d", xp->x_ccount);
9ed2dfb9
MK
762 printf("%10x", xp->x_forw);
763 printf("%9x", xp->x_back);
ceb84881
BJ
764 printf("\n");
765 }
69d3d166 766 free(xtext);
d7985207 767#endif
ceb84881
BJ
768}
769
770doproc()
771{
d7985207 772#ifdef NEWVM
1bbe0c66 773 printf("pstat: -p no longer supported (use ps)\n");
d7985207 774#else
69d3d166
BJ
775 struct proc *xproc, *aproc;
776 int nproc;
ceb84881
BJ
777 register struct proc *pp;
778 register loc, np;
caa05a92 779 /*
ceb84881 780 struct pte apte;
caa05a92 781 */
ceb84881 782
dc2a22f1 783 nproc = getword(nl[SNPROC].n_value);
69d3d166 784 xproc = (struct proc *)calloc(nproc, sizeof (struct proc));
dc2a22f1 785 aproc = (struct proc *)getword(nl[SPROC].n_value);
2e924960 786 if (nproc < 0 || nproc > 100000) {
9ed2dfb9
MK
787 fprintf(stderr, "number of procs is preposterous (%d)\n",
788 nproc);
789 return;
790 }
791 if (xproc == NULL) {
792 fprintf(stderr, "can't allocate memory for proc table\n");
793 return;
794 }
6102031f 795 kvm_read(aproc, xproc, nproc * sizeof (struct proc));
ceb84881 796 np = 0;
69d3d166 797 for (pp=xproc; pp < &xproc[nproc]; pp++)
ceb84881
BJ
798 if (pp->p_stat)
799 np++;
800 if (totflg) {
69d3d166 801 printf("%3d/%3d processes\n", np, nproc);
ceb84881
BJ
802 return;
803 }
69d3d166 804 printf("%d/%d processes\n", np, nproc);
1b27d03f 805 printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n");
69d3d166 806 for (pp=xproc; pp<&xproc[nproc]; pp++) {
ceb84881
BJ
807 if (pp->p_stat==0 && allflg==0)
808 continue;
69d3d166 809 printf("%8x", aproc + (pp - xproc));
ceb84881 810 printf(" %2d", pp->p_stat);
1b27d03f 811 printf(" %8x", pp->p_flag);
ceb84881
BJ
812 printf(" %4d", pp->p_poip);
813 printf(" %3d", pp->p_pri);
54298f71 814 printf(" %8x", pp->p_sig);
ceb84881
BJ
815 printf(" %4d", pp->p_uid);
816 printf(" %3d", pp->p_slptime);
817 printf(" %3d", pp->p_time);
818 printf(" %4d", pp->p_cpu&0377);
819 printf(" %3d", pp->p_nice);
ceb84881
BJ
820 printf(" %6d", pp->p_pid);
821 printf(" %6d", pp->p_ppid);
6102031f 822 /*
aadf0902 823 if (pp->p_flag & SLOAD) {
6102031f 824 kvm_read(pp->p_addr, &apte, sizeof(apte));
aadf0902
MK
825 printf(" %8x", apte.pg_pfnum);
826 } else
827 printf(" %8x", pp->p_swaddr);
6102031f 828 */
ceb84881
BJ
829 printf(" %4x", pp->p_rssize);
830 printf(" %4x", pp->p_swrss);
831 printf(" %5x", pp->p_dsize+pp->p_ssize);
832 printf(" %7x", clear(pp->p_wchan));
833 printf(" %7x", clear(pp->p_link));
834 printf(" %7x", clear(pp->p_textp));
ceb84881
BJ
835 printf("\n");
836 }
9ed2dfb9 837 free(xproc);
d7985207 838#endif
ceb84881
BJ
839}
840
b98ff689 841char mesg[] = " LINE RAW CAN OUT HWT LWT ADDR COL STATE SESS PGID DISC\n";
6102031f
MT
842int ttyspace = 128;
843struct tty *tty;
5cf6fff2 844
ceb84881
BJ
845dotty()
846{
ceb84881 847
13562341
MK
848 if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) {
849 printf("pstat: out of memory\n");
850 return;
851 }
b98ff689 852#ifndef hp300
ceb84881 853 printf("1 cons\n");
1d47dec3 854 kvm_read(V(nl[SCONS].n_value), tty, sizeof(*tty));
ceb84881 855 printf(mesg);
13562341 856 ttyprt(&tty[0], 0);
b98ff689 857#endif
4242be26 858#ifdef vax
bac975ad
MT
859 if (nl[SNQD].n_type != 0)
860 doqdss();
5cf6fff2
KM
861 if (nl[SNDZ].n_type != 0)
862 dottytype("dz", SDZ, SNDZ);
863 if (nl[SNDH].n_type != 0)
864 dottytype("dh", SDH, SNDH);
865 if (nl[SNDMF].n_type != 0)
866 dottytype("dmf", SDMF, SNDMF);
867 if (nl[SNDHU].n_type != 0)
868 dottytype("dhu", SDHU, SNDHU);
35d0530f
JB
869 if (nl[SNDMZ].n_type != 0)
870 dottytype("dmz", SDMZ, SNDMZ);
4242be26
SL
871#endif
872#ifdef tahoe
873 if (nl[SNVX].n_type != 0)
874 dottytype("vx", SVX, SNVX);
c6864ab6
KB
875 if (nl[SNMP].n_type != 0)
876 dottytype("mp", SMP, SNMP);
b98ff689
MK
877#endif
878#ifdef hp300
879 if (nl[SNITE].n_type != 0)
880 dottytype("ite", SITE, SNITE);
881 if (nl[SNDCA].n_type != 0)
882 dottytype("dca", SDCA, SNDCA);
883 if (nl[SNDCM].n_type != 0)
884 dottytype("dcm", SDCM, SNDCM);
885 if (nl[SNDCL].n_type != 0)
886 dottytype("dcl", SDCL, SNDCL);
4242be26 887#endif
5cf6fff2
KM
888 if (nl[SNPTY].n_type != 0)
889 dottytype("pty", SPTY, SNPTY);
890}
891
bac975ad 892/*
844d8384
MT
893 * Special case the qdss: there are 4 ttys per qdss,
894 * but only the first of each is used as a tty.
bac975ad
MT
895 */
896#ifdef vax
897doqdss()
898{
899 int nqd;
900 register struct tty *tp;
901
1d47dec3 902 kvm_read(V(nl[SNQD].n_value), &nqd, sizeof(nqd));
bac975ad 903 printf("%d qd\n", nqd);
1d47dec3 904 kvm_read((V(nl[SQD].n_value), tty, nqd * sizeof(struct tty) * 4);
bac975ad
MT
905 printf(mesg);
906 for (tp = tty; tp < &tty[nqd * 4]; tp += 4)
907 ttyprt(tp, tp - tty);
908}
909#endif
910
5cf6fff2
KM
911dottytype(name, type, number)
912char *name;
913{
914 int ntty;
915 register struct tty *tp;
916 extern char *realloc();
917
bac975ad 918 if (tty == (struct tty *)0)
890571d1 919 return;
1d47dec3 920 kvm_read(V(nl[number].n_value), &ntty, sizeof(ntty));
5cf6fff2 921 printf("%d %s lines\n", ntty, name);
13562341
MK
922 if (ntty > ttyspace) {
923 ttyspace = ntty;
924 if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) {
925 printf("pstat: out of memory\n");
926 return;
927 }
676bc34a 928 }
1d47dec3 929 kvm_read(V(nl[type].n_value), tty, ntty * sizeof(struct tty));
8faa0fee 930 printf(mesg);
13562341
MK
931 for (tp = tty; tp < &tty[ntty]; tp++)
932 ttyprt(tp, tp - tty);
ceb84881
BJ
933}
934
844d8384
MT
935struct {
936 int flag;
937 char val;
938} ttystates[] = {
939 TS_WOPEN, 'W',
940 TS_ISOPEN, 'O',
941 TS_CARR_ON, 'C',
942 TS_TIMEOUT, 'T',
943 TS_FLUSH, 'F',
944 TS_BUSY, 'B',
945 TS_ASLEEP, 'A',
946 TS_XCLUDE, 'X',
947 TS_TTSTOP, 'S',
844d8384
MT
948 TS_TBLOCK, 'K',
949 TS_RCOLL, 'R',
950 TS_WCOLL, 'I', /* running short on letters ! */
951 TS_ASYNC, 'Y',
952 TS_BKSL, 'D',
953 TS_ERASE, 'E',
954 TS_LNCH, 'L',
955 TS_TYPEN, 'P',
956 TS_CNTTB, 'N',
957 0, 0
958};
959
ceb84881
BJ
960ttyprt(atp, line)
961struct tty *atp;
962{
963 register struct tty *tp;
844d8384
MT
964 char state[20];
965 register i, j;
551215f4
MT
966 char *name;
967 extern char *devname();
968 pid_t pgid;
ceb84881 969
ceb84881 970 tp = atp;
7e7bb114 971 if (nflg || tp->t_dev == 0 ||
551215f4
MT
972 (name = devname(tp->t_dev, S_IFCHR)) == NULL)
973 printf("%7d ", line);
974 else
975 printf("%7s ", name);
976 printf("%2d %3d ", tp->t_rawq.c_cc, tp->t_canq.c_cc);
b98ff689 977 printf("%3d %4d %3d %8x %3d ", tp->t_outq.c_cc,
844d8384
MT
978 tp->t_hiwat, tp->t_lowat, tp->t_addr, tp->t_col);
979 for (i = j = 0; ttystates[i].flag; i++)
980 if (tp->t_state&ttystates[i].flag)
981 state[j++] = ttystates[i].val;
b98ff689
MK
982 if (j == 0)
983 state[j++] = '-';
844d8384 984 state[j] = '\0';
b98ff689 985 printf("%-4s %6x", state, (u_long)tp->t_session & ~KERNBASE);
551215f4
MT
986 if (tp->t_pgrp == NULL || kvm_read(&tp->t_pgrp->pg_id, &pgid,
987 sizeof (pid_t)) != sizeof (pid_t))
988 pgid = 0;
989 printf("%6d ", pgid);
ceb84881
BJ
990 switch (tp->t_line) {
991
b98ff689 992 case TTYDISC:
844d8384 993 printf("term\n");
ceb84881
BJ
994 break;
995
8faa0fee 996 case TABLDISC:
844d8384 997 printf("tab\n");
8faa0fee
EW
998 break;
999
399e4254 1000 case SLIPDISC:
844d8384 1001 printf("slip\n");
399e4254
KB
1002 break;
1003
8faa0fee 1004 default:
844d8384 1005 printf("%d\n", tp->t_line);
ceb84881 1006 }
ceb84881
BJ
1007}
1008
1d47dec3
MT
1009/*
1010 * The user structure is going away. What's left here won't
1011 * be around for long.
1012 */
ceb84881
BJ
1013dousr()
1014{
d7985207
MK
1015#ifdef NEWVM
1016 printf("nothing left in user structure in this system\n");
1017#else
8a5d2599 1018 register struct user *up;
ceb84881 1019 register i, j, *ip;
2e924960 1020 register struct nameidata *nd;
8a5d2599 1021 struct proc *p;
2e924960 1022 int ret;
ceb84881 1023
2e924960
MT
1024 if ((ret = kvm_getprocs(KINFO_PROC_PID, upid)) != 1) {
1025 if (ret == -1)
1026 error("kvm_getproc: %s", kvm_geterr());
1027 else
1028 error("can't locate process %d", upid);
8a5d2599
MT
1029 return (1);
1030 }
2e924960 1031 if ((p = kvm_nextproc()) == NULL) {
8a5d2599
MT
1032 error("kvm_nextproc: %s", kvm_geterr());
1033 return (1);
1034 }
2e924960 1035 if ((up = kvm_getu(p)) == NULL) {
8a5d2599
MT
1036 error("kvm_getu: %s", kvm_geterr());
1037 return (1);
1038 }
2e924960 1039 nd = &up->u_nd;
ceb84881 1040 printf("pcb");
8a5d2599 1041 ip = (int *)&up->u_pcb;
2e924960
MT
1042 i = 0;
1043 while (ip < (int *)((char *)&up->u_pcb + sizeof (struct pcb))) {
1044 if (i%4 == 0)
1045 putchar('\t');
1046 printf("%#10x ", *ip++);
1047 if (i%4 == 3)
1048 putchar('\n');
1049 i++;
ceb84881 1050 }
2e924960
MT
1051 if (i%4)
1052 putchar('\n');
1053 printf("procp\t%#x\n", up->u_procp);
1054 printf("ar0\t%#x\n", up->u_ar0);
1055 printf("sizes\ttext %d data %d stack %d\n",
1056 up->u_tsize, up->u_dsize, up->u_ssize);
2e924960
MT
1057 printf("ssave");
1058 for (i=0; i<sizeof(label_t)/sizeof(int); i++) {
ceb84881
BJ
1059 if (i%5==0)
1060 printf("\t");
2e924960 1061 printf("%#11x", up->u_ssave.val[i]);
ceb84881
BJ
1062 if (i%5==4)
1063 printf("\n");
1064 }
1065 if (i%5)
1066 printf("\n");
2e924960
MT
1067 printf("odsize\t%#x\n", up->u_odsize);
1068 printf("ossize\t%#x\n", up->u_ossize);
1069 printf("outime\t%d\n", up->u_outime);
1070 printf("mmap\t%#x\n", up->u_mmap);
1071 printf("sigs");
1072 for (i=0; i<NSIG; i++) {
aadf0902
MK
1073 if (i % 8 == 0)
1074 printf("\t");
2e924960 1075 printf("%#x ", up->u_signal[i]);
aadf0902
MK
1076 if (i % 8 == 7)
1077 printf("\n");
1078 }
1079 if (i % 8)
1080 printf("\n");
2e924960
MT
1081 printf("sigmask");
1082 for (i=0; i<NSIG; i++) {
aadf0902
MK
1083 if (i % 8 == 0)
1084 printf("\t");
2e924960 1085 printf("%#x ", up->u_sigmask[i]);
aadf0902
MK
1086 if (i % 8 == 7)
1087 printf("\n");
1088 }
1089 if (i % 8)
1090 printf("\n");
2e924960
MT
1091 printf("sigonstack\t%#x\n", up->u_sigonstack);
1092 printf("sigintr\t%#x\n", up->u_sigintr);
1093 printf("oldmask\t%#x\n", up->u_oldmask);
1094 printf("sigstack\t%#x %#x\n",
1095 up->u_sigstack.ss_sp, up->u_sigstack.ss_onstack);
1096 printf("sig\t%#x\n", up->u_sig);
1097 printf("code\t%#x\n", up->u_code);
2e924960
MT
1098 printf("start\t%ld secs %ld usecs\n",
1099 up->u_start.tv_sec, up->u_start.tv_usec);
1100 printf("acflag\t%#x\n", up->u_acflag);
1101 printf("prof\t%#x %#x %#x %#x\n", up->u_prof.pr_base, up->u_prof.pr_size,
8a5d2599 1102 up->u_prof.pr_off, up->u_prof.pr_scale);
88a58f27 1103 printf("ru\t");
8a5d2599
MT
1104 ip = (int *)&up->u_ru;
1105 for (i = 0; i < sizeof(up->u_ru)/sizeof(int); i++)
b9e98a4b 1106 printf("%ld ", ip[i]);
ceb84881 1107 printf("\n");
8a5d2599 1108 ip = (int *)&up->u_cru;
88a58f27 1109 printf("cru\t");
8a5d2599 1110 for (i = 0; i < sizeof(up->u_cru)/sizeof(int); i++)
b9e98a4b 1111 printf("%ld ", ip[i]);
ceb84881 1112 printf("\n");
d7985207 1113#endif
ceb84881
BJ
1114}
1115
1116oatoi(s)
1117char *s;
1118{
1119 register v;
1120
1121 v = 0;
1122 while (*s)
1123 v = (v<<3) + *s++ - '0';
1124 return(v);
1125}
1126
69d3d166 1127dofile()
ceb84881 1128{
ceb84881 1129 register struct file *fp;
1bbe0c66
MT
1130 struct file *addr;
1131 char *buf;
1132 int len, maxfile, nfile;
1133 struct nlist fnl[] = {
1134#define FNL_NFILE 0
1135 {"_nfiles"},
1136#define FNL_MAXFILE 1
1137 {"_maxfiles"},
1138 {""}
1139 };
71c73ab0 1140 static char *dtypes[] = { "???", "inode", "socket" };
ceb84881 1141
1bbe0c66
MT
1142 if (kvm_nlist(fnl) != 0) {
1143 error("kvm_nlist: no _nfiles or _maxfiles: %s",
1144 kvm_geterr());
9ed2dfb9
MK
1145 return;
1146 }
1bbe0c66
MT
1147 kvm_read(V(fnl[FNL_MAXFILE].n_value), &maxfile,
1148 sizeof (maxfile));
ceb84881 1149 if (totflg) {
1bbe0c66
MT
1150 kvm_read(V(fnl[FNL_NFILE].n_value), &nfile, sizeof (nfile));
1151 printf("%3d/%3d files\n", nfile, maxfile);
ceb84881
BJ
1152 return;
1153 }
1bbe0c66
MT
1154 if (getfiles(&buf, &len) == -1)
1155 return;
1156 /*
1157 * getfiles returns in malloc'd buf a pointer to the first file
1158 * structure, and then an array of file structs (whose
1159 * addresses are derivable from the previous entry)
1160 */
1161 addr = *((struct file **)buf);
1162 fp = (struct file *)(buf + sizeof (struct file *));
1163 nfile = (len - sizeof (struct file *)) / sizeof (struct file);
1164
1165 printf("%d/%d open files\n", nfile, maxfile);
192c0cf3 1166 printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n");
1bbe0c66
MT
1167 for (; (char *)fp < buf + len; addr = fp->f_filef, fp++) {
1168 printf("%x ", addr);
71c73ab0 1169 if (fp->f_type <= DTYPE_SOCKET)
ae1f9014
SL
1170 printf("%-8.8s", dtypes[fp->f_type]);
1171 else
ff8002b1 1172 printf("%8d", fp->f_type);
ceb84881
BJ
1173 putf(fp->f_flag&FREAD, 'R');
1174 putf(fp->f_flag&FWRITE, 'W');
ae1f9014 1175 putf(fp->f_flag&FAPPEND, 'A');
38e88f54 1176#ifdef FSHLOCK /* currently gone */
192c0cf3
SL
1177 putf(fp->f_flag&FSHLOCK, 'S');
1178 putf(fp->f_flag&FEXLOCK, 'X');
1bbe0c66
MT
1179#else
1180 putf(0, ' ');
1181 putf(0, ' ');
38e88f54 1182#endif
192c0cf3 1183 putf(fp->f_flag&FASYNC, 'I');
1bbe0c66
MT
1184 printf(" %3d", fp->f_count);
1185 printf(" %3d", fp->f_msgcount);
71c73ab0
SL
1186 printf(" %8.1x", fp->f_data);
1187 if (fp->f_offset < 0)
1188 printf(" %x\n", fp->f_offset);
676bc34a
BJ
1189 else
1190 printf(" %ld\n", fp->f_offset);
ceb84881 1191 }
1bbe0c66 1192 free(buf);
ceb84881
BJ
1193}
1194
1bbe0c66
MT
1195getfiles(abuf, alen)
1196 char **abuf;
1197 int *alen;
1198{
1199 char *buf;
1200 int len;
1201
1202 if (fcore != NULL) {
1203 /*
1204 * add emulation of KINFO_FILE here
1205 */
1206 error("files on dead kernel, not impl\n");
1207 exit(1);
1208 }
1209 if ((len = getkerninfo(KINFO_FILE, NULL, NULL, 0)) == -1) {
1210 syserror("getkerninfo estimate");
1211 return (-1);
1212 }
1213 if ((buf = (char *)malloc(len)) == NULL) {
1214 error("out of memory");
1215 return (-1);
1216 }
1217 if ((len = getkerninfo(KINFO_FILE, buf, &len, 0)) == -1) {
1218 syserror("getkerninfo");
1219 return (-1);
1220 }
1221 *abuf = buf;
1222 *alen = len;
1223 return (0);
1224}
1225
1226
d7985207
MK
1227#ifdef NEWVM
1228doswap()
1229{
1230 printf("swap statistics not yet supported in this system\n");
1231}
1232
1233#else /* NEWVM */
e79dc02e
SL
1234int dmmin, dmmax, nswdev;
1235
ceb84881
BJ
1236doswap()
1237{
69d3d166
BJ
1238 struct proc *proc;
1239 int nproc;
1240 struct text *xtext;
1241 int ntext;
1242 struct map *swapmap;
1243 int nswapmap;
b94a50ef 1244 struct swdevt *swdevt, *sw;
ceb84881 1245 register struct proc *pp;
e79dc02e
SL
1246 int nswap, used, tused, free, waste;
1247 int db, sb;
df3e00cc 1248 register struct mapent *me;
ceb84881 1249 register struct text *xp;
e79dc02e 1250 int i, j;
f85d329a 1251 long rmalloc();
ceb84881 1252
dc2a22f1
KM
1253 nproc = getword(nl[SNPROC].n_value);
1254 ntext = getword(nl[SNTEXT].n_value);
9ed2dfb9
MK
1255 if (nproc < 0 || nproc > 10000 || ntext < 0 || ntext > 10000) {
1256 fprintf(stderr, "number of procs/texts is preposterous (%d, %d)\n",
1257 nproc, ntext);
1258 return;
1259 }
1260 proc = (struct proc *)calloc(nproc, sizeof (struct proc));
1261 if (proc == NULL) {
1262 fprintf(stderr, "can't allocate memory for proc table\n");
1263 exit(1);
1264 }
b94a50ef 1265 xtext = (struct text *)calloc(ntext, sizeof (struct text));
9ed2dfb9
MK
1266 if (xtext == NULL) {
1267 fprintf(stderr, "can't allocate memory for text table\n");
1268 exit(1);
1269 }
dc2a22f1 1270 nswapmap = getword(nl[SNSWAPMAP].n_value);
69d3d166 1271 swapmap = (struct map *)calloc(nswapmap, sizeof (struct map));
9ed2dfb9
MK
1272 if (swapmap == NULL) {
1273 fprintf(stderr, "can't allocate memory for swapmap\n");
1274 exit(1);
1275 }
dc2a22f1 1276 nswdev = getword(nl[SNSWDEV].n_value);
b94a50ef 1277 swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt));
9ed2dfb9
MK
1278 if (swdevt == NULL) {
1279 fprintf(stderr, "can't allocate memory for swdevt table\n");
1280 exit(1);
1281 }
1d47dec3 1282 kvm_read(V(nl[SSWDEVT].n_value), swdevt,
2e924960 1283 nswdev * sizeof (struct swdevt));
1d47dec3 1284 kvm_read(V(getword(nl[SPROC].n_value)), proc,
2e924960 1285 nproc * sizeof (struct proc));
1d47dec3 1286 kvm_read(V(getword(nl[STEXT].n_value)), xtext,
2e924960 1287 ntext * sizeof (struct text));
1d47dec3 1288 kvm_read(V(getword(nl[SWAPMAP].n_value)), swapmap,
2e924960 1289 nswapmap * sizeof (struct map));
6102031f 1290
33b2e9da 1291 swapmap->m_name = "swap";
e49b41bc 1292 swapmap->m_limit = (struct mapent *)&swapmap[nswapmap];
dc2a22f1
KM
1293 dmmin = getword(nl[SDMMIN].n_value);
1294 dmmax = getword(nl[SDMMAX].n_value);
b94a50ef
SL
1295 nswap = 0;
1296 for (sw = swdevt; sw < &swdevt[nswdev]; sw++)
491de191
KM
1297 if (sw->sw_freed)
1298 nswap += sw->sw_nblks;
ceb84881 1299 free = 0;
df3e00cc
BJ
1300 for (me = (struct mapent *)(swapmap+1);
1301 me < (struct mapent *)&swapmap[nswapmap]; me++)
1302 free += me->m_size;
ceb84881 1303 tused = 0;
69d3d166 1304 for (xp = xtext; xp < &xtext[ntext]; xp++)
9eecf21c 1305 if (xp->x_vptr!=NULL) {
79877ea5 1306 tused += ctod(clrnd(xp->x_size));
9eecf21c 1307 if (xp->x_flag & XPAGV)
79877ea5 1308 tused += ctod(clrnd(ctopt(xp->x_size)));
b94a50ef 1309 }
ceb84881 1310 used = tused;
e79dc02e 1311 waste = 0;
69d3d166 1312 for (pp = proc; pp < &proc[nproc]; pp++) {
ceb84881
BJ
1313 if (pp->p_stat == 0 || pp->p_stat == SZOMB)
1314 continue;
1315 if (pp->p_flag & SSYS)
1316 continue;
b94a50ef
SL
1317 db = ctod(pp->p_dsize), sb = up(db);
1318 used += sb;
1319 waste += sb - db;
1320 db = ctod(pp->p_ssize), sb = up(db);
1321 used += sb;
1322 waste += sb - db;
ceb84881 1323 if ((pp->p_flag&SLOAD) == 0)
13562341 1324 used += ctod(vusize(pp));
ceb84881 1325 }
ceb84881 1326 if (totflg) {
b94a50ef
SL
1327#define btok(x) ((x) / (1024 / DEV_BSIZE))
1328 printf("%3d/%3d 00k swap\n",
1329 btok(used/100), btok((used+free)/100));
ceb84881
BJ
1330 return;
1331 }
b94a50ef
SL
1332 printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n",
1333 btok(used), btok(tused), btok(free), btok(waste),
1334/* a dmmax/2 block goes to argmap */
1335 btok(nswap - dmmax/2 - (used + free)));
e79dc02e
SL
1336 printf("avail: ");
1337 for (i = dmmax; i >= dmmin; i /= 2) {
1338 j = 0;
1339 while (rmalloc(swapmap, i) != 0)
1340 j++;
b94a50ef 1341 if (j) printf("%d*%dk ", j, btok(i));
e79dc02e 1342 }
b94a50ef
SL
1343 free = 0;
1344 for (me = (struct mapent *)(swapmap+1);
1345 me < (struct mapent *)&swapmap[nswapmap]; me++)
1346 free += me->m_size;
1347 printf("%d*1k\n", btok(free));
ceb84881
BJ
1348}
1349
1350up(size)
1351 register int size;
1352{
1353 register int i, block;
1354
1355 i = 0;
e79dc02e 1356 block = dmmin;
ceb84881
BJ
1357 while (i < size) {
1358 i += block;
e79dc02e 1359 if (block < dmmax)
ceb84881
BJ
1360 block *= 2;
1361 }
1362 return (i);
1363}
1364
b94a50ef
SL
1365/*
1366 * Compute number of pages to be allocated to the u. area
1367 * and data and stack area page tables, which are stored on the
1368 * disk immediately after the u. area.
1369 */
ceb84881 1370vusize(p)
b94a50ef 1371 register struct proc *p;
ceb84881
BJ
1372{
1373 register int tsz = p->p_tsize / NPTEPG;
1374
b94a50ef
SL
1375 /*
1376 * We do not need page table space on the disk for page
1377 * table pages wholly containing text.
1378 */
1379 return (clrnd(UPAGES +
1380 clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz));
e79dc02e
SL
1381}
1382
1383/*
1384 * Allocate 'size' units from the given
1385 * map. Return the base of the allocated space.
1386 * In a map, the addresses are increasing and the
1387 * list is terminated by a 0 size.
1388 *
1389 * Algorithm is first-fit.
1390 *
1391 * This routine knows about the interleaving of the swapmap
1392 * and handles that.
1393 */
1394long
1395rmalloc(mp, size)
1396 register struct map *mp;
1397 long size;
1398{
1399 register struct mapent *ep = (struct mapent *)(mp+1);
1400 register int addr;
1401 register struct mapent *bp;
1402 swblk_t first, rest;
1403
1404 if (size <= 0 || size > dmmax)
1405 return (0);
1406 /*
1407 * Search for a piece of the resource map which has enough
1408 * free space to accomodate the request.
1409 */
1410 for (bp = ep; bp->m_size; bp++) {
1411 if (bp->m_size >= size) {
1412 /*
1413 * If allocating from swapmap,
1414 * then have to respect interleaving
1415 * boundaries.
1416 */
1417 if (nswdev > 1 &&
1418 (first = dmmax - bp->m_addr%dmmax) < bp->m_size) {
1419 if (bp->m_size - first < size)
1420 continue;
1421 addr = bp->m_addr + first;
1422 rest = bp->m_size - first - size;
1423 bp->m_size = first;
1424 if (rest)
1425 rmfree(mp, rest, addr+size);
1426 return (addr);
1427 }
1428 /*
1429 * Allocate from the map.
1430 * If there is no space left of the piece
1431 * we allocated from, move the rest of
1432 * the pieces to the left.
1433 */
1434 addr = bp->m_addr;
1435 bp->m_addr += size;
1436 if ((bp->m_size -= size) == 0) {
1437 do {
1438 bp++;
1439 (bp-1)->m_addr = bp->m_addr;
1440 } while ((bp-1)->m_size = bp->m_size);
1441 }
1442 if (addr % CLSIZE)
1443 return (0);
1444 return (addr);
1445 }
1446 }
1447 return (0);
1448}
1449
1450/*
1451 * Free the previously allocated space at addr
1452 * of size units into the specified map.
1453 * Sort addr into map and combine on
1454 * one or both ends if possible.
1455 */
1456rmfree(mp, size, addr)
1457 struct map *mp;
1458 long size, addr;
1459{
1460 struct mapent *firstbp;
1461 register struct mapent *bp;
1462 register int t;
1463
1464 /*
1465 * Both address and size must be
1466 * positive, or the protocol has broken down.
1467 */
1468 if (addr <= 0 || size <= 0)
1469 goto badrmfree;
1470 /*
1471 * Locate the piece of the map which starts after the
1472 * returned space (or the end of the map).
1473 */
1474 firstbp = bp = (struct mapent *)(mp + 1);
1475 for (; bp->m_addr <= addr && bp->m_size != 0; bp++)
1476 continue;
1477 /*
1478 * If the piece on the left abuts us,
1479 * then we should combine with it.
1480 */
1481 if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) {
1482 /*
1483 * Check no overlap (internal error).
1484 */
1485 if ((bp-1)->m_addr+(bp-1)->m_size > addr)
1486 goto badrmfree;
1487 /*
1488 * Add into piece on the left by increasing its size.
1489 */
1490 (bp-1)->m_size += size;
1491 /*
1492 * If the combined piece abuts the piece on
1493 * the right now, compress it in also,
1494 * by shifting the remaining pieces of the map over.
1495 */
1496 if (bp->m_addr && addr+size >= bp->m_addr) {
1497 if (addr+size > bp->m_addr)
1498 goto badrmfree;
1499 (bp-1)->m_size += bp->m_size;
1500 while (bp->m_size) {
1501 bp++;
1502 (bp-1)->m_addr = bp->m_addr;
1503 (bp-1)->m_size = bp->m_size;
1504 }
1505 }
1506 goto done;
1507 }
1508 /*
1509 * Don't abut on the left, check for abutting on
1510 * the right.
1511 */
1512 if (addr+size >= bp->m_addr && bp->m_size) {
1513 if (addr+size > bp->m_addr)
1514 goto badrmfree;
1515 bp->m_addr -= size;
1516 bp->m_size += size;
1517 goto done;
1518 }
1519 /*
1520 * Don't abut at all. Make a new entry
1521 * and check for map overflow.
1522 */
1523 do {
1524 t = bp->m_addr;
1525 bp->m_addr = addr;
1526 addr = t;
1527 t = bp->m_size;
1528 bp->m_size = size;
1529 bp++;
1530 } while (size = t);
1531 /*
1532 * Segment at bp is to be the delimiter;
1533 * If there is not room for it
1534 * then the table is too full
1535 * and we must discard something.
1536 */
1537 if (bp+1 > mp->m_limit) {
1538 /*
1539 * Back bp up to last available segment.
1540 * which contains a segment already and must
1541 * be made into the delimiter.
1542 * Discard second to last entry,
1543 * since it is presumably smaller than the last
1544 * and move the last entry back one.
1545 */
1546 bp--;
1547 printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name,
1548 (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size);
1549 bp[-1] = bp[0];
1550 bp[0].m_size = bp[0].m_addr = 0;
1551 }
1552done:
1553 return;
1554badrmfree:
1555 printf("bad rmfree\n");
ceb84881 1556}
d7985207 1557#endif /* NEWVM */
6102031f
MT
1558
1559#include <varargs.h>
1560
1561error(va_alist)
1562 va_dcl
1563{
1564 char *fmt;
1565 va_list ap;
1566 extern errno;
1567
1568 fprintf(stderr, "%s: ", Program);
1569 va_start(ap);
1570 fmt = va_arg(ap, char *);
1571 (void) vfprintf(stderr, fmt, ap);
1572 va_end(ap);
1573 fprintf(stderr, "\n");
1574}
1575
1576syserror(va_alist)
1577 va_dcl
76ea98af 1578{
6102031f
MT
1579 char *fmt;
1580 va_list ap;
1581 extern errno;
1582
1583 fprintf(stderr, "%s: ", Program);
1584 va_start(ap);
1585 fmt = va_arg(ap, char *);
1586 (void) vfprintf(stderr, fmt, ap);
1587 va_end(ap);
1588 fprintf(stderr, ": %s\n", strerror(errno));
76ea98af 1589}