xref: /onnv-gate/usr/src/cmd/acct/acctmerg.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23*0Sstevel@tonic-gate /*	  All Rights Reserved  	*/
24*0Sstevel@tonic-gate /*	Copyright (c) 1999 by Sun Microsystems, Inc. */
25*0Sstevel@tonic-gate /*	All rights reserved. */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.10	*/
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate /*
31*0Sstevel@tonic-gate  *	acctmerg [-a] [-i] [-p] [-t] [-u] [-v] [file...]
32*0Sstevel@tonic-gate  *	-a	output in tacct.h/ascii (instead of tacct.h)
33*0Sstevel@tonic-gate  *	-i	input is in tacct.h/ascii (instead of tacct.h)
34*0Sstevel@tonic-gate  *	-p	print input files with no processing
35*0Sstevel@tonic-gate  *	-t	output single record that totals all input
36*0Sstevel@tonic-gate  *	-u	summarize by uid, rather than uid/name
37*0Sstevel@tonic-gate  *	-v	output in verbose tacct.h/ascii
38*0Sstevel@tonic-gate  *	reads std input and 0-NFILE files, all in tacct.h format,
39*0Sstevel@tonic-gate  *	sorted by uid/name.
40*0Sstevel@tonic-gate  *	merge/adds all records with same uid/name (or same uid if -u,
41*0Sstevel@tonic-gate  *	or all records if -t], writes to std. output
42*0Sstevel@tonic-gate  *	(still in tacct.h format)
43*0Sstevel@tonic-gate  *	note that this can be used to summarize the std input
44*0Sstevel@tonic-gate  */
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate #include <stdio.h>
47*0Sstevel@tonic-gate #include <sys/types.h>
48*0Sstevel@tonic-gate #include <sys/param.h>
49*0Sstevel@tonic-gate #include "acctdef.h"
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate int	nfile;			/* index of last used in fl */
52*0Sstevel@tonic-gate FILE	*fl[NFILE]	= {stdin};
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate struct	tacct tb[NFILE];	/* current record from each file */
55*0Sstevel@tonic-gate struct	tacct	tt = {
56*0Sstevel@tonic-gate 	0,
57*0Sstevel@tonic-gate 	"TOTAL"
58*0Sstevel@tonic-gate };
59*0Sstevel@tonic-gate int	asciiout;
60*0Sstevel@tonic-gate int	asciiinp;
61*0Sstevel@tonic-gate int	printonly;
62*0Sstevel@tonic-gate int	totalonly;
63*0Sstevel@tonic-gate int	uidsum;
64*0Sstevel@tonic-gate int	verbose;
65*0Sstevel@tonic-gate struct tacct	*getleast();
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate int 	exitcode = 0;
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate main(argc, argv)
70*0Sstevel@tonic-gate int argc;
71*0Sstevel@tonic-gate char **argv;
72*0Sstevel@tonic-gate {
73*0Sstevel@tonic-gate 	register i;
74*0Sstevel@tonic-gate 	register struct tacct *tp;
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	while (--argc > 0) {
77*0Sstevel@tonic-gate 		if (**++argv == '-')
78*0Sstevel@tonic-gate 			switch (*++*argv) {
79*0Sstevel@tonic-gate 			case 'a':
80*0Sstevel@tonic-gate 				asciiout++;
81*0Sstevel@tonic-gate 				continue;
82*0Sstevel@tonic-gate 			case 'i':
83*0Sstevel@tonic-gate 				asciiinp++;
84*0Sstevel@tonic-gate 				continue;
85*0Sstevel@tonic-gate 			case 'p':
86*0Sstevel@tonic-gate 				printonly++;
87*0Sstevel@tonic-gate 				continue;
88*0Sstevel@tonic-gate 			case 't':
89*0Sstevel@tonic-gate 				totalonly++;
90*0Sstevel@tonic-gate 				continue;
91*0Sstevel@tonic-gate 			case 'u':
92*0Sstevel@tonic-gate 				uidsum++;
93*0Sstevel@tonic-gate 				continue;
94*0Sstevel@tonic-gate 			case 'v':
95*0Sstevel@tonic-gate 				verbose++;
96*0Sstevel@tonic-gate 				asciiout++;
97*0Sstevel@tonic-gate 				continue;
98*0Sstevel@tonic-gate 			}
99*0Sstevel@tonic-gate 		else {
100*0Sstevel@tonic-gate 			if (++nfile >= NFILE) {
101*0Sstevel@tonic-gate 				fprintf(stderr, "acctmerg: >%d files\n", NFILE);
102*0Sstevel@tonic-gate 				exit(1);
103*0Sstevel@tonic-gate 			}
104*0Sstevel@tonic-gate 			if ((fl[nfile] = fopen(*argv, "r")) == NULL) {
105*0Sstevel@tonic-gate 				fprintf(stderr, "acctmerg: can't open %s\n", *argv);
106*0Sstevel@tonic-gate 				exitcode = 1;
107*0Sstevel@tonic-gate 				/*	exit(1); 	*/
108*0Sstevel@tonic-gate 			}
109*0Sstevel@tonic-gate 		}
110*0Sstevel@tonic-gate 	}
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 	if (printonly) {
113*0Sstevel@tonic-gate 		for (i = 0; i <= nfile; i++)
114*0Sstevel@tonic-gate 			while (getnext(i))
115*0Sstevel@tonic-gate 				prtacct(&tb[i]);
116*0Sstevel@tonic-gate 		exit(exitcode);
117*0Sstevel@tonic-gate 	}
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	for (i = 0; i <= nfile; i++)
120*0Sstevel@tonic-gate 		if(getnext(i) == 0) {
121*0Sstevel@tonic-gate 			fprintf(stderr,"acctmerg: read error file %d.  File may be empty.\n", i);
122*0Sstevel@tonic-gate 			exitcode = 2;
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 		}
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	while ((tp = getleast()) != NULL)	/* get least uid of all files, */
127*0Sstevel@tonic-gate 		sumcurr(tp);			/* sum all entries for that uid, */
128*0Sstevel@tonic-gate 	if (totalonly)				/* and write the 'summed' record */
129*0Sstevel@tonic-gate 		output(&tt);
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate 	exit(exitcode);
132*0Sstevel@tonic-gate }
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate /*
135*0Sstevel@tonic-gate  *	getleast returns ptr to least (lowest uid)  element of current
136*0Sstevel@tonic-gate  *	avail, NULL if none left; always returns 1st of equals
137*0Sstevel@tonic-gate  */
138*0Sstevel@tonic-gate struct tacct *getleast()
139*0Sstevel@tonic-gate {
140*0Sstevel@tonic-gate 	register struct tacct *tp, *least;
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	least = NULL;
143*0Sstevel@tonic-gate 	for (tp = tb; tp <= &tb[nfile]; tp++) {
144*0Sstevel@tonic-gate 		if (tp->ta_name[0] == '\0')
145*0Sstevel@tonic-gate 			continue;
146*0Sstevel@tonic-gate 		if (least == NULL ||
147*0Sstevel@tonic-gate 			tp->ta_uid < least->ta_uid ||
148*0Sstevel@tonic-gate 			((tp->ta_uid == least->ta_uid) &&
149*0Sstevel@tonic-gate 			!uidsum &&
150*0Sstevel@tonic-gate 			(strncmp(tp->ta_name, least->ta_name, NSZ) < 0)))
151*0Sstevel@tonic-gate 			least = tp;
152*0Sstevel@tonic-gate 	}
153*0Sstevel@tonic-gate 	return(least);
154*0Sstevel@tonic-gate }
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate /*
157*0Sstevel@tonic-gate  *	sumcurr sums all entries with same uid/name (into tp->tacct record)
158*0Sstevel@tonic-gate  *	writes it out, gets new entry
159*0Sstevel@tonic-gate  */
160*0Sstevel@tonic-gate sumcurr(tp)
161*0Sstevel@tonic-gate register struct tacct *tp;
162*0Sstevel@tonic-gate {
163*0Sstevel@tonic-gate 	struct tacct tc;
164*0Sstevel@tonic-gate 	char *memcpy();
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	memcpy(&tc, tp, sizeof(struct tacct));
167*0Sstevel@tonic-gate 	tacctadd(&tt, tp);	/* gets total of all uids */
168*0Sstevel@tonic-gate 	getnext(tp-&tb[0]);	/* get next one in same file */
169*0Sstevel@tonic-gate 	while (tp <= &tb[nfile])
170*0Sstevel@tonic-gate 		if (tp->ta_name[0] != '\0' &&
171*0Sstevel@tonic-gate 			tp->ta_uid == tc.ta_uid &&
172*0Sstevel@tonic-gate 			(uidsum || EQN(tp->ta_name, tc.ta_name))) {
173*0Sstevel@tonic-gate 			tacctadd(&tc, tp);
174*0Sstevel@tonic-gate 			tacctadd(&tt, tp);
175*0Sstevel@tonic-gate 			getnext(tp-&tb[0]);
176*0Sstevel@tonic-gate 		} else
177*0Sstevel@tonic-gate 			tp++;	/* look at next file */
178*0Sstevel@tonic-gate 	if (!totalonly)
179*0Sstevel@tonic-gate 		output(&tc);
180*0Sstevel@tonic-gate }
181*0Sstevel@tonic-gate 
182*0Sstevel@tonic-gate tacctadd(t1, t2)
183*0Sstevel@tonic-gate register struct tacct *t1, *t2;
184*0Sstevel@tonic-gate {
185*0Sstevel@tonic-gate 	t1->ta_cpu[0] = t1->ta_cpu[0] + t2->ta_cpu[0];
186*0Sstevel@tonic-gate 	t1->ta_cpu[1] = t1->ta_cpu[1] + t2->ta_cpu[1];
187*0Sstevel@tonic-gate 	t1->ta_kcore[0] = t1->ta_kcore[0] + t2->ta_kcore[0];
188*0Sstevel@tonic-gate 	t1->ta_kcore[1] = t1->ta_kcore[1] + t2->ta_kcore[1];
189*0Sstevel@tonic-gate 	t1->ta_con[0] = t1->ta_con[0] + t2->ta_con[0];
190*0Sstevel@tonic-gate 	t1->ta_con[1] = t1->ta_con[1] + t2->ta_con[1];
191*0Sstevel@tonic-gate 	t1->ta_du = t1->ta_du + t2->ta_du;
192*0Sstevel@tonic-gate 	t1->ta_pc += t2->ta_pc;
193*0Sstevel@tonic-gate 	t1->ta_sc += t2->ta_sc;
194*0Sstevel@tonic-gate 	t1->ta_dc += t2->ta_dc;
195*0Sstevel@tonic-gate 	t1->ta_fee += t2->ta_fee;
196*0Sstevel@tonic-gate }
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate output(tp)
199*0Sstevel@tonic-gate register struct tacct *tp;
200*0Sstevel@tonic-gate {
201*0Sstevel@tonic-gate 	if (asciiout)
202*0Sstevel@tonic-gate 		prtacct(tp);
203*0Sstevel@tonic-gate 	else
204*0Sstevel@tonic-gate 		fwrite(tp, sizeof(*tp), 1, stdout);
205*0Sstevel@tonic-gate }
206*0Sstevel@tonic-gate /*
207*0Sstevel@tonic-gate  *	getnext reads next record from stream i, returns 1 if one existed
208*0Sstevel@tonic-gate  */
209*0Sstevel@tonic-gate getnext(i)
210*0Sstevel@tonic-gate register i;
211*0Sstevel@tonic-gate {
212*0Sstevel@tonic-gate 	register struct tacct *tp;
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate 	tp = &tb[i];
215*0Sstevel@tonic-gate 	tp->ta_name[0] = '\0';
216*0Sstevel@tonic-gate 	if (fl[i] == NULL)
217*0Sstevel@tonic-gate 		return(0);
218*0Sstevel@tonic-gate 	if (asciiinp) {
219*0Sstevel@tonic-gate 		if (fscanf(fl[i],
220*0Sstevel@tonic-gate 			"%ld\t%s\t%e %e %e %e %e %e %e %lu\t%hu\t%hu\t%hu",
221*0Sstevel@tonic-gate 			&tp->ta_uid,
222*0Sstevel@tonic-gate 			tp->ta_name,
223*0Sstevel@tonic-gate 			&tp->ta_cpu[0], &tp->ta_cpu[1],
224*0Sstevel@tonic-gate 			&tp->ta_kcore[0], &tp->ta_kcore[1],
225*0Sstevel@tonic-gate 			&tp->ta_con[0], &tp->ta_con[1],
226*0Sstevel@tonic-gate 			&tp->ta_du,
227*0Sstevel@tonic-gate 			&tp->ta_pc,
228*0Sstevel@tonic-gate 			&tp->ta_sc,
229*0Sstevel@tonic-gate 			&tp->ta_dc,
230*0Sstevel@tonic-gate 			&tp->ta_fee) != EOF)
231*0Sstevel@tonic-gate 			return(1);
232*0Sstevel@tonic-gate 	} else {
233*0Sstevel@tonic-gate 		if (fread(tp, sizeof(*tp), 1, fl[i]) == 1)
234*0Sstevel@tonic-gate 			return(1);
235*0Sstevel@tonic-gate 	}
236*0Sstevel@tonic-gate 	fclose(fl[i]);
237*0Sstevel@tonic-gate 	fl[i] = NULL;
238*0Sstevel@tonic-gate 	return(0);
239*0Sstevel@tonic-gate }
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate char fmt[] = "%ld\t%.*s\t%.0f\t%.0f\t%.0f\t%.0f\t%.0f\t%.0f\t%.0f\t%lu\t%hu\t%hu\t%hu\n";
242*0Sstevel@tonic-gate char fmtv[] = "%ld\t%.*s\t%e %e %e %e %e %e %e %lu %hu\t%hu\t%hu\n";
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate prtacct(tp)
245*0Sstevel@tonic-gate register struct tacct *tp;
246*0Sstevel@tonic-gate {
247*0Sstevel@tonic-gate 	printf(verbose ? fmtv : fmt,
248*0Sstevel@tonic-gate 	    tp->ta_uid,
249*0Sstevel@tonic-gate 	    OUTPUT_NSZ,
250*0Sstevel@tonic-gate 	    tp->ta_name,
251*0Sstevel@tonic-gate 	    tp->ta_cpu[0], tp->ta_cpu[1],
252*0Sstevel@tonic-gate 	    tp->ta_kcore[0], tp->ta_kcore[1],
253*0Sstevel@tonic-gate 	    tp->ta_con[0], tp->ta_con[1],
254*0Sstevel@tonic-gate 	    tp->ta_du,
255*0Sstevel@tonic-gate 	    tp->ta_pc,
256*0Sstevel@tonic-gate 	    tp->ta_sc,
257*0Sstevel@tonic-gate 	    tp->ta_dc,
258*0Sstevel@tonic-gate 	    tp->ta_fee);
259*0Sstevel@tonic-gate }
260