/*======================================================================
                    R C F I L E . C 
                    doc: Fri Mar 13 16:24:22 1992
                    dlm: Tue Jul 20 17:21:05 1993
                    (c) 1992 ant@ips.id.ethz.ch
                    uE-Info: 18 0 T 0 0 72 10 2 8 ofnI
======================================================================*/

#include	<stdio.h>
#include	<ctype.h>
#include	<string.h>
#include	<sys/param.h>
#include	<sys/types.h>
#include	<rpc/rpc.h>
#include	"inetray.h"
#include	"config.h"
#include	"common.h"

typedef struct infoList {
	struct infoList *next;			/* linked list */
	char	name[MAXHOSTNAMELEN];		/* name */
	int	nSvcs;				/* # of workers to params */
	int	uid;				/* remote uid */
} infoList;

static infoList *ignore = NULL;			/* ignore hosts */
static infoList *host = NULL;			/* use hosts */
static infoList *net = NULL;			/* use nets */
static infoList local;				/* local params */

short	portNumber = RESULTPORT;		/* result port */
int	rTimeout = RTIMEOUT;			/* non-default timeout */
int	minWorkers = 0;				/* wait for at least those */
int	maxWorkers = 99999;			/* ignore if more than those */
int	minBlockSize = MINBLOCKSIZE;		/* from config.h */
int	maxBlockSize = 99999;			/* cutoff after this */
int	blocksPerServer = BLOCKSPERSERVER;	/* from config.h */

extern	int	sendrpc_timeout;		/* from sendrpc.c */

doThis(hName)					/* do this machine? */
char *hName;
{
	infoList	*dont;

	for (dont=ignore; dont!=NULL; dont=dont->next)
		if (strcasecmp(dont->name,hName) == 0) return FALSE;
	return TRUE;
}

getHost(first,hName,nSvcs,uid)			/* get next to do */
int first; char **hName; int *nSvcs,*uid;
{
	static infoList *cur;

	if (first) cur = host;			/* get current */
	else cur = cur->next;
	while ((cur != NULL) &&
	       (cur->name[0] == '\0'))
		cur = cur->next;
	if (cur == NULL) return FALSE;		/* end of list */
	*hName = cur->name;
	*nSvcs = cur->nSvcs;
	*uid = cur->uid;
	return TRUE;
}

getNet(first,name,nSvcs,uid)			/* get next to do */
int first; char **name; int *nSvcs,*uid;
{
	static infoList *cur;

	if (first) cur = net;			/* get current */
	else cur = cur->next;
	while ((cur != NULL) &&
	       (cur->name[0] == '\0')) 
		cur = cur->next;
	if (cur == NULL) return FALSE;		/* end of list */
	*name = cur->name;
	*nSvcs = cur->nSvcs;
	*uid = cur->uid;
	return TRUE;
}

getLocal(name,nSvcs,uid)			/* get next to do */
char **name; int *nSvcs,*uid;
{
	*name = local.name;
	*nSvcs = local.nSvcs;
	*uid = local.uid;
	return TRUE;
}

void addUseList(ac,av)				/* add one to use list */
int ac; char *av[];
{
	char	buf[1024];
	int	a,i,p;
	void	parseUseList();
	
	local.next = NULL;
	strcpy(local.name,"Local Net");
	local.nSvcs = 0;
	local.uid = geteuid();

	for (a=1,p=0; a<ac; a++) {		/* loop over args */
		for (i=0; p<1023; i++) {	/* loop over chars */
			if (av[a][i] != '\0')
				buf[p++] = av[a][i];
			else
				break;
		}
		if (p<1023) buf[p++] = ' ';	/* inter arg space */
	}
	buf[p] = '\0';				/* end of args */
	parseUseList(buf);
}
	
/*----------------------------------------------------------------------*/

void readRc()					/* read RCFILE */
{
	FILE	*fp;
	char	*home,buf[1024],*sp,*getenv();
	int	pos;

	local.next = NULL;			/* init local info */
	strcpy(local.name,"Local Net");
	local.nSvcs = 1;
	local.uid = geteuid();
	
	fp = fopen(RCFILE,"r");			/* open file */
	if (fp == NULL) {
		home = getenv("HOME");
		if (home == NULL) return;
		sprintf(buf,"%s/%s",home,RCFILE);
		fp = fopen(buf,"r");
		if (fp == NULL) return;
	}
	while (fgets(buf,1024,fp) != NULL) {
		sp = strchr(buf,'#');		/* kill comments */
		if (sp != NULL) *sp = '\0';
		if (isEmpty(buf)) continue;	/* select command type */
		if (isUse(buf)) continue;
		if (isIgnore(buf)) continue;
		if (isPortNr(buf)) continue;
		if (isTimeout(buf)) continue;
		if (isMinWorkers(buf)) continue;
		if (isMaxWorkers(buf)) continue;
		if (isMinBlockSize(buf)) continue;
		if (isMaxBlockSize(buf)) continue;
		if (isBlocksPerServer(buf)) continue;
		sp = strchr(buf,'\n');		/* kill newline */
		if (sp != NULL) *sp = '\0';
		fprintf(stderr,"%s: <%s> ignored!\n",RCFILE,buf);
	}
	sendrpc_timeout = rTimeout;
}

static char *compare(s,trg)			/* special compare */
char *s,*trg;
{
	while (*trg != '\0') {
		while (isspace(*s)) s++;	/* skip spaces */
		if (toupper(*s) != *trg)	/* check next char */
			return NULL;
		s++; trg++;
	}
	return s;
}

static char *getToken(s,tBuf)			/* copy token */
char *s,*tBuf;
{
	while (isspace(*s) || (*s == ',')) s++;	/* skip space */
	if (*s == '\0') return NULL;		/* is there token? */
	while (!isspace(*s) && (*s != ',')) 
		*tBuf++ = *s++;			/* copy token */
	*tBuf = '\0';
	while (isspace(*s)) s++;		/* skip space */
	return s;
}

static void parseUseList(s)			/* use: removed */
char *s;
{
	infoList *new;
	char	*ts,numBuf[256],isLocal;
	
	do {
		new = (infoList *)malloc(sizeof(infoList));
		if (new == NULL) {
			fprintf(stderr,"malloc() failed\n");
			exit(1);
		}
		s = getToken(s,new->name);	/* get name */
		if (s == NULL) {
			fprintf(stderr,"Use List: missing token\n");
			exit(1);
		}
		isLocal = FALSE;
		if (isdigit(new->name[0])) {	/* net or host? */
			new->next = net;
			net = new;
		} else if (compare(new->name,"LOCAL") == NULL) {
	                new->next = host;
			host = new;
		} else {
			isLocal = TRUE;
		}
		new->nSvcs = 1;
		new->uid = geteuid();
		while ((*s != '\0') && (*s != ',')) {	/* options */
			ts = compare(s,"N=");
			if (ts != NULL) {
				s = ts;	
				s = getToken(s,numBuf);
				if (s == NULL) {
					fprintf(stderr,
						"Use List: N= val missing\n");
					exit(1);
				}
				new->nSvcs = atoi(numBuf);
			} else {
				s = compare(s,"UID=");
				if (s == NULL) {
					fprintf(stderr,
						"Use List: option missing\n");
					exit(1);
				}
				s = getToken(s,numBuf);
				if (s == NULL) {
					fprintf(stderr,
						"Use List: UID= val missing\n");
					exit(1);
				}
				new->uid = atoi(numBuf);
			}
		}
		if (isLocal) {
			local.nSvcs = new->nSvcs;
			local.uid = new->uid;
			free(new);
		}
	} while (*s == ',');
}

/*----------------------------------------------------------------------*/

static isEmpty(s)				/* test if empty */
char *s;
{
	while (*s != '\0') {
		if (!isspace(*s)) return FALSE;
		s++;
	}
	return TRUE;
}

static isIgnore(s)				/* test if ignore host */
char *s;
{
	infoList *new;
	
	s = compare(s,"IGNORE:");
	if (s == NULL) return FALSE;
	do {					/* get number of tokens */
		new = (infoList *)malloc(sizeof(infoList));
		if (new == NULL) {
			fprintf(stderr,"malloc() failed\n");
			exit(1);
		}
		s = getToken(s,new->name);
		if (s == NULL) {
			fprintf(stderr,"%s: missing token\n",RCFILE);
			exit(1);
		}
		new->next = ignore;
		ignore = new;
	} while (*s == ',');
	return TRUE;
}

static isUse(s)					/* test if use-list */
char *s;
{
	s = compare(s,"USE:");
	if (s == NULL) return FALSE;
	parseUseList(s);
	return TRUE;
}

static isPortNr(s)				/* test if port # */
char *s;
{
	char numBuf[256];
	
	s = compare(s,"RESULTPORT:");
	if (s == NULL) return FALSE;
	s = getToken(s,numBuf);
	portNumber = (short)atoi(numBuf);
	return TRUE;
}
	
static isTimeout(s)				/* test if timeout value */
char *s;
{
	char numBuf[256];
	
	s = compare(s,"TIMEOUT:");
	if (s == NULL) return FALSE;
	s = getToken(s,numBuf);
	rTimeout = atoi(numBuf);
	return TRUE;
}
	
static isMinWorkers(s)
char *s;
{
	char numBuf[256];
	
	s = compare(s,"MINWORKERS:");
	if (s == NULL) return FALSE;
	s = getToken(s,numBuf);
	minWorkers = atoi(numBuf);
	return TRUE;
}
	
static isMaxWorkers(s)
char *s;
{
	char numBuf[256];
	
	s = compare(s,"MAXWORKERS:");
	if (s == NULL) return FALSE;
	s = getToken(s,numBuf);
	maxWorkers = atoi(numBuf);
	return TRUE;
}
	
static isMinBlockSize(s)
char *s;
{
	char numBuf[256];
	
	s = compare(s,"MINBLOCKSIZE:");
	if (s == NULL) return FALSE;
	s = getToken(s,numBuf);
	minBlockSize = atoi(numBuf);
	return TRUE;
}
	
static isMaxBlockSize(s)
char *s;
{
	char numBuf[256];
	
	s = compare(s,"MAXBLOCKSIZE:");
	if (s == NULL) return FALSE;
	s = getToken(s,numBuf);
	maxBlockSize = atoi(numBuf);
	return TRUE;
}
	
static isBlocksPerServer(s)
char *s;
{
	char numBuf[256];
	
	s = compare(s,"BLOCKSPERSERVER:");
	if (s == NULL) return FALSE;
	s = getToken(s,numBuf);
	blocksPerServer = atoi(numBuf);
	return TRUE;
}
	

