#include <stdio.h>
#include <utmp.h>
#include <sys/types.h>
#include <sys/timeb.h>

/*
 *	tty names are of the form "ttyX" or "ttyXX".
 *	We have tty0 - tty3 and tty00 - tty47
 *	ttyX -> 0-9, ttyXX -> 10-57
 */

#define NTTYS 58

char *ctime();
char *strcpy();
time_t getdate();
static int ttynum();
static void logoff();

static char wtmp[] = "/usr/adm/wtmp";

static struct login {
	char name[8];
	char line[8];
	time_t time;	/* time they logged on at */
} tty[NTTYS];

static time_t earlytime, latetime;	/* the period we are interested in */
static int vflag = 0;
static int Vflag = 0;

main(argc, argv)
char **argv;
{
	struct utmp u;
	register int i;		/* used to index tty[] */
	int ufd;
	struct timeb timeb;	/* somewhere to put current time */
	char from[26], to[26];	/* for munging ctime's output */
	time_t now;		/* used when EOF is reached */

	/*
	 *	Get the time at the moment (for getdate)
	 */
	ftime(&timeb);

	if (argc>=2 && argv[1][0] == '-') {
		switch(argv[1][1]) {
		case 'v':
			vflag = 1;
			break;
		case 'V':
			Vflag = 1;
			break;
		default:
			goto usage;
		}
		argv++; argc--;
	}

	switch (argc) {
	case 1:
	default:
usage:		fputs("Usage: a.out [-v] from [to]\n", stderr);
		exit(1);
	
	case 2:
		earlytime = latetime = getdate(argv[1], &timeb);
		break;

	case 3:
		earlytime = getdate(argv[1], &timeb);
		latetime = getdate(argv[2], &timeb);
		break;
	}
	(void) strcpy(from, ctime(&earlytime));
	(void) strcpy(to, ctime(&latetime));
	from[24] = to[24] = '\0';	/* poke out the newlines */
	fprintf(stderr, "%s - %s\n", from, to);

	if (earlytime > latetime) {
		time_t temp;

		fputs("Time range is later - earlier, swapping.\n", stderr);
		temp = earlytime;
		earlytime = latetime;
		latetime = temp;
	}

	ufd = open(wtmp, 0);
	if (ufd < 0) {
		fprintf(stderr, "Cannot open %s\n", wtmp);
		exit(-1);
	}
	/*
	 *	Start: all users logged off
	 */
	for (i=0; i<NTTYS; i++) tty[i].name[0] = '\0';

	while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u)) {
		if (Vflag || (vflag && earlytime <= u.ut_time && u.ut_time <= latetime) ) printf("%8s %5s %s", u.ut_name, u.ut_line, ctime(&u.ut_time));
		switch (u.ut_line[0]) {
		case '~':
			/* Indicates reboot at this time */
			/* Log everybody off */
			for (i=0; i<NTTYS; i++) {
				if (tty[i].name[0] != '\0') {
					logoff(tty[i].name, tty[i].line, tty[i].time, u.ut_time);
					tty[i].name[0] = '\0';
				}
			}
			goto nextwtmp;
		case '|':
		case '{':	/* } need this so % works in vi (!) */
			/* Time just before and after the date was changed */
			goto nextwtmp;
		case 't':
			/* looks like a normal tty to me. */
			break;
		default:
			/* hunh? */
			fprintf(stderr, "blurglewurgle %s\n", u.ut_line);
			goto nextwtmp;
		}

		switch (u.ut_name[0]) {
		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
		case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
		case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
		case 's': case 't': case 'u': case 'v': case 'w': case 'x':
		case 'y': case 'z':
			/* User login on this tty */
			i = ttynum(u.ut_line);
			if (tty[i].name[0] != '\0') {
				char on[26], already[26];
				(void) strcpy(on, ctime(&u.ut_time));
				(void) strcpy(already, ctime(&tty[i].time));
				on[24] = already[24] = '\0';	/* shoot the newlines */
				fprintf(stderr, "%s: %s logs onto %s occupied by %s since %s!\n", on, u.ut_name, u.ut_line, tty[i].name, already);
				goto nextwtmp;
			}
			(void) strcpy(tty[i].name, u.ut_name);
			(void) strcpy(tty[i].line, u.ut_line);
			tty[i].time = u.ut_time;
			break;
		case '\0':
			/* Null username indicates logoff on that tty */
			i = ttynum(u.ut_line);
			logoff(tty[i].name, tty[i].line, tty[i].time, u.ut_time);
			tty[i].name[0] = '\0';
			break;
		default:
			/* Wurrgh! Blurgle! */
			fprintf(stderr, "Illegal first char in username: \"%s\"\n", u.ut_name);
			goto nextwtmp;

		}
nextwtmp:	;
	}

	/* log out all those logged on */
	now = time(0);
	for (i=0; i<NTTYS; i++) {
		if (tty[i].name[0] != '\0') {
			logoff(tty[i].name, tty[i].line, tty[i].time, now);
		}
	}
	exit(0);
}

static int
ttynum(name)
char *name;
{
	/*
	 *	Nasty routine depends upon names of the form
	 *	ttyX and ttyXX
	 */
	if (name[4] == '\0') {
		/* ttyX */
		return(name[3] - '0');
	}
	return( 10 + name[3] * 10 + name[4] - ('0' * 10 + '0' ) );
}

static void
logoff(name, line, timeon, timeoff)
char *name, *line;
time_t timeon, timeoff;
{
	if (timeon > timeoff) {
		char on[26], off[26];
		(void) strcpy(on, ctime(&timeon));
		(void) strcpy(off, ctime(&timeoff));
		on[24] = off[24] = '\0';	/* shoot the newlines */
		fprintf(stderr, "%s logged on to %s at %s AFTER he logged off at %s!\n", name, line, on, off);
		return;
	}

	/*
	 *	Check the login period to see whether we shuold print it
	 *	If the period overlaps at all, we print.
	 *	ie we only print if both early and late fall on the same side
	 *	of the login period
	 *	it is gusranteed that latetime >= earlytime.
	 */

	if ( latetime >= timeon && earlytime <= timeoff ) {
		char on[26], off[26];
		(void) strcpy(on, ctime(&timeon));
		(void) strcpy(off, ctime(&timeoff));
		on[24] = off[24] = '\0';	/* shoot the newlines */
		printf("%s\t%s\t%s - %s\n", name, line, on, off);
	}
}
