#define WTMP "/usr/actg/data/wtmp" #define FEE "/usr/actg/data/fee" #define LOG "/usr/actg/data/log" #define LOGSIZE 512 #define UACCT "/usr/actg/data/uacct" #define USIZE 256 #define UELTSIZE 44 #define SSIZE 10 /* size of system table */ #define SYST '?' /* * * MODIFICATION OF acct.c SOURCE * */ #define TSIZE 80 /* * entry in wtmp file * connect time is in seconds from login * later converted to minutes (float) * */ struct wtmprec { char name[8]; char tty; char fill1; float time; int fill2; } ibuf; /* * * structure of UACCT file * */ struct uacct { float cutm; float cstm; float crtm; float cctm[2]; int dc; float du; int msamp; float msize; float mproc; int fee; int fill; float spare; } uacct[USIZE]; struct utab { char name[8]; float conn[2]; } utab[USIZE]; struct systab { char system[8]; int boots; } systab[SSIZE]; /* info by system */ /* * information by line * ttime -- last time line on/off * userp -- pointer to entry in utab of user on the line */ struct tbuf { struct utab *userp; float ttime; } tbuf[TSIZE]; int holidays[8] { /* day of year (less 1) */ 1, /* New Year's */ 51, /* Washington's Birthday (76) */ 149, /* Memorial Day */ 184, /* Indep. Day */ 247, /* Labor Day */ 327, /* Thanksgiving */ 328, /* day after */ 359 /* Christmas */ }; char *wtmp WTMP; char *syst SYST; int wtmpfd; int pflag; double midnight; double dtime; double lastime; double day 1440.;/* minutes per day */ int pcount; char **pptr; double bmins,emins,atof(); char *now ""; int reboots; int line, page; int log[USIZE]; int ndate; int *thistime, *localtime(); int ffee[USIZE], zeros[256]; main(argc, argv) char **argv; { int i, c, fl; char *ip; int f; /* get begin/end times for prime shift in minutes */ bmins = 9*60.0 + 0.0; emins = 16*60.0 + 59.0; while (--argc > 0) if (**++argv == '-') switch(*++*argv) { case 'w': if (--argc>0) wtmp = *++argv; continue; case 'p': pflag++; pcount = --argc; argc = 0; pptr = ++argv; continue; default: syst = **argv; continue; } if ( (wtmpfd=open(wtmp,0)) < 0 ) { printf("No %s\n", wtmp); return; } if ((i=open(FEE,0))<0) { printf("can't open fee\n"); exit(9); } if (read(i,ffee,USIZE*2) != USIZE*2) { printf("can't read fee\n"); exit(9); } close(i); /* * open the UACCT file */ if ( (i=open(UACCT,0)) < 0) {printf("can't open %s\n",UACCT); exit(9); } if ( read(i,uacct,USIZE*UELTSIZE) != USIZE*UELTSIZE) {printf("error reading %s\n",UACCT); exit(9); } if ((i=open(LOG,0))<0) printf("can't open date log\n"); else if (read(i,log,LOGSIZE) != LOGSIZE) printf("can't read date log\n"); for(;;) { if( read(wtmpfd,&ibuf,16) != 16) goto brk; fl = 0; for (i=0; i<8; i++) { c = ibuf.name[i]; if ('0'<=c&&c<='9'||'a'<=c&&c<='z'||'A'<=c&&c<='Z') { if (fl) goto skip; continue; } if (c==' ' || c=='\0') { fl++; ibuf.name[i] = '\0'; } else goto skip; } loop(); skip:; } brk: ibuf.name[0] = '\0'; ibuf.tty = 'x'; time(&ibuf.time); loop(); reboots--; /* EOF -- not really a reboot */ output(); } loop() { double ltod(); int i; struct tbuf *tp; struct utab *up; if(ibuf.fill2) return; if( ibuf.fill1 && (ibuf.fill1 != 'h') ) return; thistime = localtime(&ibuf.time); if (*now == '\0') hdg(); /* first time, print heading */ /* change time()-produced time to float minutes */ ibuf.time = ltod(&ibuf.time)/60.0; if(ibuf.tty == '|') { dtime = ibuf.time; return; } if(ibuf.tty == '}') { if(dtime == 0.) return; for(tp = tbuf; tp < &tbuf[TSIZE]; tp++) tp->ttime =+ ibuf.time-dtime; dtime = 0.; return; } if (lastime>ibuf.time || lastime+(1.5*day)<ibuf.time) midnight = 0.0; if (midnight==0.0) newday(); lastime = ibuf.time; /* * if a reboot, update all lines not yet hung up */ if (ibuf.tty=='x') { reboot(); ibuf.name[0] = '\0'; upall(); return; } /* * get an index # from the tty letter */ i = ibuf.tty; i =- '0'; if (i<0 || i>=TSIZE) i = TSIZE-1; tp = &tbuf[i]; update(tp); } /* * proceed through utab * a) calculate today's total connect minutes * b) update user connect time in UACCT * c) if -p, print connect time by user */ output() { int i,j, idx; float ttime, t, tptime, tnptime; if (pflag) { printf("\n\tuser \t prime hrs non-prime hrs\n\n"); line =+ 3; } ttime = tptime = tnptime = 0.0; for (i=0; i<USIZE; i++) { t = utab[i].conn[0] + utab[i].conn[1]; if (ffee[i] > 0) uacct[i].fee =+ ffee[i]; if (t>0.0) { ttime = ttime + t; utab[i].name[7] = '\0'; if((idx = cvtlid(utab[i].name))<0) continue; uacct[idx].cctm[0] = uacct[idx].cctm[0] + utab[i].conn[0]; uacct[idx].cctm[1] = uacct[idx].cctm[1] + utab[i].conn[1]; log[idx] = ndate; tptime = tptime + utab[i].conn[0]; tnptime = tnptime + utab[i].conn[1]; } if (among(i) && t > 0.0) { /* print connect hours leave minutes in utab */ printf("\t%-9s\t%9.2f\t%9.2f\n", utab[i].name, utab[i].conn[0]/60.0, utab[i].conn[1]/60.0); if (++line > 56) /* do the page eject */ {while (line < 66) {putchar('\n'); line++; } printf("\n\n\t\t\tPage%3d\n\n",++page); line = 5; } } } if (ttime > 0.0) { /* print connect time in hours */ printf("\n\ttotal \t%9.2f \t%9.2f \t%9.2f\n", tptime/60.0,tnptime/60.0,ttime/60.0); line =+ 2; } printf("\n\tnumber of reboots: \t%2d\n",reboots); line =+ 2; /* dump out system table */ for (i=0;i<SSIZE;i++) {if (systab[i].system[0] == '\0') break; printf("\t\t%-8s\t%2d\n", systab[i].system, systab[i].boots); line++; } if ((i=creat(LOG,0644))<0) printf("can't creat date log\n"); else { write(i,log,LOGSIZE); close(i); } while(line < 66) {putchar('\n'); line++; } /* * write out updated UACCT info */ if ( (i=creat(UACCT,0644)) < 0) {printf("can't creat %s\n",UACCT); exit(9); } if ((j=creat(FEE,0644))<0) { printf("can't creat fee\n"); exit(9); } write(j,zeros,512); close(j); write(i,uacct,USIZE*UELTSIZE); close(i); } upall() { /* * logoff all tty's in use */ struct tbuf *tp; for (tp=tbuf; tp < &tbuf[TSIZE]; tp++) update(tp); } update(tp) struct tbuf *tp; { int i, j; struct utab *up; double t, t1; t = ibuf.time; /* * if a user at this tty, then he just logged off * update his connect time */ if (tp->userp) { t1 = t - tp->ttime; if (t1>0.0 && t1 < 1.5*day) { connect(tp->userp,t1); } } tp->ttime = t; /* * if an actual logoff (name is \0) * then remove entry from tty table * else set up tty table to point to the new user of this line */ if (ibuf.name[0]=='\0') { tp->userp = 0; return; } for (up=utab; up < &utab[USIZE]; up++) { if (up->name[0] == '\0') break; for (j=0; j<8 && up->name[j]==ibuf.name[j]; j++); if (j>=8) break; } for (j=0; j<8; j++) up->name[j] = ibuf.name[j]; tp->userp = up; } among(i) { int j, k; char *p; if (pflag==0) return(0); if (pcount==0) return(1); for (j=0; j<pcount; j++) { p = pptr[j]; for (k=0; k<8; k++) { if (*p == utab[i].name[k]) { if (*p++ == '\0') return(1); } else break; } } return(0); } newday() { while (midnight <= ibuf.time) midnight = midnight + day; } /* * determine prime/non-prime connect minutes */ connect(up,cmins) struct utab *up; double cmins; { double tmins,smins,p,np; /* * if this is Saturday or Sunday, * then connect time is non-prime */ if( SSH(thistime) ) {up->conn[1] = up->conn[1] + cmins; return; } /* compute this logoff time in minutes */ tmins = thistime[2]*60.0 + thistime[1]; while(tmins<cmins) tmins = tmins + day; /* connected over 24 hrs*/ /* * compute prime/non-prime mins */ p=np=0.0; while(cmins >0) { /* start time of to-be-charged connect time */ smins = tmins - cmins; if(smins<bmins) {np = (tmins<bmins?tmins:bmins)-smins; cmins = cmins - np; continue; } if(smins<emins) {p=(tmins<emins?tmins:emins)-smins; cmins = cmins - p; continue; } {np = np + cmins; cmins = cmins - np; } } /* update information in user table */ up->conn[0] = up->conn[0] + p; up->conn[1] = up->conn[1] + np; } /* * print a heading */ hdg() {int tvec[2]; char save[26]; struct wtmprec lastrec; page = 1; strcpy(save,ctime(&ibuf.time)); save[24]= '\0'; time(tvec); strcpy(now,ctime(tvec)); ndate = (localtime(tvec))[7]; now[24] = '\0'; /* read the last record */ seek(wtmpfd,-16,2); read(wtmpfd,&lastrec,16); seek(wtmpfd,16,0); /* reset read pointer */ printf("\n\nConnect Time / System %c Date: %s\tPage%3d\n\n%s to %s\n", syst,now,page,save,ctime(&lastrec.time)); line = 6; } /* * * get info about loading of new system * */ reboot() { struct systab *sp; int j; /* * enter system into systab or incr its boot count * if it's there */ reboots++; /* incr total reboots */ /* check for not system name in a reboot record */ if (ibuf.name[0] == '\0') return; for (sp=systab;sp < &systab[SSIZE];sp++) { if (sp->system[0] == '\0') break; for(j=0;j<8 && sp->system[j]==ibuf.name[j];j++); if (j>=8) break; } /* put system and count into entry */ for (j=0;j<8;j++) sp->system[j] = ibuf.name[j]; sp->boots++; } /* determine if Saturday, Sunday, or Holiday * if so, return 1, else return 0 */ SSH(ltp) int *ltp; { int i; if( ltp[6] == 0 || ltp[6] == 6 ) return(1); for(i=0;i<8;i++) if( ltp[7] == holidays[i] ) return(1); return(0); }