|
|
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.