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

struct utmp	who[64];
int *lt;
char *getwtmp(), *wtmp;

char	ttyslt[64][8];
int	nttys = 0;
char buf[5120];


main(c,v)
char **v;
{
	register struct utmp *pw;
	register r;
	register short i;
	int fd;
	long ptime, gtime(), nowt;

	if(c == 2)wtmp = getwtmp(*++v, 0);
	else	if(c == 3){
		wtmp = v[2];
		getwtmp(*++v, 1);
		}	else	getwtmp("0", 0);

	if((fd = open(wtmp, 0)) == -1){
		printf("Can not open %s\n", wtmp);
		exit(1);
	}

	ptime = gtime(*v);
	time(&nowt);
	if(ptime > nowt){
		lt[5] =- 1;
		ptime = gtime(*v);
	}
	printf("Who on: %s (%s)\n", ctime(&ptime), wtmp);

	while((r = read(fd, buf, (sizeof (struct utmp))*64)) %
		(sizeof (struct utmp)) == 0 && r)
		for(pw = buf; pw < &buf[r]; pw++){
			if(pw->ut_time > ptime)goto gotit;
			if(pw->ut_line[0] == '~'){
				for(i = 0; i < 64; i++)
					who[i].ut_name[0] = 0;
				continue;
			}
			if(pw->ut_type == DEAD_PROCESS)
				who[ttynum(pw->ut_line)].ut_name[0] = 0;
			else	copy(&who[ttynum(pw->ut_line)], pw);
		}

gotit:
	pwho();
	close(fd);
}

copy(s,t)
register char *s, *t;
{
	register int i;
	for(i = 0; i < sizeof (struct utmp); i++)
		*s++ = *t++;
}

pwho(){
	register struct utmp *pw;
	register char *s;

	for(pw = who; pw < &who[64]; pw++)
		if(pw->ut_name[0]){
			s = ctime(&(pw->ut_time));
			printf("%-8.8s %-8.8s %20.20s\n", pw->ut_name, pw->ut_line, s+4);
		}
}

int mon[13] = { 0 , 0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 };


long gtime(s)
register char *s;
{
	long i;
	int m , d , y , h , min;

	i = 0L;

	y = 1900 + lt[5];
	m = lt[4];
	d = lt[3];
	h = lt[2];
	min = lt[1];
	if(m < 1 || m > 12)write(2,"?Month\n", 7);
	else	if(d < 1 || d > 31)write(2,"?Day\n", 5);
		else	if(h < 0 || h > 23)write(2,"?Hour\n", 6);
			else	if(min < 0 || min > 59)write(2,"?Minute\n", 8);
				else	if(m == 2 && y%4 && d > 28)write(2,"?Leap\n", 6);
					else goto ok;
	exit(1);
ok:

	h =+ 5;
	if((m > 4 && m < 10) ||
	(m == 4 && d > 26) || (m == 10 && d < 25) ||
	(m == 4 && d == 26 && h > 6) ||
	(m == 10 && d == 25 && h == 5))h--;

	i = (y - 1970)*365L + (y-1)/4L - 492L;
	i = (i + mon[m] + (m > 2 && ((y%4) == 0)) + d - 1)*24L;
	i = ((i + h)*60L + min)*60L;
	return(i);
}


val(s)
register char *s;
{
	register int j;

	j = (*s - '0')*10 + (*(s+1)-'0');
	return(j);
}



struct	lst	{
	char nmm[14];
	struct lst *pl;
	struct lst *pr;
} lst[400];

struct	lst	*base, *next, *last;


char *getwtmp(s, f)
register f;
char *s;
{
	register struct lst *p;
	register int *t;

	int *localtime(), tv[2];

	char *swt = "/accting/wtmp/w.00.00.00.00";
	char *wt = "w.00.00.00.00";
	char *now = "w.00.00.00.00";

	time(tv);
	t = lt = localtime(tv);
	t[4] =+ 1;
	mkwtmp(t, now);

	switch(strlen(s)){

	case 2:
		t[2] = val(s);
		t[1] = 0;
		break;

	case 4:
		t[2] = val(s);
		t[1] = val(s+2);
		break;

	case 6:
rest:
		t[3] = val(s);
		t[2] = val(s+2);
		t[1] = val(s+4);
		break;

	case 8:
		t[4] = val(s);
		s =+ 2;
		goto rest;

	default:
		printf("Usage: owho HH [file]\n\towho HHMM [file]\n\t");
		printf("owho DDHHMM [file]\n\towho MMDDHHMM [file]\n");
		exit(1);
	}
	mkwtmp(t, wt);
	fill();

	for(p = last; p != 0; p = p->pl)
		if(strcmp(wt, p->nmm) >= 0)break;

	if(p == last ||
		 (strcmp(now, p->pr->nmm) < 0 && strcmp(wt, now) < 0))
			return("/etc/wtmp");
	if(p == 0){
		printf("Confused.\n");
		exit(1);
	}
	strcpy(swt+14, p->pr->nmm);
	return(swt);
}

mkwtmp(t, s)
int t[];
register char *s;
{
	cov(s+2, t[4]);
	cov(s+5, t[3]);
	cov(s+8, t[2]);
	cov(s+11, t[1]);
}

cov(s,n)
register char *s;
register n;
{
	*s++ = n/10 + '0';
	*s = n%10 + '0';
}

fill()
{
	char buf[512];
	register struct {
		int ino;
		char nm[14];
	} *pd;
	register r;
	int fd;


	next = base = lst;

	if((fd = open("/accting/wtmp", 0)) == -1){
		printf("No henry directory\n");
		exit(3);
	}

	while(r = read(fd, buf, 512))
		for(pd = buf; pd < &buf[r]; pd++)
			if(pd->ino && pd->nm[4] == '.')add(pd->nm);
	close(fd);
}

add(s)
register char *s;
{
	register struct lst *nxt, *p;

	if(s[13])return;
	nxt = next;

	strcpy(nxt->nmm, s);

	if(base == nxt){
		nxt->pl = 0;
		last = base;
		base->pr = ++nxt;
		nxt->pl = base;
		nxt->pr = 0;
		next = nxt;
		return;
	}

	for(p = base; p != nxt; p = p->pr)
		if(strcmp(s, p->nmm) < 0){
			nxt->pr = p;
			nxt->pl = p->pl;
			if(p->pl)p->pl->pr = nxt;
			else	base = nxt;
			p->pl = nxt++;
			nxt->pl = last;
			nxt->pr = 0;
			last->pr = nxt;
			next = nxt;
			return;
		}

	p = nxt;
	last = p;
	p->pr = ++nxt;
	nxt->pl = p;
	nxt->pr = 0;
	next = nxt;
}


ttynum(s)
register char *s;
{
	register i;

	for(i = 0; i < nttys; i++){
		if(strncmp(s, ttyslt[i], 8) == 0)
			return(i);
	}
	strncpy(ttyslt[i], s, 8);
	nttys++;
	return(i);
}

