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