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.40 (Berkeley) 04/13/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 #ifdef mips 132 #define SDC (SNPTY+1) 133 { "_dc_tty" }, 134 #define SNDC (SNPTY+2) 135 { "_dc_cnt" }, 136 #endif 137 138 { "" } 139 }; 140 141 int vnof; 142 int txtf; 143 int prcf; 144 int ttyf; 145 int usrf; 146 int upid; 147 int filf; 148 int swpf; 149 int totflg; 150 char partab[1]; 151 struct cdevsw cdevsw[1]; 152 struct bdevsw bdevsw[1]; 153 int allflg; 154 int nflg; 155 u_long getword(); 156 off_t mkphys(); 157 kvm_t *kd; 158 159 #define V(x) (u_long)(x) 160 161 main(argc, argv) 162 int argc; 163 char *argv[]; 164 { 165 extern char *optarg; 166 extern int optind; 167 int ch, ret; 168 char buf[_POSIX2_LINE_MAX]; 169 170 while ((ch = getopt(argc, argv, "TafvikptU:sxnu")) != EOF) 171 switch (ch) { 172 case 'T': 173 totflg++; 174 break; 175 case 'a': 176 allflg++; 177 /*FALLTHROUGH*/ 178 case 'p': 179 prcf++; 180 break; 181 case 'f': 182 filf++; 183 break; 184 case 'v': 185 case 'i': 186 vnof++; 187 break; 188 case 't': 189 ttyf++; 190 break; 191 case 'U': 192 usrf++; 193 sscanf(optarg, "%d", &upid); 194 break; 195 case 's': 196 swpf++; 197 break; 198 case 'x': 199 txtf++; 200 break; 201 case 'n': 202 nflg++; 203 break; 204 case 'u': 205 fprintf(stderr, "pstat: use [ -U pid ] for -u\n"); 206 exit(1); 207 case '?': 208 default: 209 usage(); 210 } 211 argc -= optind; 212 argv += optind; 213 214 if (argc > 1) 215 memf = argv[1]; 216 if (argc > 0) 217 nlistf = argv[0]; 218 219 /* 220 * Discard setgid privileges if not the running kernel so that bad 221 * guys can't print interesting stuff from kernel memory. 222 */ 223 if (nlistf != NULL || memf != NULL) 224 setgid(getgid()); 225 226 if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == 0) { 227 error("kvm_openfiles: %s", buf); 228 exit(1); 229 } 230 if ((ret = kvm_nlist(kd, nl)) != 0) { 231 int i, quit = 0; 232 233 if (ret == -1) { 234 error("kvm_nlist: %s", kvm_geterr(kd)); 235 exit(1); 236 } 237 for (i = 0; i <= NLMANDATORY; i++) { 238 if (!nl[i].n_value) { 239 quit = 1; 240 error("undefined symbol: %s\n", 241 nl[i].n_name); 242 } 243 } 244 if (quit) 245 exit(1); 246 } 247 if (!(filf | totflg | vnof | prcf | txtf | ttyf | usrf | swpf)) 248 usage(); 249 if (filf||totflg) 250 dofile(); 251 if (vnof||totflg) 252 dovnode(); 253 if (prcf||totflg) 254 doproc(); 255 if (txtf||totflg) 256 dotext(); 257 if (ttyf) 258 dotty(); 259 if (usrf) 260 dousr(); 261 if (swpf||totflg) 262 doswap(); 263 } 264 265 usage() 266 { 267 268 fprintf(stderr, 269 "usage: pstat -[Tafiptsx] [-U [pid]] [system] [core]\n"); 270 exit(1); 271 } 272 273 struct e_vnode { 274 struct vnode *avnode; 275 struct vnode vnode; 276 }; 277 278 dovnode() 279 { 280 register struct e_vnode *e_vnodebase, *endvnode, *evp; 281 register struct vnode *vp; 282 register struct mount *maddr = NULL, *mp; 283 int numvnodes; 284 struct e_vnode *loadvnodes(); 285 struct mount *getmnt(); 286 287 e_vnodebase = loadvnodes(&numvnodes); 288 if (totflg) { 289 printf("%7d vnodes\n", numvnodes); 290 return; 291 } 292 endvnode = e_vnodebase + numvnodes; 293 printf("%d active vnodes\n", numvnodes); 294 295 296 #define ST mp->mnt_stat 297 for (evp = e_vnodebase; evp < endvnode; evp++) { 298 vp = &evp->vnode; 299 if (vp->v_mount != maddr) { 300 /* 301 * New filesystem 302 */ 303 if ((mp = getmnt(vp->v_mount)) == NULL) 304 continue; 305 maddr = vp->v_mount; 306 mount_print(mp); 307 vnode_header(); 308 switch(ST.f_type) { 309 case MOUNT_UFS: 310 case MOUNT_MFS: 311 ufs_header(); 312 break; 313 case MOUNT_NFS: 314 nfs_header(); 315 break; 316 case MOUNT_NONE: 317 case MOUNT_PC: 318 default: 319 break; 320 } 321 printf("\n"); 322 } 323 vnode_print(evp->avnode, vp); 324 switch(ST.f_type) { 325 case MOUNT_UFS: 326 case MOUNT_MFS: 327 ufs_print(vp); 328 break; 329 case MOUNT_NFS: 330 nfs_print(vp); 331 break; 332 case MOUNT_NONE: 333 case MOUNT_PC: 334 default: 335 break; 336 } 337 printf("\n"); 338 } 339 free(e_vnodebase); 340 } 341 342 vnode_header() 343 { 344 printf("ADDR TYP VFLAG USE HOLD"); 345 } 346 347 vnode_print(avnode, vp) 348 struct vnode *avnode; 349 struct vnode *vp; 350 { 351 char *type, flags[16]; 352 char *fp = flags; 353 register flag; 354 355 /* 356 * set type 357 */ 358 switch(vp->v_type) { 359 case VNON: 360 type = "non"; break; 361 case VREG: 362 type = "reg"; break; 363 case VDIR: 364 type = "dir"; break; 365 case VBLK: 366 type = "blk"; break; 367 case VCHR: 368 type = "chr"; break; 369 case VLNK: 370 type = "lnk"; break; 371 case VSOCK: 372 type = "soc"; break; 373 case VFIFO: 374 type = "fif"; break; 375 case VBAD: 376 type = "bad"; break; 377 default: 378 type = "unk"; break; 379 } 380 /* 381 * gather flags 382 */ 383 flag = vp->v_flag; 384 if (flag & VROOT) 385 *fp++ = 'R'; 386 if (flag & VTEXT) 387 *fp++ = 'T'; 388 if (flag & VSYSTEM) 389 *fp++ = 'S'; 390 if (flag & VXLOCK) 391 *fp++ = 'L'; 392 if (flag & VXWANT) 393 *fp++ = 'W'; 394 if (flag & VBWAIT) 395 *fp++ = 'B'; 396 if (flag & VALIASED) 397 *fp++ = 'A'; 398 if (flag == 0) 399 *fp++ = '-'; 400 *fp = '\0'; 401 /* 402 * print it 403 */ 404 printf("%8x %s %5s %4d %4d", 405 avnode, type, flags, vp->v_usecount, vp->v_holdcnt); 406 } 407 408 ufs_header() 409 { 410 printf(" FILEID IFLAG RDEV|SZ"); 411 } 412 413 ufs_print(vp) 414 struct vnode *vp; 415 { 416 struct inode inode, *ip = &inode; 417 char flagbuf[16], *flags = flagbuf; 418 register flag; 419 char *name; 420 mode_t type; 421 extern char *devname(); 422 423 if (kvm_read(kd, V(VTOI(vp)), &inode, sizeof(struct inode)) != 424 sizeof(struct inode)) { 425 error("can't read inode for %x", vp); 426 return; 427 } 428 flag = ip->i_flag; 429 if (flag & ILOCKED) 430 *flags++ = 'L'; 431 if (flag & IWANT) 432 *flags++ = 'W'; 433 if (flag & IRENAME) 434 *flags++ = 'R'; 435 if (flag & IUPD) 436 *flags++ = 'U'; 437 if (flag & IACC) 438 *flags++ = 'A'; 439 if (flag & ICHG) 440 *flags++ = 'C'; 441 if (flag & IMOD) 442 *flags++ = 'M'; 443 if (flag & ISHLOCK) 444 *flags++ = 'S'; 445 if (flag & IEXLOCK) 446 *flags++ = 'E'; 447 if (flag & ILWAIT) 448 *flags++ = 'Z'; 449 if (flag == 0) 450 *flags++ = '-'; 451 *flags = '\0'; 452 453 printf(" %6d %5s", ip->i_number, flagbuf); 454 type = ip->i_mode & S_IFMT; 455 if (type == S_IFCHR || type == S_IFBLK) 456 if (nflg || ((name = devname(ip->i_rdev, type)) == NULL)) 457 printf(" %2d,%-2d", 458 major(ip->i_rdev), minor(ip->i_rdev)); 459 else 460 printf(" %7s", name); 461 else 462 printf(" %7qd", ip->i_size); 463 } 464 465 nfs_header() 466 { 467 printf(" FILEID NFLAG RDEV|SZ"); 468 } 469 470 nfs_print(vp) 471 struct vnode *vp; 472 { 473 struct nfsnode nfsnode, *np = &nfsnode; 474 char flagbuf[16], *flags = flagbuf; 475 register flag; 476 char *name; 477 mode_t type; 478 extern char *devname(); 479 480 if (kvm_read(kd, V(VTONFS(vp)), &nfsnode, sizeof(struct nfsnode)) != 481 sizeof(struct nfsnode)) { 482 error("can't read nfsnode for %x", vp); 483 return; 484 } 485 flag = np->n_flag; 486 if (flag & NFLUSHWANT) 487 *flags++ = 'W'; 488 if (flag & NFLUSHINPROG) 489 *flags++ = 'P'; 490 if (flag & NMODIFIED) 491 *flags++ = 'M'; 492 if (flag & NWRITEERR) 493 *flags++ = 'E'; 494 if (flag & NQNFSNONCACHE) 495 *flags++ = 'X'; 496 if (flag & NQNFSWRITE) 497 *flags++ = 'O'; 498 if (flag & NQNFSEVICTED) 499 *flags++ = 'G'; 500 if (flag == 0) 501 *flags++ = '-'; 502 *flags = '\0'; 503 504 #define VT np->n_vattr 505 printf(" %6d %5s", VT.va_fileid, flagbuf); 506 type = VT.va_mode & S_IFMT; 507 if (type == S_IFCHR || type == S_IFBLK) 508 if (nflg || ((name = devname(VT.va_rdev, type)) == NULL)) 509 printf(" %2d,%-2d", 510 major(VT.va_rdev), minor(VT.va_rdev)); 511 else 512 printf(" %7s", name); 513 else 514 printf(" %7qd", np->n_size); 515 } 516 517 /* 518 * Given a pointer to a mount structure in kernel space, 519 * read it in and return a usable pointer to it. 520 */ 521 struct mount * 522 getmnt(maddr) 523 struct mount *maddr; 524 { 525 static struct mtab { 526 struct mtab *next; 527 struct mount *maddr; 528 struct mount mount; 529 } *mhead = NULL; 530 register struct mtab *mt; 531 532 for (mt = mhead; mt != NULL; mt = mt->next) 533 if (maddr == mt->maddr) 534 return (&mt->mount); 535 if ((mt = (struct mtab *)malloc(sizeof (struct mtab))) == NULL) { 536 error("out of memory"); 537 exit(1); 538 } 539 if (kvm_read(kd, V(maddr), &mt->mount, sizeof(struct mount)) != 540 sizeof(struct mount)) { 541 error("can't read mount table at %x", maddr); 542 return (NULL); 543 } 544 mt->maddr = maddr; 545 mt->next = mhead; 546 mhead = mt; 547 return (&mt->mount); 548 } 549 550 mount_print(mp) 551 struct mount *mp; 552 { 553 char *type = "unknown"; 554 register flags; 555 556 #define ST mp->mnt_stat 557 printf("*** MOUNT "); 558 switch (ST.f_type) { 559 case MOUNT_NONE: 560 type = "none"; 561 break; 562 case MOUNT_UFS: 563 type = "ufs"; 564 break; 565 case MOUNT_NFS: 566 type = "nfs"; 567 break; 568 case MOUNT_MFS: 569 type = "mfs"; 570 break; 571 case MOUNT_PC: 572 type = "pc"; 573 break; 574 } 575 printf("%s %s on %s", type, ST.f_mntfromname, ST.f_mntonname); 576 if (flags = mp->mnt_flag) { 577 char *comma = "("; 578 579 putchar(' '); 580 /* user visable flags */ 581 if (flags & MNT_RDONLY) { 582 printf("%srdonly", comma); 583 flags &= ~MNT_RDONLY; 584 comma = ","; 585 } 586 if (flags & MNT_SYNCHRONOUS) { 587 printf("%ssynchronous", comma); 588 flags &= ~MNT_SYNCHRONOUS; 589 comma = ","; 590 } 591 if (flags & MNT_NOEXEC) { 592 printf("%snoexec", comma); 593 flags &= ~MNT_NOEXEC; 594 comma = ","; 595 } 596 if (flags & MNT_NOSUID) { 597 printf("%snosuid", comma); 598 flags &= ~MNT_NOSUID; 599 comma = ","; 600 } 601 if (flags & MNT_NODEV) { 602 printf("%snodev", comma); 603 flags &= ~MNT_NODEV; 604 comma = ","; 605 } 606 if (flags & MNT_EXPORTED) { 607 printf("%sexport", comma); 608 flags &= ~MNT_EXPORTED; 609 comma = ","; 610 } 611 if (flags & MNT_EXRDONLY) { 612 printf("%sexrdonly", comma); 613 flags &= ~MNT_EXRDONLY; 614 comma = ","; 615 } 616 if (flags & MNT_LOCAL) { 617 printf("%slocal", comma); 618 flags &= ~MNT_LOCAL; 619 comma = ","; 620 } 621 if (flags & MNT_QUOTA) { 622 printf("%squota", comma); 623 flags &= ~MNT_QUOTA; 624 comma = ","; 625 } 626 /* filesystem control flags */ 627 if (flags & MNT_UPDATE) { 628 printf("%supdate", comma); 629 flags &= ~MNT_UPDATE; 630 comma = ","; 631 } 632 if (flags & MNT_MLOCK) { 633 printf("%slock", comma); 634 flags &= ~MNT_MLOCK; 635 comma = ","; 636 } 637 if (flags & MNT_MWAIT) { 638 printf("%swait", comma); 639 flags &= ~MNT_MWAIT; 640 comma = ","; 641 } 642 if (flags & MNT_MPBUSY) { 643 printf("%sbusy", comma); 644 flags &= ~MNT_MPBUSY; 645 comma = ","; 646 } 647 if (flags & MNT_MPWANT) { 648 printf("%swant", comma); 649 flags &= ~MNT_MPWANT; 650 comma = ","; 651 } 652 if (flags & MNT_UNMOUNT) { 653 printf("%sunmount", comma); 654 flags &= ~MNT_UNMOUNT; 655 comma = ","; 656 } 657 if (flags) 658 printf("%sunknown_flags:%x", flags); 659 printf(")"); 660 } 661 printf("\n"); 662 #undef ST 663 } 664 665 struct e_vnode * 666 loadvnodes(avnodes) 667 int *avnodes; 668 { 669 int mib[2]; 670 size_t copysize; 671 struct e_vnode *vnodebase; 672 struct e_vnode *kinfo_vnodes(); 673 674 if (memf != NULL) { 675 /* 676 * do it by hand 677 */ 678 return (kinfo_vnodes(avnodes)); 679 } 680 mib[0] = CTL_KERN; 681 mib[1] = KERN_VNODE; 682 if (sysctl(mib, 2, NULL, ©size, NULL, 0) == -1) { 683 syserror("can't get estimate from sysctl"); 684 exit(1); 685 } 686 if ((vnodebase = (struct e_vnode *)malloc(copysize)) == NULL) { 687 error("out of memory"); 688 exit(1); 689 } 690 if (sysctl(mib, 2, vnodebase, ©size, NULL, 0) == -1) { 691 syserror("can't get vnode list"); 692 exit(1); 693 } 694 if (copysize % sizeof (struct e_vnode)) { 695 error("vnode size mismatch"); 696 exit(1); 697 } 698 *avnodes = copysize / sizeof (struct e_vnode); 699 700 return (vnodebase); 701 } 702 703 /* 704 * simulate what a running kernel does in in kinfo_vnode 705 */ 706 struct e_vnode * 707 kinfo_vnodes(avnodes) 708 int *avnodes; 709 { 710 struct nlist vnl[] = { 711 #define V_NUMV 0 712 { "_numvnodes" }, 713 #define V_ROOTFS 1 714 { "_rootfs" }, 715 {""} 716 }; 717 int numvnodes; 718 struct mount *rootfs, *mp, mount; 719 char *vbuf, *evbuf, *bp; 720 struct vnode *vp, vnode; 721 int num; 722 723 #define VPTRSZ sizeof (struct vnode *) 724 #define VNODESZ sizeof (struct vnode) 725 #define NVAL(indx) vnl[(indx)].n_value 726 727 if (kvm_nlist(kd, vnl) != 0) { 728 error("nlist vnl: %s", kvm_geterr(kd)); 729 exit(1); 730 } 731 numvnodes = getword(NVAL(V_NUMV)); 732 if ((vbuf = (char *)malloc((numvnodes + 20) * (VPTRSZ + VNODESZ))) 733 == NULL) { 734 error("out of memory"); 735 exit(1); 736 } 737 bp = vbuf; 738 evbuf = vbuf + (numvnodes + 20) * (VPTRSZ + VNODESZ); 739 mp = rootfs = (struct mount *)getword(NVAL(V_ROOTFS)); 740 do { 741 kvm_read(kd, V(mp), &mount, sizeof(mount)); 742 for (vp = mount.mnt_mounth; vp; vp = vnode.v_mountf) { 743 kvm_read(kd, V(vp), &vnode, sizeof (vnode)); 744 if ((bp + VPTRSZ + VNODESZ) > evbuf) { 745 /* XXX - should realloc */ 746 fprintf(stderr, "pstat: ran out of room for vnodes\n"); 747 exit(1); 748 } 749 bcopy(&vp, bp, VPTRSZ); 750 bp += VPTRSZ; 751 bcopy(&vnode, bp, VNODESZ); 752 bp += VNODESZ; 753 num++; 754 } 755 mp = mount.mnt_next; 756 } while (mp != rootfs); 757 *avnodes = num; 758 return ((struct e_vnode *)vbuf); 759 } 760 761 762 u_long 763 getword(loc) 764 int loc; 765 { 766 u_long word; 767 768 kvm_read(kd, V(loc), &word, sizeof (word)); 769 return (word); 770 } 771 772 putf(v, n) 773 { 774 if (v) 775 printf("%c", n); 776 else 777 printf(" "); 778 } 779 780 dotext() 781 { 782 783 printf("no text table in this system\n"); 784 } 785 786 doproc() 787 { 788 if (!totflg) 789 printf("pstat: -p no longer supported (use ps)\n"); 790 } 791 792 char mesg[] = " LINE RAW CAN OUT HWT LWT ADDR COL STATE SESS PGID DISC\n"; 793 int ttyspace = 128; 794 struct tty *tty; 795 796 dotty() 797 { 798 799 if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) { 800 printf("pstat: out of memory\n"); 801 return; 802 } 803 #ifndef hp300 804 printf("1 cons\n"); 805 kvm_read(kd, V(nl[SCONS].n_value), tty, sizeof(*tty)); 806 printf(mesg); 807 ttyprt(&tty[0], 0); 808 #endif 809 #ifdef vax 810 if (nl[SNQD].n_type != 0) 811 doqdss(); 812 if (nl[SNDZ].n_type != 0) 813 dottytype("dz", SDZ, SNDZ); 814 if (nl[SNDH].n_type != 0) 815 dottytype("dh", SDH, SNDH); 816 if (nl[SNDMF].n_type != 0) 817 dottytype("dmf", SDMF, SNDMF); 818 if (nl[SNDHU].n_type != 0) 819 dottytype("dhu", SDHU, SNDHU); 820 if (nl[SNDMZ].n_type != 0) 821 dottytype("dmz", SDMZ, SNDMZ); 822 #endif 823 #ifdef tahoe 824 if (nl[SNVX].n_type != 0) 825 dottytype("vx", SVX, SNVX); 826 if (nl[SNMP].n_type != 0) 827 dottytype("mp", SMP, SNMP); 828 #endif 829 #ifdef hp300 830 if (nl[SNITE].n_type != 0) 831 dottytype("ite", SITE, SNITE); 832 if (nl[SNDCA].n_type != 0) 833 dottytype("dca", SDCA, SNDCA); 834 if (nl[SNDCM].n_type != 0) 835 dottytype("dcm", SDCM, SNDCM); 836 if (nl[SNDCL].n_type != 0) 837 dottytype("dcl", SDCL, SNDCL); 838 #endif 839 #ifdef mips 840 if (nl[SNDC].n_type != 0) 841 dottytype("dc", SDC, SNDC); 842 #endif 843 if (nl[SNPTY].n_type != 0) 844 dottytype("pty", SPTY, SNPTY); 845 } 846 847 /* 848 * Special case the qdss: there are 4 ttys per qdss, 849 * but only the first of each is used as a tty. 850 */ 851 #ifdef vax 852 doqdss() 853 { 854 int nqd; 855 register struct tty *tp; 856 857 kvm_read(kd, V(nl[SNQD].n_value), &nqd, sizeof(nqd)); 858 printf("%d qd\n", nqd); 859 kvm_read(kd, V(nl[SQD].n_value), tty, nqd * sizeof(struct tty) * 4); 860 printf(mesg); 861 for (tp = tty; tp < &tty[nqd * 4]; tp += 4) 862 ttyprt(tp, tp - tty); 863 } 864 #endif 865 866 dottytype(name, type, number) 867 char *name; 868 { 869 int ntty; 870 register struct tty *tp; 871 extern char *realloc(); 872 873 if (tty == (struct tty *)0) 874 return; 875 kvm_read(kd, V(nl[number].n_value), &ntty, sizeof(ntty)); 876 printf("%d %s %s\n", ntty, name, (ntty == 1) ? "line" : 877 "lines"); 878 if (ntty > ttyspace) { 879 ttyspace = ntty; 880 if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { 881 printf("pstat: out of memory\n"); 882 return; 883 } 884 } 885 kvm_read(kd, V(nl[type].n_value), tty, ntty * sizeof(struct tty)); 886 printf(mesg); 887 for (tp = tty; tp < &tty[ntty]; tp++) 888 ttyprt(tp, tp - tty); 889 } 890 891 struct { 892 int flag; 893 char val; 894 } ttystates[] = { 895 TS_WOPEN, 'W', 896 TS_ISOPEN, 'O', 897 TS_CARR_ON, 'C', 898 TS_TIMEOUT, 'T', 899 TS_FLUSH, 'F', 900 TS_BUSY, 'B', 901 TS_ASLEEP, 'A', 902 TS_XCLUDE, 'X', 903 TS_TTSTOP, 'S', 904 TS_TBLOCK, 'K', 905 TS_ASYNC, 'Y', 906 TS_BKSL, 'D', 907 TS_ERASE, 'E', 908 TS_LNCH, 'L', 909 TS_TYPEN, 'P', 910 TS_CNTTB, 'N', 911 0, 0 912 }; 913 914 ttyprt(atp, line) 915 struct tty *atp; 916 { 917 register struct tty *tp; 918 char state[20]; 919 register i, j; 920 char *name; 921 extern char *devname(); 922 pid_t pgid; 923 924 tp = atp; 925 if (nflg || tp->t_dev == 0 || 926 (name = devname(tp->t_dev, S_IFCHR)) == NULL) 927 printf("%7d ", line); 928 else 929 printf("%7s ", name); 930 printf("%2d %3d ", tp->t_rawq.c_cc, tp->t_canq.c_cc); 931 printf("%3d %4d %3d %8x %3d ", tp->t_outq.c_cc, 932 tp->t_hiwat, tp->t_lowat, tp->t_addr, tp->t_col); 933 for (i = j = 0; ttystates[i].flag; i++) 934 if (tp->t_state&ttystates[i].flag) 935 state[j++] = ttystates[i].val; 936 if (j == 0) 937 state[j++] = '-'; 938 state[j] = '\0'; 939 printf("%-4s %6x", state, (u_long)tp->t_session & ~KERNBASE); 940 if (tp->t_pgrp == NULL || kvm_read(kd, V(&tp->t_pgrp->pg_id), &pgid, 941 sizeof (pid_t)) != sizeof (pid_t)) 942 pgid = 0; 943 printf("%6d ", pgid); 944 switch (tp->t_line) { 945 946 case TTYDISC: 947 printf("term\n"); 948 break; 949 950 case TABLDISC: 951 printf("tab\n"); 952 break; 953 954 case SLIPDISC: 955 printf("slip\n"); 956 break; 957 958 default: 959 printf("%d\n", tp->t_line); 960 } 961 } 962 963 /* 964 * The user structure is going away. What's left here won't 965 * be around for long. 966 */ 967 dousr() 968 { 969 970 printf("nothing left in user structure in this system\n"); 971 } 972 973 oatoi(s) 974 char *s; 975 { 976 register v; 977 978 v = 0; 979 while (*s) 980 v = (v<<3) + *s++ - '0'; 981 return(v); 982 } 983 984 dofile() 985 { 986 register struct file *fp; 987 struct file *addr; 988 char *buf; 989 int len, maxfile, nfile; 990 struct nlist fnl[] = { 991 #define FNL_NFILE 0 992 {"_nfiles"}, 993 #define FNL_MAXFILE 1 994 {"_maxfiles"}, 995 {""} 996 }; 997 static char *dtypes[] = { "???", "inode", "socket" }; 998 999 if (kvm_nlist(kd, fnl) != 0) { 1000 error("kvm_nlist: no _nfiles or _maxfiles: %s", 1001 kvm_geterr(kd)); 1002 return; 1003 } 1004 kvm_read(kd, V(fnl[FNL_MAXFILE].n_value), &maxfile, 1005 sizeof (maxfile)); 1006 if (totflg) { 1007 kvm_read(kd, V(fnl[FNL_NFILE].n_value), &nfile, sizeof (nfile)); 1008 printf("%3d/%3d files\n", nfile, maxfile); 1009 return; 1010 } 1011 if (getfiles(&buf, &len) == -1) 1012 return; 1013 /* 1014 * getfiles returns in malloc'd buf a pointer to the first file 1015 * structure, and then an array of file structs (whose 1016 * addresses are derivable from the previous entry) 1017 */ 1018 addr = *((struct file **)buf); 1019 fp = (struct file *)(buf + sizeof (struct file *)); 1020 nfile = (len - sizeof (struct file *)) / sizeof (struct file); 1021 1022 printf("%d/%d open files\n", nfile, maxfile); 1023 printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n"); 1024 for (; (char *)fp < buf + len; addr = fp->f_filef, fp++) { 1025 if ((unsigned)fp->f_type > DTYPE_SOCKET) 1026 continue; 1027 printf("%x ", addr); 1028 printf("%-8.8s", dtypes[fp->f_type]); 1029 putf(fp->f_flag&FREAD, 'R'); 1030 putf(fp->f_flag&FWRITE, 'W'); 1031 putf(fp->f_flag&FAPPEND, 'A'); 1032 #ifdef FSHLOCK /* currently gone */ 1033 putf(fp->f_flag&FSHLOCK, 'S'); 1034 putf(fp->f_flag&FEXLOCK, 'X'); 1035 #else 1036 putf(0, ' '); 1037 putf(0, ' '); 1038 #endif 1039 putf(fp->f_flag&FASYNC, 'I'); 1040 printf(" %3d", fp->f_count); 1041 printf(" %3d", fp->f_msgcount); 1042 printf(" %8.1x", fp->f_data); 1043 if (fp->f_offset < 0) 1044 printf(" %x\n", fp->f_offset); 1045 else 1046 printf(" %ld\n", fp->f_offset); 1047 } 1048 free(buf); 1049 } 1050 1051 getfiles(abuf, alen) 1052 char **abuf; 1053 int *alen; 1054 { 1055 char *buf; 1056 int mib[2]; 1057 size_t len; 1058 1059 if (memf != NULL) { 1060 /* 1061 * add emulation of KINFO_FILE here 1062 */ 1063 error("files on dead kernel, not impl\n"); 1064 exit(1); 1065 } 1066 mib[0] = CTL_KERN; 1067 mib[1] = KERN_FILE; 1068 if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1) { 1069 syserror("sysctl size estimate"); 1070 return (-1); 1071 } 1072 if ((buf = (char *)malloc(len)) == NULL) { 1073 error("out of memory"); 1074 return (-1); 1075 } 1076 if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) { 1077 syserror("sysctl"); 1078 return (-1); 1079 } 1080 *abuf = buf; 1081 *alen = len; 1082 return (0); 1083 } 1084 1085 1086 doswap() 1087 { 1088 printf("swap statistics not yet supported in this system\n"); 1089 } 1090 1091 #include <varargs.h> 1092 1093 error(va_alist) 1094 va_dcl 1095 { 1096 char *fmt; 1097 va_list ap; 1098 extern errno; 1099 1100 fprintf(stderr, "pstat: "); 1101 va_start(ap); 1102 fmt = va_arg(ap, char *); 1103 (void) vfprintf(stderr, fmt, ap); 1104 va_end(ap); 1105 fprintf(stderr, "\n"); 1106 } 1107 1108 syserror(va_alist) 1109 va_dcl 1110 { 1111 char *fmt; 1112 va_list ap; 1113 extern errno; 1114 1115 fprintf(stderr, "pstat: "); 1116 va_start(ap); 1117 fmt = va_arg(ap, char *); 1118 (void) vfprintf(stderr, fmt, ap); 1119 va_end(ap); 1120 fprintf(stderr, ": %s\n", strerror(errno)); 1121 } 1122