|
|
1.1 root 1: static char *sccsid = "@(#)sa.c 4.1 (Berkeley) 10/1/80";
2: #include <stdio.h>
3: #include <sys/types.h>
4: #include <sys/acct.h>
5: #include <signal.h>
6:
7: /* interpret command time accounting */
8:
9: #define size 2500
10: #define NC sizeof(acctbuf.ac_comm)
11: struct acct acctbuf;
12: int lflg;
13: int cflg;
14: int Dflg;
15: int dflg;
16: int iflg;
17: int jflg;
18: int Kflg;
19: int kflg;
20: int nflg;
21: int aflg;
22: int rflg;
23: int oflg;
24: int tflg;
25: int vflg;
26: int uflg;
27: int thres = 1;
28: int sflg;
29: int bflg;
30: int mflg;
31:
32: struct user {
33: int us_cnt;
34: double us_ctime;
35: double us_io;
36: double us_imem;
37: } user[1000];
38:
39: struct tab {
40: char name[NC];
41: int count;
42: double realt;
43: double cput;
44: double syst;
45: double imem;
46: double io;
47: } tab[size];
48:
49: double treal;
50: double tcpu;
51: double tsys;
52: double tio;
53: double timem;
54: int junkp = -1;
55: char *sname;
56: double ncom;
57: time_t expand();
58: char *getname();
59:
60: main(argc, argv)
61: char **argv;
62: {
63: FILE *ff;
64: int i, j, k;
65: int (*cmp)();
66: extern tcmp(), ncmp(), bcmp(), dcmp(), Dcmp(), kcmp(), Kcmp();
67: extern double sum();
68: double ft;
69:
70: cmp = tcmp;
71: if (argc>1)
72: if (argv[1][0]=='-') {
73: argv++;
74: argc--;
75: for(i=1; argv[0][i]; i++)
76: switch(argv[0][i]) {
77:
78: case 'o':
79: oflg++;
80: break;
81:
82: case 'i':
83: iflg++;
84: break;
85:
86: case 'b':
87: bflg++;
88: cmp = bcmp;
89: break;
90:
91: case 'l':
92: lflg++;
93: break;
94:
95: case 'c':
96: cflg++;
97: break;
98:
99: case 'd':
100: dflg++;
101: cmp = dcmp;
102: break;
103:
104: case 'D':
105: Dflg++;
106: cmp = Dcmp;
107: break;
108:
109: case 'j':
110: jflg++;
111: break;
112:
113: case 'k':
114: kflg++;
115: cmp = kcmp;
116: break;
117:
118: case 'K':
119: Kflg++;
120: cmp = Kcmp;
121: break;
122:
123: case 'n':
124: nflg++;
125: cmp = ncmp;
126: break;
127:
128: case 'a':
129: aflg++;
130: break;
131:
132: case 'r':
133: rflg++;
134: break;
135:
136: case 't':
137: tflg++;
138: break;
139:
140: case 's':
141: sflg++;
142: aflg++;
143: break;
144:
145: case '0':
146: case '1':
147: case '2':
148: case '3':
149: case '4':
150: case '5':
151: case '6':
152: case '7':
153: case '8':
154: case '9':
155: thres = argv[0][i]-'0';
156: break;
157:
158: case 'v':
159: vflg++;
160: break;
161:
162: case 'u':
163: uflg++;
164: break;
165:
166: case 'm':
167: mflg++;
168: break;
169: }
170: }
171: if (iflg==0)
172: init();
173: if (argc<2)
174: doacct("/usr/adm/acct");
175: else while (--argc)
176: doacct(*++argv);
177: if (uflg) {
178: return;
179: }
180:
181: /*
182: * cleanup pass
183: * put junk together
184: */
185:
186: if (vflg)
187: strip();
188: if(!aflg)
189: for (i=0; i<size; i++)
190: if (tab[i].name[0]) {
191: for(j=0; j<NC; j++)
192: if(tab[i].name[j] == '?')
193: goto yes;
194: if(tab[i].count != 1)
195: continue;
196: yes:
197: if(junkp == -1)
198: junkp = enter("***other");
199: tab[junkp].count += tab[i].count;
200: tab[junkp].realt += tab[i].realt;
201: tab[junkp].cput += tab[i].cput;
202: tab[junkp].syst += tab[i].syst;
203: tab[junkp].imem += tab[i].imem;
204: tab[junkp].io += tab[i].io;
205: tab[i].name[0] = 0;
206: }
207: for(i=k=0; i<size; i++)
208: if(tab[i].name[0]) {
209: tab[k] = tab[i];
210: k++;
211: }
212: if (sflg) {
213: signal(SIGINT, SIG_IGN);
214: if ((ff = fopen("/usr/adm/usracct", "w")) != NULL) {
215: fwrite((char *)user, sizeof(user), 1, ff);
216: fclose(ff);
217: }
218: if ((ff = fopen("/usr/adm/savacct", "w")) == NULL) {
219: printf("Can't save\n");
220: exit(0);
221: }
222: fwrite((char *)tab, sizeof(tab[0]), k, ff);
223: fclose(ff);
224: creat("/usr/adm/acct", 0644);
225: signal(SIGINT, SIG_DFL);
226: }
227: /*
228: * sort and print
229: */
230:
231: if (mflg) {
232: printmoney();
233: exit(0);
234: }
235: qsort(tab, k, sizeof(tab[0]), cmp);
236: column(ncom, treal, tcpu, tsys, timem, tio);
237: printf("\n");
238: for (i=0; i<k; i++)
239: if (tab[i].name[0]) {
240: ft = tab[i].count;
241: column(ft, tab[i].realt, tab[i].cput, tab[i].syst, tab[i].imem, tab[i].io);
242: printf(" %.14s\n", tab[i].name);
243: }
244: }
245:
246: printmoney()
247: {
248: register i;
249: char buf[128];
250: register char *cp;
251:
252: for (i=0; i<sizeof(user)/sizeof(user[0]); i++) {
253: if (user[i].us_cnt && user[i].us_ctime) {
254: cp = getname(i);
255: if (cp == 0)
256: printf("%-8d", i);
257: else
258: printf("%-8s", cp);
259: printf("%7u %9.2fcpu %10.0ftio %12.0fk*sec\n",
260: user[i].us_cnt, user[i].us_ctime/60,
261: user[i].us_io,
262: user[i].us_imem / (60 * 2));
263: }
264: }
265: }
266:
267: column(n, a, b, c, d, e)
268: double n, a, b, c, d, e;
269: {
270:
271: printf("%8.0f", n);
272: if(cflg) {
273: if(n == ncom)
274: printf("%9s", ""); else
275: printf("%8.2f%%", 100.*n/ncom);
276: }
277: col(n, a, treal, "re");
278: if (oflg)
279: col(n, 3600*(b/(b+c)), tcpu+tsys, "u/s");
280: else if(lflg) {
281: col(n, b, tcpu, "u");
282: col(n, c, tsys, "s");
283: } else
284: col(n, b+c, tcpu+tsys, "cp");
285: if(tflg)
286: printf("%8.1f", a/(b+c), "re/cp");
287: if(dflg || !Dflg)
288: printf("%10.0favio", e/(n?n:1));
289: else
290: printf("%10.0ftio", e);
291: if (kflg || !Kflg)
292: printf("%10.0fk", d/(2*((b+c)!=0.0?(b+c):1.0)));
293: else
294: printf("%10.0fk*sec", d/(2*60));
295: }
296:
297: col(n, a, m, cp)
298: double n, a, m;
299: char *cp;
300: {
301:
302: if(jflg)
303: printf("%11.2f%s", a/(n*60.), cp); else
304: printf("%11.2f%s", a/3600., cp);
305: if(cflg) {
306: if(a == m)
307: printf("%9s", ""); else
308: printf("%8.2f%%", 100.*a/m);
309: }
310: }
311:
312: doacct(f)
313: char *f;
314: {
315: int i;
316: FILE *ff;
317: long x, y, z;
318: struct acct fbuf;
319: register char *cp;
320: register int c;
321:
322: if (sflg && sname) {
323: printf("Only 1 file with -s\n");
324: exit(0);
325: }
326: if (sflg)
327: sname = f;
328: if ((ff = fopen(f, "r"))==NULL) {
329: printf("Can't open %s\n", f);
330: return;
331: }
332: while (fread((char *)&fbuf, sizeof(fbuf), 1, ff) == 1) {
333: if (fbuf.ac_comm[0]==0) {
334: fbuf.ac_comm[0] = '?';
335: }
336: for (cp = fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++) {
337: c = *cp & 0377;
338: if (c && (c < ' ' || c >= 0200)) {
339: *cp = '?';
340: }
341: }
342: if (fbuf.ac_flag&AFORK) {
343: for (cp=fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++)
344: if (*cp==0) {
345: *cp = '*';
346: break;
347: }
348: }
349: x = expand(fbuf.ac_utime) + expand(fbuf.ac_stime);
350: y = fbuf.ac_mem;
351: z = expand(fbuf.ac_io);
352: if (uflg) {
353: printf("%3d%6.1fcp %6dmem %6dio %.14s\n",
354: fbuf.ac_uid, x/60.0, y, z,
355: fbuf.ac_comm);
356: continue;
357: }
358: c = fbuf.ac_uid;
359: user[c].us_cnt++;
360: user[c].us_ctime += x/60.;
361: user[c].us_imem += x * y;
362: user[c].us_io += z;
363: ncom += 1.0;
364: i = enter(fbuf.ac_comm);
365: tab[i].imem += x * y;
366: timem += x * y;
367: tab[i].count++;
368: x = expand(fbuf.ac_etime)*60;
369: tab[i].realt += x;
370: treal += x;
371: x = expand(fbuf.ac_utime);
372: tab[i].cput += x;
373: tcpu += x;
374: x = expand(fbuf.ac_stime);
375: tab[i].syst += x;
376: tsys += x;
377: tab[i].io += z;
378: tio += z;
379: }
380: fclose(ff);
381: }
382:
383: ncmp(p1, p2)
384: struct tab *p1, *p2;
385: {
386:
387: if(p1->count == p2->count)
388: return(tcmp(p1, p2));
389: if(rflg)
390: return(p1->count - p2->count);
391: return(p2->count - p1->count);
392: }
393:
394: bcmp(p1, p2)
395: struct tab *p1, *p2;
396: {
397: double f1, f2;
398: double sum();
399:
400: f1 = sum(p1)/p1->count;
401: f2 = sum(p2)/p2->count;
402: if(f1 < f2) {
403: if(rflg)
404: return(-1);
405: return(1);
406: }
407: if(f1 > f2) {
408: if(rflg)
409: return(1);
410: return(-1);
411: }
412: return(0);
413: }
414:
415: Kcmp(p1, p2)
416: struct tab *p1, *p2;
417: {
418:
419: if (p1->imem < p2->imem) {
420: if(rflg)
421: return(-1);
422: return(1);
423: }
424: if (p1->imem > p2->imem) {
425: if(rflg)
426: return(1);
427: return(-1);
428: }
429: return(0);
430: }
431:
432: kcmp(p1, p2)
433: struct tab *p1, *p2;
434: {
435: double a1, a2;
436:
437: a1 = p1->imem / ((p1->cput+p1->syst)?(p1->cput+p1->syst):1);
438: a2 = p2->imem / ((p2->cput+p2->syst)?(p2->cput+p2->syst):1);
439: if (a1 < a2) {
440: if(rflg)
441: return(-1);
442: return(1);
443: }
444: if (a1 > a2) {
445: if(rflg)
446: return(1);
447: return(-1);
448: }
449: return(0);
450: }
451:
452: dcmp(p1, p2)
453: struct tab *p1, *p2;
454: {
455: double a1, a2;
456:
457: a1 = p1->io / (p1->count?p1->count:1);
458: a2 = p2->io / (p2->count?p2->count:1);
459: if (a1 < a2) {
460: if(rflg)
461: return(-1);
462: return(1);
463: }
464: if (a1 > a2) {
465: if(rflg)
466: return(1);
467: return(-1);
468: }
469: return(0);
470: }
471:
472: Dcmp(p1, p2)
473: struct tab *p1, *p2;
474: {
475:
476: if (p1->io < p2->io) {
477: if(rflg)
478: return(-1);
479: return(1);
480: }
481: if (p1->io > p2->io) {
482: if(rflg)
483: return(1);
484: return(-1);
485: }
486: return(0);
487: }
488:
489: tcmp(p1, p2)
490: struct tab *p1, *p2;
491: {
492: extern double sum();
493: double f1, f2;
494:
495: f1 = sum(p1);
496: f2 = sum(p2);
497: if(f1 < f2) {
498: if(rflg)
499: return(-1);
500: return(1);
501: }
502: if(f1 > f2) {
503: if(rflg)
504: return(1);
505: return(-1);
506: }
507: return(0);
508: }
509:
510: double sum(p)
511: struct tab *p;
512: {
513:
514: if(p->name[0] == 0)
515: return(0.0);
516: return(
517: p->cput+
518: p->syst);
519: }
520:
521: init()
522: {
523: struct tab tbuf;
524: int i;
525: FILE *f;
526:
527: if ((f = fopen("/usr/adm/savacct", "r")) == NULL)
528: goto gshm;
529: while (fread((char *)&tbuf, sizeof(tbuf), 1, f) == 1) {
530: i = enter(tbuf.name);
531: ncom += tbuf.count;
532: tab[i].count = tbuf.count;
533: treal += tbuf.realt;
534: tab[i].realt = tbuf.realt;
535: tcpu += tbuf.cput;
536: tab[i].cput = tbuf.cput;
537: tsys += tbuf.syst;
538: tab[i].syst = tbuf.syst;
539: tio += tbuf.io;
540: tab[i].io = tbuf.io;
541: timem += tbuf.imem;
542: tab[i].imem = tbuf.imem;
543: }
544: fclose(f);
545: gshm:
546: if ((f = fopen("/usr/adm/usracct", "r")) == NULL)
547: return;
548: fread((char *)user, sizeof(user), 1, f);
549: fclose(f);
550: }
551:
552: enter(np)
553: char *np;
554: {
555: int i, j;
556:
557: for (i=j=0; i<NC; i++) {
558: if (np[i]==0)
559: j = i;
560: if (j)
561: np[i] = 0;
562: }
563: for (i=j=0; j<NC; j++) {
564: i = i*7 + np[j];
565: }
566: if (i < 0)
567: i = -i;
568: for (i%=size; tab[i].name[0]; i = (i+1)%size) {
569: for (j=0; j<NC; j++)
570: if (tab[i].name[j]!=np[j])
571: goto no;
572: goto yes;
573: no:;
574: }
575: for (j=0; j<NC; j++)
576: tab[i].name[j] = np[j];
577: yes:
578: return(i);
579: }
580:
581: strip()
582: {
583: int i, j, c;
584:
585: j = enter("**junk**");
586: for (i = 0; i<size; i++) {
587: if (tab[i].name[0] && tab[i].count<=thres) {
588: printf("%.14s--", tab[i].name);
589: if ((c=getchar())=='y') {
590: tab[i].name[0] = '\0';
591: tab[j].count += tab[i].count;
592: tab[j].realt += tab[i].realt;
593: tab[j].cput += tab[i].cput;
594: tab[j].syst += tab[i].syst;
595: }
596: while (c && c!='\n')
597: c = getchar();
598: }
599: }
600: }
601:
602: time_t
603: expand(t)
604: unsigned t;
605: {
606: register time_t nt;
607:
608: nt = t&017777;
609: t >>= 13;
610: while (t!=0) {
611: t--;
612: nt <<= 3;
613: }
614: return(nt);
615: }
616:
617: #include <utmp.h>
618: #include <pwd.h>
619:
620: struct utmp utmp;
621: #define NMAX sizeof (utmp.ut_name)
622: #define NUID 2048
623:
624: char names[NUID][NMAX+1];
625:
626: char *
627: getname(uid)
628: {
629: register struct passwd *pw;
630: static init;
631: struct passwd *getpwent();
632:
633: if (names[uid][0])
634: return (&names[uid][0]);
635: if (init == 2)
636: return (0);
637: if (init == 0)
638: setpwent(), init = 1;
639: while (pw = getpwent()) {
640: if (pw->pw_uid >= NUID)
641: continue;
642: if (names[pw->pw_uid][0])
643: continue;
644: strncpy(names[pw->pw_uid], pw->pw_name, NMAX);
645: if (pw->pw_uid == uid)
646: return (&names[uid][0]);
647: }
648: init = 2;
649: endpwent();
650: return (0);
651: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.