#ifndef LINT
static char *rcsid="mainloop.c,v 1.1.1.1 1999/08/12 19:36:46 woods Exp";
#endif

/*
	mainloop.c,v
	Revision 1.1.1.1  1999/08/12 19:36:46  woods
	whoson version 1.08
	
	Revision 1.5  1998/07/28 17:51:53  crosser
	make 64bit architecure happy

	Revision 1.4  1998/07/05 00:26:18  crosser
	Change copyright

	Revision 1.3  1998/07/02 18:01:15  crosser
	change error reporting to syslog

	Revision 1.2  1998/07/01 13:39:18  crosser
	make it work on Solaris

	Revision 1.1  1998/07/01 05:01:22  crosser
	Initial revision

*/

/*
	WHAT IS IT:
		Implementation of experimental "whoson" protocol
	AUTHOR:
		Eugene G. Crosser <crosser@average.org>
	COPYRIGHT:
		Public domain
*/

#include "config.h"

#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <stdio.h>
#include <string.h>
#include <limits.h>

#include "whosond.h"
#include "report.h"

void mainloop(struct _evdesc (*evvec[]) (int fd, void *priv), void *priv[])
{
	fd_set rfds,wfds,efds;
	struct timeval seltimer;
	int i,maxfd,rc;
	struct _evdesc evdesc;
	time_t now,until;
	time_t ttl[FD_SETSIZE];

	maxfd=0;
	for (i=0;i<FD_SETSIZE;i++) {
		if (evvec[i]) {
			maxfd=i;
		}
		ttl[i]=(time_t)0;
	}

	(void)time(&now);
	for (;;) {
		FD_ZERO(&rfds);
		FD_ZERO(&wfds);
		FD_ZERO(&efds);
		/* until=INT_MAX; */
		until=now+999999L;
		for (i=0;i<=maxfd;i++) if (evvec[i]) {
			if (ttl[i] && (ttl[i] < until) && (ttl[i] > now))
				 until=ttl[i];
			if (ttl[i] && (ttl[i] <= now)) {
				ERRLOG((LOG_INFO,"kill fd=%d\n",i))
				(void)evvec[i](-i,priv[i]);
				evvec[i]=NULL;
				priv[i]=NULL;
				ttl[i]=0;
			} else
				FD_SET(i,&rfds);
		}
		seltimer.tv_sec=until-now;
		seltimer.tv_usec=0;

#if (DPRINT)

		for (i=0;i<FD_SETSIZE;i++) {
			DPRINT(("%c",FD_ISSET(i,&rfds)?'1':'0'))
		}
#endif

		DPRINT(("\nselect maxfd+1=%d tv_sec=%ld tv_usec=%ld\n",
				maxfd+1,(long)seltimer.tv_sec,
				(long)seltimer.tv_usec))

		rc=select(maxfd+1,&rfds,&wfds,&efds,&seltimer);
		if (rc >= 0) (void)time(&now);
		if (rc > 0) {
			for (i=0;i<=maxfd;i++) if (FD_ISSET(i,&rfds)) {
				if (evvec[i]) {
					evdesc=evvec[i](i,priv[i]);
					if (evdesc.fd >= 0) {
						evvec[evdesc.fd]=evdesc.evproc;
						if (evdesc.ttl)
							ttl[evdesc.fd]=
								now+evdesc.ttl;
						priv[evdesc.fd]=evdesc.priv;
					}
					if (evdesc.fd > maxfd)
						maxfd=evdesc.fd;
				} else {
					ERRLOG((LOG_WARNING,"spurious fd=%d\n",i))
				}
			}
		} else if (rc == 0) {
			printf("timeout\n");
		} else {
			ERRLOG((LOG_ERR,"select failure: %m"))
		}
	}
}
