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.39 (Berkeley) 04/02/93"; 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 #include <sys/file.h> 26 #include <ufs/ufs/quota.h> 27 #include <ufs/ufs/inode.h> 28 #undef KERNEL 29 #define NFS 30 #include <sys/mount.h> 31 #undef NFS 32 #include <sys/stat.h> 33 #include <nfs/nfsnode.h> 34 /* #include <nfs/nfsv2.h> */ 35 /* #include <nfs/nfs.h> */ 36 #include <sys/ioctl.h> 37 #include <sys/tty.h> 38 #include <sys/conf.h> 39 40 #include <sys/sysctl.h> 41 42 #include <nlist.h> 43 #include <kvm.h> 44 #include <stdio.h> 45 #include <limits.h> 46 #include "pathnames.h" 47 48 #define mask(x) (x&0377) 49 #define clear(x) ((int)x &~ KERNBASE) 50 51 char *nlistf = NULL; 52 char *memf = NULL; 53 54 struct nlist nl[] = { 55 #define SWAPMAP 0 56 { "_swapmap" }, 57 #define SNSWAPMAP 1 58 { "_nswapmap" }, 59 #define SDMMIN 2 60 { "_dmmin" }, 61 #define SDMMAX 3 62 { "_dmmax" }, 63 #define SNSWDEV 4 64 { "_nswdev" }, 65 #define SSWDEVT 5 66 { "_swdevt" }, 67 #define NLMANDATORY SSWDEVT /* names up to here are mandatory */ 68 #define SCONS NLMANDATORY + 1 69 { "_cons" }, 70 #define SPTY NLMANDATORY + 2 71 { "_pt_tty" }, 72 #define SNPTY NLMANDATORY + 3 73 { "_npty" }, 74 #ifdef vax 75 #define SDZ (SNPTY+1) 76 { "_dz_tty" }, 77 #define SNDZ (SNPTY+2) 78 { "_dz_cnt" }, 79 #define SDMF (SNPTY+3) 80 { "_dmf_tty" }, 81 #define SNDMF (SNPTY+4) 82 { "_ndmf" }, 83 #define SDH (SNPTY+5) 84 { "_dh11" }, 85 #define SNDH (SNPTY+6) 86 { "_ndh11" }, 87 #define SDHU (SNPTY+7) 88 { "_dhu_tty" }, 89 #define SNDHU (SNPTY+8) 90 { "_ndhu" }, 91 #define SDMZ (SNPTY+9) 92 { "_dmz_tty" }, 93 #define SNDMZ (SNPTY+10) 94 { "_ndmz" }, 95 #define SQD (SNPTY+11) 96 { "_qd_tty" }, 97 #define SNQD (SNPTY+12) 98 { "_nNQD" }, 99 #endif 100 101 #ifdef tahoe 102 #define SVX (SNPTY+1) 103 { "_vx_tty" }, 104 #define SNVX (SNPTY+2) 105 { "_nvx" }, 106 #define SMP (SNPTY+3) 107 { "_mp_tty" }, 108 #define SNMP (SNPTY+4) 109 { "_nmp" }, 110 #endif 111 112 #ifdef hp300 113 #define SDCA (SNPTY+1) 114 { "_dca_tty" }, 115 #define SNDCA (SNPTY+2) 116 { "_ndca" }, 117 #define SDCM (SNPTY+3) 118 { "_dcm_tty" }, 119 #define SNDCM (SNPTY+4) 120 { "_ndcm" }, 121 #define SDCL (SNPTY+5) 122 { "_dcl_tty" }, 123 #define SNDCL (SNPTY+6) 124 { "_ndcl" }, 125 #define SITE (SNPTY+7) 126 { "_ite_tty" }, 127 #define SNITE (SNPTY+8) 128 { "_nite" }, 129 #endif 130 { "" } 131 }; 132 133 int vnof; 134 int txtf; 135 int prcf; 136 int ttyf; 137 int usrf; 138 int upid; 139 int filf; 140 int swpf; 141 int totflg; 142 char partab[1]; 143 struct cdevsw cdevsw[1]; 144 struct bdevsw bdevsw[1]; 145 int allflg; 146 int nflg; 147 u_long getword(); 148 off_t mkphys(); 149 kvm_t *kd; 150 151 #define V(x) (u_long)(x) 152 153 main(argc, argv) 154 int argc; 155 char *argv[]; 156 { 157 extern char *optarg; 158 extern int optind; 159 int ch, ret; 160 char buf[_POSIX2_LINE_MAX]; 161 162 while ((ch = getopt(argc, argv, "TafvikptU:sxnu")) != EOF) 163 switch (ch) { 164 case 'T': 165 totflg++; 166 break; 167 case 'a': 168 allflg++; 169 /*FALLTHROUGH*/ 170 case 'p': 171 prcf++; 172 break; 173 case 'f': 174 filf++; 175 break; 176 case 'v': 177 case 'i': 178 vnof++; 179 break; 180 case 't': 181 ttyf++; 182 break; 183 case 'U': 184 usrf++; 185 sscanf(optarg, "%d", &upid); 186 break; 187 case 's': 188 swpf++; 189 break; 190 case 'x': 191 txtf++; 192 break; 193 case 'n': 194 nflg++; 195 break; 196 case 'u': 197 fprintf(stderr, "pstat: use [ -U pid ] for -u\n"); 198 exit(1); 199 case '?': 200 default: 201 usage(); 202 } 203 argc -= optind; 204 argv += optind; 205 206 if (argc > 1) 207 memf = argv[1]; 208 if (argc > 0) 209 nlistf = argv[0]; 210 211 /* 212 * Discard setgid privileges if not the running kernel so that bad 213 * guys can't print interesting stuff from kernel memory. 214 */ 215 if (nlistf != NULL || memf != NULL) 216 setgid(getgid()); 217 218 if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == 0) { 219 error("kvm_openfiles: %s", buf); 220 exit(1); 221 } 222 if ((ret = kvm_nlist(kd, nl)) != 0) { 223 int i, quit = 0; 224 225 if (ret == -1) { 226 error("kvm_nlist: %s", kvm_geterr(kd)); 227 exit(1); 228 } 229 for (i = 0; i <= NLMANDATORY; i++) { 230 if (!nl[i].n_value) { 231 quit = 1; 232 error("undefined symbol: %s\n", 233 nl[i].n_name); 234 } 235 } 236 if (quit) 237 exit(1); 238 } 239 if (!(filf | totflg | vnof | prcf | txtf | ttyf | usrf | swpf)) 240 usage(); 241 if (filf||totflg) 242 dofile(); 243 if (vnof||totflg) 244 dovnode(); 245 if (prcf||totflg) 246 doproc(); 247 if (txtf||totflg) 248 dotext(); 249 if (ttyf) 250 dotty(); 251 if (usrf) 252 dousr(); 253 if (swpf||totflg) 254 doswap(); 255 } 256 257 usage() 258 { 259 260 fprintf(stderr, 261 "usage: pstat -[Tafiptsx] [-U [pid]] [system] [core]\n"); 262 exit(1); 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 inode, *ip = &inode; 409 char flagbuf[16], *flags = flagbuf; 410 register flag; 411 char *name; 412 mode_t type; 413 extern char *devname(); 414 415 if (kvm_read(kd, V(VTOI(vp)), &inode, sizeof(struct inode)) != 416 sizeof(struct inode)) { 417 error("can't read inode for %x", vp); 418 return; 419 } 420 flag = ip->i_flag; 421 if (flag & ILOCKED) 422 *flags++ = 'L'; 423 if (flag & IWANT) 424 *flags++ = 'W'; 425 if (flag & IRENAME) 426 *flags++ = 'R'; 427 if (flag & IUPD) 428 *flags++ = 'U'; 429 if (flag & IACC) 430 *flags++ = 'A'; 431 if (flag & ICHG) 432 *flags++ = 'C'; 433 if (flag & IMOD) 434 *flags++ = 'M'; 435 if (flag & ISHLOCK) 436 *flags++ = 'S'; 437 if (flag & IEXLOCK) 438 *flags++ = 'E'; 439 if (flag & ILWAIT) 440 *flags++ = 'Z'; 441 if (flag == 0) 442 *flags++ = '-'; 443 *flags = '\0'; 444 445 printf(" %6d %5s", ip->i_number, flagbuf); 446 type = ip->i_mode & S_IFMT; 447 if (type == S_IFCHR || type == S_IFBLK) 448 if (nflg || ((name = devname(ip->i_rdev, type)) == NULL)) 449 printf(" %2d,%-2d", 450 major(ip->i_rdev), minor(ip->i_rdev)); 451 else 452 printf(" %7s", name); 453 else 454 printf(" %7qd", ip->i_size); 455 } 456 457 nfs_header() 458 { 459 printf(" FILEID NFLAG RDEV|SZ"); 460 } 461 462 nfs_print(vp) 463 struct vnode *vp; 464 { 465 struct nfsnode nfsnode, *np = &nfsnode; 466 char flagbuf[16], *flags = flagbuf; 467 register flag; 468 char *name; 469 mode_t type; 470 extern char *devname(); 471 472 if (kvm_read(kd, V(VTONFS(vp)), &nfsnode, sizeof(struct nfsnode)) != 473 sizeof(struct nfsnode)) { 474 error("can't read nfsnode for %x", vp); 475 return; 476 } 477 flag = np->n_flag; 478 if (flag & NFLUSHWANT) 479 *flags++ = 'W'; 480 if (flag & NFLUSHINPROG) 481 *flags++ = 'P'; 482 if (flag & NMODIFIED) 483 *flags++ = 'M'; 484 if (flag & NWRITEERR) 485 *flags++ = 'E'; 486 if (flag & NQNFSNONCACHE) 487 *flags++ = 'X'; 488 if (flag & NQNFSWRITE) 489 *flags++ = 'O'; 490 if (flag & NQNFSEVICTED) 491 *flags++ = 'G'; 492 if (flag == 0) 493 *flags++ = '-'; 494 *flags = '\0'; 495 496 #define VT np->n_vattr 497 printf(" %6d %5s", VT.va_fileid, flagbuf); 498 type = VT.va_mode & S_IFMT; 499 if (type == S_IFCHR || type == S_IFBLK) 500 if (nflg || ((name = devname(VT.va_rdev, type)) == NULL)) 501 printf(" %2d,%-2d", 502 major(VT.va_rdev), minor(VT.va_rdev)); 503 else 504 printf(" %7s", name); 505 else 506 printf(" %7qd", np->n_size); 507 } 508 509 /* 510 * Given a pointer to a mount structure in kernel space, 511 * read it in and return a usable pointer to it. 512 */ 513 struct mount * 514 getmnt(maddr) 515 struct mount *maddr; 516 { 517 static struct mtab { 518 struct mtab *next; 519 struct mount *maddr; 520 struct mount mount; 521 } *mhead = NULL; 522 register struct mtab *mt; 523 524 for (mt = mhead; mt != NULL; mt = mt->next) 525 if (maddr == mt->maddr) 526 return (&mt->mount); 527 if ((mt = (struct mtab *)malloc(sizeof (struct mtab))) == NULL) { 528 error("out of memory"); 529 exit(1); 530 } 531 if (kvm_read(kd, V(maddr), &mt->mount, sizeof(struct mount)) != 532 sizeof(struct mount)) { 533 error("can't read mount table at %x", maddr); 534 return (NULL); 535 } 536 mt->maddr = maddr; 537 mt->next = mhead; 538 mhead = mt; 539 return (&mt->mount); 540 } 541 542 mount_print(mp) 543 struct mount *mp; 544 { 545 char *type = "unknown"; 546 register flags; 547 548 #define ST mp->mnt_stat 549 printf("*** MOUNT "); 550 switch (ST.f_type) { 551 case MOUNT_NONE: 552 type = "none"; 553 break; 554 case MOUNT_UFS: 555 type = "ufs"; 556 break; 557 case MOUNT_NFS: 558 type = "nfs"; 559 break; 560 case MOUNT_MFS: 561 type = "mfs"; 562 break; 563 case MOUNT_PC: 564 type = "pc"; 565 break; 566 } 567 printf("%s %s on %s", type, ST.f_mntfromname, ST.f_mntonname); 568 if (flags = mp->mnt_flag) { 569 char *comma = "("; 570 571 putchar(' '); 572 /* user visable flags */ 573 if (flags & MNT_RDONLY) { 574 printf("%srdonly", comma); 575 flags &= ~MNT_RDONLY; 576 comma = ","; 577 } 578 if (flags & MNT_SYNCHRONOUS) { 579 printf("%ssynchronous", comma); 580 flags &= ~MNT_SYNCHRONOUS; 581 comma = ","; 582 } 583 if (flags & MNT_NOEXEC) { 584 printf("%snoexec", comma); 585 flags &= ~MNT_NOEXEC; 586 comma = ","; 587 } 588 if (flags & MNT_NOSUID) { 589 printf("%snosuid", comma); 590 flags &= ~MNT_NOSUID; 591 comma = ","; 592 } 593 if (flags & MNT_NODEV) { 594 printf("%snodev", comma); 595 flags &= ~MNT_NODEV; 596 comma = ","; 597 } 598 if (flags & MNT_EXPORTED) { 599 printf("%sexport", comma); 600 flags &= ~MNT_EXPORTED; 601 comma = ","; 602 } 603 if (flags & MNT_EXRDONLY) { 604 printf("%sexrdonly", comma); 605 flags &= ~MNT_EXRDONLY; 606 comma = ","; 607 } 608 if (flags & MNT_LOCAL) { 609 printf("%slocal", comma); 610 flags &= ~MNT_LOCAL; 611 comma = ","; 612 } 613 if (flags & MNT_QUOTA) { 614 printf("%squota", comma); 615 flags &= ~MNT_QUOTA; 616 comma = ","; 617 } 618 /* filesystem control flags */ 619 if (flags & MNT_UPDATE) { 620 printf("%supdate", comma); 621 flags &= ~MNT_UPDATE; 622 comma = ","; 623 } 624 if (flags & MNT_MLOCK) { 625 printf("%slock", comma); 626 flags &= ~MNT_MLOCK; 627 comma = ","; 628 } 629 if (flags & MNT_MWAIT) { 630 printf("%swait", comma); 631 flags &= ~MNT_MWAIT; 632 comma = ","; 633 } 634 if (flags & MNT_MPBUSY) { 635 printf("%sbusy", comma); 636 flags &= ~MNT_MPBUSY; 637 comma = ","; 638 } 639 if (flags & MNT_MPWANT) { 640 printf("%swant", comma); 641 flags &= ~MNT_MPWANT; 642 comma = ","; 643 } 644 if (flags & MNT_UNMOUNT) { 645 printf("%sunmount", comma); 646 flags &= ~MNT_UNMOUNT; 647 comma = ","; 648 } 649 if (flags) 650 printf("%sunknown_flags:%x", flags); 651 printf(")"); 652 } 653 printf("\n"); 654 #undef ST 655 } 656 657 struct e_vnode * 658 loadvnodes(avnodes) 659 int *avnodes; 660 { 661 int mib[2]; 662 size_t copysize; 663 struct e_vnode *vnodebase; 664 struct e_vnode *kinfo_vnodes(); 665 666 if (memf != NULL) { 667 /* 668 * do it by hand 669 */ 670 return (kinfo_vnodes(avnodes)); 671 } 672 mib[0] = CTL_KERN; 673 mib[1] = KERN_VNODE; 674 if (sysctl(mib, 2, NULL, ©size, NULL, 0) == -1) { 675 syserror("can't get estimate from sysctl"); 676 exit(1); 677 } 678 if ((vnodebase = (struct e_vnode *)malloc(copysize)) == NULL) { 679 error("out of memory"); 680 exit(1); 681 } 682 if (sysctl(mib, 2, vnodebase, ©size, NULL, 0) == -1) { 683 syserror("can't get vnode list"); 684 exit(1); 685 } 686 if (copysize % sizeof (struct e_vnode)) { 687 error("vnode size mismatch"); 688 exit(1); 689 } 690 *avnodes = copysize / sizeof (struct e_vnode); 691 692 return (vnodebase); 693 } 694 695 /* 696 * simulate what a running kernel does in in kinfo_vnode 697 */ 698 struct e_vnode * 699 kinfo_vnodes(avnodes) 700 int *avnodes; 701 { 702 struct nlist vnl[] = { 703 #define V_NUMV 0 704 { "_numvnodes" }, 705 #define V_ROOTFS 1 706 { "_rootfs" }, 707 {""} 708 }; 709 int numvnodes; 710 struct mount *rootfs, *mp, mount; 711 char *vbuf, *evbuf, *bp; 712 struct vnode *vp, vnode; 713 int num; 714 715 #define VPTRSZ sizeof (struct vnode *) 716 #define VNODESZ sizeof (struct vnode) 717 #define NVAL(indx) vnl[(indx)].n_value 718 719 if (kvm_nlist(kd, vnl) != 0) { 720 error("nlist vnl: %s", kvm_geterr(kd)); 721 exit(1); 722 } 723 numvnodes = getword(NVAL(V_NUMV)); 724 if ((vbuf = (char *)malloc((numvnodes + 20) * (VPTRSZ + VNODESZ))) 725 == NULL) { 726 error("out of memory"); 727 exit(1); 728 } 729 bp = vbuf; 730 evbuf = vbuf + (numvnodes + 20) * (VPTRSZ + VNODESZ); 731 mp = rootfs = (struct mount *)getword(NVAL(V_ROOTFS)); 732 do { 733 kvm_read(kd, V(mp), &mount, sizeof(mount)); 734 for (vp = mount.mnt_mounth; vp; vp = vnode.v_mountf) { 735 kvm_read(kd, V(vp), &vnode, sizeof (vnode)); 736 if ((bp + VPTRSZ + VNODESZ) > evbuf) { 737 /* XXX - should realloc */ 738 fprintf(stderr, "pstat: ran out of room for vnodes\n"); 739 exit(1); 740 } 741 bcopy(&vp, bp, VPTRSZ); 742 bp += VPTRSZ; 743 bcopy(&vnode, bp, VNODESZ); 744 bp += VNODESZ; 745 num++; 746 } 747 mp = mount.mnt_next; 748 } while (mp != rootfs); 749 *avnodes = num; 750 return ((struct e_vnode *)vbuf); 751 } 752 753 754 u_long 755 getword(loc) 756 int loc; 757 { 758 u_long word; 759 760 kvm_read(kd, V(loc), &word, sizeof (word)); 761 return (word); 762 } 763 764 putf(v, n) 765 { 766 if (v) 767 printf("%c", n); 768 else 769 printf(" "); 770 } 771 772 dotext() 773 { 774 775 printf("no text table in this system\n"); 776 } 777 778 doproc() 779 { 780 if (!totflg) 781 printf("pstat: -p no longer supported (use ps)\n"); 782 } 783 784 char mesg[] = " LINE RAW CAN OUT HWT LWT ADDR COL STATE SESS PGID DISC\n"; 785 int ttyspace = 128; 786 struct tty *tty; 787 788 dotty() 789 { 790 791 if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) { 792 printf("pstat: out of memory\n"); 793 return; 794 } 795 #ifndef hp300 796 printf("1 cons\n"); 797 kvm_read(kd, V(nl[SCONS].n_value), tty, sizeof(*tty)); 798 printf(mesg); 799 ttyprt(&tty[0], 0); 800 #endif 801 #ifdef vax 802 if (nl[SNQD].n_type != 0) 803 doqdss(); 804 if (nl[SNDZ].n_type != 0) 805 dottytype("dz", SDZ, SNDZ); 806 if (nl[SNDH].n_type != 0) 807 dottytype("dh", SDH, SNDH); 808 if (nl[SNDMF].n_type != 0) 809 dottytype("dmf", SDMF, SNDMF); 810 if (nl[SNDHU].n_type != 0) 811 dottytype("dhu", SDHU, SNDHU); 812 if (nl[SNDMZ].n_type != 0) 813 dottytype("dmz", SDMZ, SNDMZ); 814 #endif 815 #ifdef tahoe 816 if (nl[SNVX].n_type != 0) 817 dottytype("vx", SVX, SNVX); 818 if (nl[SNMP].n_type != 0) 819 dottytype("mp", SMP, SNMP); 820 #endif 821 #ifdef hp300 822 if (nl[SNITE].n_type != 0) 823 dottytype("ite", SITE, SNITE); 824 if (nl[SNDCA].n_type != 0) 825 dottytype("dca", SDCA, SNDCA); 826 if (nl[SNDCM].n_type != 0) 827 dottytype("dcm", SDCM, SNDCM); 828 if (nl[SNDCL].n_type != 0) 829 dottytype("dcl", SDCL, SNDCL); 830 #endif 831 if (nl[SNPTY].n_type != 0) 832 dottytype("pty", SPTY, SNPTY); 833 } 834 835 /* 836 * Special case the qdss: there are 4 ttys per qdss, 837 * but only the first of each is used as a tty. 838 */ 839 #ifdef vax 840 doqdss() 841 { 842 int nqd; 843 register struct tty *tp; 844 845 kvm_read(kd, V(nl[SNQD].n_value), &nqd, sizeof(nqd)); 846 printf("%d qd\n", nqd); 847 kvm_read(kd, V(nl[SQD].n_value), tty, nqd * sizeof(struct tty) * 4); 848 printf(mesg); 849 for (tp = tty; tp < &tty[nqd * 4]; tp += 4) 850 ttyprt(tp, tp - tty); 851 } 852 #endif 853 854 dottytype(name, type, number) 855 char *name; 856 { 857 int ntty; 858 register struct tty *tp; 859 extern char *realloc(); 860 861 if (tty == (struct tty *)0) 862 return; 863 kvm_read(kd, V(nl[number].n_value), &ntty, sizeof(ntty)); 864 printf("%d %s %s\n", ntty, name, (ntty == 1) ? "line" : 865 "lines"); 866 if (ntty > ttyspace) { 867 ttyspace = ntty; 868 if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { 869 printf("pstat: out of memory\n"); 870 return; 871 } 872 } 873 kvm_read(kd, V(nl[type].n_value), tty, ntty * sizeof(struct tty)); 874 printf(mesg); 875 for (tp = tty; tp < &tty[ntty]; tp++) 876 ttyprt(tp, tp - tty); 877 } 878 879 struct { 880 int flag; 881 char val; 882 } ttystates[] = { 883 TS_WOPEN, 'W', 884 TS_ISOPEN, 'O', 885 TS_CARR_ON, 'C', 886 TS_TIMEOUT, 'T', 887 TS_FLUSH, 'F', 888 TS_BUSY, 'B', 889 TS_ASLEEP, 'A', 890 TS_XCLUDE, 'X', 891 TS_TTSTOP, 'S', 892 TS_TBLOCK, 'K', 893 TS_ASYNC, 'Y', 894 TS_BKSL, 'D', 895 TS_ERASE, 'E', 896 TS_LNCH, 'L', 897 TS_TYPEN, 'P', 898 TS_CNTTB, 'N', 899 0, 0 900 }; 901 902 ttyprt(atp, line) 903 struct tty *atp; 904 { 905 register struct tty *tp; 906 char state[20]; 907 register i, j; 908 char *name; 909 extern char *devname(); 910 pid_t pgid; 911 912 tp = atp; 913 if (nflg || tp->t_dev == 0 || 914 (name = devname(tp->t_dev, S_IFCHR)) == NULL) 915 printf("%7d ", line); 916 else 917 printf("%7s ", name); 918 printf("%2d %3d ", tp->t_rawq.c_cc, tp->t_canq.c_cc); 919 printf("%3d %4d %3d %8x %3d ", tp->t_outq.c_cc, 920 tp->t_hiwat, tp->t_lowat, tp->t_addr, tp->t_col); 921 for (i = j = 0; ttystates[i].flag; i++) 922 if (tp->t_state&ttystates[i].flag) 923 state[j++] = ttystates[i].val; 924 if (j == 0) 925 state[j++] = '-'; 926 state[j] = '\0'; 927 printf("%-4s %6x", state, (u_long)tp->t_session & ~KERNBASE); 928 if (tp->t_pgrp == NULL || kvm_read(kd, V(&tp->t_pgrp->pg_id), &pgid, 929 sizeof (pid_t)) != sizeof (pid_t)) 930 pgid = 0; 931 printf("%6d ", pgid); 932 switch (tp->t_line) { 933 934 case TTYDISC: 935 printf("term\n"); 936 break; 937 938 case TABLDISC: 939 printf("tab\n"); 940 break; 941 942 case SLIPDISC: 943 printf("slip\n"); 944 break; 945 946 default: 947 printf("%d\n", tp->t_line); 948 } 949 } 950 951 /* 952 * The user structure is going away. What's left here won't 953 * be around for long. 954 */ 955 dousr() 956 { 957 958 printf("nothing left in user structure in this system\n"); 959 } 960 961 oatoi(s) 962 char *s; 963 { 964 register v; 965 966 v = 0; 967 while (*s) 968 v = (v<<3) + *s++ - '0'; 969 return(v); 970 } 971 972 dofile() 973 { 974 register struct file *fp; 975 struct file *addr; 976 char *buf; 977 int len, maxfile, nfile; 978 struct nlist fnl[] = { 979 #define FNL_NFILE 0 980 {"_nfiles"}, 981 #define FNL_MAXFILE 1 982 {"_maxfiles"}, 983 {""} 984 }; 985 static char *dtypes[] = { "???", "inode", "socket" }; 986 987 if (kvm_nlist(kd, fnl) != 0) { 988 error("kvm_nlist: no _nfiles or _maxfiles: %s", 989 kvm_geterr(kd)); 990 return; 991 } 992 kvm_read(kd, V(fnl[FNL_MAXFILE].n_value), &maxfile, 993 sizeof (maxfile)); 994 if (totflg) { 995 kvm_read(kd, V(fnl[FNL_NFILE].n_value), &nfile, sizeof (nfile)); 996 printf("%3d/%3d files\n", nfile, maxfile); 997 return; 998 } 999 if (getfiles(&buf, &len) == -1) 1000 return; 1001 /* 1002 * getfiles returns in malloc'd buf a pointer to the first file 1003 * structure, and then an array of file structs (whose 1004 * addresses are derivable from the previous entry) 1005 */ 1006 addr = *((struct file **)buf); 1007 fp = (struct file *)(buf + sizeof (struct file *)); 1008 nfile = (len - sizeof (struct file *)) / sizeof (struct file); 1009 1010 printf("%d/%d open files\n", nfile, maxfile); 1011 printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n"); 1012 for (; (char *)fp < buf + len; addr = fp->f_filef, fp++) { 1013 if ((unsigned)fp->f_type > DTYPE_SOCKET) 1014 continue; 1015 printf("%x ", addr); 1016 printf("%-8.8s", dtypes[fp->f_type]); 1017 putf(fp->f_flag&FREAD, 'R'); 1018 putf(fp->f_flag&FWRITE, 'W'); 1019 putf(fp->f_flag&FAPPEND, 'A'); 1020 #ifdef FSHLOCK /* currently gone */ 1021 putf(fp->f_flag&FSHLOCK, 'S'); 1022 putf(fp->f_flag&FEXLOCK, 'X'); 1023 #else 1024 putf(0, ' '); 1025 putf(0, ' '); 1026 #endif 1027 putf(fp->f_flag&FASYNC, 'I'); 1028 printf(" %3d", fp->f_count); 1029 printf(" %3d", fp->f_msgcount); 1030 printf(" %8.1x", fp->f_data); 1031 if (fp->f_offset < 0) 1032 printf(" %x\n", fp->f_offset); 1033 else 1034 printf(" %ld\n", fp->f_offset); 1035 } 1036 free(buf); 1037 } 1038 1039 getfiles(abuf, alen) 1040 char **abuf; 1041 int *alen; 1042 { 1043 char *buf; 1044 int mib[2]; 1045 size_t len; 1046 1047 if (memf != NULL) { 1048 /* 1049 * add emulation of KINFO_FILE here 1050 */ 1051 error("files on dead kernel, not impl\n"); 1052 exit(1); 1053 } 1054 mib[0] = CTL_KERN; 1055 mib[1] = KERN_FILE; 1056 if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1) { 1057 syserror("sysctl size estimate"); 1058 return (-1); 1059 } 1060 if ((buf = (char *)malloc(len)) == NULL) { 1061 error("out of memory"); 1062 return (-1); 1063 } 1064 if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) { 1065 syserror("sysctl"); 1066 return (-1); 1067 } 1068 *abuf = buf; 1069 *alen = len; 1070 return (0); 1071 } 1072 1073 1074 doswap() 1075 { 1076 printf("swap statistics not yet supported in this system\n"); 1077 } 1078 1079 #include <varargs.h> 1080 1081 error(va_alist) 1082 va_dcl 1083 { 1084 char *fmt; 1085 va_list ap; 1086 extern errno; 1087 1088 fprintf(stderr, "pstat: "); 1089 va_start(ap); 1090 fmt = va_arg(ap, char *); 1091 (void) vfprintf(stderr, fmt, ap); 1092 va_end(ap); 1093 fprintf(stderr, "\n"); 1094 } 1095 1096 syserror(va_alist) 1097 va_dcl 1098 { 1099 char *fmt; 1100 va_list ap; 1101 extern errno; 1102 1103 fprintf(stderr, "pstat: "); 1104 va_start(ap); 1105 fmt = va_arg(ap, char *); 1106 (void) vfprintf(stderr, fmt, ap); 1107 va_end(ap); 1108 fprintf(stderr, ": %s\n", strerror(errno)); 1109 } 1110