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 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif /* not lint */ 12 13 #ifndef lint 14 static char sccsid[] = "@(#)pstat.c 5.35 (Berkeley) 06/26/91"; 15 #endif /* not lint */ 16 17 /* 18 * Print system stuff 19 */ 20 #include <sys/param.h> 21 #include <sys/user.h> 22 #include <sys/proc.h> 23 #include <sys/time.h> 24 #include <sys/vnode.h> 25 #include <sys/map.h> 26 #define KERNEL 27 #define NFS 28 #include <sys/file.h> 29 #include <sys/mount.h> 30 #include <ufs/quota.h> 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> 36 #include <sys/ioctl.h> 37 #include <sys/tty.h> 38 #undef KERNEL 39 #include <sys/conf.h> 40 41 #ifdef SPPWAIT 42 #define NEWVM 43 #endif 44 45 #ifndef NEWVM 46 #include <sys/vm.h> 47 #include <machine/pte.h> 48 #include <sys/text.h> 49 #endif 50 #include <sys/kinfo.h> 51 52 #include <nlist.h> 53 #include <kvm.h> 54 #include <stdio.h> 55 #include "pathnames.h" 56 57 #define mask(x) (x&0377) 58 #define clear(x) ((int)x &~ KERNBASE) 59 60 char *fnlist = NULL; 61 char *fcore = NULL; 62 63 struct nlist nl[] = { 64 #define SWAPMAP 0 65 { "_swapmap" }, 66 #define SNSWAPMAP 1 67 { "_nswapmap" }, 68 #define SDMMIN 2 69 { "_dmmin" }, 70 #define SDMMAX 3 71 { "_dmmax" }, 72 #define SNSWDEV 4 73 { "_nswdev" }, 74 #define SSWDEVT 5 75 { "_swdevt" }, 76 #ifdef NEWVM 77 #define NLMANDATORY SSWDEVT /* names up to here are mandatory */ 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 91 { "_cons" }, 92 #define SPTY NLMANDATORY + 2 93 { "_pt_tty" }, 94 #define SNPTY NLMANDATORY + 3 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) 102 { "_dmf_tty" }, 103 #define SNDMF (SNPTY+4) 104 { "_ndmf" }, 105 #define SDH (SNPTY+5) 106 { "_dh11" }, 107 #define SNDH (SNPTY+6) 108 { "_ndh11" }, 109 #define SDHU (SNPTY+7) 110 { "_dhu_tty" }, 111 #define SNDHU (SNPTY+8) 112 { "_ndhu" }, 113 #define SDMZ (SNPTY+9) 114 { "_dmz_tty" }, 115 #define SNDMZ (SNPTY+10) 116 { "_ndmz" }, 117 #define SQD (SNPTY+11) 118 { "_qd_tty" }, 119 #define SNQD (SNPTY+12) 120 { "_nNQD" }, 121 #endif 122 123 #ifdef tahoe 124 #define SVX (SNPTY+1) 125 { "_vx_tty" }, 126 #define SNVX (SNPTY+2) 127 { "_nvx" }, 128 #define SMP (SNPTY+3) 129 { "_mp_tty" }, 130 #define SNMP (SNPTY+4) 131 { "_nmp" }, 132 #endif 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) 142 { "_ndcm" }, 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 152 { "" } 153 }; 154 155 int vnof; 156 int txtf; 157 int prcf; 158 int ttyf; 159 int usrf; 160 int upid; 161 int filf; 162 int swpf; 163 int totflg; 164 char partab[1]; 165 struct cdevsw cdevsw[1]; 166 struct bdevsw bdevsw[1]; 167 int allflg; 168 int nflg; 169 u_long getword(); 170 off_t mkphys(); 171 172 char *Program; 173 174 #define V(x) (void *)(x) 175 176 main(argc, argv) 177 int argc; 178 char **argv; 179 { 180 extern char *optarg; 181 extern int optind; 182 int ch, ret; 183 184 Program = argv[0]; 185 while ((ch = getopt(argc, argv, "TafvikptU:sxnu")) != EOF) 186 switch (ch) { 187 case 'T': 188 totflg++; 189 break; 190 case 'a': 191 allflg++; 192 /*FALLTHROUGH*/ 193 case 'p': 194 prcf++; 195 break; 196 case 'f': 197 filf++; 198 break; 199 case 'v': 200 case 'i': 201 vnof++; 202 break; 203 case 't': 204 ttyf++; 205 break; 206 case 'U': 207 usrf++; 208 sscanf(optarg, "%d", &upid); 209 break; 210 case 's': 211 swpf++; 212 break; 213 case 'x': 214 txtf++; 215 break; 216 case 'n': 217 nflg++; 218 break; 219 case 'u': 220 fprintf(stderr, "pstat: use [ -U pid ] for -u\n"); 221 exit(1); 222 case '?': 223 default: 224 fprintf(stderr, "usage: pstat -[Tafiptsx] [-U [pid]] [system] [core]\n"); 225 exit(1); 226 } 227 argc -= optind; 228 argv += optind; 229 230 if (argc > 1) 231 fcore = argv[1]; 232 if (argc > 0) 233 fnlist = argv[0]; 234 if (kvm_openfiles(fnlist, fcore, NULL) == -1) { 235 error("kvm_openfiles: %s", kvm_geterr()); 236 exit(1); 237 } 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); 254 } 255 if (!(filf | totflg | vnof | prcf | txtf | ttyf | usrf | swpf)) { 256 printf("pstat: one or more of -[aivxptfsU] is required\n"); 257 exit(1); 258 } 259 if (filf||totflg) 260 dofile(); 261 if (vnof||totflg) 262 dovnode(); 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 275 struct e_vnode { 276 struct vnode *avnode; 277 struct vnode vnode; 278 }; 279 280 dovnode() 281 { 282 register struct e_vnode *e_vnodebase, *endvnode, *evp; 283 register struct vnode *vp; 284 register struct mount *maddr = NULL, *mp; 285 int numvnodes; 286 struct e_vnode *loadvnodes(); 287 struct mount *getmnt(); 288 289 e_vnodebase = loadvnodes(&numvnodes); 290 if (totflg) { 291 printf("%7d vnodes\n", numvnodes); 292 return; 293 } 294 endvnode = e_vnodebase + numvnodes; 295 printf("%d active vnodes\n", numvnodes); 296 297 298 #define ST mp->mnt_stat 299 for (evp = e_vnodebase; evp < endvnode; evp++) { 300 vp = &evp->vnode; 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 } 325 vnode_print(evp->avnode, vp); 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"); 340 } 341 free(e_vnodebase); 342 } 343 344 vnode_header() 345 { 346 printf("ADDR TYP VFLAG USE HOLD"); 347 } 348 349 vnode_print(avnode, vp) 350 struct vnode *avnode; 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'; 390 if (flag & VSYSTEM) 391 *fp++ = 'S'; 392 if (flag & VXLOCK) 393 *fp++ = 'L'; 394 if (flag & VXWANT) 395 *fp++ = 'W'; 396 if (flag & VBWAIT) 397 *fp++ = 'B'; 398 if (flag & VALIASED) 399 *fp++ = 'A'; 400 if (flag == 0) 401 *fp++ = '-'; 402 *fp = '\0'; 403 /* 404 * print it 405 */ 406 printf("%8x %s %5s %4d %4d", 407 avnode, type, flags, vp->v_usecount, vp->v_holdcnt); 408 } 409 410 ufs_header() 411 { 412 printf(" FILEID IFLAG RDEV|SZ"); 413 } 414 415 ufs_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 450 printf(" %6d %5s", ip->i_number, flagbuf); 451 type = ip->i_mode & S_IFMT; 452 if (type == S_IFCHR || type == S_IFBLK) 453 if (nflg || ((name = devname(ip->i_rdev, type)) == NULL)) 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 462 nfs_header() 463 { 464 printf(" FILEID NFLAG RDEV|SZ"); 465 } 466 467 nfs_print(vp) 468 struct vnode *vp; 469 { 470 struct nfsnode *np = VTONFS(vp); 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'; 484 if (flag & NWRITEERR) 485 *flags++ = 'E'; 486 if (flag == 0) 487 *flags++ = '-'; 488 *flags = '\0'; 489 490 #define VT np->n_vattr 491 printf(" %6d %5s", VT.va_fileid, flagbuf); 492 type = VT.va_mode & S_IFMT; 493 if (type == S_IFCHR || type == S_IFBLK) 494 if (nflg || ((name = devname(VT.va_rdev, type)) == NULL)) 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 */ 507 struct mount * 508 getmnt(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 } 525 if (kvm_read(V(maddr), &mt->mount, sizeof(struct mount)) != 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 536 mount_print(mp) 537 struct mount *mp; 538 { 539 char *type = "unknown"; 540 register flags; 541 542 #define ST mp->mnt_stat 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); 562 if (flags = mp->mnt_flag) { 563 char *comma = "("; 564 565 putchar(' '); 566 /* user visable flags */ 567 if (flags & MNT_RDONLY) { 568 printf("%srdonly", comma); 569 flags &= ~MNT_RDONLY; 570 comma = ","; 571 } 572 if (flags & MNT_SYNCHRONOUS) { 573 printf("%ssynchronous", comma); 574 flags &= ~MNT_SYNCHRONOUS; 575 comma = ","; 576 } 577 if (flags & MNT_NOEXEC) { 578 printf("%snoexec", comma); 579 flags &= ~MNT_NOEXEC; 580 comma = ","; 581 } 582 if (flags & MNT_NOSUID) { 583 printf("%snosuid", comma); 584 flags &= ~MNT_NOSUID; 585 comma = ","; 586 } 587 if (flags & MNT_NODEV) { 588 printf("%snodev", comma); 589 flags &= ~MNT_NODEV; 590 comma = ","; 591 } 592 if (flags & MNT_EXPORTED) { 593 printf("%sexport", comma); 594 flags &= ~MNT_EXPORTED; 595 comma = ","; 596 } 597 if (flags & MNT_EXRDONLY) { 598 printf("%sexrdonly", comma); 599 flags &= ~MNT_EXRDONLY; 600 comma = ","; 601 } 602 if (flags & MNT_LOCAL) { 603 printf("%slocal", comma); 604 flags &= ~MNT_LOCAL; 605 comma = ","; 606 } 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) { 619 printf("%slock", comma); 620 flags &= ~MNT_MLOCK; 621 comma = ","; 622 } 623 if (flags & MNT_MWAIT) { 624 printf("%swait", comma); 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; 636 comma = ","; 637 } 638 if (flags & MNT_UNMOUNT) { 639 printf("%sunmount", comma); 640 flags &= ~MNT_UNMOUNT; 641 comma = ","; 642 } 643 if (flags) 644 printf("%sunknown_flags:%x", flags); 645 printf(")"); 646 } 647 printf("\n"); 648 #undef ST 649 } 650 651 struct e_vnode * 652 loadvnodes(avnodes) 653 int *avnodes; 654 { 655 int ret, copysize; 656 struct e_vnode *vnodebase; 657 658 if (fcore != NULL) { 659 /* 660 * add emulation of KINFO_VNODE here 661 */ 662 error("vnodes on dead kernel, not impl\n"); 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; 670 if ((vnodebase = (struct e_vnode *)malloc(copysize)) 671 == NULL) { 672 error("out of memory"); 673 exit(1); 674 } 675 if ((ret = getkerninfo(KINFO_VNODE, vnodebase, ©size, 0)) 676 == -1) { 677 syserror("can't get vnode list"); 678 exit(1); 679 } 680 if (copysize % sizeof (struct e_vnode)) { 681 error("vnode size mismatch"); 682 exit(1); 683 } 684 *avnodes = copysize / sizeof (struct e_vnode); 685 686 return (vnodebase); 687 } 688 689 u_long 690 getword(loc) 691 int loc; 692 { 693 u_long word; 694 695 kvm_read(V(loc), &word, sizeof (word)); 696 return (word); 697 } 698 699 putf(v, n) 700 { 701 if (v) 702 printf("%c", n); 703 else 704 printf(" "); 705 } 706 707 dotext() 708 { 709 #ifdef NEWVM 710 printf("no text table in this system\n"); 711 #else 712 register struct text *xp; 713 int ntext; 714 struct text *xtext, *atext; 715 int ntx, ntxca; 716 717 ntx = ntxca = 0; 718 ntext = getword(nl[SNTEXT].n_value); 719 xtext = (struct text *)calloc(ntext, sizeof (struct text)); 720 atext = (struct text *)getword(nl[STEXT].n_value); 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 } 730 kvm_read(atext, xtext, ntext * sizeof (struct text)); 731 for (xp = xtext; xp < &xtext[ntext]; xp++) { 732 if (xp->x_vptr != NULL) 733 ntxca++; 734 if (xp->x_count != 0) 735 ntx++; 736 } 737 if (totflg) { 738 printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca); 739 return; 740 } 741 printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca); 742 printf("\ 743 LOC FLAGS DADDR CADDR RSS SIZE VPTR CNT CCNT FORW BACK\n"); 744 for (xp = xtext; xp < &xtext[ntext]; xp++) { 745 if (xp->x_vptr == NULL) 746 continue; 747 printf("%8.1x", atext + (xp - xtext)); 748 printf(" "); 749 putf(xp->x_flag&XPAGV, 'P'); 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'); 755 printf("%5x", xp->x_daddr[0]); 756 printf("%10x", xp->x_caddr); 757 printf("%5d", xp->x_rssize); 758 printf("%5d", xp->x_size); 759 printf("%10.1x", xp->x_vptr); 760 printf("%5d", xp->x_count&0377); 761 printf("%5d", xp->x_ccount); 762 printf("%10x", xp->x_forw); 763 printf("%9x", xp->x_back); 764 printf("\n"); 765 } 766 free(xtext); 767 #endif 768 } 769 770 doproc() 771 { 772 #ifdef NEWVM 773 printf("pstat: -p no longer supported (use ps)\n"); 774 #else 775 struct proc *xproc, *aproc; 776 int nproc; 777 register struct proc *pp; 778 register loc, np; 779 /* 780 struct pte apte; 781 */ 782 783 nproc = getword(nl[SNPROC].n_value); 784 xproc = (struct proc *)calloc(nproc, sizeof (struct proc)); 785 aproc = (struct proc *)getword(nl[SPROC].n_value); 786 if (nproc < 0 || nproc > 100000) { 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 } 795 kvm_read(aproc, xproc, nproc * sizeof (struct proc)); 796 np = 0; 797 for (pp=xproc; pp < &xproc[nproc]; pp++) 798 if (pp->p_stat) 799 np++; 800 if (totflg) { 801 printf("%3d/%3d processes\n", np, nproc); 802 return; 803 } 804 printf("%d/%d processes\n", np, nproc); 805 printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n"); 806 for (pp=xproc; pp<&xproc[nproc]; pp++) { 807 if (pp->p_stat==0 && allflg==0) 808 continue; 809 printf("%8x", aproc + (pp - xproc)); 810 printf(" %2d", pp->p_stat); 811 printf(" %8x", pp->p_flag); 812 printf(" %4d", pp->p_poip); 813 printf(" %3d", pp->p_pri); 814 printf(" %8x", pp->p_sig); 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); 820 printf(" %6d", pp->p_pid); 821 printf(" %6d", pp->p_ppid); 822 /* 823 if (pp->p_flag & SLOAD) { 824 kvm_read(pp->p_addr, &apte, sizeof(apte)); 825 printf(" %8x", apte.pg_pfnum); 826 } else 827 printf(" %8x", pp->p_swaddr); 828 */ 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)); 835 printf("\n"); 836 } 837 free(xproc); 838 #endif 839 } 840 841 char mesg[] = " LINE RAW CAN OUT HWT LWT ADDR COL STATE SESS PGID DISC\n"; 842 int ttyspace = 128; 843 struct tty *tty; 844 845 dotty() 846 { 847 848 if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) { 849 printf("pstat: out of memory\n"); 850 return; 851 } 852 #ifndef hp300 853 printf("1 cons\n"); 854 kvm_read(V(nl[SCONS].n_value), tty, sizeof(*tty)); 855 printf(mesg); 856 ttyprt(&tty[0], 0); 857 #endif 858 #ifdef vax 859 if (nl[SNQD].n_type != 0) 860 doqdss(); 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); 869 if (nl[SNDMZ].n_type != 0) 870 dottytype("dmz", SDMZ, SNDMZ); 871 #endif 872 #ifdef tahoe 873 if (nl[SNVX].n_type != 0) 874 dottytype("vx", SVX, SNVX); 875 if (nl[SNMP].n_type != 0) 876 dottytype("mp", SMP, SNMP); 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); 887 #endif 888 if (nl[SNPTY].n_type != 0) 889 dottytype("pty", SPTY, SNPTY); 890 } 891 892 /* 893 * Special case the qdss: there are 4 ttys per qdss, 894 * but only the first of each is used as a tty. 895 */ 896 #ifdef vax 897 doqdss() 898 { 899 int nqd; 900 register struct tty *tp; 901 902 kvm_read(V(nl[SNQD].n_value), &nqd, sizeof(nqd)); 903 printf("%d qd\n", nqd); 904 kvm_read((V(nl[SQD].n_value), tty, nqd * sizeof(struct tty) * 4); 905 printf(mesg); 906 for (tp = tty; tp < &tty[nqd * 4]; tp += 4) 907 ttyprt(tp, tp - tty); 908 } 909 #endif 910 911 dottytype(name, type, number) 912 char *name; 913 { 914 int ntty; 915 register struct tty *tp; 916 extern char *realloc(); 917 918 if (tty == (struct tty *)0) 919 return; 920 kvm_read(V(nl[number].n_value), &ntty, sizeof(ntty)); 921 printf("%d %s lines\n", ntty, name); 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 } 928 } 929 kvm_read(V(nl[type].n_value), tty, ntty * sizeof(struct tty)); 930 printf(mesg); 931 for (tp = tty; tp < &tty[ntty]; tp++) 932 ttyprt(tp, tp - tty); 933 } 934 935 struct { 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', 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 960 ttyprt(atp, line) 961 struct tty *atp; 962 { 963 register struct tty *tp; 964 char state[20]; 965 register i, j; 966 char *name; 967 extern char *devname(); 968 pid_t pgid; 969 970 tp = atp; 971 if (nflg || tp->t_dev == 0 || 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); 977 printf("%3d %4d %3d %8x %3d ", tp->t_outq.c_cc, 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; 982 if (j == 0) 983 state[j++] = '-'; 984 state[j] = '\0'; 985 printf("%-4s %6x", state, (u_long)tp->t_session & ~KERNBASE); 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); 990 switch (tp->t_line) { 991 992 case TTYDISC: 993 printf("term\n"); 994 break; 995 996 case TABLDISC: 997 printf("tab\n"); 998 break; 999 1000 case SLIPDISC: 1001 printf("slip\n"); 1002 break; 1003 1004 default: 1005 printf("%d\n", tp->t_line); 1006 } 1007 } 1008 1009 /* 1010 * The user structure is going away. What's left here won't 1011 * be around for long. 1012 */ 1013 dousr() 1014 { 1015 #ifdef NEWVM 1016 printf("nothing left in user structure in this system\n"); 1017 #else 1018 register struct user *up; 1019 register i, j, *ip; 1020 register struct nameidata *nd; 1021 struct proc *p; 1022 int ret; 1023 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); 1029 return (1); 1030 } 1031 if ((p = kvm_nextproc()) == NULL) { 1032 error("kvm_nextproc: %s", kvm_geterr()); 1033 return (1); 1034 } 1035 if ((up = kvm_getu(p)) == NULL) { 1036 error("kvm_getu: %s", kvm_geterr()); 1037 return (1); 1038 } 1039 nd = &up->u_nd; 1040 printf("pcb"); 1041 ip = (int *)&up->u_pcb; 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++; 1050 } 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); 1057 printf("ssave"); 1058 for (i=0; i<sizeof(label_t)/sizeof(int); i++) { 1059 if (i%5==0) 1060 printf("\t"); 1061 printf("%#11x", up->u_ssave.val[i]); 1062 if (i%5==4) 1063 printf("\n"); 1064 } 1065 if (i%5) 1066 printf("\n"); 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++) { 1073 if (i % 8 == 0) 1074 printf("\t"); 1075 printf("%#x ", up->u_signal[i]); 1076 if (i % 8 == 7) 1077 printf("\n"); 1078 } 1079 if (i % 8) 1080 printf("\n"); 1081 printf("sigmask"); 1082 for (i=0; i<NSIG; i++) { 1083 if (i % 8 == 0) 1084 printf("\t"); 1085 printf("%#x ", up->u_sigmask[i]); 1086 if (i % 8 == 7) 1087 printf("\n"); 1088 } 1089 if (i % 8) 1090 printf("\n"); 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); 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, 1102 up->u_prof.pr_off, up->u_prof.pr_scale); 1103 printf("ru\t"); 1104 ip = (int *)&up->u_ru; 1105 for (i = 0; i < sizeof(up->u_ru)/sizeof(int); i++) 1106 printf("%ld ", ip[i]); 1107 printf("\n"); 1108 ip = (int *)&up->u_cru; 1109 printf("cru\t"); 1110 for (i = 0; i < sizeof(up->u_cru)/sizeof(int); i++) 1111 printf("%ld ", ip[i]); 1112 printf("\n"); 1113 #endif 1114 } 1115 1116 oatoi(s) 1117 char *s; 1118 { 1119 register v; 1120 1121 v = 0; 1122 while (*s) 1123 v = (v<<3) + *s++ - '0'; 1124 return(v); 1125 } 1126 1127 dofile() 1128 { 1129 register struct file *fp; 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 }; 1140 static char *dtypes[] = { "???", "inode", "socket" }; 1141 1142 if (kvm_nlist(fnl) != 0) { 1143 error("kvm_nlist: no _nfiles or _maxfiles: %s", 1144 kvm_geterr()); 1145 return; 1146 } 1147 kvm_read(V(fnl[FNL_MAXFILE].n_value), &maxfile, 1148 sizeof (maxfile)); 1149 if (totflg) { 1150 kvm_read(V(fnl[FNL_NFILE].n_value), &nfile, sizeof (nfile)); 1151 printf("%3d/%3d files\n", nfile, maxfile); 1152 return; 1153 } 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); 1166 printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n"); 1167 for (; (char *)fp < buf + len; addr = fp->f_filef, fp++) { 1168 printf("%x ", addr); 1169 if (fp->f_type <= DTYPE_SOCKET) 1170 printf("%-8.8s", dtypes[fp->f_type]); 1171 else 1172 printf("%8d", fp->f_type); 1173 putf(fp->f_flag&FREAD, 'R'); 1174 putf(fp->f_flag&FWRITE, 'W'); 1175 putf(fp->f_flag&FAPPEND, 'A'); 1176 #ifdef FSHLOCK /* currently gone */ 1177 putf(fp->f_flag&FSHLOCK, 'S'); 1178 putf(fp->f_flag&FEXLOCK, 'X'); 1179 #else 1180 putf(0, ' '); 1181 putf(0, ' '); 1182 #endif 1183 putf(fp->f_flag&FASYNC, 'I'); 1184 printf(" %3d", fp->f_count); 1185 printf(" %3d", fp->f_msgcount); 1186 printf(" %8.1x", fp->f_data); 1187 if (fp->f_offset < 0) 1188 printf(" %x\n", fp->f_offset); 1189 else 1190 printf(" %ld\n", fp->f_offset); 1191 } 1192 free(buf); 1193 } 1194 1195 getfiles(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 1227 #ifdef NEWVM 1228 doswap() 1229 { 1230 printf("swap statistics not yet supported in this system\n"); 1231 } 1232 1233 #else /* NEWVM */ 1234 int dmmin, dmmax, nswdev; 1235 1236 doswap() 1237 { 1238 struct proc *proc; 1239 int nproc; 1240 struct text *xtext; 1241 int ntext; 1242 struct map *swapmap; 1243 int nswapmap; 1244 struct swdevt *swdevt, *sw; 1245 register struct proc *pp; 1246 int nswap, used, tused, free, waste; 1247 int db, sb; 1248 register struct mapent *me; 1249 register struct text *xp; 1250 int i, j; 1251 long rmalloc(); 1252 1253 nproc = getword(nl[SNPROC].n_value); 1254 ntext = getword(nl[SNTEXT].n_value); 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 } 1265 xtext = (struct text *)calloc(ntext, sizeof (struct text)); 1266 if (xtext == NULL) { 1267 fprintf(stderr, "can't allocate memory for text table\n"); 1268 exit(1); 1269 } 1270 nswapmap = getword(nl[SNSWAPMAP].n_value); 1271 swapmap = (struct map *)calloc(nswapmap, sizeof (struct map)); 1272 if (swapmap == NULL) { 1273 fprintf(stderr, "can't allocate memory for swapmap\n"); 1274 exit(1); 1275 } 1276 nswdev = getword(nl[SNSWDEV].n_value); 1277 swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); 1278 if (swdevt == NULL) { 1279 fprintf(stderr, "can't allocate memory for swdevt table\n"); 1280 exit(1); 1281 } 1282 kvm_read(V(nl[SSWDEVT].n_value), swdevt, 1283 nswdev * sizeof (struct swdevt)); 1284 kvm_read(V(getword(nl[SPROC].n_value)), proc, 1285 nproc * sizeof (struct proc)); 1286 kvm_read(V(getword(nl[STEXT].n_value)), xtext, 1287 ntext * sizeof (struct text)); 1288 kvm_read(V(getword(nl[SWAPMAP].n_value)), swapmap, 1289 nswapmap * sizeof (struct map)); 1290 1291 swapmap->m_name = "swap"; 1292 swapmap->m_limit = (struct mapent *)&swapmap[nswapmap]; 1293 dmmin = getword(nl[SDMMIN].n_value); 1294 dmmax = getword(nl[SDMMAX].n_value); 1295 nswap = 0; 1296 for (sw = swdevt; sw < &swdevt[nswdev]; sw++) 1297 if (sw->sw_freed) 1298 nswap += sw->sw_nblks; 1299 free = 0; 1300 for (me = (struct mapent *)(swapmap+1); 1301 me < (struct mapent *)&swapmap[nswapmap]; me++) 1302 free += me->m_size; 1303 tused = 0; 1304 for (xp = xtext; xp < &xtext[ntext]; xp++) 1305 if (xp->x_vptr!=NULL) { 1306 tused += ctod(clrnd(xp->x_size)); 1307 if (xp->x_flag & XPAGV) 1308 tused += ctod(clrnd(ctopt(xp->x_size))); 1309 } 1310 used = tused; 1311 waste = 0; 1312 for (pp = proc; pp < &proc[nproc]; pp++) { 1313 if (pp->p_stat == 0 || pp->p_stat == SZOMB) 1314 continue; 1315 if (pp->p_flag & SSYS) 1316 continue; 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; 1323 if ((pp->p_flag&SLOAD) == 0) 1324 used += ctod(vusize(pp)); 1325 } 1326 if (totflg) { 1327 #define btok(x) ((x) / (1024 / DEV_BSIZE)) 1328 printf("%3d/%3d 00k swap\n", 1329 btok(used/100), btok((used+free)/100)); 1330 return; 1331 } 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))); 1336 printf("avail: "); 1337 for (i = dmmax; i >= dmmin; i /= 2) { 1338 j = 0; 1339 while (rmalloc(swapmap, i) != 0) 1340 j++; 1341 if (j) printf("%d*%dk ", j, btok(i)); 1342 } 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)); 1348 } 1349 1350 up(size) 1351 register int size; 1352 { 1353 register int i, block; 1354 1355 i = 0; 1356 block = dmmin; 1357 while (i < size) { 1358 i += block; 1359 if (block < dmmax) 1360 block *= 2; 1361 } 1362 return (i); 1363 } 1364 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 */ 1370 vusize(p) 1371 register struct proc *p; 1372 { 1373 register int tsz = p->p_tsize / NPTEPG; 1374 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)); 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 */ 1394 long 1395 rmalloc(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 */ 1456 rmfree(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 } 1552 done: 1553 return; 1554 badrmfree: 1555 printf("bad rmfree\n"); 1556 } 1557 #endif /* NEWVM */ 1558 1559 #include <varargs.h> 1560 1561 error(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 1576 syserror(va_alist) 1577 va_dcl 1578 { 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)); 1589 } 1590