#
/*
 * acct [ -w wtmp ] [ -d ] [ -p people ]
 */
#define	TSIZE	100
#define	USIZE	200
struct {
	char	name[8];
	char	line[2];
	float	time;
	int	pid;
} ibuf;
struct ubuf {
	char	name[8];
	float	utime;
} ubuf[USIZE];
struct tbuf {
	struct	ubuf	*userp;
	float	ttime;
} tbuf[TSIZE];
char	*wtmp;
int	pflag, byday;
double	dtime;
double	midnight;
double	lastime;
double	day	1440.;
int	pcount;
char	**pptr;
int	montab[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
		31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char	*monasc[] {
	"Jan",
	"Feb",
	"Mar",
	"Apr",
	"May",
	"Jun",
	"Jul",
	"Aug",
	"Sep",
	"Oct",
	"Nov",
	"Dec"
};
int snum[TSIZE];
main(argc, argv) 
char **argv;
{
	register i;
	register char *ip;
	extern fin;
	int c,f,fl;
	wtmp = "/etc/wtmp";
	while (--argc > 0 && **++argv == '-')
	switch(*++*argv) {
	case 'd':
		byday++;
		continue;
	case 'w':
		if (--argc>0)
			wtmp = *++argv;
		continue;
	case 'p':
		pflag++;
		continue;
	}
	pcount = argc;
	pptr = argv;
	if (fopen(wtmp, &fin) < 0) {
		printf("No %s\n", wtmp);
		exit(-1);
	}
	printf("Total user connect time in hours:\n");
	for(;;) {
		ip = &ibuf;
		for (i=0; i<16; i++) {
			if ((c=getc(&fin)) < 0)
				goto brk;
			*ip++ = c;
		}
		if(ibuf.line[0]=='R' && ibuf.line[1]=='L')
			continue;
		fl = 0;
		for (i=0; i<8; i++) {
			if (i==0)
				ibuf.name[i] =& ~0200;
			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:	continue;
	}
    brk:
	ibuf.name[0] = '\0';
	ibuf.line[0] = '!';
	ibuf.line[1] = 'B';
	time(&ibuf.time);
	loop();
	print();
	exit(0);
}
loop()
{
	double ltod();
	register i;
	register struct tbuf *tp;
	register struct ubuf *up;
	ibuf.time = ltod(&ibuf.time)/60.;
	if(ibuf.line[0] == 'O' && ibuf.line[1] == 'T') {
		dtime = ibuf.time;
		return;
	}
	if(ibuf.line[0] == 'N' && ibuf.line[1] == 'T') {
		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 (byday && ibuf.time > midnight) {
		upall(1);
		print();
		newday();
		for (up=ubuf; up < &ubuf[USIZE]; up++)
			up->utime = 0.0;
	}
	if (ibuf.line[0] == '!' && ibuf.line[1] == 'B') {
		ibuf.name[0] = '\0';
		upall(0);
		return;
	}
	if((i=tmap()) < 0) return;
	tp = &tbuf[i];
	update(tp, 0);
}
print()
{
	int i;
	float ttime, t;
	ttime = 0.0;
	for (i=0; i<USIZE; i++) {
		if(!among(i))
			continue;
		t = ubuf[i].utime;
		if (t>0.0)
			ttime =+ t;
		if (pflag && ubuf[i].utime > 0.0) {
			printf("\t%-8.8s%6.2f\n",
			    ubuf[i].name, ubuf[i].utime/60.);
		}
	}
	if (ttime > 0.0) {
		pdate();
		printf("\ttotal%9.2f\n", ttime/60.);
	}
}
upall(f)
{
	register struct tbuf *tp;
	for (tp=tbuf; tp < &tbuf[TSIZE]; tp++)
		update(tp, f);
}
update(tp, f)
struct tbuf *tp;
{
	int i, j;
	struct ubuf *up;
	double t, t1;
	if (f)
		t = midnight;
	else
		t = ibuf.time;
	if (tp->userp) {
		t1 = t - tp->ttime;
		if (t1>0.0 && t1 < 1.5*day)
			tp->userp->utime =+ t1;
	}
	tp->ttime = t;
	if (f)
		return;
	if (ibuf.name[0]=='\0') {
		tp->userp = 0;
		return;
	}
	for (up=ubuf; up < &ubuf[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)
{
	register j, k;
	register char *p;
	if (pcount==0)
		return(1);
	for (j=0; j<pcount; j++) {
		p = pptr[j];
		for (k=0; k<8; k++) {
			if (*p == ubuf[i].name[k]) {
				if (*p++ == '\0')
					return(1);
			} else
				break;
		}
	}
	return(0);
}
newday()
{
	if(midnight == 0.)
		midnight = 240.;
	while (midnight <= ibuf.time)
		midnight =+ day;
}
pdate()
{
	register days, mons, yrs;
	double year, tim;
	if (byday==0)
		return;
	yrs = 2;
	tim = 0.0;
	for(;;) {
		year = 365. * day;
		if(yrs%4 == 0)
			year =+ day;
		if(tim+year > midnight)
			break;
		yrs++;
		tim =+ year;
	}
	days = (midnight-tim-720.)/day;
	montab[1] = 28;
	if(yrs%4 == 0)
		montab[1]++;
	for (mons=0; montab[mons]<=days; mons++)
		days =- montab[mons];
	mons =% 12;
	printf("%s %2d", monasc[mons], days+1);
}
tmap()
{
	register int i;
	struct{
	    char lobyte;
	    char hibyte;
	};
	for(i=0;i<TSIZE;i++){
		if(ibuf.line[0]==snum[i].lobyte && ibuf.line[1]==snum[i].hibyte)
			return(i);
		if(snum[i] == 0){
			snum[i].lobyte = ibuf.line[0];
			snum[i].hibyte = ibuf.line[1];
			return(i);
		}
	}
	printf("TSIZE < number of line id's-- increase TSIZE\n");
	return(-1);
}
