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