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