1: #include <stdio.h> 2: #include <sys/types.h> 3: #include <sys/acct.h> 4: #include <signal.h> 5: 6: /* interpret command time accounting */ 7: 8: #define size 1000 9: #define NC sizeof(acctbuf.ac_comm) 10: struct acct acctbuf; 11: int lflg; 12: int cflg; 13: int iflg; 14: int jflg; 15: int nflg; 16: int aflg; 17: int rflg; 18: int oflg; 19: int tflg; 20: int vflg; 21: int uflg; 22: int thres = 1; 23: int sflg; 24: int bflg; 25: int mflg; 26: 27: struct user { 28: int ncomm; 29: int fill; 30: float fctime; 31: } user[256]; 32: 33: struct tab { 34: char name[NC]; 35: int count; 36: float realt; 37: float cput; 38: float syst; 39: } tab[size]; 40: 41: float treal; 42: float tcpu; 43: float tsys; 44: int junkp = -1; 45: char *sname; 46: float ncom; 47: time_t expand(); 48: 49: main(argc, argv) 50: char **argv; 51: { 52: FILE *ff; 53: int i, j, k; 54: extern tcmp(), ncmp(), bcmp(); 55: extern float sum(); 56: float ft; 57: 58: if (argc>1) 59: if (argv[1][0]=='-') { 60: argv++; 61: argc--; 62: for(i=1; argv[0][i]; i++) 63: switch(argv[0][i]) { 64: 65: case 'o': 66: oflg++; 67: break; 68: 69: case 'i': 70: iflg++; 71: break; 72: 73: case 'b': 74: bflg++; 75: break; 76: 77: case 'l': 78: lflg++; 79: break; 80: 81: case 'c': 82: cflg++; 83: break; 84: 85: case 'j': 86: jflg++; 87: break; 88: 89: case 'n': 90: nflg++; 91: break; 92: 93: case 'a': 94: aflg++; 95: break; 96: 97: case 'r': 98: rflg++; 99: break; 100: 101: case 't': 102: tflg++; 103: break; 104: 105: case 's': 106: sflg++; 107: aflg++; 108: break; 109: 110: case '0': 111: case '1': 112: case '2': 113: case '3': 114: case '4': 115: case '5': 116: case '6': 117: case '7': 118: case '8': 119: case '9': 120: thres = argv[0][i]-'0'; 121: break; 122: 123: case 'v': 124: vflg++; 125: break; 126: 127: case 'u': 128: uflg++; 129: break; 130: 131: case 'm': 132: mflg++; 133: break; 134: } 135: } 136: if (iflg==0) 137: init(); 138: if (argc<2) 139: doacct("/usr/adm/acct"); 140: else while (--argc) 141: doacct(*++argv); 142: if (uflg) { 143: return; 144: } 145: 146: /* 147: * cleanup pass 148: * put junk together 149: */ 150: 151: if (vflg) 152: strip(); 153: if(!aflg) 154: for (i=0; i<size; i++) 155: if (tab[i].name[0]) { 156: for(j=0; j<NC; j++) 157: if(tab[i].name[j] == '?') 158: goto yes; 159: if(tab[i].count != 1) 160: continue; 161: yes: 162: if(junkp == -1) 163: junkp = enter("***other"); 164: tab[junkp].count += tab[i].count; 165: tab[junkp].realt += tab[i].realt; 166: tab[junkp].cput += tab[i].cput; 167: tab[junkp].syst += tab[i].syst; 168: tab[i].name[0] = 0; 169: } 170: for(i=k=0; i<size; i++) 171: if(tab[i].name[0]) { 172: for(j=0; j<NC; j++) 173: tab[k].name[j] = tab[i].name[j]; 174: tab[k].count = tab[i].count; 175: tab[k].realt = tab[i].realt; 176: tab[k].cput = tab[i].cput; 177: tab[k].syst = tab[i].syst; 178: k++; 179: } 180: if (sflg) { 181: signal(SIGINT, SIG_IGN); 182: if ((ff = fopen("/usr/adm/usracct", "w")) != NULL) { 183: fwrite((char *)user, sizeof(user), 1, ff); 184: fclose(ff); 185: } 186: if ((ff = fopen("/usr/adm/savacct", "w")) == NULL) { 187: printf("Can't save\n"); 188: exit(0); 189: } 190: fwrite((char *)tab, sizeof(tab[0]), k, ff); 191: fclose(ff); 192: signal(SIGINT, SIG_DFL); 193: } 194: /* 195: * sort and print 196: */ 197: 198: if (mflg) { 199: printmoney(); 200: exit(0); 201: } 202: qsort(tab, k, sizeof(tab[0]), nflg? ncmp: (bflg?bcmp:tcmp)); 203: column(ncom, treal, tcpu, tsys); 204: printf("\n"); 205: for (i=0; i<k; i++) 206: if (tab[i].name[0]) { 207: ft = tab[i].count; 208: column(ft, tab[i].realt, tab[i].cput, tab[i].syst); 209: printf(" %.10s\n", tab[i].name); 210: } 211: } 212: 213: printmoney() 214: { 215: register i; 216: char buf[128]; 217: register char *cp; 218: 219: for (i=0; i<256; i++) { 220: if (user[i].ncomm) { 221: if (getpw(i, buf)!=0) 222: printf("%-8d", i); 223: else { 224: cp = buf; 225: while (*cp!=':' &&*cp!='\n' && *cp) 226: cp++; 227: *cp = 0; 228: printf("%-8s", buf); 229: } 230: printf("%5u %7.2f\n", 231: user[i].ncomm, user[i].fctime/60); 232: } 233: } 234: } 235: 236: column(n, a, b, c) 237: double n, a, b, c; 238: { 239: 240: printf("%6.0f", n); 241: if(cflg) { 242: if(n == ncom) 243: printf("%7s", ""); else 244: printf("%6.2f%%", 100.*n/ncom); 245: } 246: col(n, a, treal); 247: if (oflg) 248: col(n, 3600*(b/(b+c)), tcpu+tsys); 249: else if(lflg) { 250: col(n, b, tcpu); 251: col(n, c, tsys); 252: } else 253: col(n, b+c, tcpu+tsys); 254: if(tflg) 255: printf("%6.1f", a/(b+c)); 256: } 257: 258: col(n, a, m) 259: double n, a, m; 260: { 261: 262: if(jflg) 263: printf("%9.2f", a/(n*60.)); else 264: printf("%9.2f", a/3600.); 265: if(cflg) { 266: if(a == m) 267: printf("%7s", ""); else 268: printf("%6.2f%%", 100.*a/m); 269: } 270: } 271: 272: doacct(f) 273: char *f; 274: { 275: int i; 276: FILE *ff; 277: long x; 278: struct acct fbuf; 279: register char *cp; 280: register int c; 281: 282: if (sflg && sname) { 283: printf("Only 1 file with -s\n"); 284: exit(0); 285: } 286: if (sflg) 287: sname = f; 288: if ((ff = fopen(f, "r"))==NULL) { 289: printf("Can't open %s\n", f); 290: return; 291: } 292: while (fread((char *)&fbuf, sizeof(fbuf), 1, ff) == 1) { 293: if (fbuf.ac_comm[0]==0) { 294: fbuf.ac_comm[0] = '?'; 295: } 296: for (cp = fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++) { 297: c = *cp & 0377; 298: if (c && (c < ' ' || c >= 0200)) { 299: *cp = '?'; 300: } 301: } 302: if (fbuf.ac_flag&AFORK) { 303: for (cp=fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++) 304: if (*cp==0) { 305: *cp = '*'; 306: break; 307: } 308: } 309: x = expand(fbuf.ac_utime) + expand(fbuf.ac_stime); 310: if (uflg) { 311: printf("%3d%6.1f %.10s\n", fbuf.ac_uid&0377, x/60.0, 312: fbuf.ac_comm); 313: continue; 314: } 315: c = fbuf.ac_uid&0377; 316: user[c].ncomm++; 317: user[c].fctime += x/60.; 318: ncom += 1.0; 319: i = enter(fbuf.ac_comm); 320: tab[i].count++; 321: x = expand(fbuf.ac_etime)*60; 322: tab[i].realt += x; 323: treal += x; 324: x = expand(fbuf.ac_utime); 325: tab[i].cput += x; 326: tcpu += x; 327: x = expand(fbuf.ac_stime); 328: tab[i].syst += x; 329: tsys += x; 330: } 331: fclose(ff); 332: } 333: 334: ncmp(p1, p2) 335: struct tab *p1, *p2; 336: { 337: 338: if(p1->count == p2->count) 339: return(tcmp(p1, p2)); 340: if(rflg) 341: return(p1->count - p2->count); 342: return(p2->count - p1->count); 343: } 344: 345: bcmp(p1, p2) 346: struct tab *p1, *p2; 347: { 348: float f1, f2; 349: float sum(); 350: 351: f1 = sum(p1)/p1->count; 352: f2 = sum(p2)/p2->count; 353: if(f1 < f2) { 354: if(rflg) 355: return(-1); 356: return(1); 357: } 358: if(f1 > f2) { 359: if(rflg) 360: return(1); 361: return(-1); 362: } 363: return(0); 364: } 365: tcmp(p1, p2) 366: struct tab *p1, *p2; 367: { 368: extern float sum(); 369: float f1, f2; 370: 371: f1 = sum(p1); 372: f2 = sum(p2); 373: if(f1 < f2) { 374: if(rflg) 375: return(-1); 376: return(1); 377: } 378: if(f1 > f2) { 379: if(rflg) 380: return(1); 381: return(-1); 382: } 383: return(0); 384: } 385: 386: float sum(p) 387: struct tab *p; 388: { 389: 390: if(p->name[0] == 0) 391: return(0.0); 392: return( 393: p->cput+ 394: p->syst); 395: } 396: 397: init() 398: { 399: struct tab tbuf; 400: int i; 401: FILE *f; 402: 403: if ((f = fopen("/usr/adm/savacct", "r")) == NULL) 404: goto gshm; 405: while (fread((char *)&tbuf, sizeof(tbuf), 1, f) == 1) { 406: i = enter(tbuf.name); 407: ncom += tbuf.count; 408: tab[i].count = tbuf.count; 409: treal += tbuf.realt; 410: tab[i].realt = tbuf.realt; 411: tcpu += tbuf.cput; 412: tab[i].cput = tbuf.cput; 413: tsys += tbuf.syst; 414: tab[i].syst = tbuf.syst; 415: } 416: fclose(f); 417: gshm: 418: if ((f = fopen("/usr/adm/usracct", "r")) == NULL) 419: return; 420: fread((char *)user, sizeof(user), 1, f); 421: fclose(f); 422: } 423: 424: enter(np) 425: char *np; 426: { 427: int i, j; 428: 429: for (i=j=0; i<NC; i++) { 430: if (np[i]==0) 431: j = i; 432: if (j) 433: np[i] = 0; 434: } 435: for (i=j=0; j<NC; j++) { 436: i = i*7 + np[j]; 437: } 438: if (i < 0) 439: i = -i; 440: for (i%=size; tab[i].name[0]; i = (i+1)%size) { 441: for (j=0; j<NC; j++) 442: if (tab[i].name[j]!=np[j]) 443: goto no; 444: goto yes; 445: no:; 446: } 447: for (j=0; j<NC; j++) 448: tab[i].name[j] = np[j]; 449: yes: 450: return(i); 451: } 452: 453: strip() 454: { 455: int i, j, c; 456: 457: j = enter("**junk**"); 458: for (i = 0; i<size; i++) { 459: if (tab[i].name[0] && tab[i].count<=thres) { 460: printf("%.10s--", tab[i].name); 461: if ((c=getchar())=='y') { 462: tab[i].name[0] = '\0'; 463: tab[j].count += tab[i].count; 464: tab[j].realt += tab[i].realt; 465: tab[j].cput += tab[i].cput; 466: tab[j].syst += tab[i].syst; 467: } 468: while (c && c!='\n') 469: c = getchar(); 470: } 471: } 472: } 473: 474: time_t 475: expand(t) 476: unsigned t; 477: { 478: register time_t nt; 479: 480: nt = t&017777; 481: t >>= 13; 482: while (t!=0) { 483: t--; 484: nt <<= 3; 485: } 486: return(nt); 487: }