|
|
1.1 root 1: /*
2: * Modifications copyright INETCO Systems Ltd.
3: *
4: * Print out process statuses.
5: *
6: * $Log: ps.c,v $
7: * Revision 1.3 91/07/17 14:22:55 bin
8: * stevesf supplied as INETCO source because previous sources are of
9: * questionable origin... this one works
10: *
11: * Revision 1.2 89/06/12 15:15:22 src
12: * Bug: A directory at the end of the '/dev' directory would cause 'ps'
13: * to crash with the message "Cannot open <dir> in /dev".
14: * Fix: A stat was being done without the return code being checked. (ART)
15: *
16: * Revision 1.1 89/06/12 14:42:24 src
17: * Initial revision
18: *
19: * 88/02/15 Allan Cornish /usr/src/cmd/cmd/ps.c
20: * Kernel processes are now displayed regardless of -ax flags.
21: *
22: * 87/11/25 Allan Cornish /usr/src/cmd/cmd/ps.c
23: * Debug flag now -D. Drivers now displayed by -d flag.
24: *
25: * 87/11/12 Allan Cornish /usr/src/cmd/cmd/ps.c
26: * Modified to support Coherent 9.0 [protected mode] segmentation.
27: *
28: * 87/10/20 Allan Cornish /usr/src/cmd/cmd/ps.c
29: * Now extracts cmd name from u_comm field in uproc struct for kernel procs.
30: * Kernel processes only displayed if -d [debug] flag given.
31: *
32: * 87/09/28 Phil Selby /usr/src/cmd/cmd/ps.c
33: * Altered so that the terminal name rather than major and minor
34: * device number is printed out
35: *
36: * 84/08/21 Rec
37: * Added gflag for group identification.
38: *
39: * 84/07/16 Lauren Weinstein
40: * Initial version.
41: */
42:
43: #include <stdio.h>
44: #include <ctype.h>
45: #include <sys/const.h>
46: #include <l.out.h>
47: #include <pwd.h>
48: #include <sys/proc.h>
49: #include <sys/sched.h>
50: #include <sys/dir.h>
51: #include <sys/seg.h>
52: #include <sys/stat.h>
53: #include <sys/uproc.h>
54:
55: /*
56: * This is a kludge for the i8086 only and will be
57: * made to disappear when the segmentation (jproto)
58: * is thrown away.
59: */
60: #undef SISTACK
61: #define SISTACK SIPDATA
62:
63: /*
64: * Terminal information stored in memory for use by ps in TTY field
65: */
66:
67: struct handle {
68: dev_t dnum; /* device number */
69: char dname[DIRSIZ]; /* device name */
70: struct handle *nptr; /* pointer to next */
71: } *fptr, *lptr;
72:
73: /*
74: * Maximum sizes.
75: */
76: #define ARGSIZE 512
77:
78: /*
79: * Functions to see if a pointer is in alloc space and to map a
80: * pointer from alloc space to this process.
81: */
82: #define range(p) (p>=(char *)(aend) && p<(char *)(aend)+casize)
83: #define map(p) (&allp[(char *)p - (char *)aend])
84:
85: /*
86: * For easy referencing.
87: */
88: #define aprocq nl[0].n_value
89: #define autime nl[1].n_value
90: #define astime nl[2].n_value
91: #define aasize nl[3].n_value
92: #define aend nl[4].n_value
93:
94: /*
95: * Variables.
96: */
97: int aflag; /* All processes */
98: int dflag; /* Driver flag */
99: int dbflag; /* Debug flag */
100: int fflag; /* Print out all fields */
101: int gflag; /* Print out process groups */
102: int lflag; /* Long format */
103: int mflag; /* Print scheduling values */
104: int nflag; /* No header */
105: int rflag; /* Print out real sizes */
106: int tflag; /* Print times */
107: int wflag; /* Wide format */
108: int xflag; /* Get special processes */
109: dev_t ttdev; /* Terminal device */
110:
111: /*
112: * Table for namelist.
113: */
114: struct nlist nl[] ={
115: "procq_", 0, 0,
116: "utimer_", 0, 0,
117: "stimer_", 0, 0,
118: "asize_", 0, 0,
119: "end_", 0, 0,
120: ""
121: };
122:
123: /*
124: * Symbols.
125: */
126: char *allp; /* Pointer to alloc space */
127: char *kfile; /* Kernel data memory file */
128: char *nfile; /* Namelist file */
129: char *mfile; /* Memory file */
130: char *dfile; /* Swap file */
131: char argp[ARGSIZE]; /* Arguments */
132: int kfd; /* Kernel memory file descriptor */
133: int mfd; /* Memory file descriptor */
134: int dfd; /* Swap file descriptor */
135: struct uproc u; /* User process area */
136: int cutime; /* Unsigned time */
137: PROC cprocq; /* Process queue header */
138: unsigned casize; /* Size of alloc area */
139:
140: main(argc, argv)
141: char *argv[];
142: {
143: register int i;
144: register char *cp;
145:
146: initialise();
147: for (i=1; i<argc; i++) {
148: for (cp=&argv[i][0]; *cp; cp++) {
149: switch (*cp) {
150: case '-':
151: continue;
152: case 'a':
153: aflag++;
154: continue;
155: case 'c':
156: if (++i >= argc)
157: usage();
158: nfile = argv[i];
159: continue;
160: case 'd':
161: dflag++;
162: continue;
163: case 'D':
164: dbflag++;
165: continue;
166: case 'f':
167: fflag++;
168: continue;
169: case 'g':
170: gflag++;
171: continue;
172: case 'k':
173: if (++i >= argc)
174: usage();
175: mfile = argv[i];
176: continue;
177: case 'l':
178: lflag++;
179: continue;
180: case 'm':
181: mflag++;
182: continue;
183: case 'n':
184: nflag++;
185: continue;
186: case 'r':
187: rflag++;
188: continue;
189: case 't':
190: tflag++;
191: continue;
192: case 'w':
193: wflag++;
194: continue;
195: case 'x':
196: xflag++;
197: continue;
198: default:
199: usage();
200: }
201: }
202: }
203: execute();
204: exit(0);
205: }
206:
207: /*
208: * Initialise.
209: */
210: initialise()
211: {
212: register char *cp;
213:
214: aflag = 0;
215: gflag = 0;
216: lflag = 0;
217: mflag = 0;
218: nflag = 0;
219: xflag = 0;
220: nfile = "/coherent";
221: kfile = "/dev/kmem";
222: mfile = "/dev/mem";
223: dfile = "/dev/swap";
224: if ((cp=malloc(BUFSIZ)) != NULL)
225: setbuf(stdout, cp);
226: }
227:
228: /*
229: * Print out usage.
230: */
231: usage()
232: {
233: panic("Usage: ps [-][acdfgklmnrtwx]");
234: }
235:
236: /*
237: * Print out information about processes.
238: */
239: execute()
240: {
241: int c, l;
242: register PROC *pp1, *pp2;
243:
244: nlist(nfile, nl);
245: if (nl[0].n_type == 0)
246: panic("Bad namelist file %s", nfile);
247: if ((mfd=open(mfile, 0)) < 0)
248: panic("Cannot open %s", mfile);
249: if ((kfd = open(kfile, 0)) < 0)
250: panic("Cannot open %s", kfile);
251:
252: /*
253: * Open swap device if it exists
254: */
255: dfd = open(dfile, 0);
256:
257: kread((long)aasize, &casize, sizeof (casize));
258: kread((long)aprocq, &cprocq, sizeof (cprocq));
259:
260: if ((allp=malloc(casize)) == NULL)
261: panic( "Out of core or invalid kernel specified" );
262:
263: kread((long)aend, allp, casize);
264: kread((long)autime, &cutime, sizeof (cutime));
265: settdev();
266: fttys( "/dev"); /* load all the devices in dev */
267: l = 9;
268: if (dbflag)
269: l += 7;
270: if (gflag)
271: l += 6;
272: if (lflag)
273: l += 34;
274: if (mflag)
275: l += 26;
276: if (tflag)
277: l += 12;
278: if (nflag == 0) {
279: if (dbflag)
280: printf(" ");
281: printf("TTY PID");
282: if (gflag)
283: printf(" GROUP");
284: if (lflag)
285: printf(" PPID UID K F S EVENT");
286: if (mflag)
287: printf(" CVAL SVAL IVAL RVAL");
288: if (tflag)
289: printf(" UTIME STIME");
290: putchar('\n');
291: fflush(stdout);
292: }
293: pp1 = &cprocq;
294: while ((pp2=pp1->p_nback) != aprocq) {
295:
296: if (range((char *)pp2) == 0)
297: panic("Fragmented list");
298: pp1 = (PROC *) map(pp2);
299:
300: /*
301: * Kernel process - display only if '-d' argument given.
302: */
303: if ( pp1->p_flags & PFKERN ) {
304: if ( dflag == 0 )
305: continue;
306: }
307:
308: /*
309: * Unattached process - display only if '-x' argument given.
310: */
311: else if ( pp1->p_ttdev == NODEV ) {
312: if ( xflag == 0 )
313: continue;
314: }
315:
316: /*
317: * Attached to other terminal - display only if '-a' arg given.
318: */
319: else if ( pp1->p_ttdev != ttdev ) {
320: if ( aflag == 0 )
321: continue;
322: }
323:
324: if (dbflag)
325: printf("%06o ", pp2);
326: ptty(pp1);
327: printf(" %5d", pp1->p_pid);
328: if (gflag)
329: printf(" %5d", pp1->p_group);
330: if (lflag) {
331: printf(" %5d", pp1->p_ppid);
332: printf(" %8.8s", uname(pp1));
333: psize(pp1);
334: printf(" %4o", pp1->p_flags);
335: printf(" %c", c=state(pp1, pp2));
336: if (c == 'S')
337: printf(" %06o", pp1->p_event);
338: else {
339: if (fflag)
340: printf(" -");
341: else
342: printf(" ");
343: }
344: }
345: if (mflag) {
346: printf(" %5u", cval(pp1, pp2));
347: printf(" %5u", pp1->p_sval);
348: printf(" %6d", pp1->p_ival);
349: printf(" %6d", pp1->p_rval);
350: }
351: if (tflag) {
352: ptime(pp1->p_utime);
353: ptime(pp1->p_stime);
354: }
355: printf(" ");
356: printl(pp1, (wflag?132:80)-l-1);
357: putchar('\n');
358: fflush(stdout);
359: }
360: rttys(); /* release all alloced space */
361: }
362:
363: /*
364: * Set our terminal device.
365: */
366: settdev()
367: {
368: register PROC *pp1, *pp2;
369: register int p;
370:
371: p = getpid();
372: pp1 = &cprocq;
373: while ((pp2=pp1->p_nforw) != aprocq) {
374: if (range((char *)pp2) == 0)
375: break;
376: pp1 = (PROC *) map(pp2);
377: if (pp1->p_pid == p) {
378: ttdev = pp1->p_ttdev;
379: return;
380: }
381: }
382: ttdev = NODEV;
383: }
384:
385: /*
386: * Finds all special file in the specified directory (e.g. /dev)
387: */
388:
389: fttys( dirname)
390:
391: char *dirname;
392:
393: {
394: int filein; /* directory file descriptor */
395: struct stat sbuf; /* stat structure */
396: struct direct dbuf; /* directory buffer structure */
397:
398: /* move to the appropriate directory and open file for reading */
399:
400: chdir( dirname );
401:
402: if( ( filein = open( ".", 0) ) < 0 ) {
403: fprintf( stderr, "Cannot open '%s' in /dev\n", dirname );
404: exit( 1 );
405: }
406:
407: read( filein, &dbuf, sizeof(dbuf) ); /* read . */
408: read( filein, &dbuf, sizeof(dbuf) ); /* read .. */
409:
410: while( read( filein, &dbuf, sizeof(dbuf) ) ) {
411: if( stat( dbuf.d_name, &sbuf ) < 0 )
412: continue;
413:
414: if( sbuf.st_mode & S_IFCHR )
415: addname( dbuf.d_name, sbuf.st_rdev );
416:
417: else if( sbuf.st_mode & S_IFDIR )
418: fttys( dbuf.d_name );
419: }
420:
421: close( filein );
422: chdir( ".." );
423: }
424:
425: /*
426: * Adds a name and and device number of type handle
427: */
428:
429: addname( devname, devnum )
430:
431: char *devname;
432: dev_t devnum;
433:
434: {
435: extern struct handle *fptr;
436: extern struct handle *lptr;
437:
438: if( fptr == (struct handle *) NULL ) {
439: if( (fptr=(struct handle *) malloc( sizeof(struct handle))) ==
440: (struct handle *) NULL ) {
441: fprintf( stderr, "Out of memory\n");
442: exit( 1 );
443: }
444:
445: fptr->nptr = (struct handle *) NULL;
446: strcpy( fptr->dname, devname);
447: fptr->dnum = devnum;
448: }
449:
450: else {
451: lptr = fptr;
452:
453: while( ( lptr->nptr != (struct handle *) NULL ) &&
454: ( lptr->dnum != devnum ) ) lptr = lptr->nptr;
455:
456: if( lptr->dnum == devnum )
457: return;
458:
459: if( (lptr->nptr=(struct handle *)malloc(sizeof(struct handle)))
460: == (struct handle *) NULL ) {
461: fprintf( stderr, "Out of memory\n");
462: exit( 1 );
463: }
464:
465: lptr = lptr->nptr;
466: lptr->nptr = (struct handle *) NULL;
467: strcpy( lptr->dname, devname);
468: lptr->dnum = devnum;
469: }
470: }
471:
472: /*
473: * Release allocated space on exit (default action anyway)
474: */
475:
476: rttys()
477: {
478: /* release allocated space */
479:
480: lptr = fptr;
481: while( lptr->nptr != (struct handle *) NULL ) {
482: fptr = lptr;
483: lptr = fptr->nptr;
484: free( fptr);
485: }
486: free( lptr);
487: }
488:
489: /*
490: * Print the controlling terminal name. If not found it prints the
491: * major and minor device numbers. If no controlling terminal on the
492: * process than '--------' is printed.
493: */
494:
495: ptty( pp )
496: register PROC *pp;
497: {
498: register int d;
499:
500: /* when supplied with a device number, look for the name
501: of the special file from the dev directory */
502:
503: if( ( d = pp->p_ttdev ) == NODEV ) {
504: printf( "-------");
505: return;
506: }
507:
508: lptr = fptr;
509: while( lptr->nptr != (struct handle *) NULL ) {
510: if( lptr->dnum == d ) {
511: printf( "%-7.7s", lptr->dname);
512: return;
513: }
514: lptr = lptr->nptr;
515: }
516: if( lptr->dnum == d ) {
517: printf( "%-7.7s", lptr->dname);
518: return;
519: }
520: printf( "%3d %3d", major( d ), minor( d ) );
521: return;
522: }
523:
524: /*
525: * Given a process, return it's user name.
526: */
527: uname(pp)
528: register PROC *pp;
529: {
530: static char name[8];
531: register struct passwd *pwp;
532:
533: if ((pwp=getpwuid(pp->p_ruid)) != NULL)
534: return (pwp->pw_name);
535: sprintf(name, "%d", pp->p_ruid);
536: return (name);
537: }
538:
539: /*
540: * Return the core value for a process.
541: */
542: cval(pp1, pp2)
543: register PROC *pp1;
544: {
545: unsigned u;
546: register PROC *pp3, *pp4;
547:
548: if (pp1->p_state == PSSLEEP) {
549: u = (cutime-pp1->p_lctim) * 1;
550: if (pp1->p_cval+u > pp1->p_cval)
551: return (pp1->p_cval+u);
552: return (-1);
553: }
554: u = 0;
555: pp3 = &cprocq;
556: while ((pp4=pp3->p_lforw) != aprocq) {
557: if (range((char *)pp4) == 0)
558: break;
559: pp3 = (PROC *) map(pp4);
560: u -= pp3->p_cval;
561: if (pp2 == pp4)
562: return (u);
563: }
564: if (pp1->p_pid == getpid())
565: return (pp1->p_cval);
566: return (0);
567: }
568:
569: /*
570: * Return the size in K of the given process.
571: */
572: psize(pp)
573: register PROC *pp;
574: {
575: long l;
576: register SEG *sp;
577: register int n;
578:
579: l = 0;
580: for (n=0; n<NUSEG+1; n++) {
581: if (rflag == 0)
582: if (n==SIUSERP || n==SIAUXIL)
583: continue;
584: if ((sp=pp->p_segp[n]) == NULL)
585: continue;
586: if (range((char *)sp) == 0) {
587: printf(" ?K");
588: return;
589: }
590: sp = (SEG *) map(sp);
591: l += sp->s_size;
592: }
593: if (l != 0)
594: printf("%4ldK", l/1024);
595: else {
596: if (fflag)
597: printf(" -");
598: else
599: printf(" ");
600: }
601: }
602:
603: /*
604: * Get the state of the process.
605: */
606: state(pp1, pp2)
607: register PROC *pp1;
608: {
609: register int s;
610:
611: s = pp1->p_state;
612: if (s == PSSLEEP) {
613: if (pp1->p_event == pp2)
614: return ('W');
615: if ((pp1->p_flags&PFSTOP) != 0)
616: return ('T');
617: return ('S');
618: }
619: if (s == PSRUN)
620: return ('R');
621: if (s == PSDEAD)
622: return ('Z');
623: return ('?');
624: }
625:
626: /*
627: * Given a time in HZ, print it out.
628: */
629: ptime(l)
630: long l;
631: {
632: register unsigned m;
633:
634: if ((l=(l+HZ/2)/HZ) == 0) {
635: if (fflag)
636: printf(" -");
637: else
638: printf(" ");
639: return;
640: }
641: if ((m=l/60) >= 100) {
642: printf("%6d", m);
643: return;
644: }
645: printf(" %2d:%02d", m, (unsigned)l%60);
646: }
647:
648: /*
649: * Print out the command line of a process.
650: */
651: printl(pp, m)
652: register PROC *pp;
653: {
654: register char *cp;
655: register int c;
656: register int argc;
657: register int n;
658:
659: if (pp->p_state == PSDEAD)
660: return;
661: if (pp->p_pid == 0) {
662: printf("<idle>");
663: return;
664: }
665: if (segread(pp->p_segp[SIUSERP], 0, &u, sizeof (u)) == 0)
666: return;
667:
668: /*
669: * Handle kernel processes.
670: */
671: if ( pp->p_flags & PFKERN ) {
672: printf("<%.*s>",sizeof(u.u_comm), u.u_comm[0] ? u.u_comm : "");
673: return;
674: }
675:
676: n = segread(pp->p_segp[SISTACK], (u.u_argp-u.u_segl[SISTACK].sr_base),
677: argp, sizeof (argp));
678:
679: if (n == 0)
680: return;
681:
682: if ((argc=u.u_argc) <= 0)
683: return;
684:
685: m -= 2;
686: cp = argp;
687:
688: while (argc--) {
689: while ((c=*cp++) != '\0') {
690: if (!isascii(c) || !isprint(c))
691: return;
692: if (m-- == 0)
693: return;
694: putchar(c);
695: }
696: if (m-- == 0)
697: return;
698: if (argc != 0)
699: putchar(' ');
700: }
701: }
702:
703: /*
704: * Given a segment pointer `sp' and an offset into the segment,
705: * `s', read `n' bytes from the segment into the buffer `bp'.
706: */
707: segread(sp, s, bp, n)
708:
709: SEG *sp;
710: vaddr_t s;
711: char *bp;
712:
713: {
714: register SEG *sp1;
715:
716: if (range((char *)sp) == 0)
717: return (0);
718:
719: sp1 = (SEG *) map(sp);
720:
721: if ((sp1->s_flags&SFCORE) != 0)
722: mread( sp1->s_paddr + s, bp, n );
723:
724: else
725: if( dread( (long)sp1->s_daddr*BSIZE + s, bp, n ) < 0 )
726: return( 0 );
727:
728: return (1);
729: }
730:
731: /*
732: * Read `n' bytes into the buffer `bp' from kernel memory
733: * starting at seek position `s'.
734: */
735: kread(s, bp, n)
736: long s;
737: {
738: lseek(kfd, (long)s, 0);
739: if (read(kfd, bp, n) != n)
740: panic("Kernel memory read error");
741: }
742:
743: /*
744: * Read `n' bytes into the buffer `bp' from absolute memory
745: * starting at seek position `s'.
746: */
747: mread(s, bp, n)
748: long s;
749: {
750: lseek(mfd, (long)s, 0);
751: if (read(mfd, bp, n) != n)
752: panic("Memory read error");
753: }
754:
755: /*
756: * Read `n' bytes into the buffer `bp' from the swap file
757: * starting at seek position `s'.
758: */
759: dread(s, bp, n)
760: long s;
761: {
762: /*
763: * If swap device exists go look at it
764: */
765: if( dfd > 0 ) {
766: lseek(dfd, (long)s, 0);
767:
768: if (read(dfd, bp, n) != n)
769: panic("Swap read error");
770:
771: return( 1 );
772: }
773:
774: return( 0 );
775: }
776:
777: /*
778: * Print out an error message and exit.
779: */
780: panic(a1)
781: char *a1;
782: {
783: fflush(stdout);
784: fprintf(stderr, "%r", &a1);
785: fprintf(stderr, "\n");
786: exit(1);
787: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.