#ifndef LINT
static char *rcsid="whosond.c,v 1.2 1999/08/30 01:39:53 woods Exp";
#endif

/*
	whosond.c,v
	Revision 1.2  1999/08/30 01:39:53  woods
	- version.h is not needed with automake
	
	Revision 1.13  1998/07/28 17:51:53  crosser
	make 64bit architecure happy

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

	Revision 1.11  1998/07/05 00:01:27  crosser
	add user and group set

	Revision 1.10  1998/07/03 09:32:48  crosser
	autoconf for signal and detach

	Revision 1.9  1998/07/02 18:17:12  crosser
	fix proc. of -v option

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

	Revision 1.7  1998/07/01 21:55:16  crosser
	cosmetics

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

	Revision 1.5  1998/07/01 05:18:09  crosser
	minor warnings fix

	Revision 1.4  1998/07/01 05:01:22  crosser
	Big reorganization

*/

/*
	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 <time.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#include "whosond.h"
#include "serv_common.h"
#include "rtconfig.h"
#include "report.h"
 
int wso_verbose=0;

static void showver(char *name)
{
	fprintf(stderr,"%s Version %s Build %s\n",name,VERSION,__DATE__);
}

static void showhelp(char *name)
{
	fprintf(stderr,"Usage: %s -I configfile -V -v -h\n",name);
	fprintf(stderr,"\t-I configfile\t- replacement config [default: %s]\n",DEFAULT_CONFIG);
	fprintf(stderr,"\t-d\t\t- do not go to background\n");
	fprintf(stderr,"\t-V\t\t- print version\n");
	fprintf(stderr,"\t-v\t\t- increase verbosity\n");
	fprintf(stderr,"\t-h\t\t- print this help message\n");
}

int main(int argc, char *argv[])
{
	struct _evdesc (*evvec[FD_SETSIZE]) (int fd, void *priv);
	void *priv[FD_SETSIZE];
	struct _evdesc evdesc;
	struct _servdesc *servdesc;
	int i;
	char *configfile=DEFAULT_CONFIG;
	int daemon=1;

	while ((i=getopt(argc,argv,"I:dvVh")) != EOF) switch (i) {
	case 'I':
		/* if someone decides to modify the name displayed in
		   the "ps" output it may be useful to copy the arg... */
		configfile=(char *)malloc(strlen(optarg)+1);
		strcpy(configfile,optarg);
		break;
	case 'd':
		daemon=0;
		break;
	case 'V':
		showver(argv[0]);
		return 0;
	case 'v':
		wso_verbose++;
		break;
	case 'h':
		showhelp(argv[0]);
		return 0;
	default:
		showhelp(argv[0]);
		return 1;
	}

	if (daemon) {
		int child;
		if ((child=fork()) > 0) {
			sleep(1);
			return 0;
		} else if (child < 0) {
			ERRLOG((LOG_ERR,"fork error: %m"))
			return 1;
		} else {
			fflush(stdin);
			fflush(stdout);
			fflush(stderr);
			setbuf(stdin,NULL);
			setbuf(stdout,NULL);
			setbuf(stderr,NULL);
			close(0);
			close(1);
			close(2);
			open("/dev/null",O_RDWR);
			dup(0);
			dup(0);
#ifdef HAVE_SETSID
			setsid();
#else
#ifdef HAVE_SETPGRP
#ifdef SETPGRP_VOID
			setpgrp();
#else
			setpgrp(0,0);
#endif
#endif
#endif
		}
	}

#ifdef HAVE_SYSLOG
	openlog("whosond",LOG_CONS|LOG_PID,LOG_DAEMON);
#endif

	for (i=0;i<FD_SETSIZE;i++) {
		evvec[i]=0;
		priv[i]=0;
	}

	if (!(servdesc=wso_read_config(configfile,1))) {
		ERRLOG((LOG_ERR,"No configured servers\n"))
		return 1;
	}

	i=0;
	for (;servdesc;servdesc=servdesc->next) {
		evdesc=(servdesc->root.init)(servdesc->priv);
		if (evdesc.fd >= 0) {
			evvec[evdesc.fd]=evdesc.evproc;
			priv[evdesc.fd]=evdesc.priv;
			i++;
		}
	}

	if (i == 0) {
		ERRLOG((LOG_ERR,"No initialized servers\n"))
		return 1;
	}

	if (rungid) {
		setegid(rungid);
		setgid(rungid);
	}
	if (runuid) {
		seteuid(runuid);
		setuid(runuid);
	}

	mainloop(evvec,priv);

	return 0;
}
