|
|
1.1 ! root 1: static char _version[]="ps version 2.10"; ! 2: /* ! 3: * Modifications copyright INETCO Systems Ltd. ! 4: * ! 5: * Print out process statuses. ! 6: * ! 7: * $Log: ps.c,v $ ! 8: * Revision 1.7 92/09/18 09:42:29 bin ! 9: * version 210 fom piggy ! 10: * ! 11: * Revision 1.3 91/07/17 14:22:55 bin ! 12: * stevesf supplied as INETCO source because previous sources are of ! 13: * questionable origin... this one works ! 14: * ! 15: * Revision 1.2 89/06/12 15:15:22 src ! 16: * Bug: A directory at the end of the '/dev' directory would cause 'ps' ! 17: * to crash with the message "Cannot open <dir> in /dev". ! 18: * Fix: A stat was being done without the return code being checked. (ART) ! 19: * ! 20: * Revision 1.1 89/06/12 14:42:24 src ! 21: * Initial revision ! 22: * ! 23: * 88/02/15 Allan Cornish /usr/src/cmd/cmd/ps.c ! 24: * Kernel processes are now displayed regardless of -ax flags. ! 25: * ! 26: * 87/11/25 Allan Cornish /usr/src/cmd/cmd/ps.c ! 27: * Debug flag now -D. Drivers now displayed by -d flag. ! 28: * ! 29: * 87/11/12 Allan Cornish /usr/src/cmd/cmd/ps.c ! 30: * Modified to support Coherent 9.0 [protected mode] segmentation. ! 31: * ! 32: * 87/10/20 Allan Cornish /usr/src/cmd/cmd/ps.c ! 33: * Now extracts cmd name from u_comm field in uproc struct for kernel procs. ! 34: * Kernel processes only displayed if -d [debug] flag given. ! 35: * ! 36: * 87/09/28 Phil Selby /usr/src/cmd/cmd/ps.c ! 37: * Altered so that the terminal name rather than major and minor ! 38: * device number is printed out ! 39: * ! 40: * 84/08/21 Rec ! 41: * Added gflag for group identification. ! 42: * ! 43: * 84/07/16 Lauren Weinstein ! 44: * Initial version. ! 45: */ ! 46: ! 47: #include <sys/coherent.h> ! 48: #include <sys/param.h> ! 49: #include <sys/proc.h> ! 50: #include <sys/sched.h> ! 51: #include <dirent.h> ! 52: #include <sys/seg.h> ! 53: #include <sys/stat.h> ! 54: #include <sys/uproc.h> ! 55: #include <sys/mmu.h> ! 56: #include <signal.h> ! 57: #include <access.h> ! 58: #include <fcntl.h> ! 59: #include <stdio.h> ! 60: #include <ctype.h> ! 61: #include <coff.h> ! 62: #include <pwd.h> ! 63: ! 64: /* ! 65: * This is a kludge for the i8086 only and will be ! 66: * made to disappear when the segmentation (jproto) ! 67: * is thrown away. ! 68: #undef SISTACK ! 69: #define SISTACK SIPDATA ! 70: */ ! 71: ! 72: /* ! 73: * Terminal information stored in memory for use by ps in TTY field ! 74: */ ! 75: ! 76: struct handle { ! 77: dev_t dnum; /* device number */ ! 78: char dname[DIRSIZ]; /* device name */ ! 79: struct handle *nptr; /* pointer to next */ ! 80: } *fptr, *lptr; ! 81: ! 82: /* ! 83: * Maximum sizes. ! 84: */ ! 85: #define ARGSIZE 512 ! 86: ! 87: /* ! 88: * Functions to see if a pointer is in alloc space and to map a ! 89: * pointer from alloca space to this process. ! 90: */ ! 91: #define map(p) (&(allp[(char *)(p) - (char *) callocp.sr_base])) ! 92: ! 93: /* ! 94: * For easy referencing. ! 95: */ ! 96: #define NUM_SYMS 7 /* Number of symbols to look up. */ ! 97: #define aprocq nl[0].n_value ! 98: #define autime nl[1].n_value ! 99: #define astime nl[2].n_value ! 100: #define aallocp nl[3].n_value ! 101: #define aend nl[4].n_value ! 102: #define asysmem nl[5].n_value ! 103: #define au nl[6].n_value ! 104: ! 105: #define TRUE (1==1) ! 106: #define FALSE (1==2) ! 107: #define LESSER(a, b) ((a < b)?a:b) ! 108: ! 109: /* ! 110: * Defines for referencing page tables. ! 111: */ ! 112: #define BPCSHIFT 12 /* Shift this many to convert bytes to clicks. */ ! 113: #define ONE_CLICK 4096 /* Bytes in a click. */ ! 114: #define CLICK_OFFSET 0x00000fffL /* Bits in virtual address indexing into page. */ ! 115: #define PT_CLICK_ADDR 0xfffff000L /* Bits in pte pointing at the page. */ ! 116: #define PT_PRESENT(entry) (0x01 == (entry & 0x01)) /* Is the page for ! 117: * this pte present? ! 118: */ ! 119: /* ! 120: * This is the address of the start of the U area segment. This ! 121: * should probably be extracted somehow from an include file. ! 122: * It can be derived with much pain from the s_vmem field in the seg ! 123: * struct from the U area segment. ! 124: */ ! 125: #define USEG_BASE 0xfffff000 ! 126: ! 127: /* ! 128: * Variables. ! 129: */ ! 130: int aflag; /* All processes */ ! 131: int dflag; /* Driver flag */ ! 132: int dbflag; /* Debug flag */ ! 133: int fflag; /* Print out all fields */ ! 134: int gflag; /* Print out process groups */ ! 135: int lflag; /* Long format */ ! 136: int mflag; /* Print scheduling values */ ! 137: int nflag; /* No header */ ! 138: int rflag; /* Print out real sizes */ ! 139: int tflag; /* Print times */ ! 140: int wflag; /* Wide format */ ! 141: int xflag; /* Get special processes */ ! 142: int Pflag; /* UNDOCUMENTED: ignore present bit. */ ! 143: dev_t ttdev; /* Terminal device */ ! 144: ! 145: /* ! 146: * Table for namelist. ! 147: */ ! 148: SYMENT nl[NUM_SYMS]; ! 149: ! 150: /* ! 151: * Symbols. ! 152: */ ! 153: char *allp; /* Pointer to alloc space */ ! 154: char *kfile; /* Kernel data memory file */ ! 155: char *nfile; /* Namelist file */ ! 156: char *mfile; /* Memory file */ ! 157: char *dfile; /* Swap file */ ! 158: char argp[ARGSIZE]; /* Arguments */ ! 159: int kfd; /* Kernel memory file descriptor */ ! 160: int mfd; /* Memory file descriptor */ ! 161: int dfd; /* Swap file descriptor */ ! 162: struct uproc u; /* User process area */ ! 163: unsigned cutime; /* Unsigned time */ ! 164: PROC cprocq; /* Process queue header */ ! 165: SR callocp; /* Size of alloc area */ ! 166: SYSMEM sysmem; /* Useful system-memory info. ! 167: * This variable MUST be called ! 168: * "sysmem" for the MAPIO() macro. ! 169: */ ! 170: char *malloc(); ! 171: char *uname(); ! 172: unsigned cval(); ! 173: cseg_t pt_index(); ! 174: char *pick_nfile(); ! 175: ! 176: main(argc, argv) ! 177: int argc; ! 178: char *argv[]; ! 179: { ! 180: register int i; ! 181: register char *cp; ! 182: ! 183: #if 0 ! 184: fprintf(stderr, "initialise()\n"); /* DEBUG */ ! 185: #endif /* 0 */ ! 186: initialise(); ! 187: #if 0 ! 188: fprintf(stderr, "parse args()\n"); /* DEBUG */ ! 189: #endif /* 0 */ ! 190: for (i=1; i<argc; i++) { ! 191: for (cp=&argv[i][0]; *cp; cp++) { ! 192: switch (*cp) { ! 193: case '-': ! 194: continue; ! 195: case 'a': ! 196: aflag++; ! 197: continue; ! 198: case 'c': ! 199: if (++i >= argc) ! 200: usage(); ! 201: nfile = argv[i]; ! 202: continue; ! 203: case 'd': ! 204: dflag++; ! 205: continue; ! 206: case 'D': ! 207: dbflag++; ! 208: continue; ! 209: case 'f': ! 210: fflag++; ! 211: continue; ! 212: case 'g': ! 213: gflag++; ! 214: continue; ! 215: case 'k': ! 216: if (++i >= argc) ! 217: usage(); ! 218: mfile = argv[i]; ! 219: continue; ! 220: case 'l': ! 221: lflag++; ! 222: continue; ! 223: case 'm': ! 224: mflag++; ! 225: continue; ! 226: case 'n': ! 227: nflag++; ! 228: continue; ! 229: case 'P': ! 230: Pflag++; ! 231: continue; ! 232: case 'r': ! 233: rflag++; ! 234: continue; ! 235: case 't': ! 236: tflag++; ! 237: continue; ! 238: case 'w': ! 239: wflag++; ! 240: continue; ! 241: case 'x': ! 242: xflag++; ! 243: continue; ! 244: default: ! 245: usage(); ! 246: } ! 247: } ! 248: } ! 249: ! 250: #if 0 ! 251: fprintf(stderr, "execute()\n"); /* DEBUG */ ! 252: #endif /* 0 */ ! 253: execute(); ! 254: ! 255: #if 0 ! 256: fprintf(stderr, "exit(0)\n"); /* DEBUG */ ! 257: #endif /* 0 */ ! 258: exit(0); ! 259: } ! 260: ! 261: /* ! 262: * Initialise. ! 263: */ ! 264: initialise() ! 265: { ! 266: register char *cp; ! 267: ! 268: aflag = 0; ! 269: gflag = 0; ! 270: lflag = 0; ! 271: mflag = 0; ! 272: nflag = 0; ! 273: Pflag = 0; ! 274: xflag = 0; ! 275: nfile = pick_nfile(); ! 276: kfile = "/dev/kmem"; ! 277: mfile = "/dev/mem"; ! 278: dfile = "/dev/swap"; ! 279: if ((cp=malloc(BUFSIZ)) != NULL) ! 280: setbuf(stdout, cp); ! 281: ! 282: /* Initialise the request for coffnlist(). */ ! 283: strcpy(nl[0]._n._n_name, "procq"); ! 284: nl[0].n_type = -1; ! 285: strcpy(nl[1]._n._n_name, "utimer"); ! 286: nl[1].n_type = -1; ! 287: strcpy(nl[2]._n._n_name, "stimer"); ! 288: nl[2].n_type = -1; ! 289: strcpy(nl[3]._n._n_name, "allocp"); ! 290: nl[3].n_type = -1; ! 291: strcpy(nl[4]._n._n_name, "end"); ! 292: nl[4].n_type = -1; ! 293: strcpy(nl[5]._n._n_name, "sysmem"); ! 294: nl[5].n_type = -1; ! 295: strcpy(nl[6]._n._n_name, "u"); ! 296: nl[6].n_type = -1; ! 297: ! 298: } ! 299: ! 300: /* ! 301: * Print out usage. ! 302: */ ! 303: usage() ! 304: { ! 305: panic("Usage: ps [-][acdfgklmnrtwx]"); ! 306: } ! 307: ! 308: ! 309: /* ! 310: * Print out information about processes. ! 311: */ ! 312: execute() ! 313: { ! 314: int fd; ! 315: int c, l; ! 316: int loop_count; /* Keep track of the number of entries read. */ ! 317: register PROC *pp1, *pp2; ! 318: ! 319: #if 0 ! 320: printf("execute()\n"); ! 321: fflush(stdout); ! 322: #endif /* 0 */ ! 323: ! 324: /* ! 325: * Check to see if the desired kernel exists and is accessable. ! 326: * NB: the access() system call uses the REAL uid to check ! 327: * permissions--it will not work here. ! 328: */ ! 329: if (-1 == (fd = open(nfile, O_RDONLY))) { ! 330: panic("%s is not readable or does not exist.", nfile); ! 331: } ! 332: close(fd); ! 333: ! 334: #if 0 ! 335: fprintf(stderr, "Extract symbol information from the kernel %s.\n", nfile); /* DEBUG */ ! 336: #endif /* 0 */ ! 337: /* ! 338: * Extract symbol information from the kernel. ! 339: */ ! 340: if (0 == coffnlist(nfile, nl, "", NUM_SYMS) ) { ! 341: panic("Can not use kernel image %s.", nfile); ! 342: } ! 343: ! 344: if (nl[0].n_type == -1) { ! 345: panic("Bad namelist file %s", nfile); ! 346: } ! 347: ! 348: #if 0 ! 349: fprintf(stderr, "Open the physical memory device.\n"); /* DEBUG */ ! 350: fflush(stderr); ! 351: #endif /* 0 */ ! 352: /* ! 353: * Open the physical memory device. ! 354: */ ! 355: if ((mfd=open(mfile, 0)) < 0) { ! 356: panic("Cannot open %s", mfile); ! 357: } ! 358: ! 359: #if 0 ! 360: fprintf(stderr, "Open the virtual memory device.\n"); /* DEBUG */ ! 361: fflush(stderr); ! 362: #endif /* 0 */ ! 363: /* ! 364: * Open the virtual memory device. ! 365: */ ! 366: if ((kfd = open(kfile, 0)) < 0) { ! 367: panic("Cannot open %s", kfile); ! 368: } ! 369: ! 370: /* ! 371: * Open swap device if it exists ! 372: */ ! 373: dfd = open(dfile, 0); ! 374: ! 375: #if 0 ! 376: fprintf(stderr, "Fetch the head of the process queue.\n"); /* DEBUG */ ! 377: fflush(stderr); ! 378: #endif /* 0 */ ! 379: /* ! 380: * Fetch the head of the process queue. ! 381: */ ! 382: kread((long)aprocq, &cprocq, sizeof (cprocq)); ! 383: ! 384: /* ! 385: * Fetch information about system memory. ! 386: */ ! 387: kread((long)asysmem, &sysmem, sizeof (sysmem)); ! 388: ! 389: ! 390: ! 391: #if 0 ! 392: fprintf(stderr, "Take a snapshot of kernel memory.\n"); /* DEBUG */ ! 393: fflush(stderr); ! 394: #endif /* 0 */ ! 395: /* ! 396: * Take a snapshot of kernel memory. ! 397: */ ! 398: kread((unsigned long)aallocp, &callocp, sizeof (callocp)); ! 399: ! 400: #if 0 ! 401: fprintf(stderr, "callocp.sr_size: %x\n", callocp.sr_size); ! 402: fflush(stderr); ! 403: #endif /* 0 */ ! 404: ! 405: if ((allp=malloc(callocp.sr_size)) == NULL) { ! 406: panic( "Out of core or invalid kernel specified" ); ! 407: } ! 408: ! 409: #if 0 ! 410: fprintf(stderr, "kread(%x, %x, %x)\n", /* DEBUG */ ! 411: (unsigned long)callocp.sr_base, allp, callocp.sr_size); ! 412: fflush(stderr); ! 413: #endif /* 0 */ ! 414: ! 415: kread((unsigned long)callocp.sr_base, allp, callocp.sr_size); ! 416: ! 417: ! 418: #if 0 ! 419: fprintf(stderr, "Fetch the current tick time.\n"); /* DEBUG */ ! 420: fflush(stderr); ! 421: #endif /* 0 */ ! 422: /* ! 423: * Fetch the current tick time. ! 424: */ ! 425: kread((long)autime, &cutime, sizeof (cutime)); ! 426: ! 427: #if 0 ! 428: fprintf(stderr, "Find out what our controlling terminal is.\n"); /* DEBUG */ ! 429: fflush(stderr); ! 430: #endif /* 0 */ ! 431: /* ! 432: * Find out what our controlling terminal is. ! 433: */ ! 434: settdev(); ! 435: ! 436: fttys( "/dev"); /* load all the devices in dev */ ! 437: ! 438: #if 0 ! 439: fprintf(stderr, "Calculate the length of the output line.\n"); /* DEBUG */ ! 440: fflush(stderr); ! 441: #endif /* 0 */ ! 442: /* ! 443: * Calculate the length of the output line. ! 444: */ ! 445: l = strlen("TTY PID"); ! 446: if (dbflag) ! 447: l += strlen("0xffffffff "); ! 448: if (gflag) ! 449: l += strlen(" GROUP"); ! 450: if (lflag) ! 451: l += strlen(" PPID UID K F S EVENT"); ! 452: if (mflag) ! 453: l += strlen(" CVAL SVAL IVAL RVAL"); ! 454: if (tflag) ! 455: l += strlen(" UTIME STIME"); ! 456: if (nflag == 0) { ! 457: if (dbflag) ! 458: printf(" "); ! 459: printf("TTY PID"); ! 460: if (gflag) ! 461: printf(" GROUP"); ! 462: if (lflag) ! 463: printf(" PPID UID K F S EVENT"); ! 464: if (mflag) ! 465: printf(" CVAL SVAL IVAL RVAL"); ! 466: if (tflag) ! 467: printf(" UTIME STIME"); ! 468: putchar('\n'); ! 469: fflush(stdout); ! 470: } ! 471: ! 472: #if 0 ! 473: fprintf(stderr, "Walk through the process queue printing out each entry.\n"); /* DEBUG */ ! 474: fflush(stderr); ! 475: #endif /* 0 */ ! 476: /* ! 477: * Walk through the process queue printing out each entry. ! 478: */ ! 479: loop_count = 0; /* How many PROC entries have we seen? */ ! 480: pp1 = &cprocq; ! 481: while ((pp2=pp1->p_nback) != (PROC *) aprocq) { ! 482: loop_count++; ! 483: ! 484: #if 0 ! 485: fprintf(stderr, "count: %d\n", loop_count); /* DEBUG */ ! 486: fflush(stderr); ! 487: #endif /* 0 */ ! 488: ! 489: if (range((char *)pp2) == 0) ! 490: panic("Fragmented list"); ! 491: pp1 = map(pp2); ! 492: ! 493: /* ! 494: * Kernel process - display only if '-d' argument given. ! 495: */ ! 496: if ( pp1->p_flags & PFKERN ) { ! 497: #if 0 ! 498: fprintf(stderr, "PFKERN\n"); /* DEBUG */ ! 499: fflush(stderr); ! 500: #endif /* 0 */ ! 501: if ( dflag == 0 ) { ! 502: continue; ! 503: } ! 504: } ! 505: ! 506: /* ! 507: * Unattached process - display only if '-x' argument given. ! 508: */ ! 509: else if ( pp1->p_ttdev == NODEV ) { ! 510: #if 0 ! 511: fprintf(stderr, "NODEV\n"); /* DEBUG */ ! 512: fflush(stderr); ! 513: #endif /* 0 */ ! 514: if ( xflag == 0 ) { ! 515: continue; ! 516: } ! 517: } ! 518: ! 519: /* ! 520: * Attached to other terminal - display only if '-a' arg given. ! 521: */ ! 522: else if ( pp1->p_ttdev != ttdev ) { ! 523: #if 0 ! 524: fprintf(stderr, "Other tty\n"); /* DEBUG */ ! 525: fflush(stderr); ! 526: #endif /* 0 */ ! 527: if ( aflag == 0 ) ! 528: continue; ! 529: } ! 530: ! 531: #if 0 ! 532: fprintf(stderr, "ASSERTION: pp1 is a proc entry we want to print.\n"); /* DEBUG */ ! 533: fflush(stderr); ! 534: #endif /* 0 */ ! 535: /* ! 536: * ASSERTION: pp1 is a proc entry we want to print. ! 537: */ ! 538: ! 539: if (dbflag) ! 540: printf("0x%8x ", pp2); ! 541: ptty(pp1); ! 542: printf(" %5d", pp1->p_pid); ! 543: if (gflag) ! 544: printf(" %5d", pp1->p_group); ! 545: if (lflag) { ! 546: printf(" %5d", pp1->p_ppid); ! 547: fflush(stdout); ! 548: printf(" %8.8s", uname(pp1)); ! 549: fflush(stdout); ! 550: psize(pp1); ! 551: fflush(stdout); ! 552: printf(" %4o", pp1->p_flags); ! 553: fflush(stdout); ! 554: printf(" %c", c=state(pp1, pp2)); ! 555: fflush(stdout); ! 556: if (c == 'S') { ! 557: print_event(pp1); ! 558: } else { ! 559: if (fflag) ! 560: printf(" -"); ! 561: else ! 562: printf(" "); ! 563: } ! 564: fflush(stdout); ! 565: } ! 566: if (mflag) { ! 567: printf(" %9u", cval(pp1, pp2)); ! 568: printf(" %9u", pp1->p_sval); ! 569: printf(" %10d", pp1->p_ival); ! 570: printf(" %10d", pp1->p_rval); ! 571: } ! 572: if (tflag) { ! 573: ptime(pp1->p_utime); ! 574: ptime(pp1->p_stime); ! 575: } ! 576: printf(" "); ! 577: printl(pp1, (wflag?132:80)-l-1); ! 578: ! 579: putchar('\n'); ! 580: fflush(stdout); ! 581: } ! 582: rttys(); /* release all alloced space */ ! 583: } ! 584: ! 585: /* ! 586: * Set our terminal device. ! 587: */ ! 588: settdev() ! 589: { ! 590: register PROC *pp1, *pp2; ! 591: register int p; ! 592: int loop_count; ! 593: ! 594: p = getpid(); ! 595: pp1 = &cprocq; ! 596: ! 597: loop_count = 0; /* How many PROC entries have we seen? */ ! 598: while ((pp2=pp1->p_nforw) != (PROC *) aprocq) { ! 599: loop_count++; ! 600: #if 0 ! 601: fprintf(stderr, "settdev() count: %d\n", loop_count); /* DEBUG */ ! 602: fflush(stderr); ! 603: #endif /* 0 */ ! 604: ! 605: #if 0 ! 606: fprintf(stderr, "range():sr_base: %x < %x < sr_base + sr_size: %x\n", ! 607: callocp.sr_base, pp2, callocp.sr_base + callocp.sr_size); /* DEBUG */ ! 608: fflush(stderr); ! 609: #endif /* 0 */ ! 610: if (range((char *)pp2) == 0) ! 611: break; ! 612: ! 613: #if 0 ! 614: fprintf(stderr, "About to map %x\n", pp2); /* DEBUG */ ! 615: fflush(stderr); ! 616: ! 617: fprintf(stderr, "offset = (%x - sr_base) = %x \n", ! 618: pp2, ((char *)pp2) - callocp.sr_base ); /* DEBUG */ ! 619: fflush(stderr); ! 620: fprintf(stderr, "(allp:%x + offset): \n", ! 621: allp, allp + ( ((char *) pp2) - ( (char *) callocp.sr_base) ) ); /* DEBUG */ ! 622: fflush(stderr); ! 623: #endif /* 0 */ ! 624: ! 625: pp1 = map(pp2); ! 626: ! 627: #if 0 ! 628: fprintf(stderr, "mapped %x to %x\n", pp2, pp1); /* DEBUG */ ! 629: fflush(stderr); ! 630: #endif /* 0 */ ! 631: if (pp1->p_pid == p) { ! 632: ttdev = pp1->p_ttdev; ! 633: return; ! 634: } ! 635: } ! 636: ttdev = NODEV; ! 637: } ! 638: ! 639: /* ! 640: * Finds all special files in the specified directory (e.g. /dev) ! 641: */ ! 642: ! 643: fttys( dirname) ! 644: ! 645: char *dirname; ! 646: ! 647: { ! 648: int filein; /* directory file descriptor */ ! 649: struct stat sbuf; /* stat structure */ ! 650: struct direct dbuf; /* directory buffer structure */ ! 651: ! 652: /* move to the appropriate directory and open file for reading */ ! 653: ! 654: chdir( dirname ); ! 655: ! 656: if( ( filein = open( ".", 0) ) < 0 ) { ! 657: fprintf( stderr, "Cannot open '%s' in /dev\n", dirname ); ! 658: exit( 1 ); ! 659: } ! 660: ! 661: read( filein, &dbuf, sizeof(dbuf) ); /* read . */ ! 662: read( filein, &dbuf, sizeof(dbuf) ); /* read .. */ ! 663: ! 664: while( read( filein, &dbuf, sizeof(dbuf) ) ) { ! 665: if( stat( dbuf.d_name, &sbuf ) < 0 ) ! 666: continue; ! 667: ! 668: if( sbuf.st_mode & S_IFCHR ) ! 669: addname( dbuf.d_name, sbuf.st_rdev ); ! 670: ! 671: else if( sbuf.st_mode & S_IFDIR ) ! 672: fttys( dbuf.d_name ); ! 673: } ! 674: ! 675: close( filein ); ! 676: chdir( ".." ); ! 677: } ! 678: ! 679: /* ! 680: * Adds a name and device to the master list of ttys. ! 681: */ ! 682: ! 683: addname( devname, devnum ) ! 684: char *devname; ! 685: dev_t devnum; ! 686: { ! 687: extern struct handle *fptr; ! 688: extern struct handle *lptr; ! 689: ! 690: if( fptr == (struct handle *) NULL ) { ! 691: if( (fptr=(struct handle *) malloc( sizeof(struct handle))) == ! 692: (struct handle *) NULL ) { ! 693: fprintf( stderr, "Out of memory\n"); ! 694: exit( 1 ); ! 695: } ! 696: ! 697: fptr->nptr = (struct handle *) NULL; ! 698: strcpy( fptr->dname, devname); ! 699: fptr->dnum = devnum; ! 700: } ! 701: ! 702: else { ! 703: lptr = fptr; ! 704: ! 705: while( ( lptr->nptr != (struct handle *) NULL ) && ! 706: ( lptr->dnum != devnum ) ) lptr = lptr->nptr; ! 707: ! 708: if( lptr->dnum == devnum ) ! 709: return; ! 710: ! 711: if( (lptr->nptr=(struct handle *)malloc(sizeof(struct handle))) ! 712: == (struct handle *) NULL ) { ! 713: fprintf( stderr, "Out of memory\n"); ! 714: exit( 1 ); ! 715: } ! 716: ! 717: lptr = lptr->nptr; ! 718: lptr->nptr = (struct handle *) NULL; ! 719: strcpy( lptr->dname, devname); ! 720: lptr->dnum = devnum; ! 721: } ! 722: } ! 723: ! 724: /* ! 725: * Release allocated space on exit (default action anyway) ! 726: */ ! 727: ! 728: rttys() ! 729: { ! 730: /* release allocated space */ ! 731: ! 732: lptr = fptr; ! 733: while( lptr->nptr != (struct handle *) NULL ) { ! 734: fptr = lptr; ! 735: lptr = fptr->nptr; ! 736: free( fptr); ! 737: } ! 738: free( lptr); ! 739: } ! 740: ! 741: /* ! 742: * Print the controlling terminal name. If not found it prints the ! 743: * major and minor device numbers. If no controlling terminal on the ! 744: * process then '--------' is printed. ! 745: */ ! 746: ! 747: ptty( pp ) ! 748: register PROC *pp; ! 749: { ! 750: register dev_t d; ! 751: ! 752: /* when supplied with a device number, look for the name ! 753: of the special file from the dev directory */ ! 754: ! 755: if( ((dev_t)( d = pp->p_ttdev )) == NODEV ) { ! 756: printf( "-------"); ! 757: return; ! 758: } ! 759: ! 760: lptr = fptr; ! 761: while( lptr->nptr != (struct handle *) NULL ) { ! 762: if( lptr->dnum == d ) { ! 763: printf( "%-7.7s", lptr->dname); ! 764: return; ! 765: } ! 766: lptr = lptr->nptr; ! 767: } ! 768: if( lptr->dnum == d ) { ! 769: printf( "%-7.7s", lptr->dname); ! 770: return; ! 771: } ! 772: printf( "%3d %3d", major( d ), minor( d ) ); ! 773: return; ! 774: } ! 775: ! 776: /* ! 777: * Given a process, return it's user name. ! 778: */ ! 779: char * ! 780: uname(pp) ! 781: register PROC *pp; ! 782: { ! 783: static char name[8]; ! 784: register struct passwd *pwp; ! 785: ! 786: if ((pwp=getpwuid(pp->p_ruid)) != NULL) ! 787: return (pwp->pw_name); ! 788: sprintf(name, "%d", pp->p_ruid); ! 789: return (name); ! 790: } ! 791: ! 792: /* ! 793: * Return the core value for a process. ! 794: */ ! 795: unsigned ! 796: cval(pp1, pp2) ! 797: register PROC *pp1; ! 798: PROC *pp2; ! 799: { ! 800: unsigned u; ! 801: register PROC *pp3, *pp4; ! 802: ! 803: if (pp1->p_state == PSSLEEP) { ! 804: u = (cutime-pp1->p_lctim) * 1; ! 805: if (pp1->p_cval+u > pp1->p_cval) ! 806: return (pp1->p_cval+u); ! 807: return (-1); ! 808: } ! 809: u = 0; ! 810: pp3 = &cprocq; ! 811: while ((pp4=pp3->p_lforw) != (PROC *) aprocq) { ! 812: if (range((char *)pp4) == 0) ! 813: break; ! 814: pp3 = map(pp4); ! 815: u -= pp3->p_cval; ! 816: if (pp2 == pp4) ! 817: return (u); ! 818: } ! 819: if (pp1->p_pid == getpid()) ! 820: return (pp1->p_cval); ! 821: return (0); ! 822: } /* cval() */ ! 823: ! 824: /* ! 825: * Return the size in K of the given process. ! 826: */ ! 827: psize(pp) ! 828: register PROC *pp; ! 829: { ! 830: long len; ! 831: register SEG *sp; ! 832: register int n; ! 833: ! 834: len = 0; ! 835: for (n=0; n<NUSEG+1; n++) { ! 836: if (rflag == 0) ! 837: if (n==SIUSERP || n==SIAUXIL) ! 838: continue; ! 839: if ((sp=pp->p_segp[n]) == NULL) ! 840: continue; ! 841: if (range((char *)sp) == 0) { ! 842: printf(" ?K"); ! 843: return; ! 844: } ! 845: sp = map(sp); ! 846: len += sp->s_size; ! 847: } ! 848: if (len != 0) ! 849: printf("%4ldK", len/1024); ! 850: else { ! 851: if (fflag) ! 852: printf(" -"); ! 853: else ! 854: printf(" "); ! 855: } ! 856: } ! 857: ! 858: /* ! 859: * Get the state of the process. ! 860: */ ! 861: state(pp1, pp2) ! 862: register PROC *pp1; ! 863: char *pp2; ! 864: { ! 865: register unsigned s; ! 866: ! 867: s = pp1->p_state; ! 868: if (s == PSSLEEP) { ! 869: if (pp1->p_event == pp2) ! 870: return ('W'); ! 871: if ((pp1->p_flags&PFSTOP) != 0) ! 872: return ('T'); ! 873: return ('S'); ! 874: } ! 875: if (s == PSRUN) ! 876: return ('R'); ! 877: if (s == PSDEAD) ! 878: return ('Z'); ! 879: return ('?'); ! 880: } ! 881: ! 882: /* ! 883: * Given a time in HZ, print it out. ! 884: */ ! 885: ptime(l) ! 886: long l; ! 887: { ! 888: register unsigned m; ! 889: ! 890: if ((l=(l+HZ/2)/HZ) == 0) { ! 891: if (fflag) ! 892: printf(" -"); ! 893: else ! 894: printf(" "); ! 895: return; ! 896: } ! 897: if ((m=l/60) >= 100) { ! 898: printf("%6d", m); ! 899: return; ! 900: } ! 901: printf(" %2d:%02d", m, (unsigned)l%60); ! 902: } ! 903: ! 904: /* ! 905: * Print out the reason for a sleep. ! 906: */ ! 907: print_event(pp) ! 908: register PROC *pp; ! 909: { ! 910: /* Only print the u.u_sleep field if it is non-empty. */ ! 911: ! 912: if ( (u_init(pp->p_segp[SIUSERP], &u) != 0) && ! 913: ('\0' != u.u_sleep[0]) ) { ! 914: printf(" %10.10s", u.u_sleep ); ! 915: } else { ! 916: /* Otherwise, print the address we are sleeping on. */ ! 917: printf(" 0x%08X", pp->p_event); ! 918: } ! 919: ! 920: fflush(stdout); ! 921: } /* print_event() */ ! 922: ! 923: /* ! 924: * Print out the command line of a process. ! 925: */ ! 926: printl(pp, m) ! 927: register PROC *pp; ! 928: { ! 929: register char *cp; ! 930: register int c; ! 931: register int argc; ! 932: register int n; ! 933: static SR *srp; ! 934: ! 935: if (pp->p_state == PSDEAD) { ! 936: printf("<zombie>"); ! 937: return; ! 938: } ! 939: if (pp->p_pid == 0) { ! 940: printf("<idle>"); ! 941: return; ! 942: } ! 943: ! 944: if (u_init(pp->p_segp[SIUSERP], &u) == 0) { ! 945: printf("<ghost>"); ! 946: return; ! 947: } ! 948: ! 949: printf(" %.10s", u.u_comm); ! 950: return; ! 951: ! 952: /* ! 953: * Handle kernel processes. ! 954: */ ! 955: if ( pp->p_flags & PFKERN ) { ! 956: printf("<%.*s>",sizeof(u.u_comm), u.u_comm[0] ? u.u_comm : ""); ! 957: return; ! 958: } ! 959: ! 960: if ((argc=u.u_argc) <= 0) ! 961: return; ! 962: ! 963: srp = &u.u_segl[SISTACK]; ! 964: printf("segread 2 in printl\n"); ! 965: printf("u.u_argp: %x, srp->sr_base: %x\n", ! 966: u.u_argp, srp->sr_base); ! 967: printf("u.u_argc: %x srp->sr_size: %x\n", u.u_argc, srp->sr_size); ! 968: ! 969: n = segread(&u.u_segl[SISTACK], u.u_argp, argp, 64); ! 970: ! 971: if (n == 0) { ! 972: fprintf(stderr, "Bad segread()\n"); /* DEBUG */ ! 973: return; ! 974: } ! 975: ! 976: m -= 2; ! 977: cp = argp; ! 978: ! 979: while (argc--) { ! 980: while ((c=*cp++) != '\0') { ! 981: if (!isascii(c) || !isprint(c)) { ! 982: #if 0 /* Blocked out for test purposes. */ ! 983: return; ! 984: #else ! 985: putchar('.'); ! 986: continue; ! 987: #endif /* 0 */ ! 988: } ! 989: if (m-- == 0) ! 990: return; ! 991: putchar(c); ! 992: } ! 993: fflush(stdout); ! 994: #if 0 /* Blocked out for test purposes. */ ! 995: if (m-- == 0) ! 996: return; ! 997: #endif /* 0 */ ! 998: if (argc != 0) ! 999: putchar(' '); ! 1000: } ! 1001: } ! 1002: ! 1003: ! 1004: /* ! 1005: * Given a segment pointer `sp', read a u area into buffer `bp'. ! 1006: */ ! 1007: u_init(sp, bp) ! 1008: SEG *sp; ! 1009: char *bp; ! 1010: { ! 1011: #ifdef UPROC_VERSION ! 1012: /* Have we verrified the uproc version number? */ ! 1013: static version_ok = FALSE; ! 1014: #endif /* UPROC_VERSION */ ! 1015: ! 1016: register SEG *sp1; ! 1017: long offset; ! 1018: ! 1019: #if 0 ! 1020: printf("u_init(sp:%x, bp:%x)\n", sp, bp); ! 1021: fflush(stdout); ! 1022: #endif /* 0 */ ! 1023: ! 1024: if (range((char *)sp) == 0) { ! 1025: return (0); ! 1026: } ! 1027: ! 1028: sp1 = map(sp); ! 1029: ! 1030: /* ! 1031: * Figure out how far into the U segment the U area is. ! 1032: * We do this by subtracting the starting address of the ! 1033: * U area segment from the address of u. ! 1034: */ ! 1035: offset = au - USEG_BASE; ! 1036: ! 1037: /* ! 1038: * If the process is not swapped out, read directly from ! 1039: * main memory. Otherwise, read from the swap device. ! 1040: */ ! 1041: if ((sp1->s_flags&SFCORE) != 0) { ! 1042: if (0 == pt_mread( sp1->s_vmem, offset, bp, sizeof(UPROC) )) { ! 1043: return (0); ! 1044: } ! 1045: } else if ( ! 1046: dread((long)(sp1->s_daddr*BSIZE)+offset, bp, sizeof(UPROC)) < 0 ! 1047: ){ ! 1048: return (0); ! 1049: } ! 1050: ! 1051: #ifdef UPROC_VERSION ! 1052: /* ! 1053: * Check the version number on this U area. ! 1054: * I.e. does this ps match this kernel? ! 1055: */ ! 1056: if ( ((UPROC *) bp)->u_version != UPROC_VERSION ) { ! 1057: /* ! 1058: * Only print the warning if we have not yet seen ! 1059: * a valid version number, and then only once. ! 1060: * ! 1061: * If we have seen at least one valid version number, ! 1062: * it probably means that this process was dying. ! 1063: */ ! 1064: if (!version_ok) { ! 1065: static int printed_once = FALSE; ! 1066: if (!printed_once) { ! 1067: fprintf( stderr, ! 1068: "\nps WARNING: u area version is %x, not %x.\n", ! 1069: ((UPROC *) bp)->u_version, UPROC_VERSION ); ! 1070: printed_once = TRUE; ! 1071: } ! 1072: } ! 1073: return (0); ! 1074: } ! 1075: version_ok = TRUE; /* We've now seen one valid version number. */ ! 1076: #endif /* UPROC_VERSION */ ! 1077: ! 1078: return (1); ! 1079: } ! 1080: ! 1081: ! 1082: /* ! 1083: * Given an open segment pointer `sr' and an offset into the segment, ! 1084: * `s', read `n' bytes from the segment into the buffer `bp'. ! 1085: */ ! 1086: segread(sr, s, bp, n) ! 1087: SR *sr; ! 1088: vaddr_t s; ! 1089: char *bp; ! 1090: int n; ! 1091: { ! 1092: register SEG *sp1; ! 1093: vaddr_t offset; ! 1094: ! 1095: #if 0 ! 1096: printf("segread(sr:%x, s:%x, bp:%x, n:%x)\n", sr, s, bp, n); ! 1097: fflush(stdout); ! 1098: #endif /* 0 */ ! 1099: ! 1100: if (range((char *)sr->sr_segp) == 0) { ! 1101: return (0); ! 1102: } ! 1103: ! 1104: sp1 = map(sr->sr_segp); ! 1105: ! 1106: /* If segment grows up... */ ! 1107: if (0 == (SFDOWN & (sp1->s_flags)) ) { ! 1108: /* then sr_base is the bottom of the segment, */ ! 1109: offset = s - sr->sr_base; ! 1110: } else { ! 1111: /* otherwise sr_base is the top of the segment. */ ! 1112: offset = s - (sr->sr_base - sr->sr_size); ! 1113: } ! 1114: ! 1115: /* ! 1116: * If the process is not swapped out, read directly from ! 1117: * main memory. Otherwise, read from the swap device. ! 1118: */ ! 1119: if ((sp1->s_flags&SFCORE) != 0) { ! 1120: if (0 == pt_mread( sp1->s_vmem, offset, bp, n )) { ! 1121: return (0); ! 1122: } ! 1123: } else if (dread( (long)sp1->s_daddr*BSIZE + s, bp, n ) < 0 ) { ! 1124: return( 0 ); ! 1125: } ! 1126: return (1); ! 1127: } /* segread() */ ! 1128: ! 1129: /* ! 1130: * Read `n' bytes into the buffer `bp' from kernel memory ! 1131: * starting at seek position `s'. ! 1132: */ ! 1133: kread(s, bp, n) ! 1134: long s; ! 1135: char *bp; ! 1136: int n; ! 1137: { ! 1138: lseek(kfd, (long)s, 0); ! 1139: if (read(kfd, bp, n) != n) ! 1140: panic("Kernel memory read error"); ! 1141: } ! 1142: ! 1143: /* ! 1144: * Read `n' bytes into the buffer `bp' from absolute memory ! 1145: * starting at seek position `s'. ! 1146: */ ! 1147: mread(s, bp, n) ! 1148: long s; ! 1149: char *bp; ! 1150: int n; ! 1151: { ! 1152: lseek(mfd, (long)s, 0); ! 1153: if (read(mfd, bp, n) != n) ! 1154: panic("Memory read error"); ! 1155: } ! 1156: ! 1157: /* ! 1158: * Read `n' bytes into the buffer `bp' from the swap file ! 1159: * starting at seek position `s'. ! 1160: */ ! 1161: dread(s, bp, n) ! 1162: long s; ! 1163: char *bp; ! 1164: int n; ! 1165: { ! 1166: /* ! 1167: * If swap device exists go look at it ! 1168: */ ! 1169: if( dfd > 0 ) { ! 1170: lseek(dfd, (long)s, 0); ! 1171: ! 1172: if (read(dfd, bp, n) != n) ! 1173: panic("Swap read error"); ! 1174: ! 1175: return( 1 ); ! 1176: } ! 1177: ! 1178: return( 0 ); ! 1179: } ! 1180: ! 1181: /* ! 1182: * Print out an error message and exit. ! 1183: */ ! 1184: panic(a1) ! 1185: char *a1; ! 1186: { ! 1187: fflush(stdout); ! 1188: sleep(2); ! 1189: ! 1190: fprintf(stderr, "%r", &a1); ! 1191: fprintf(stderr, "\n"); ! 1192: ! 1193: fflush(stderr); ! 1194: exit(1); ! 1195: } ! 1196: ! 1197: /* ! 1198: * Functions to see if a pointer is in alloc space and to map a ! 1199: * pointer from alloc space to this process. ! 1200: */ ! 1201: int ! 1202: range(p) ! 1203: char *p; ! 1204: { ! 1205: return (p>=(char *)(callocp.sr_base) && ! 1206: p<(char*)(callocp.sr_base + callocp.sr_size)); ! 1207: } /* range() */ ! 1208: ! 1209: /* ! 1210: * Read `n' bytes into the buffer `bp' from physical memory ! 1211: * starting at seek position `s', relative to the page table 'table'. ! 1212: * ! 1213: * 'table' is a fraction of a 386 page table. The upper 20 bits of the ! 1214: * adjusted virtual address 's' form an index into the table. The address ! 1215: * 's' must be adjusted so that it is relative to the start of the fractional ! 1216: * table 'table'. 'table' is fractional because COH386 does not store whole ! 1217: * page tables for non-running processes. ! 1218: * ! 1219: * The entries in the table are 32 bits long (called 'pte'). The lowest bit ! 1220: * is the present bit. If this is 0 for ANY of the pages we are asked to ! 1221: * read, we return 0, indicating that we have read nothing. The upper ! 1222: * 20 bits of this entry point in physical memory to a click. The lower ! 1223: * 12 bits of the virtual address 's' are used as an index into this click ! 1224: * to find the desired data. ! 1225: * ! 1226: * All other bits in the page table entry are ignored by this routine. ! 1227: * ! 1228: * Returns 0 on failure, 1 on success. ! 1229: */ ! 1230: ! 1231: int ! 1232: pt_mread(table, s, bp, n) ! 1233: cseg_t *table; /* Page table. */ ! 1234: vaddr_t s; /* Where to start reading. */ ! 1235: char *bp; /* Buffer to copy into. */ ! 1236: int n; /* Number of bytes to read. */ ! 1237: { ! 1238: int to_read; /* Number of bytes to read next. */ ! 1239: vaddr_t page_offset; /* How far into page to start reading. */ ! 1240: cseg_t pt_entry; /* Current entry from Page Table. */ ! 1241: ! 1242: ! 1243: #if 0 ! 1244: printf("pt_mread(table: %x, s: %x, bp: %x, n: %x)\n", table, s, bp, n); ! 1245: fflush(stdout); ! 1246: sleep(1); ! 1247: #endif /* 0 */ ! 1248: ! 1249: pt_entry = pt_index(table, s>>BPCSHIFT); ! 1250: ! 1251: if (!Pflag && !PT_PRESENT(pt_entry)) { ! 1252: #if 0 /* If the page is not present, the proess probably died already. */ ! 1253: static printed_once = FALSE; ! 1254: if (!printed_once) { ! 1255: printf("\npage not present: %x\n", pt_entry); ! 1256: printed_once = TRUE; ! 1257: } ! 1258: #endif /* 0 */ ! 1259: return(0); ! 1260: } ! 1261: pt_entry &= PT_CLICK_ADDR; /* Extract Address of click. */ ! 1262: page_offset = s & CLICK_OFFSET; /* Extract offset into click. */ ! 1263: to_read = LESSER(n, ONE_CLICK - page_offset); /* How far to end of click? */ ! 1264: ! 1265: while (n > 0) { ! 1266: ! 1267: #if 0 ! 1268: printf("pt_mread(): mread(from: %x, to: %x, for: %x))\n", ! 1269: pt_entry+page_offset, bp, to_read); ! 1270: fflush(stdout); ! 1271: sleep(1); ! 1272: #endif /* 0 */ ! 1273: ! 1274: mread(pt_entry+page_offset, bp, to_read); ! 1275: ! 1276: n -= to_read; /* How many left? */ ! 1277: s += to_read; /* From where? */ ! 1278: bp += to_read; /* To where? */ ! 1279: ! 1280: pt_entry = pt_index(table, s>>BPCSHIFT); ! 1281: if (!Pflag && !PT_PRESENT(pt_entry)) { ! 1282: printf("partition not present: %x.\n", pt_entry); ! 1283: return(0); ! 1284: } ! 1285: pt_entry &= PT_CLICK_ADDR; /* Extract Address of click. */ ! 1286: page_offset = s & CLICK_OFFSET; /* Extract offset into click. */ ! 1287: to_read = LESSER(n, ONE_CLICK); ! 1288: } /* while (n > 0) */ ! 1289: ! 1290: return(1); ! 1291: } /* pt_mread() */ ! 1292: ! 1293: cseg_t ! 1294: pt_index(table, index) ! 1295: cseg_t *table; ! 1296: vaddr_t index; ! 1297: { ! 1298: cseg_t pte; /* The page table entry we are looking for. */ ! 1299: ! 1300: #if 0 ! 1301: printf("pt_index(0x%x, 0x%x)\n", table, index); ! 1302: fflush(stdout); ! 1303: sleep(1); ! 1304: #endif /* 0 */ ! 1305: ! 1306: kread(table+index, &pte, sizeof(cseg_t)); ! 1307: ! 1308: return(pte); ! 1309: } /* pt_index() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.