/*----------------------------------------------------------------------------*/
/* Hobbit monitor library.                                                    */
/*                                                                            */
/* This is a library module for Hobbit, responsible for loading the host      */
/* configuration from hobbitd.                                                */
/*                                                                            */
/* Copyright (C) 2006      Henrik Storner <henrik@hswn.dk>                    */
/*                                                                            */
/* This program is released under the GNU General Public License (GPL),       */
/* version 2. See the file "COPYING" for details.                             */
/*                                                                            */
/*----------------------------------------------------------------------------*/

static char rcsid_file[] = "$Id: loadhosts_net.c,v 1.1 2006/03/30 19:59:50 henrik Rel $";

namelist_t *load_hostnames_net(void)
{
	char *configbuf = NULL, *inbuf = NULL;
	namelist_t *nametail = NULL;
	char bbmsg[200];
	char *cnfptr;

	configloaded = 1;
	initialize_hostlist();

	strcpy(bbmsg, "hostinfo fields=BBH_HOSTNAME,BBH_PAGEPATH,BBH_GROUPID,BBH_BANKSIZE,BBH_IP,BBH_RAW");
	if (xgetenv("BBLOCATION")) sprintf(bbmsg+strlen(bbmsg), " net=%s", xgetenv("BBLOCATION"));

	if (sendmessage(bbmsg, NULL, NULL, &configbuf, 1, BBTALK_TIMEOUT) != BB_OK) return NULL;
	inbuf = strtok_r(bbmsg, "\n", &cnfptr);
	while (inbuf) {
		char *hostname, *pagepath, *groupid, *banksize, *ip;

		namelist_t *newitem = calloc(1, sizeof(namelist_t));

		hostname = pagepath = groupid = banksize = ip = NULL;
		hostname = gettok(inbuf, "|");
		if (hostname) pagepath = gettok(NULL, "|");
		if (pagepath) groupid = gettok(NULL, "|");
		if (groupid) banksize = gettok(NULL, "|");
		if (banksize) ip = gettok(NULL, "|");

		newitem->bbhostname = strdup(hostname);
		newitem->clientname = newitem->bbhostname;
		newitem->page = setup_page(pagepath);
		newitem->groupid = strdup(groupid);
		newitem->banksize = atoi(banksize);
		strcpy(newitem->ip, ip);

		if (strncmp(hostname, "@dialup", 7) == 0) {
			/* No other elements for this type of entry */
			newitem->elems = (char **)malloc(sizeof(char *));
			newitem->elems[0] = NULL;
			newitem->next = NULL;
		}

		if (namehead == NULL) 
			namehead = nametail = newitem;
		else {
			nametail->next = newitem;
			nametail = newitem;
		}

			newitem->bbhostname = strdup(hostname);
			if (ip1 || ip2 || ip3 || ip4) newitem->preference = 1; else newitem->preference = 0;
			newitem->clientname = NULL;
			newitem->logname = strdup(newitem->bbhostname);
			{ char *p = newitem->logname; while ((p = strchr(p, '.')) != NULL) { *p = '_'; } }
			newitem->downtime = NULL;
			newitem->page = curpage;
			newitem->data = NULL;
			newitem->defaulthost = defaulthost;

			clientname[0] = downtime[0] = '\0';
			startoftags = strchr(inbuf, '#');
			if (startoftags == NULL) startoftags = ""; else startoftags++;
			startoftags += strspn(startoftags, " \t\r\n");
			newitem->allelems = strdup(startoftags);
			elemsize = 5;
			newitem->elems = (char **)malloc((elemsize+1)*sizeof(char *));

			tag = newitem->allelems; elemidx = 0;
			while (tag && *tag) {
				if (elemidx == elemsize) {
					elemsize += 5;
					newitem->elems = (char **)realloc(newitem->elems, (elemsize+1)*sizeof(char *));
				}
				newitem->elems[elemidx] = tag;

				/* Skip until we hit a whitespace or a quote */
				tag += strcspn(tag, " \t\r\n\"");
				if (*tag == '"') {
					delim = tag;

					/* Hit a quote - skip until the next matching quote */
					tag = strchr(tag+1, '"');
					if (tag != NULL) { 
						/* Found end-quote, NULL the item here and move on */
						*tag = '\0'; tag++; 
					}

					/* Now move quoted data one byte down (including the NUL) to kill quotechar */
					memmove(delim, delim+1, strlen(delim));
				}
				else if (*tag) {
					/* Normal end of item, NULL it and move on */
					*tag = '\0'; tag++;
				}
				else {
					/* End of line - no more to do. */
					tag = NULL;
				}

				/* 
				 * If we find a "noconn", drop preference value to 0.
				 * If we find a "prefer", up reference value to 2.
				 */
				if ((newitem->preference == 1) && (strcmp(newitem->elems[elemidx], "noconn") == 0))
					newitem->preference = 0;
				else if (strcmp(newitem->elems[elemidx], "prefer") == 0)
					newitem->preference = 2;

				/* Skip whitespace until start of next tag */
				if (tag) tag += strspn(tag, " \t\r\n");
				elemidx++;
			}

			newitem->elems[elemidx] = NULL;

			/* See if this host is defined before */
			for (iwalk = namehead, iprev = NULL; (iwalk && strcmp(iwalk->bbhostname, newitem->bbhostname)); iprev = iwalk, iwalk = iwalk->next) ;
			if (strcasecmp(newitem->bbhostname, ".default.") == 0) {
				/* The pseudo DEFAULT host */
				newitem->next = NULL;
				defaulthost = newitem;
			}
			else if (iwalk == NULL) {
				/* New item, so add to end of list */
				newitem->next = NULL;
				if (namehead == NULL) 
					namehead = nametail = newitem;
				else {
					nametail->next = newitem;
					nametail = newitem;
				}
			}
 			else if (newitem->preference <= iwalk->preference) {
				/* Add after the existing (more preferred) entry */
				newitem->next = iwalk->next;
				iwalk->next = newitem;
			}
			else {
				/* New item has higher preference, so add before the iwalk item (i.e. after iprev) */
				if (iprev == NULL) {
					newitem->next = namehead;
					namehead = newitem;
				}
				else {
					newitem->next = iprev->next;
					iprev->next = newitem;
				}
			}

			newitem->clientname = bbh_find_item(newitem, BBH_CLIENTALIAS);
			if (newitem->clientname == NULL) newitem->clientname = newitem->bbhostname;
			newitem->downtime = bbh_find_item(newitem, BBH_DOWNTIME);

			MEMUNDEFINE(clientname);
			MEMUNDEFINE(downtime);
		}


		inbuf = strtok_r(NULL, "\n", &cnfptr);
	}
	xfree(configbuf);

	build_hosttree();
	return namehead;
}



