xref: /titanic_52/usr/src/cmd/acct/acctcms.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 /*
34  *	acctcms [-a] [-c] [-j] [-n] [-s] [-p] [-o] [-t] [file...]
35  *	summarize per-process accounting
36  *	-a	output in ascii, rather than [pt]cms.h format
37  *	-c	sort by total cpu, rather than total kcore-minutes
38  *	-j	anything used only once -> ***other
39  *	-n	sort by number of processes
40  *	-s	any following files already in pcms.h format
41  *      -p      output prime time command summary (only with -a)
42  *      -o      output non-prime time (offshift) command summary (only
43  *		with -a option)
44  *	-t	process records in total (old) style (tcms.h) format
45  *	file	file in [pt]cms.h (if -s seen already) or acct.h (if not)
46  *	expected use:
47  *	acctcms /var/adm/pacct? > today; acctcms -s old today >new
48  *	cp new old; rm new
49  *	acctcms -a today; acctcms -a old
50  */
51 #include <stdio.h>
52 #include <sys/types.h>
53 #include <sys/param.h>
54 #include "acctdef.h"
55 #include <ctype.h>
56 #include <sys/acct.h>
57 
58 int	csize = CSIZE;
59 
60 /*
61  *  Total cms records format
62  */
63 struct tcms {
64 	char	tcm_comm[8];	/* command name */
65 	long	tcm_pc;		/* number of processes */
66 	float	tcm_cpu;	/* cpu time(min) */
67 	float	tcm_real;	/* real time(min) */
68 	float	tcm_kcore;	/* kcore-minutes */
69 	ulong_t	tcm_io;		/* chars transferred */
70 	ulong_t	tcm_rw;		/* blocks read */
71 } ;
72 struct tcms	*tcm;
73 /*
74  * prime/nonprime CMS record format
75  */
76 struct pcms {
77 	char	pcm_comm[8];	/* command name */
78 	long	pcm_pc[2];	/* number of processes */
79 	float	pcm_cpu[2];	/* cpu time(min) */
80 	float	pcm_real[2];	/* real time(min) */
81 	float	pcm_kcore[2];	/* kcore-minutes */
82 	float	pcm_io[2];	/* chars transferred */
83 	float	pcm_rw[2];	/* blocks read */
84 } ;
85 struct pcms	*pcm;
86 struct  tcms    tcmtmp  = {{'*','*','*','o','t','h','e','r'}};
87 struct  pcms    pcmtmp  = {{'*','*','*','o','t','h','e','r'}};
88 int	aflg;
89 int	cflg;
90 int	jflg;
91 int	nflg;
92 int	sflg;
93 int	pflg;
94 int	oflg;
95 int	tflg;
96 int	errflg;
97 
98 int	ccmp(), kcmp(), ncmp();
99 int	tccmp(), tkcmp(), tncmp();
100 #ifdef uts
101 float   expand();
102 #else
103 ulong_t	expand();
104 #endif
105 
106 char	*strncpy();
107 
108 /*  Format specification for ASCII printing */
109 
110 char	*fmtcmd =	"%-8.8s",
111 	*fmtcnt =	"%8ld",
112 	*fmtkcore =	" %11.2f",
113 	*fmtcpu =	" %9.2f",
114 	*fmtreal =	" %12.2f",
115 	*fmtmsz =	" %7.2f",
116 	*fmtmcpu =	" %6.2f",
117 	*fmthog =	" %5.2f",
118 	*fmtcharx =	" %12.0f",
119 	*fmtblkx =	" %10.0f" ;
120 
121 main(argc, argv)
122 char **argv;
123 {
124 	int	c;
125 	extern	int	optind;
126 	extern	char	*optarg;
127 
128 	while((c = getopt(argc, argv, "acjnspot")) != EOF)
129 	switch(c) {
130 		case 'a':
131 			aflg++;
132 			continue;
133 		case 'c':
134 			cflg++;
135 			continue;
136 		case 'j':
137 			jflg++;
138 			continue;
139 		case 'n':
140 			nflg++;
141 			continue;
142 		case 's':
143 			sflg++;
144 			continue;
145 		case 'p':
146 			pflg++;
147 			continue;
148 		case 'o':
149 			oflg++;
150 			continue;
151 		case 't':
152 			tflg++;
153 			continue;
154 		default:
155 			errflg++;
156 			continue;
157 	}
158 	if(errflg){
159 		fprintf(stderr, "Usage: %s [-acjnspot] [file ...]\n", argv[0]);
160 		exit(1);
161 	}
162 	if(tflg) {
163 		if( (tcm = (struct tcms *)calloc(CSIZE, sizeof(struct tcms))) == NULL) {
164 			fprintf(stderr, "%s: Cannot allocate memory\n", argv[0]);
165 			exit(5);
166 		}
167 		for(; optind < argc; optind++)
168 			tdofile(argv[optind]);
169 		if (jflg)
170 			tfixjunk();
171 		tsqueeze();
172 		qsort(tcm, csize, sizeof(tcm[0]), nflg? tncmp: (cflg? tccmp: tkcmp));
173 		if (aflg)
174 			toutpta();
175 		else
176 			toutptc();
177 	} else {
178 		if( (pcm = (struct pcms *)calloc(CSIZE, sizeof(struct pcms))) == NULL) {
179 			fprintf(stderr, "%s: Cannot allocate memory\n", argv[0]);
180 			exit(6);
181 		}
182 		for(; optind < argc; optind++)
183 			dofile(argv[optind]);
184 		if (jflg)
185 			fixjunk();
186 		squeeze();
187 		qsort(pcm, csize, sizeof(pcm[0]), nflg? ncmp: (cflg? ccmp: kcmp));
188 		if (aflg)
189 			outputa();
190 		else
191 			outputc();
192 	}
193 	exit(0);
194 
195 }
196 
197 tdofile(fname)
198 char *fname;
199 {
200 	struct tcms cmt;
201 	union {
202 		struct acct ab;		/* SVR4 acct structure */
203 		struct o_acct oab;	/* SVR3 acct structure */
204 	} acct;
205 	int ver = 0;
206 	ulong_t	mem;
207 	ulong_t	cpu;
208 	ulong_t	real;
209 
210 	if (freopen(fname, "r", stdin) == NULL) {
211 		fprintf(stderr,  "acctcms: cannot open %s\n", fname);
212 		return;
213 	}
214 
215 	if (sflg)
216 		while (fread(&cmt, sizeof(cmt), 1, stdin) == 1)
217 			tenter(&cmt);
218 	else {
219 		if (fread(&acct.ab, sizeof(acct.ab), 1, stdin) == 1)
220 			/* check for expanded account structure flag */
221 			if (acct.ab.ac_flag & AEXPND)
222 				ver = 2;		/* 4.0 acct file */
223 			else
224 				ver = 1;		/* SVR3.x acct file */
225 
226 		rewind(stdin);	/* reset file pointer */
227 
228  		switch(ver) {
229 
230 		default:
231 				/* this can't happen */
232 			fprintf(stderr, "acctcms: encountered bad version number\n");
233 			return;
234 		case 1 :
235 			while (fread(&acct.oab, sizeof(acct.oab), 1, stdin) == 1) {
236 				CPYN(cmt.tcm_comm, acct.oab.ac_comm);
237 				cmt.tcm_pc = 1;
238 				cpu = expand(acct.oab.ac_stime)+
239 					expand(acct.oab.ac_utime);
240 				cmt.tcm_cpu = MINT(cpu);
241 				real = expand(acct.oab.ac_etime);
242 				cmt.tcm_real = MINT(real);
243 				mem = expand(acct.oab.ac_mem);
244 				cmt.tcm_kcore = MINT(KCORE(mem));
245 				cmt.tcm_io = expand(acct.oab.ac_io);
246 				cmt.tcm_rw = expand(acct.oab.ac_rw);
247 				tenter(&cmt);
248 			}
249 			break;
250 		case 2 :
251 
252 			while (fread(&acct.ab, sizeof(acct.ab), 1, stdin) == 1) {
253 				CPYN(cmt.tcm_comm, acct.ab.ac_comm);
254 				cmt.tcm_pc = 1;
255 				cpu = expand(acct.oab.ac_stime)+
256 					expand(acct.oab.ac_utime);
257 				cmt.tcm_cpu = MINT(cpu);
258 				real = expand(acct.ab.ac_etime);
259 				cmt.tcm_real = MINT(real);
260 				mem = expand(acct.ab.ac_mem);
261 				cmt.tcm_kcore = MINT(KCORE(mem));
262 				cmt.tcm_io = expand(acct.ab.ac_io);
263 				cmt.tcm_rw = expand(acct.ab.ac_rw);
264 				tenter(&cmt);
265 			}
266 			break;
267 		}
268 	}
269 }
270 
271 dofile(fname)
272 char *fname;
273 {
274 	union {
275 		struct acct ab;
276 		struct o_acct oab;
277 	} acct;
278 	struct pcms 	pcmt;
279 	double		ratio;
280 	long		elaps[2];
281 	ulong_t		etime;
282 	double	dtmp;
283 	unsigned long	ltmp;
284 	ulong_t	mem;
285 	ulong_t	cpu;
286 	ulong_t	real;
287 
288 	if (freopen(fname, "r", stdin) == NULL) {
289 		fprintf(stderr,  "acctcms: cannot open %s\n", fname);
290 		return;
291 	}
292 
293 	if (sflg)
294 		while (fread(&pcmt, sizeof(pcmt), 1, stdin) == 1)
295 			enter(&pcmt);
296 	else {
297 		int ver = 0;
298 
299 		if (fread(&acct.ab, sizeof(acct.ab), 1, stdin) == 1)
300 			/* check for expanded account structure flag */
301 			if (acct.ab.ac_flag & AEXPND)
302 				ver = 2;		/* 4.0 acct file */
303 			else
304 				ver = 1;		/* SVR3.x acct file */
305 
306 		rewind(stdin);	/* reset file pointer */
307 
308 		switch(ver) {
309 
310 		default :
311  				/* this can't happen */
312 			fprintf(stderr, "acctcms: encountered bad version number\n");
313 			return;
314 		case 1 :
315 
316 			while (fread(&acct.oab, sizeof(acct.oab), 1, stdin) == 1) {
317 				CPYN(pcmt.pcm_comm, acct.oab.ac_comm);
318 			/*
319 			** Approximate P/NP split as same as elapsed time
320 		 	*/
321 				if((etime = SECS(expand(acct.oab.ac_etime))) == 0)
322 					etime = 1;
323 				if (pnpsplit(acct.oab.ac_btime, etime, elaps)
324 				    == 0) {
325 					(void) fprintf(stderr, "acctcms: could "
326 					    "not calculate prime/non-prime "
327 					    "hours\n");
328 					exit(1);
329 				}
330 				ratio = (double)elaps[PRIME]/(double)etime;
331 				if(elaps[PRIME] > elaps[NONPRIME]) {
332 					pcmt.pcm_pc[PRIME] = 1;
333 					pcmt.pcm_pc[NONPRIME] = 0;
334 				} else {
335 					pcmt.pcm_pc[PRIME] = 0;
336 					pcmt.pcm_pc[NONPRIME] = 1;
337 				}
338 				cpu = expand(acct.oab.ac_stime)+
339 					expand(acct.oab.ac_utime);
340 				dtmp = MINT(cpu);
341 				pcmt.pcm_cpu[PRIME] = dtmp * ratio;
342 				pcmt.pcm_cpu[NONPRIME] = (ratio == 1.0) ? 0.0 :
343 					(dtmp - pcmt.pcm_cpu[PRIME]);
344 				real = expand(acct.oab.ac_etime);
345 				dtmp = MINT(real);
346 				pcmt.pcm_real[PRIME] = dtmp * ratio;
347 				pcmt.pcm_real[NONPRIME] = (ratio == 1.0) ? 0.0 :
348 					(dtmp - pcmt.pcm_real[PRIME]);
349 				mem = expand(acct.oab.ac_mem);
350 				dtmp = MINT(KCORE(mem));
351 				pcmt.pcm_kcore[PRIME] = dtmp * ratio;
352 				pcmt.pcm_kcore[NONPRIME] = (ratio == 1.0) ? 0.0 :
353 					(dtmp - pcmt.pcm_kcore[PRIME]);
354 				ltmp = expand(acct.oab.ac_io);
355 				pcmt.pcm_io[PRIME] = (double)ltmp * ratio;
356 				pcmt.pcm_io[NONPRIME] = (ratio == 1.0) ? 0.0 :
357 					((double)ltmp - pcmt.pcm_io[PRIME]);
358 				ltmp = expand(acct.oab.ac_rw);
359 				pcmt.pcm_rw[PRIME] = (double)ltmp * ratio;
360 				pcmt.pcm_rw[NONPRIME] = (ratio == 1.0) ? 0.0 :
361 					((double)ltmp - pcmt.pcm_rw[PRIME]);
362 				enter(&pcmt);
363 			}
364 
365 			break;
366 		case 2 :
367 			while (fread(&acct.ab, sizeof(acct.ab), 1, stdin) == 1) {
368 				CPYN(pcmt.pcm_comm, acct.ab.ac_comm);
369 				/*
370 				** Approximate P/NP split as same as elapsed time
371 		 		*/
372 				if((etime = SECS(expand(acct.ab.ac_etime))) == 0)
373 					etime = 1;
374 				if(pnpsplit(acct.ab.ac_btime, etime, elaps) == 0) {
375 					fprintf(stderr, "acctcms: could not calculate prime/non-prime hours\n");
376 					exit(1);
377 				}
378 				ratio = (double)elaps[PRIME]/(double)etime;
379 				if(elaps[PRIME] > elaps[NONPRIME]) {
380 					pcmt.pcm_pc[PRIME] = 1;
381 					pcmt.pcm_pc[NONPRIME] = 0;
382 				} else {
383 					pcmt.pcm_pc[PRIME] = 0;
384 					pcmt.pcm_pc[NONPRIME] = 1;
385 				}
386 				cpu = expand(acct.ab.ac_stime)+
387 					expand(acct.ab.ac_utime);
388 				dtmp = MINT(cpu);
389 				pcmt.pcm_cpu[PRIME] = dtmp * ratio;
390 				pcmt.pcm_cpu[NONPRIME] = (ratio == 1.0) ? 0.0 :
391 					(dtmp - pcmt.pcm_cpu[PRIME]);
392 				real = expand(acct.ab.ac_etime);
393 				dtmp = MINT(real);
394 				pcmt.pcm_real[PRIME] = dtmp * ratio;
395 				pcmt.pcm_real[NONPRIME] = (ratio == 1.0) ? 0.0 :
396 					(dtmp - pcmt.pcm_real[PRIME]);
397 				mem = expand(acct.ab.ac_mem);
398 				dtmp = MINT(KCORE(mem));
399 				pcmt.pcm_kcore[PRIME] = dtmp * ratio;
400 				pcmt.pcm_kcore[NONPRIME] = (ratio == 1.0) ? 0.0 :
401 					(dtmp - pcmt.pcm_kcore[PRIME]);
402 				ltmp = expand(acct.ab.ac_io);
403 				pcmt.pcm_io[PRIME] = (double)ltmp * ratio;
404 				pcmt.pcm_io[NONPRIME] = (ratio == 1.0) ? 0.0 :
405 					((double)ltmp - pcmt.pcm_io[PRIME]);
406 				ltmp = expand(acct.ab.ac_rw);
407 				pcmt.pcm_rw[PRIME] = (double)ltmp * ratio;
408 				pcmt.pcm_rw[NONPRIME] = (ratio == 1.0) ? 0.0 :
409 					((double)ltmp - pcmt.pcm_rw[PRIME]);
410 				enter(&pcmt);
411 			}
412 
413 			break;
414 		}
415 	}
416 }
417 
418 tenter(p)
419 register struct tcms *p;
420 {
421 	register i;
422 	register j;
423 	register struct tcms *ntcm;
424 	for (i = j = 0; j < sizeof(p->tcm_comm); j++) {
425 		if (p->tcm_comm[j] && p->tcm_comm[j] <= 037)
426 			p->tcm_comm[j] = '?';
427 		i = i*7 + p->tcm_comm[j];	/* hash function */
428 	}
429 	if (i < 0)
430 		i = -i;
431 	for (i %= csize, j = 0; tcm[i].tcm_comm[0] && j != csize; i = (i+1)%csize, j++)
432 		if (EQN(p->tcm_comm, tcm[i].tcm_comm))
433 			break;
434 	if(j == csize) {
435 		if ((ntcm = (struct tcms *) realloc(tcm,
436 			(csize + CSIZE - 1) * sizeof (struct tcms))) == NULL) {
437 			fprintf(stderr,
438 				"acctcms: Cannot reallocate memory (tcm)\n");
439 			return(-1);
440 		} else {
441 			memset(&ntcm[csize], 0, CSIZE - 1);
442 			tcm = ntcm;
443 			if (!EQN(p->tcm_comm, tcm[i].tcm_comm))
444 				i = csize;
445 			csize = csize + CSIZE - 1;
446 		}
447 	}
448 	if (tcm[i].tcm_comm[0] == 0)
449 		CPYN(tcm[i].tcm_comm, p->tcm_comm);
450 	tcmadd(&tcm[i], p);
451 	return(i);
452 }
453 enter(p)
454 register struct pcms *p;
455 {
456 	register i;
457 	register j;
458 	register struct pcms *npcm;
459 	for (i = j = 0; j < sizeof(p->pcm_comm); j++) {
460 		if (p->pcm_comm[j] && p->pcm_comm[j] <= 037)
461 			p->pcm_comm[j] = '?';
462 		i = i*7 + p->pcm_comm[j];	/* hash function */
463 	}
464 	if (i < 0)
465 		i = -i;
466 	for (i %= csize, j = 0; pcm[i].pcm_comm[0] && j != csize; i = (i+1)%csize, j++)
467 		if (EQN(p->pcm_comm, pcm[i].pcm_comm))
468 			break;
469 	if(j == csize) {
470 		if ((npcm = (struct pcms *) realloc(pcm,
471 			(csize + CSIZE - 1) * sizeof (struct pcms))) == NULL) {
472 			fprintf(stderr,
473 				"acctcms: Cannot reallocate memory (pcm)\n");
474 			return(-1);
475 		} else {
476 			memset(&npcm[csize], 0, CSIZE - 1);
477 			pcm = npcm;
478 			if (!EQN(p->pcm_comm, pcm[i].pcm_comm))
479 				i = csize;
480 			csize = csize + CSIZE - 1;
481 		}
482 	}
483 	if (pcm[i].pcm_comm[0] == 0)
484 		CPYN(pcm[i].pcm_comm, p->pcm_comm);
485 	pcmadd(&pcm[i], p);
486 	return(i);
487 }
488 tfixjunk()	/* combine commands used only once */
489 {
490 	register i, j;
491 	j = enter(&tcmtmp);
492 	for (i = 0; i < csize; i++)
493 		if (i != j && tcm[i].tcm_comm[0] && tcm[i].tcm_pc <= 1) {
494 			tcmadd(&tcm[j], &tcm[i]);
495 			tcm[i].tcm_comm[0] = 0;
496 		}
497 }
498 fixjunk()	/* combine commands used only once */
499 {
500 	register i, j;
501 	j = enter(&pcmtmp);
502 	for (i = 0; i < csize; i++)
503 		if (i != j && pcm[i].pcm_comm[0] && (pcm[i].pcm_pc[PRIME] + pcm[i].pcm_pc[NONPRIME]) <= 1) {
504 			pcmadd(&pcm[j], &pcm[i]);
505 			pcm[i].pcm_comm[0] = 0;
506 		}
507 }
508 
509 tcmadd(p1, p2)
510 register struct tcms *p1, *p2;
511 {
512 	p1->tcm_pc += p2->tcm_pc;
513 	p1->tcm_cpu = p1->tcm_cpu + p2->tcm_cpu;
514 	p1->tcm_real = p1->tcm_real + p2->tcm_real;
515 	p1->tcm_kcore = p1->tcm_kcore + p2->tcm_kcore;
516 	p1->tcm_io += p2->tcm_io;
517 	p1->tcm_rw += p2->tcm_rw;
518 }
519 pcmadd(p1, p2)
520 register struct pcms *p1, *p2;
521 {
522 	p1->pcm_pc[PRIME] += p2->pcm_pc[PRIME];
523 	p1->pcm_pc[NONPRIME] += p2->pcm_pc[NONPRIME];
524 	p1->pcm_cpu[PRIME] += p2->pcm_cpu[PRIME];
525 	p1->pcm_cpu[NONPRIME] += p2->pcm_cpu[NONPRIME];
526 	p1->pcm_real[PRIME] += p2->pcm_real[PRIME];
527 	p1->pcm_real[NONPRIME] += p2->pcm_real[NONPRIME];
528 	p1->pcm_kcore[PRIME] += p2->pcm_kcore[PRIME];
529 	p1->pcm_kcore[NONPRIME] += p2->pcm_kcore[NONPRIME];
530 	p1->pcm_io[PRIME] += p2->pcm_io[PRIME];
531 	p1->pcm_io[NONPRIME] += p2->pcm_io[NONPRIME];
532 	p1->pcm_rw[PRIME] += p2->pcm_rw[PRIME];
533 	p1->pcm_rw[NONPRIME] += p2->pcm_rw[NONPRIME];
534 }
535 
536 tsqueeze()	/* get rid of holes in hash table */
537 {
538 	register i, k;
539 
540 	for (i = k = 0; i < csize; i++)
541 		if (tcm[i].tcm_comm[0]) {
542 			CPYN(tcm[k].tcm_comm, tcm[i].tcm_comm);
543 			tcm[k].tcm_pc = tcm[i].tcm_pc;
544 			tcm[k].tcm_cpu = tcm[i].tcm_cpu;
545 			tcm[k].tcm_real = tcm[i].tcm_real;
546 			tcm[k].tcm_kcore = tcm[i].tcm_kcore;
547 			tcm[k].tcm_io = tcm[i].tcm_io;
548 			tcm[k].tcm_rw = tcm[i].tcm_rw;
549 			k++;
550 		}
551 	csize = k;
552 }
553 squeeze()	/* get rid of holes in hash table */
554 {
555 	register i, k;
556 
557 	for (i = k = 0; i < csize; i++)
558 		if (pcm[i].pcm_comm[0]) {
559 			CPYN(pcm[k].pcm_comm, pcm[i].pcm_comm);
560 			pcm[k].pcm_pc[PRIME] = pcm[i].pcm_pc[PRIME];
561 			pcm[k].pcm_pc[NONPRIME] = pcm[i].pcm_pc[NONPRIME];
562 			pcm[k].pcm_cpu[PRIME] = pcm[i].pcm_cpu[PRIME];
563 			pcm[k].pcm_cpu[NONPRIME] = pcm[i].pcm_cpu[NONPRIME];
564 			pcm[k].pcm_real[PRIME] = pcm[i].pcm_real[PRIME];
565 			pcm[k].pcm_real[NONPRIME] = pcm[i].pcm_real[NONPRIME];
566 			pcm[k].pcm_kcore[PRIME] = pcm[i].pcm_kcore[PRIME];
567 			pcm[k].pcm_kcore[NONPRIME] = pcm[i].pcm_kcore[NONPRIME];
568 			pcm[k].pcm_io[PRIME] = pcm[i].pcm_io[PRIME];
569 			pcm[k].pcm_io[NONPRIME] = pcm[i].pcm_io[NONPRIME];
570 			pcm[k].pcm_rw[PRIME] = pcm[i].pcm_rw[PRIME];
571 			pcm[k].pcm_rw[NONPRIME] = pcm[i].pcm_rw[NONPRIME];
572 			k++;
573 		}
574 	csize = k;
575 }
576 
577 tccmp(p1, p2)
578 register struct tcms *p1, *p2;
579 {
580 	if (p1->tcm_cpu == p2->tcm_cpu)
581 		return(0);
582 	return ((p2->tcm_cpu > p1->tcm_cpu)? 1 : -1);
583 }
584 
585 ccmp(p1, p2)
586 register struct pcms *p1, *p2;
587 {
588 	register int	index;
589 
590 	if( (pflg && oflg) || (!pflg && !oflg) ) {
591 		if (p1->pcm_cpu[PRIME] + p1->pcm_cpu[NONPRIME] == p2->pcm_cpu[PRIME] + p2->pcm_cpu[NONPRIME])
592 			return(0);
593 		return ((p2->pcm_cpu[PRIME] + p2->pcm_cpu[NONPRIME] > p1->pcm_cpu[PRIME] + p1->pcm_cpu[NONPRIME])? 1 : -1);
594 	}
595 	index = pflg ? PRIME : NONPRIME;
596 	if (p1->pcm_cpu[index] == p2->pcm_cpu[index])
597 		return(0);
598 	return ((p2->pcm_cpu[index] > p1->pcm_cpu[index])? 1 : -1);
599 }
600 
601 tkcmp(p1, p2)
602 register struct tcms *p1, *p2;
603 {
604 	if (p1->tcm_kcore == p2->tcm_kcore)
605 		return(0);
606 	return ((p2->tcm_kcore > p1->tcm_kcore)? 1 : -1);
607 }
608 
609 kcmp(p1, p2)
610 register struct pcms *p1, *p2;
611 {
612 	register int	index;
613 
614 	if( (pflg && oflg) || (!pflg && !pflg) ){
615 		if (p1->pcm_kcore[PRIME] + p1->pcm_kcore[NONPRIME] == p2->pcm_kcore[PRIME] + p2->pcm_kcore[NONPRIME])
616 			return(0);
617 		return ((p2->pcm_kcore[PRIME] + p2->pcm_kcore[NONPRIME] > p1->pcm_kcore[PRIME] + p1->pcm_kcore[NONPRIME])? 1 : -1);
618 	}
619 	index = pflg ? PRIME : NONPRIME;
620 	if (p1->pcm_kcore[index] == p2->pcm_kcore[index])
621 		return(0);
622 	return ((p2->pcm_kcore[index] > p1->pcm_kcore[index])? 1 : -1);
623 }
624 
625 tncmp(p1, p2)
626 register struct tcms *p1, *p2;
627 {
628 	if (p1->tcm_pc == p2->tcm_pc)
629 		return(0);
630 	return ((p2->tcm_pc > p1->tcm_pc)? 1 : -1);
631 }
632 
633 ncmp(p1, p2)
634 register struct pcms *p1, *p2;
635 {
636 	register int	index;
637 
638 	if( (pflg && oflg) || (!pflg && !oflg) ) {
639 		if (p1->pcm_pc[PRIME] + p1->pcm_pc[NONPRIME] == p2->pcm_pc[PRIME] + p2->pcm_pc[NONPRIME])
640 			return(0);
641 		return ((p2->pcm_pc[PRIME] + p2->pcm_pc[NONPRIME] > p1->pcm_pc[PRIME] + p1->pcm_pc[NONPRIME])? 1 : -1);
642 	}
643 	index =  pflg ? PRIME : NONPRIME;
644 	if (p1->pcm_pc[index] == p2->pcm_pc[index])
645 		return(0);
646 	return ((p2->pcm_pc[index] > p1->pcm_pc[index])? 1 : -1);
647 }
648 
649 char	thd1[] =
650 "COMMAND   NUMBER      TOTAL       TOTAL       TOTAL   MEAN     MEAN     HOG      CHARS        BLOCKS\n";
651 char	thd2[] =
652 "NAME        CMDS    KCOREMIN     CPU-MIN     REAL-MIN SIZE-K  CPU-MIN  FACTOR   TRNSFD         READ\n";
653 toutpta()
654 {
655 	register i;
656 
657 	printf(thd1);
658 	printf(thd2);
659 	printf("\n");
660 	for (i = 0; i < csize; i++)
661 		tcmadd(&tcmtmp, &tcm[i]);
662 	CPYN(tcmtmp.tcm_comm, "TOTALS");
663 	tprint(&tcmtmp);
664 	printf("\n");
665 	for (i = 0; i < csize; i++)
666 		tprint(&tcm[i]);
667 }
668 
669 tprint(p)
670 register struct tcms *p;
671 {
672 	printf("%-8.8s", p->tcm_comm);
673 	printf(" %7ld", p->tcm_pc);
674 	printf(" %11.2f", p->tcm_kcore);
675 	printf(" %10.2f", p->tcm_cpu);
676 	printf(" %12.2f", p->tcm_real);
677 	if(p->tcm_cpu == 0)  p->tcm_cpu = 1;
678 	printf(" %6.2f", p->tcm_kcore/p->tcm_cpu);
679 	if(p->tcm_pc == 0)  p->tcm_pc = 1;
680 	printf(" %7.2f", p->tcm_cpu/p->tcm_pc);
681 	if (p->tcm_real == 0)
682 		p->tcm_real = 1;
683 	printf(" %8.2f", p->tcm_cpu/p->tcm_real);
684 	printf(" %11lu", p->tcm_io);
685 	printf(" %11lu\n", p->tcm_rw);
686 }
687 
688 toutptc()
689 {
690 	register i;
691 
692 	for (i = 0; i < csize; i++)
693 		fwrite(&tcm[i], sizeof(tcm[i]), 1, stdout);
694 }
695 
696 char	hd1[] =
697 "COMMAND   NUMBER      TOTAL       TOTAL       TOTAL   MEAN    MEAN     HOG         CHARS     BLOCKS\n";
698 char	hd2[] =
699 "NAME        CMDS    KCOREMIN     CPU-MIN   REAL-MIN  SIZE-K  CPU-MIN  FACTOR      TRNSFD      READ\n";
700 char	hd3[] =
701 "COMMAND        NUMBER         TOTAL          CPU-MIN                 REAL-MIN        MEAN    MEAN      HOG       CHARS       BLOCKS\n";
702 char	hd4[] =
703 "NAME         (P)    (NP)   KCOREMIN       (P)      (NP)          (P)         (NP)  SIZE-K  CPU-MIN   FACTOR     TRNSFD        READ\n";
704 char	hdprime[] =
705 "                                   PRIME TIME COMMAND SUMMARY\n";
706 char	hdnonprime[] =
707 "                                  NON-PRIME TIME COMMAND SUMMARY\n";
708 char	hdtot[] =
709 "                                     TOTAL COMMAND SUMMARY\n";
710 char	hdp[] =
711 "                                PRIME/NON-PRIME TIME COMMAND SUMMARY\n";
712 
713 outputa()
714 {
715 	register i;
716 
717 	if( pflg && oflg ) printf(hdp);
718 	else if(pflg) printf(hdprime);
719 	else if(oflg) printf(hdnonprime);
720 	else printf(hdtot);
721 	if( (!pflg && !oflg) || (pflg ^ oflg)) {
722 		printf(hd1);
723 		printf(hd2);
724 	}
725 	else {
726 		printf(hd3);
727 		printf(hd4);
728 	}
729 	printf("\n");
730 	for (i = 0; i < csize; i++)
731 		pcmadd(&pcmtmp, &pcm[i]);
732 	CPYN(pcmtmp.pcm_comm, "TOTALS");
733 	print(&pcmtmp);
734 	printf("\n");
735 	for (i = 0; i < csize; i++)
736 		print(&pcm[i]);
737 }
738 
739 print(p)
740 register struct pcms *p;
741 {
742 	if(pflg && oflg) pprint(p);
743 	else if(pflg || oflg) prnt(p, pflg ? PRIME : NONPRIME);
744 	else totprnt(p);
745 }
746 
747 prnt(p, hr)
748 register struct pcms *p;
749 register int	hr;
750 {
751 	if(p->pcm_pc[hr] == 0) return;
752 	printf(fmtcmd, p->pcm_comm);
753 	printf(fmtcnt, p->pcm_pc[hr]);
754 	printf(fmtkcore, p->pcm_kcore[hr]);
755 	printf(fmtcpu, p->pcm_cpu[hr]);
756 	printf(fmtreal, p->pcm_real[hr]);
757 	if(p->pcm_cpu[hr] == 0)  p->pcm_cpu[hr] = 1;
758 	printf(fmtmsz, p->pcm_kcore[hr]/p->pcm_cpu[hr]);
759 	if(p->pcm_pc[hr] == 0)  p->pcm_pc[hr] = 1;
760 	printf(fmtmcpu, p->pcm_cpu[hr]/p->pcm_pc[hr]);
761 	if (p->pcm_real[hr] == 0)
762 		p->pcm_real[hr] = 1;
763 	printf(fmthog, p->pcm_cpu[hr]/p->pcm_real[hr]);
764 	printf(fmtcharx,p->pcm_io[hr]);
765 	printf(fmtblkx,p->pcm_rw[hr]);
766 	printf("\n");
767 }
768 
769 pprint(p)
770 register struct pcms *p;
771 {
772 	printf(fmtcmd, p->pcm_comm);
773 	printf(fmtcnt, p->pcm_pc[PRIME]);
774 	printf(fmtcnt, p->pcm_pc[NONPRIME]);
775 	printf(fmtkcore, TOTAL(p->pcm_kcore));
776 	printf(fmtcpu, p->pcm_cpu[PRIME]);
777 	printf(fmtcpu, p->pcm_cpu[NONPRIME]);
778 	printf(fmtreal, p->pcm_real[PRIME]);
779 	printf(fmtreal, p->pcm_real[NONPRIME]);
780 	if(TOTAL(p->pcm_cpu) == 0)  p->pcm_cpu[PRIME] = 1;
781 	printf(fmtmsz, TOTAL(p->pcm_kcore)/TOTAL(p->pcm_cpu));
782 	if(TOTAL(p->pcm_pc) == 0)  p->pcm_pc[PRIME] = 1;
783 	printf(fmtmcpu, TOTAL(p->pcm_cpu)/TOTAL(p->pcm_pc));
784 	if ( TOTAL(p->pcm_real) == 0)
785 		p->pcm_real[PRIME] = 1;
786 	printf(fmthog, TOTAL(p->pcm_cpu)/TOTAL(p->pcm_real));
787 	printf(fmtcharx,TOTAL(p->pcm_io));
788 	printf(fmtblkx, TOTAL(p->pcm_rw));
789 	printf("\n");
790 }
791 
792 totprnt(p)
793 register struct pcms *p;
794 {
795 	printf(fmtcmd, p->pcm_comm);
796 	printf(fmtcnt, TOTAL(p->pcm_pc));
797 	printf(fmtkcore, TOTAL(p->pcm_kcore));
798 	printf(fmtcpu, TOTAL(p->pcm_cpu));
799 	printf(fmtreal, TOTAL(p->pcm_real));
800 	if(TOTAL(p->pcm_cpu) == 0)  p->pcm_cpu[PRIME] = 1;
801 	printf(fmtmsz, TOTAL(p->pcm_kcore)/TOTAL(p->pcm_cpu));
802 	if(TOTAL(p->pcm_pc) == 0)  p->pcm_pc[PRIME] = 1;
803 	printf(fmtmcpu, TOTAL(p->pcm_cpu)/TOTAL(p->pcm_pc));
804 	if (TOTAL(p->pcm_real) == 0)
805 		p->pcm_real[PRIME] = 1;
806 	printf(fmthog, TOTAL(p->pcm_cpu)/TOTAL(p->pcm_real));
807 	printf(fmtcharx,TOTAL(p->pcm_io));
808 	printf(fmtblkx,TOTAL(p->pcm_rw));
809 	printf("\n");
810 }
811 outputc()
812 {
813 	register i;
814 
815 	for (i = 0; i < csize; i++)
816 		fwrite(&pcm[i], sizeof(pcm[i]), 1, stdout);
817 }
818