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