Bell 32V development
[unix-history] / usr / src / cmd / sa.c
CommitLineData
3b600ead
TL
1#include <stdio.h>
2#include <sys/types.h>
3#include <sys/acct.h>
4#include <signal.h>
5
6/* interpret command time accounting */
7
8#define size 1000
9#define NC sizeof(acctbuf.ac_comm)
10struct acct acctbuf;
11int lflg;
12int cflg;
13int iflg;
14int jflg;
15int nflg;
16int aflg;
17int rflg;
18int oflg;
19int tflg;
20int vflg;
21int uflg;
22int thres = 1;
23int sflg;
24int bflg;
25int mflg;
26
27struct user {
28 int ncomm;
29 int fill;
30 float fctime;
31} user[256];
32
33struct tab {
34 char name[NC];
35 int count;
36 float realt;
37 float cput;
38 float syst;
39} tab[size];
40
41float treal;
42float tcpu;
43float tsys;
44int junkp = -1;
45char *sname;
46float ncom;
47time_t expand();
48
49main(argc, argv)
50char **argv;
51{
52 FILE *ff;
53 int i, j, k;
54 extern tcmp(), ncmp(), bcmp();
55 extern float sum();
56 float ft;
57
58 if (argc>1)
59 if (argv[1][0]=='-') {
60 argv++;
61 argc--;
62 for(i=1; argv[0][i]; i++)
63 switch(argv[0][i]) {
64
65 case 'o':
66 oflg++;
67 break;
68
69 case 'i':
70 iflg++;
71 break;
72
73 case 'b':
74 bflg++;
75 break;
76
77 case 'l':
78 lflg++;
79 break;
80
81 case 'c':
82 cflg++;
83 break;
84
85 case 'j':
86 jflg++;
87 break;
88
89 case 'n':
90 nflg++;
91 break;
92
93 case 'a':
94 aflg++;
95 break;
96
97 case 'r':
98 rflg++;
99 break;
100
101 case 't':
102 tflg++;
103 break;
104
105 case 's':
106 sflg++;
107 aflg++;
108 break;
109
110 case '0':
111 case '1':
112 case '2':
113 case '3':
114 case '4':
115 case '5':
116 case '6':
117 case '7':
118 case '8':
119 case '9':
120 thres = argv[0][i]-'0';
121 break;
122
123 case 'v':
124 vflg++;
125 break;
126
127 case 'u':
128 uflg++;
129 break;
130
131 case 'm':
132 mflg++;
133 break;
134 }
135 }
136 if (iflg==0)
137 init();
138 if (argc<2)
139 doacct("/usr/adm/acct");
140 else while (--argc)
141 doacct(*++argv);
142 if (uflg) {
143 return;
144 }
145
146/*
147 * cleanup pass
148 * put junk together
149 */
150
151 if (vflg)
152 strip();
153 if(!aflg)
154 for (i=0; i<size; i++)
155 if (tab[i].name[0]) {
156 for(j=0; j<NC; j++)
157 if(tab[i].name[j] == '?')
158 goto yes;
159 if(tab[i].count != 1)
160 continue;
161 yes:
162 if(junkp == -1)
163 junkp = enter("***other");
164 tab[junkp].count += tab[i].count;
165 tab[junkp].realt += tab[i].realt;
166 tab[junkp].cput += tab[i].cput;
167 tab[junkp].syst += tab[i].syst;
168 tab[i].name[0] = 0;
169 }
170 for(i=k=0; i<size; i++)
171 if(tab[i].name[0]) {
172 for(j=0; j<NC; j++)
173 tab[k].name[j] = tab[i].name[j];
174 tab[k].count = tab[i].count;
175 tab[k].realt = tab[i].realt;
176 tab[k].cput = tab[i].cput;
177 tab[k].syst = tab[i].syst;
178 k++;
179 }
180 if (sflg) {
181 signal(SIGINT, SIG_IGN);
182 if ((ff = fopen("/usr/adm/usracct", "w")) != NULL) {
183 fwrite((char *)user, sizeof(user), 1, ff);
184 fclose(ff);
185 }
186 if ((ff = fopen("/usr/adm/savacct", "w")) == NULL) {
187 printf("Can't save\n");
188 exit(0);
189 }
190 fwrite((char *)tab, sizeof(tab[0]), k, ff);
191 fclose(ff);
192 signal(SIGINT, SIG_DFL);
193 }
194/*
195 * sort and print
196 */
197
198 if (mflg) {
199 printmoney();
200 exit(0);
201 }
202 qsort(tab, k, sizeof(tab[0]), nflg? ncmp: (bflg?bcmp:tcmp));
203 column(ncom, treal, tcpu, tsys);
204 printf("\n");
205 for (i=0; i<k; i++)
206 if (tab[i].name[0]) {
207 ft = tab[i].count;
208 column(ft, tab[i].realt, tab[i].cput, tab[i].syst);
209 printf(" %.14s\n", tab[i].name);
210 }
211}
212
213printmoney()
214{
215 register i;
216 char buf[128];
217 register char *cp;
218
219 for (i=0; i<256; i++) {
220 if (user[i].ncomm) {
221 if (getpw(i, buf)!=0)
222 printf("%-8d", i);
223 else {
224 cp = buf;
225 while (*cp!=':' &&*cp!='\n' && *cp)
226 cp++;
227 *cp = 0;
228 printf("%-8s", buf);
229 }
230 printf("%5u %7.2f\n",
231 user[i].ncomm, user[i].fctime/60);
232 }
233 }
234}
235
236column(n, a, b, c)
237double n, a, b, c;
238{
239
240 printf("%6.0f", n);
241 if(cflg) {
242 if(n == ncom)
243 printf("%7s", ""); else
244 printf("%6.2f%%", 100.*n/ncom);
245 }
246 col(n, a, treal);
247 if (oflg)
248 col(n, 3600*(b/(b+c)), tcpu+tsys);
249 else if(lflg) {
250 col(n, b, tcpu);
251 col(n, c, tsys);
252 } else
253 col(n, b+c, tcpu+tsys);
254 if(tflg)
255 printf("%6.1f", a/(b+c));
256}
257
258col(n, a, m)
259double n, a, m;
260{
261
262 if(jflg)
263 printf("%9.2f", a/(n*60.)); else
264 printf("%9.2f", a/3600.);
265 if(cflg) {
266 if(a == m)
267 printf("%7s", ""); else
268 printf("%6.2f%%", 100.*a/m);
269 }
270}
271
272doacct(f)
273char *f;
274{
275 int i;
276 FILE *ff;
277 long x;
278 struct acct fbuf;
279 register char *cp;
280 register int c;
281
282 if (sflg && sname) {
283 printf("Only 1 file with -s\n");
284 exit(0);
285 }
286 if (sflg)
287 sname = f;
288 if ((ff = fopen(f, "r"))==NULL) {
289 printf("Can't open %s\n", f);
290 return;
291 }
292 while (fread((char *)&fbuf, sizeof(fbuf), 1, ff) == 1) {
293 if (fbuf.ac_comm[0]==0) {
294 fbuf.ac_comm[0] = '?';
295 }
296 for (cp = fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++) {
297 c = *cp & 0377;
298 if (c && (c < ' ' || c >= 0200)) {
299 *cp = '?';
300 }
301 }
302 if (fbuf.ac_flag&AFORK) {
303 for (cp=fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++)
304 if (*cp==0) {
305 *cp = '*';
306 break;
307 }
308 }
309 x = expand(fbuf.ac_utime) + expand(fbuf.ac_stime);
310 if (uflg) {
311 printf("%3d%6.1f %.14s\n", fbuf.ac_uid&0377, x/60.0,
312 fbuf.ac_comm);
313 continue;
314 }
315 c = fbuf.ac_uid&0377;
316 user[c].ncomm++;
317 user[c].fctime += x/60.;
318 ncom += 1.0;
319 i = enter(fbuf.ac_comm);
320 tab[i].count++;
321 x = expand(fbuf.ac_etime)*60;
322 tab[i].realt += x;
323 treal += x;
324 x = expand(fbuf.ac_utime);
325 tab[i].cput += x;
326 tcpu += x;
327 x = expand(fbuf.ac_stime);
328 tab[i].syst += x;
329 tsys += x;
330 }
331 fclose(ff);
332}
333
334ncmp(p1, p2)
335struct tab *p1, *p2;
336{
337
338 if(p1->count == p2->count)
339 return(tcmp(p1, p2));
340 if(rflg)
341 return(p1->count - p2->count);
342 return(p2->count - p1->count);
343}
344
345bcmp(p1, p2)
346struct tab *p1, *p2;
347{
348 float f1, f2;
349 float sum();
350
351 f1 = sum(p1)/p1->count;
352 f2 = sum(p2)/p2->count;
353 if(f1 < f2) {
354 if(rflg)
355 return(-1);
356 return(1);
357 }
358 if(f1 > f2) {
359 if(rflg)
360 return(1);
361 return(-1);
362 }
363 return(0);
364}
365tcmp(p1, p2)
366struct tab *p1, *p2;
367{
368 extern float sum();
369 float f1, f2;
370
371 f1 = sum(p1);
372 f2 = sum(p2);
373 if(f1 < f2) {
374 if(rflg)
375 return(-1);
376 return(1);
377 }
378 if(f1 > f2) {
379 if(rflg)
380 return(1);
381 return(-1);
382 }
383 return(0);
384}
385
386float sum(p)
387struct tab *p;
388{
389
390 if(p->name[0] == 0)
391 return(0.0);
392 return(
393 p->cput+
394 p->syst);
395}
396
397init()
398{
399 struct tab tbuf;
400 int i;
401 FILE *f;
402
403 if ((f = fopen("/usr/adm/savacct", "r")) == NULL)
404 goto gshm;
405 while (fread((char *)&tbuf, sizeof(tbuf), 1, f) == 1) {
406 i = enter(tbuf.name);
407 ncom += tbuf.count;
408 tab[i].count = tbuf.count;
409 treal += tbuf.realt;
410 tab[i].realt = tbuf.realt;
411 tcpu += tbuf.cput;
412 tab[i].cput = tbuf.cput;
413 tsys += tbuf.syst;
414 tab[i].syst = tbuf.syst;
415 }
416 fclose(f);
417 gshm:
418 if ((f = fopen("/usr/adm/usracct", "r")) == NULL)
419 return;
420 fread((char *)user, sizeof(user), 1, f);
421 fclose(f);
422}
423
424enter(np)
425char *np;
426{
427 int i, j;
428
429 for (i=j=0; i<NC; i++) {
430 if (np[i]==0)
431 j = i;
432 if (j)
433 np[i] = 0;
434 }
435 for (i=j=0; j<NC; j++) {
436 i = i*7 + np[j];
437 }
438 if (i < 0)
439 i = -i;
440 for (i%=size; tab[i].name[0]; i = (i+1)%size) {
441 for (j=0; j<NC; j++)
442 if (tab[i].name[j]!=np[j])
443 goto no;
444 goto yes;
445 no:;
446 }
447 for (j=0; j<NC; j++)
448 tab[i].name[j] = np[j];
449yes:
450 return(i);
451}
452
453strip()
454{
455 int i, j, c;
456
457 j = enter("**junk**");
458 for (i = 0; i<size; i++) {
459 if (tab[i].name[0] && tab[i].count<=thres) {
460 printf("%.14s--", tab[i].name);
461 if ((c=getchar())=='y') {
462 tab[i].name[0] = '\0';
463 tab[j].count += tab[i].count;
464 tab[j].realt += tab[i].realt;
465 tab[j].cput += tab[i].cput;
466 tab[j].syst += tab[i].syst;
467 }
468 while (c && c!='\n')
469 c = getchar();
470 }
471 }
472}
473
474time_t
475expand(t)
476unsigned t;
477{
478 register time_t nt;
479
480 nt = t&017777;
481 t >>= 13;
482 while (t!=0) {
483 t--;
484 nt <<= 3;
485 }
486 return(nt);
487}