static char *sccsid = "@(#)sa.c 4.1 (Berkeley) 10/1/80"; #include <stdio.h> #include <sys/types.h> #include <sys/acct.h> #include <signal.h> /* interpret command time accounting */ #define size 2500 #define NC sizeof(acctbuf.ac_comm) struct acct acctbuf; int lflg; int cflg; int Dflg; int dflg; int iflg; int jflg; int Kflg; int kflg; int nflg; int aflg; int rflg; int oflg; int tflg; int vflg; int uflg; int thres = 1; int sflg; int bflg; int mflg; struct user { int us_cnt; double us_ctime; double us_io; double us_imem; } user[1000]; struct tab { char name[NC]; int count; double realt; double cput; double syst; double imem; double io; } tab[size]; double treal; double tcpu; double tsys; double tio; double timem; int junkp = -1; char *sname; double ncom; time_t expand(); char *getname(); main(argc, argv) char **argv; { FILE *ff; int i, j, k; int (*cmp)(); extern tcmp(), ncmp(), bcmp(), dcmp(), Dcmp(), kcmp(), Kcmp(); extern double sum(); double ft; cmp = tcmp; if (argc>1) if (argv[1][0]=='-') { argv++; argc--; for(i=1; argv[0][i]; i++) switch(argv[0][i]) { case 'o': oflg++; break; case 'i': iflg++; break; case 'b': bflg++; cmp = bcmp; break; case 'l': lflg++; break; case 'c': cflg++; break; case 'd': dflg++; cmp = dcmp; break; case 'D': Dflg++; cmp = Dcmp; break; case 'j': jflg++; break; case 'k': kflg++; cmp = kcmp; break; case 'K': Kflg++; cmp = Kcmp; break; case 'n': nflg++; cmp = ncmp; break; case 'a': aflg++; break; case 'r': rflg++; break; case 't': tflg++; break; case 's': sflg++; aflg++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': thres = argv[0][i]-'0'; break; case 'v': vflg++; break; case 'u': uflg++; break; case 'm': mflg++; break; } } if (iflg==0) init(); if (argc<2) doacct("/usr/adm/acct"); else while (--argc) doacct(*++argv); if (uflg) { return; } /* * cleanup pass * put junk together */ if (vflg) strip(); if(!aflg) for (i=0; i<size; i++) if (tab[i].name[0]) { for(j=0; j<NC; j++) if(tab[i].name[j] == '?') goto yes; if(tab[i].count != 1) continue; yes: if(junkp == -1) junkp = enter("***other"); tab[junkp].count += tab[i].count; tab[junkp].realt += tab[i].realt; tab[junkp].cput += tab[i].cput; tab[junkp].syst += tab[i].syst; tab[junkp].imem += tab[i].imem; tab[junkp].io += tab[i].io; tab[i].name[0] = 0; } for(i=k=0; i<size; i++) if(tab[i].name[0]) { tab[k] = tab[i]; k++; } if (sflg) { signal(SIGINT, SIG_IGN); if ((ff = fopen("/usr/adm/usracct", "w")) != NULL) { fwrite((char *)user, sizeof(user), 1, ff); fclose(ff); } if ((ff = fopen("/usr/adm/savacct", "w")) == NULL) { printf("Can't save\n"); exit(0); } fwrite((char *)tab, sizeof(tab[0]), k, ff); fclose(ff); creat("/usr/adm/acct", 0644); signal(SIGINT, SIG_DFL); } /* * sort and print */ if (mflg) { printmoney(); exit(0); } qsort(tab, k, sizeof(tab[0]), cmp); column(ncom, treal, tcpu, tsys, timem, tio); printf("\n"); for (i=0; i<k; i++) if (tab[i].name[0]) { ft = tab[i].count; column(ft, tab[i].realt, tab[i].cput, tab[i].syst, tab[i].imem, tab[i].io); printf(" %.14s\n", tab[i].name); } } printmoney() { register i; char buf[128]; register char *cp; for (i=0; i<sizeof(user)/sizeof(user[0]); i++) { if (user[i].us_cnt && user[i].us_ctime) { cp = getname(i); if (cp == 0) printf("%-8d", i); else printf("%-8s", cp); printf("%7u %9.2fcpu %10.0ftio %12.0fk*sec\n", user[i].us_cnt, user[i].us_ctime/60, user[i].us_io, user[i].us_imem / (60 * 2)); } } } column(n, a, b, c, d, e) double n, a, b, c, d, e; { printf("%8.0f", n); if(cflg) { if(n == ncom) printf("%9s", ""); else printf("%8.2f%%", 100.*n/ncom); } col(n, a, treal, "re"); if (oflg) col(n, 3600*(b/(b+c)), tcpu+tsys, "u/s"); else if(lflg) { col(n, b, tcpu, "u"); col(n, c, tsys, "s"); } else col(n, b+c, tcpu+tsys, "cp"); if(tflg) printf("%8.1f", a/(b+c), "re/cp"); if(dflg || !Dflg) printf("%10.0favio", e/(n?n:1)); else printf("%10.0ftio", e); if (kflg || !Kflg) printf("%10.0fk", d/(2*((b+c)!=0.0?(b+c):1.0))); else printf("%10.0fk*sec", d/(2*60)); } col(n, a, m, cp) double n, a, m; char *cp; { if(jflg) printf("%11.2f%s", a/(n*60.), cp); else printf("%11.2f%s", a/3600., cp); if(cflg) { if(a == m) printf("%9s", ""); else printf("%8.2f%%", 100.*a/m); } } doacct(f) char *f; { int i; FILE *ff; long x, y, z; struct acct fbuf; register char *cp; register int c; if (sflg && sname) { printf("Only 1 file with -s\n"); exit(0); } if (sflg) sname = f; if ((ff = fopen(f, "r"))==NULL) { printf("Can't open %s\n", f); return; } while (fread((char *)&fbuf, sizeof(fbuf), 1, ff) == 1) { if (fbuf.ac_comm[0]==0) { fbuf.ac_comm[0] = '?'; } for (cp = fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++) { c = *cp & 0377; if (c && (c < ' ' || c >= 0200)) { *cp = '?'; } } if (fbuf.ac_flag&AFORK) { for (cp=fbuf.ac_comm; cp < &fbuf.ac_comm[NC]; cp++) if (*cp==0) { *cp = '*'; break; } } x = expand(fbuf.ac_utime) + expand(fbuf.ac_stime); y = fbuf.ac_mem; z = expand(fbuf.ac_io); if (uflg) { printf("%3d%6.1fcp %6dmem %6dio %.14s\n", fbuf.ac_uid, x/60.0, y, z, fbuf.ac_comm); continue; } c = fbuf.ac_uid; user[c].us_cnt++; user[c].us_ctime += x/60.; user[c].us_imem += x * y; user[c].us_io += z; ncom += 1.0; i = enter(fbuf.ac_comm); tab[i].imem += x * y; timem += x * y; tab[i].count++; x = expand(fbuf.ac_etime)*60; tab[i].realt += x; treal += x; x = expand(fbuf.ac_utime); tab[i].cput += x; tcpu += x; x = expand(fbuf.ac_stime); tab[i].syst += x; tsys += x; tab[i].io += z; tio += z; } fclose(ff); } ncmp(p1, p2) struct tab *p1, *p2; { if(p1->count == p2->count) return(tcmp(p1, p2)); if(rflg) return(p1->count - p2->count); return(p2->count - p1->count); } bcmp(p1, p2) struct tab *p1, *p2; { double f1, f2; double sum(); f1 = sum(p1)/p1->count; f2 = sum(p2)/p2->count; if(f1 < f2) { if(rflg) return(-1); return(1); } if(f1 > f2) { if(rflg) return(1); return(-1); } return(0); } Kcmp(p1, p2) struct tab *p1, *p2; { if (p1->imem < p2->imem) { if(rflg) return(-1); return(1); } if (p1->imem > p2->imem) { if(rflg) return(1); return(-1); } return(0); } kcmp(p1, p2) struct tab *p1, *p2; { double a1, a2; a1 = p1->imem / ((p1->cput+p1->syst)?(p1->cput+p1->syst):1); a2 = p2->imem / ((p2->cput+p2->syst)?(p2->cput+p2->syst):1); if (a1 < a2) { if(rflg) return(-1); return(1); } if (a1 > a2) { if(rflg) return(1); return(-1); } return(0); } dcmp(p1, p2) struct tab *p1, *p2; { double a1, a2; a1 = p1->io / (p1->count?p1->count:1); a2 = p2->io / (p2->count?p2->count:1); if (a1 < a2) { if(rflg) return(-1); return(1); } if (a1 > a2) { if(rflg) return(1); return(-1); } return(0); } Dcmp(p1, p2) struct tab *p1, *p2; { if (p1->io < p2->io) { if(rflg) return(-1); return(1); } if (p1->io > p2->io) { if(rflg) return(1); return(-1); } return(0); } tcmp(p1, p2) struct tab *p1, *p2; { extern double sum(); double f1, f2; f1 = sum(p1); f2 = sum(p2); if(f1 < f2) { if(rflg) return(-1); return(1); } if(f1 > f2) { if(rflg) return(1); return(-1); } return(0); } double sum(p) struct tab *p; { if(p->name[0] == 0) return(0.0); return( p->cput+ p->syst); } init() { struct tab tbuf; int i; FILE *f; if ((f = fopen("/usr/adm/savacct", "r")) == NULL) goto gshm; while (fread((char *)&tbuf, sizeof(tbuf), 1, f) == 1) { i = enter(tbuf.name); ncom += tbuf.count; tab[i].count = tbuf.count; treal += tbuf.realt; tab[i].realt = tbuf.realt; tcpu += tbuf.cput; tab[i].cput = tbuf.cput; tsys += tbuf.syst; tab[i].syst = tbuf.syst; tio += tbuf.io; tab[i].io = tbuf.io; timem += tbuf.imem; tab[i].imem = tbuf.imem; } fclose(f); gshm: if ((f = fopen("/usr/adm/usracct", "r")) == NULL) return; fread((char *)user, sizeof(user), 1, f); fclose(f); } enter(np) char *np; { int i, j; for (i=j=0; i<NC; i++) { if (np[i]==0) j = i; if (j) np[i] = 0; } for (i=j=0; j<NC; j++) { i = i*7 + np[j]; } if (i < 0) i = -i; for (i%=size; tab[i].name[0]; i = (i+1)%size) { for (j=0; j<NC; j++) if (tab[i].name[j]!=np[j]) goto no; goto yes; no:; } for (j=0; j<NC; j++) tab[i].name[j] = np[j]; yes: return(i); } strip() { int i, j, c; j = enter("**junk**"); for (i = 0; i<size; i++) { if (tab[i].name[0] && tab[i].count<=thres) { printf("%.14s--", tab[i].name); if ((c=getchar())=='y') { tab[i].name[0] = '\0'; tab[j].count += tab[i].count; tab[j].realt += tab[i].realt; tab[j].cput += tab[i].cput; tab[j].syst += tab[i].syst; } while (c && c!='\n') c = getchar(); } } } time_t expand(t) unsigned t; { register time_t nt; nt = t&017777; t >>= 13; while (t!=0) { t--; nt <<= 3; } return(nt); } #include <utmp.h> #include <pwd.h> struct utmp utmp; #define NMAX sizeof (utmp.ut_name) #define NUID 2048 char names[NUID][NMAX+1]; char * getname(uid) { register struct passwd *pw; static init; struct passwd *getpwent(); if (names[uid][0]) return (&names[uid][0]); if (init == 2) return (0); if (init == 0) setpwent(), init = 1; while (pw = getpwent()) { if (pw->pw_uid >= NUID) continue; if (names[pw->pw_uid][0]) continue; strncpy(names[pw->pw_uid], pw->pw_name, NMAX); if (pw->pw_uid == uid) return (&names[uid][0]); } init = 2; endpwent(); return (0); }