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