Esempio n. 1
0
void *load_web_access_config(char *accessfn)
{
	FILE *fd;
	strbuffer_t *buf;

	if (acctree) return 0;
	acctree = xtreeNew(strcasecmp);

	fd = stackfopen(accessfn, "r", NULL);
	if (fd == NULL) return NULL;

	buf = newstrbuffer(0);
	while (stackfgets(buf, NULL)) {
		char *group, *member;
		char *key;

		group = strtok(STRBUF(buf), ": \n");
		if (!group) continue;

		member = strtok(NULL, ", \n");
		while (member) {
			key = (char *)malloc(strlen(group) + strlen(member) + 2);
			sprintf(key, "%s %s", group, member);
			xtreeAdd(acctree, key, NULL);
			member = strtok(NULL, ", \n");
		}
	}
	stackfclose(fd);

	return acctree;
}
Esempio n. 2
0
static int prepare_fromfile(char *hostsfn, char *extrainclude)
{
	static void *hostfiles = NULL;
	FILE *hosts;
	strbuffer_t *inbuf;

	/* First check if there were no modifications at all */
	if (hostfiles) {
		if (!stackfmodified(hostfiles)){
			return 1;
		}
		else {
			stackfclist(&hostfiles);
			hostfiles = NULL;
		}
	}

	if (!contentbuffer) contentbuffer = newstrbuffer(0);
	clearstrbuffer(contentbuffer);

	hosts = stackfopen(hostsfn, "r", &hostfiles);
	if (hosts == NULL) return -1;

	inbuf = newstrbuffer(0);
	while (stackfgets(inbuf, extrainclude)) {
		sanitize_input(inbuf, 0, 0);
		addtostrbuffer(contentbuffer, inbuf);
		addtobuffer(contentbuffer, "\n");
	}

	stackfclose(hosts);
	freestrbuffer(inbuf);

	return 0;
}
Esempio n. 3
0
int main(int argc, char *argv[])
{
	char *fn, *p;
	char cmd[1024];
	FILE *fd;
	strbuffer_t *inbuf = newstrbuffer(0);
	void *listhead = NULL;
	int done, linenum;

	fn = strdup(argv[1]);
	strcpy(cmd, "!");
	done = 0;
	while (!done) {
		if (*cmd == '!') {
			fd = stackfopen(fn, "r", &listhead);
			linenum = 1;
			if (!fd) { errprintf("Cannot open file %s\n", fn); continue; }

			while (stackfgets(inbuf, NULL)) {
				linenum++;
				printf("%s", STRBUF(inbuf));
			}
			stackfclose(fd);
		}
		else if (*cmd == '?') {
			filelist_t *walk = (filelist_t *)listhead;

			while (walk) {
				printf("%s %lu\n", walk->filename, (unsigned long)walk->fsize);
				walk = walk->next;
			}
			if (stackfmodified(listhead)) printf("File(s) have been modified\n");
			else printf("No changes\n");
		}
		else if (*cmd == '.') {
			done = 1;
			continue;
		}
		else {
			xfree(fn); fn = strdup(cmd);
			stackfclist(&listhead);
			strcpy(cmd, "!");
			continue;
		}

		printf("\nCmd: "); fflush(stdout);
		fgets(cmd, sizeof(cmd), stdin);
		p = strchr(cmd, '\n'); if (p) *p = '\0';
	}

	xfree(fn);
	stackfclist(&listhead);

	return 0;
}
Esempio n. 4
0
void loadenv(char *envfile, char *area)
{
	FILE *fd;
	strbuffer_t *inbuf;
	char *p, *oneenv;
	int n;

	MEMDEFINE(l);
	inbuf = newstrbuffer(0);

	fd = stackfopen(envfile, "r", NULL);
	if (fd) {
		while (stackfgets(inbuf, NULL)) {
			sanitize_input(inbuf, 1, 1);

			if (STRBUFLEN(inbuf) && strchr(STRBUF(inbuf), '=')) {
				/*
				 * Do the environment "area" stuff: If the input
				 * is of the form AREA/NAME=VALUE, then setup the variable
				 * only if we're called with the correct AREA setting.
				 */
				oneenv = NULL;

				p = STRBUF(inbuf) + strcspn(STRBUF(inbuf), "=/");
				if (*p == '/') {
					if (area) {
						*p = '\0';
						if (strcasecmp(STRBUF(inbuf), area) == 0) oneenv = strdup(expand_env(p+1));
					}
				}
				else oneenv = strdup(expand_env(STRBUF(inbuf)));

				if (oneenv) {
					p = strchr(oneenv, '=');
					if (*(p+1) == '"') {
						/* Move string over the first '"' */
						memmove(p+1, p+2, strlen(p+2)+1);
						/* Kill a trailing '"' */
						if (*(oneenv + strlen(oneenv) - 1) == '"') *(oneenv + strlen(oneenv) - 1) = '\0';
					}
					n = putenv(oneenv);
				}
			}
		}
		stackfclose(fd);
	}
	else {
		errprintf("Cannot open env file %s - %s\n", envfile, strerror(errno));
	}

	freestrbuffer(inbuf);
	MEMUNDEFINE(l);
}
Esempio n. 5
0
int main(int argc, char *argv[])
{ 
	FILE *bbhosts;
	char *fn = NULL;
	strbuffer_t *inbuf;
	int argi;
	char *include2 = NULL;


	for (argi=1; (argi < argc); argi++) {
		if (strcmp(argv[argi], "--version") == 0) {
			printf("bbhostshow version %s\n", VERSION);
			exit(0);
		}
		else if (strcmp(argv[argi], "--help") == 0) {
			printf("Usage:\n%s [filename]\n", argv[0]);
			exit(0);
		}
		else if (strcmp(argv[argi], "--bbnet") == 0) {
			include2 = "netinclude";
		}
		else if (strcmp(argv[argi], "--bbdisp") == 0) {
			include2 = "dispinclude";
		}
		else if (*argv[argi] != '-') {
			fn = strdup(argv[argi]);
		}
	}

	if (!fn || (strlen(fn) == 0)) {
		fn = getenv("BBHOSTS");
		if (!fn) {
			errprintf("Environment variable BBHOSTS is not set - aborting\n");
			exit(2);
		}
	}

	bbhosts = stackfopen(fn, "r", NULL);
	if (bbhosts == NULL) {
		printf("Cannot open the BBHOSTS file '%s'\n", fn);
		exit(1);
	}

	inbuf = newstrbuffer(0);
	while (stackfgets(inbuf, include2)) {
		printf("%s", STRBUF(inbuf));
	}

	stackfclose(bbhosts);
	freestrbuffer(inbuf);
	return 0;
}
Esempio n. 6
0
void loadenv(char *envfile, char *area)
{
	FILE *fd;
	strbuffer_t *inbuf;
	char *p, *oneenv;

	MEMDEFINE(l);
	inbuf = newstrbuffer(0);

	fd = stackfopen(envfile, "r", NULL);
	if (fd) {
		while (stackfgets(inbuf, NULL)) {
			char *equalpos;
			int appendto = 0;

			sanitize_input(inbuf, 1, 1);

			if ((STRBUFLEN(inbuf) == 0) || ((equalpos = strchr(STRBUF(inbuf), '=')) == NULL)) continue;

			appendto = ((equalpos > STRBUF(inbuf)) && (*(equalpos-1) == '+'));

			/*
			 * Do the environment "area" stuff: If the input
			 * is of the form AREA/NAME=VALUE, then setup the variable
			 * only if we're called with the correct AREA setting.
			 */
			oneenv = NULL;

			p = STRBUF(inbuf) + strcspn(STRBUF(inbuf), "=/");
			if (*p == '/') {
				if (area) {
					*p = '\0';
					if (strcasecmp(STRBUF(inbuf), area) == 0) oneenv = strdup(expand_env(p+1));
				}
			}
			else oneenv = strdup(expand_env(STRBUF(inbuf)));

			if (oneenv) {
				p = strchr(oneenv, '=');
				if (*(p+1) == '"') {
					/* Move string over the first '"' */
					memmove(p+1, p+2, strlen(p+2)+1);
					/* Kill a trailing '"' */
					if (*(oneenv + strlen(oneenv) - 1) == '"') *(oneenv + strlen(oneenv) - 1) = '\0';
				}

				if (appendto) {
					char *oldval, *addstring, *p;

					addstring = strchr(oneenv, '='); if (addstring) { *addstring = '\0'; addstring++; }
					p = strchr(oneenv, '+'); if (p) *p = '\0';

					oldval = getenv(oneenv);
					if (oldval) {
						char *combinedenv = (char *)malloc(strlen(oneenv) + strlen(oldval) + strlen(addstring) + 2);
						sprintf(combinedenv, "%s=%s%s", oneenv, oldval, (addstring));
						xfree(oneenv);
						oneenv = combinedenv;
					}
					else {
						/* oneenv is now VARxxVALUE, so fix it to be a normal env. variable format */
						strcat(oneenv, "=");
						memmove(oneenv+strlen(oneenv), addstring, strlen(addstring) + 1);
					}
				}

				if (putenv(oneenv) != 0) errprintf("Cannot set environment: %s\n", strerror(errno));
			}
		}
		stackfclose(fd);
	}
	else {
		errprintf("Cannot open env file %s - %s\n", envfile, strerror(errno));
	}

	freestrbuffer(inbuf);
	MEMUNDEFINE(l);
}
Esempio n. 7
0
char *stackfgets(strbuffer_t *buffer, char *extraincl)
{
	char *result;

	result = unlimfgets(buffer, fdhead->fd);

	if (result) {
		char *bufpastwhitespace = STRBUF(buffer) + strspn(STRBUF(buffer), " \t");

		if ( (strncmp(bufpastwhitespace, "include ", 8) == 0) ||
		     (extraincl && (strncmp(bufpastwhitespace, extraincl, strlen(extraincl)) == 0)) ) {
			char *newfn, *eol, eolchar;

			eol = bufpastwhitespace + strcspn(bufpastwhitespace, "\r\n"); if (eol) { eolchar = *eol; *eol = '\0'; }
			newfn = bufpastwhitespace + strcspn(bufpastwhitespace, " \t");
			newfn += strspn(newfn, " \t");
		
			if (*newfn && (stackfopen(newfn, "r", (void **)fdhead->listhead) != NULL))
				return stackfgets(buffer, extraincl);
			else {
				errprintf("WARNING: Cannot open include file '%s', line was:%s\n", 
					  newfn, STRBUF(buffer));
				if (eol) *eol = eolchar;
				return result;
			}
		}
		else if (strncmp(bufpastwhitespace, "directory ", 10) == 0) {
			char *dirfn, *eol, eolchar;

			eol = bufpastwhitespace + strcspn(bufpastwhitespace, "\r\n"); if (eol) { eolchar = *eol; *eol = '\0'; }
			dirfn = bufpastwhitespace + 9;
			dirfn += strspn(dirfn, " \t");

			if (*dirfn) addtofnlist(dirfn, (void **)fdhead->listhead);
			if (fnlist && (stackfopen(fnlist->name, "r", (void **)fdhead->listhead) != NULL)) {
				htnames_t *tmp = fnlist;

				fnlist = fnlist->next;
				xfree(tmp->name); xfree(tmp);
				return stackfgets(buffer, extraincl);
			}
			else if (fnlist) {
				htnames_t *tmp = fnlist;

				errprintf("WARNING: Cannot open include file '%s', line was:%s\n", fnlist->name, buffer);
				fnlist = fnlist->next;
				xfree(tmp->name); xfree(tmp);
				if (eol) *eol = eolchar;
				return result;
			}
			else {
				/* Empty directory include - return a blank line */
				*result = '\0'; 
				return result;
			}
		}
	}
	else if (result == NULL) {
		/* end-of-file on read */
		stackfclose(NULL);
		if (fnlist) {
			if (stackfopen(fnlist->name, "r", (void **)fdhead->listhead) != NULL) {
				htnames_t *tmp = fnlist;

				fnlist = fnlist->next;
				xfree(tmp->name); xfree(tmp);
				return stackfgets(buffer, extraincl);
			}
			else {
				htnames_t *tmp = fnlist;

				errprintf("WARNING: Cannot open include file '%s', line was:%s\n", fnlist->name, buffer);
				fnlist = fnlist->next;
				xfree(tmp->name); xfree(tmp);
				return result;
			}
		}
		else if (fdhead != NULL)
			return stackfgets(buffer, extraincl);
		else
			return NULL;
	}

	return result;
}
Esempio n. 8
0
static void load_rrddefs(void)
{
	char fn[PATH_MAX];
	FILE *fd;
	strbuffer_t *inbuf = newstrbuffer(0);
	char *key = NULL, *p;
	char **defs = NULL;
	int defcount = 0;
	rrddeftree_t *newrec;

	rrddeftree = xtreeNew(strcasecmp);

	sprintf(fn, "%s/etc/rrddefinitions.cfg", xgetenv("XYMONHOME"));
	fd = stackfopen(fn, "r", NULL);
	if (fd == NULL) goto loaddone;

	while (stackfgets(inbuf, NULL)) {
		sanitize_input(inbuf, 1, 0); if (STRBUFLEN(inbuf) == 0) continue;

		if (*(STRBUF(inbuf)) == '[') {
			if (key && (defcount > 0)) {
				/* Save the current record */
				newrec = (rrddeftree_t *)malloc(sizeof(rrddeftree_t));
				newrec->key = key;
				newrec->defs = defs;
				newrec->count = defcount;
				xtreeAdd(rrddeftree, newrec->key, newrec);

				key = NULL; defs = NULL; defcount = 0;
			}

			key = strdup(STRBUF(inbuf)+1);
			p = strchr(key, ']'); if (p) *p = '\0';
		}
		else if (key) {
			if (!defs) {
				defcount = 1;
				defs = (char **)malloc(sizeof(char *));
			}
			else {
				defcount++;
				defs = (char **)realloc(defs, defcount * sizeof(char *));
			}
			p = STRBUF(inbuf); p += strspn(p, " \t");
			defs[defcount-1] = strdup(p);
		}
	}

	if (key && (defcount > 0)) {
		/* Save the last record */
		newrec = (rrddeftree_t *)malloc(sizeof(rrddeftree_t));
		newrec->key = key;
		newrec->defs = defs;
		newrec->count = defcount;
		xtreeAdd(rrddeftree, newrec->key, newrec);
	}

	stackfclose(fd);

loaddone:
	freestrbuffer(inbuf);

	/* Check if the default record exists */
	if (xtreeFind(rrddeftree, "") == xtreeEnd(rrddeftree)) {
		/* Create the default record */
		newrec = (rrddeftree_t *)malloc(sizeof(rrddeftree_t));
		newrec->key = strdup("");
		newrec->defs = (char **)malloc(4 * sizeof(char *));;
		newrec->defs[0] = strdup("RRA:AVERAGE:0.5:1:576");
		newrec->defs[1] = strdup("RRA:AVERAGE:0.5:6:576");
		newrec->defs[2] = strdup("RRA:AVERAGE:0.5:24:576");
		newrec->defs[3] = strdup("RRA:AVERAGE:0.5:288:576");
		newrec->count = 4;
		xtreeAdd(rrddeftree, newrec->key, newrec);
	}
}
Esempio n. 9
0
void load_clientconfig(void)
{
	static char *configfn = NULL;
	static void *clientconflist = NULL;
	FILE *fd;
	strbuffer_t *buf;
	char *sectstart;

	if (!configfn) {
		configfn = (char *)malloc(strlen(xgetenv("XYMONHOME"))+ strlen("/etc/client-local.cfg") + 1);
		sprintf(configfn, "%s/etc/client-local.cfg", xgetenv("XYMONHOME"));
	}

	/* First check if there were no modifications at all */
	if (clientconflist) {
		if (!stackfmodified(clientconflist)){
			dbgprintf("No files modified, skipping reload of %s\n", configfn);
			return;
		}
		else {
			stackfclist(&clientconflist);
			clientconflist = NULL;
		}
	}

	if (!clientconfigs) {
		clientconfigs = newstrbuffer(0);
	}
	else {
		xtreeDestroy(rbconfigs);
		clearstrbuffer(clientconfigs);
	}

	rbconfigs = xtreeNew(strcasecmp);
	addtobuffer(clientconfigs, "\n");
	buf = newstrbuffer(0);

	fd = stackfopen(configfn, "r", &clientconflist); if (!fd) return;
	while (stackfgets(buf, NULL)) addtostrbuffer(clientconfigs, buf);
	stackfclose(fd);

	sectstart = strstr(STRBUF(clientconfigs), "\n[");
	while (sectstart) {
		char *key, *nextsect;

		sectstart += 2;
		key = sectstart;

		sectstart += strcspn(sectstart, "]\n");
		if (*sectstart == ']') {
			*sectstart = '\0'; sectstart++;
			sectstart += strcspn(sectstart, "\n");
		}

		nextsect = strstr(sectstart, "\n[");
		if (nextsect) *(nextsect+1) = '\0';

		xtreeAdd(rbconfigs, key, sectstart+1);
		sectstart = nextsect;
	}

	freestrbuffer(buf);
}
Esempio n. 10
0
void load_config(char *conffn)
{
	static void *configfiles = NULL;
	tasklist_t *twalk, *curtask = NULL;
	FILE *fd;
	strbuffer_t *inbuf;
	char *p;
	char myhostname[256];

	/* First check if there were no modifications at all */
	if (configfiles) {
	        if (!stackfmodified(configfiles) && (!forcereload)) {
			dbgprintf("No files modified, skipping reload of %s\n", conffn);
			return;
		}
		else {
			stackfclist(&configfiles);
			configfiles = NULL;
		}
	}

	errprintf("Loading tasklist configuration from %s\n", conffn);
	if (gethostname(myhostname, sizeof(myhostname)) != 0) {
		errprintf("Cannot get the local hostname, using 'localhost' (error: %s)\n", strerror(errno));
		strcpy(myhostname, "localhost");
	}

	/* The cfload flag: -1=delete task, 0=old task unchanged, 1=new/changed task */
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		twalk->cfload = -1;
		twalk->group = NULL;
		/* Create a copy, but retain the settings and pointers are the same */
		twalk->copy = xmalloc(sizeof(tasklist_t));
		memcpy(twalk->copy,twalk,sizeof(tasklist_t));
		/* These should get cleared */
		twalk->copy->next = NULL;
		twalk->copy->copy = NULL;
		/* And clean the values of all others, so that we really can detect a difference */
		twalk->disabled = 0;
		twalk->cmd = NULL;
		twalk->interval = 0;
		twalk->maxruntime = 0;
		twalk->group = NULL;
		twalk->logfile = NULL;
		twalk->envfile = NULL;
		twalk->envarea = NULL;
		twalk->onhostptn = NULL;
		twalk->cronstr = NULL;
		twalk->crondate = NULL;
		twalk->depends = NULL;
	}

	fd = stackfopen(conffn, "r", &configfiles);
	if (fd == NULL) {
		errprintf("Cannot open configuration file %s: %s\n", conffn, strerror(errno));
		return;
	}

	inbuf = newstrbuffer(0);
	while (stackfgets(inbuf, NULL)) {
		sanitize_input(inbuf, 1, 0); if (STRBUFLEN(inbuf) == 0) continue;

		p = STRBUF(inbuf);
		if (*p == '[') {
			/* New task */
			char *endp;
			/* get name */
			p++; endp = strchr(p, ']');
			if (endp == NULL) continue;
			*endp = '\0';

			/* try to find the task */
			for (twalk = taskhead; (twalk && (strcmp(twalk->key, p))); twalk = twalk->next);

			if (twalk) {
				curtask=twalk;
			} else {
				/* New task, just create it */
				curtask = (tasklist_t *)calloc(1, sizeof(tasklist_t));
				curtask->key = strdup(p);
				/* add it to the list */
				if (taskhead == NULL) taskhead = curtask;
				else tasktail->next = curtask;
				tasktail = curtask;
			}
			/* mark task as configured */
			curtask->cfload = 0;
		}
		else if (curtask && (strncasecmp(p, "CMD ", 4) == 0)) {
			p += 3;
			p += strspn(p, " \t");
			/* Handle + - options as well */
			if (*p == '+') {
				/* append to command */
				if (curtask->cmd) {
					int l1 = strlen(curtask->cmd);
					int l2 = strlen(p);
					char *newcmd = xcalloc(1, l1+l2+1);

					strncpy(newcmd,curtask->cmd,l1);
					strncpy(newcmd+l1,p,l2);
					newcmd[l1]=' '; /* this also overwrites the + */

					/* free and assign new */
					xfreeassign(curtask->cmd,newcmd);
				}
			} 
			else if (*p == '-') {
				/* remove from command */
				if (curtask->cmd) {
					int l = strlen(p)-1;
					if (l > 0) {
						char *found;

						while((found = strstr(curtask->cmd,p+1)) != NULL) {
							/* doing a copy - can not use strcpy as we are overlapping */
							char *s = found + l;

							while (*s) {
								*found=*s; 
								found++;
								s++;
							}

							*found=0;
						}
					} 
					else {
						errprintf("Configuration error, empty command removal (CMD -) for task %s\n", curtask->key);
					}
				}
			} else {
				xfreedup(curtask->cmd,p);
			}
		}
		else if (strncasecmp(p, "GROUP ", 6) == 0) {
			/* Note: GROUP can be used by itself to define a group, or inside a task definition */
			char *groupname;
			int maxuse;
			grouplist_t *gwalk;

			p += 6;
			p += strspn(p, " \t");
			groupname = p;
			p += strcspn(p, " \t");
			if (isdigit((int) *p)) maxuse = atoi(p); else maxuse = 1;

			/* Find or create the grouplist entry */
			for (gwalk = grouphead; (gwalk && (strcmp(gwalk->groupname, groupname))); gwalk = gwalk->next);
			if (gwalk == NULL) {
				gwalk = (grouplist_t *)malloc(sizeof(grouplist_t));
				gwalk->groupname = strdup(groupname);
				gwalk->maxuse = maxuse;
				gwalk->currentuse = 0;
				gwalk->next = grouphead;
				grouphead = gwalk;
			}

			if (curtask) curtask->group = gwalk;
		}
		else if (curtask && (strncasecmp(p, "INTERVAL ", 9) == 0)) {
			char *tspec;
			p += 9;
			curtask->interval = atoi(p);
			tspec = p + strspn(p, "0123456789");
			switch (*tspec) {
			  case 'm': curtask->interval *= 60; break;	/* Minutes */
			  case 'h': curtask->interval *= 3600; break;	/* Hours */
			  case 'd': curtask->interval *= 86400; break;	/* Days */
			}
		}
		else if (curtask && (strncasecmp(p, "CRONDATE ", 9) == 0)) {
			p+= 9;
			xfreedup(curtask->cronstr,p);
			if (curtask->crondate) crondatefree(curtask->crondate);
			curtask->crondate = parse_cron_time(curtask->cronstr);
			if (!curtask->crondate) {
				errprintf("Can't parse cron date: %s->%s\n", curtask->key, curtask->cronstr);
				curtask->disabled = 1;
			}
			curtask->interval = -1; /* disable interval */
		}
		else if (curtask && (strncasecmp(p, "MAXTIME ", 8) == 0)) {
			char *tspec;
			p += 8;
			curtask->maxruntime = atoi(p);
			tspec = p + strspn(p, "0123456789");
			switch (*tspec) {
			  case 'm': curtask->maxruntime *= 60; break;	/* Minutes */
			  case 'h': curtask->maxruntime *= 3600; break;	/* Hours */
			  case 'd': curtask->maxruntime *= 86400; break;	/* Days */
			}
		}
		else if (curtask && (strncasecmp(p, "LOGFILE ", 8) == 0)) {
			p += 7;
			p += strspn(p, " \t");
			xfreedup(curtask->logfile,p);
		}
		else if (curtask && (strncasecmp(p, "NEEDS ", 6) == 0)) {
			p += 6;
			p += strspn(p, " \t");
			for (twalk = taskhead; (twalk && strcmp(twalk->key, p)); twalk = twalk->next);
			if (twalk) {
				curtask->depends = twalk;
			}
			else {
				errprintf("Configuration error, unknown dependency %s->%s\n", curtask->key, p);
			}
		}
		else if (curtask && (strncasecmp(p, "ENVFILE ", 8) == 0)) {
			p += 7;
			p += strspn(p, " \t");
			xfreedup(curtask->envfile,p);
		}
		else if (curtask && (strncasecmp(p, "ENVAREA ", 8) == 0)) {
			p += 7;
			p += strspn(p, " \t");
			xfreedup(curtask->envarea,p);
		}
		else if (curtask && (strcasecmp(p, "DISABLED") == 0)) {
			curtask->disabled = 1;
		}
		else if (curtask && (strcasecmp(p, "ENABLED") == 0)) {
			curtask->disabled = 0;
		}
		else if (curtask && (strncasecmp(p, "ONHOST ", 7) == 0)) {
			regex_t cpattern;
			int status;

			p += 7;
			p += strspn(p, " \t");

			xfreedup(curtask->onhostptn,p);

			/* Match the hostname against the pattern; if it doesnt match then disable the task */
			status = regcomp(&cpattern, curtask->onhostptn, REG_EXTENDED|REG_ICASE|REG_NOSUB);
			if (status == 0) {
				status = regexec(&cpattern, myhostname, 0, NULL, 0);
				if (status == REG_NOMATCH) curtask->disabled = 1;
			}
			else {
				errprintf("ONHOST pattern '%s' is invalid\n", p);
			}
		}
	}
	stackfclose(fd);
	freestrbuffer(inbuf);

	/* Running tasks that have been deleted or changed are killed off now. */
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		/* compare the current settings with the copy - if we have one */
		if (twalk->cfload == 0) {
			if (twalk->copy) {
				/* compare the current version with the new version and decide if we have changed */
				int changed=0;
				int reload=0;
				/* first the nummeric ones */
				if (twalk->disabled!=twalk->copy->disabled) { changed++; }
				if (twalk->interval!=twalk->copy->interval) { changed++; }
				if (twalk->maxruntime!=twalk->copy->maxruntime) { changed++; }
				if (twalk->group!=twalk->copy->group) { changed++; reload++;}
				/* then the string versions */
#define twalkstrcmp(k,doreload) {					\
					if (twalk->k!=twalk->copy->k) {	\
						if (twalk->copy->k) {	\
							if (twalk->k) {	\
								if (strcmp(twalk->k,twalk->copy->k)) { \
									changed++;reload+=doreload; \
								}	\
							} else {	\
								changed++;reload+=doreload; \
							}		\
							/* we can always delete the copy*/ \
							xfree(twalk->copy->k); \
							twalk->copy->k=NULL; \
						} else {		\
							changed++;reload+=doreload; \
						}			\
					}				\
				}
				twalkstrcmp(cmd,1);
				twalkstrcmp(logfile,1);
				twalkstrcmp(envfile,1);
				twalkstrcmp(envarea,1);
				twalkstrcmp(onhostptn,0);
				twalkstrcmp(cronstr,0);
				if ((twalk->copy->cronstr == NULL) && twalk->copy->crondate) {
					crondatefree(twalk->copy->crondate);
					twalk->copy->crondate = NULL;
				}
				
				/* we can release the copy now - not using xfree, as this releases it from the list making a mess...*/
				xfreenull(twalk->copy);
				/* now make the decision for reloading 
				   - if we have changed, then we may assign cfload,
				   - otherwise the entry does not exist any longer */
				if (reload) { reload=1;}
				if (changed) { twalk->cfload=reload; }
			} else {
				/* new object, so we need to do this */
				twalk->cfload=1;
			}
		}

		/* and based on this decide what to do */
		switch (twalk->cfload) {
		  case -1:
			/* Kill the task, if active */
			if (twalk->pid) {
				dbgprintf("Killing task %s PID %d\n", twalk->key, (int)twalk->pid);
				twalk->beingkilled = 1;
				kill(twalk->pid, SIGTERM);
			}
			/* And prepare to free this tasklist entry */
			xfreenull(twalk->key); 
			xfreenull(twalk->cmd); 
			xfreenull(twalk->logfile);
			xfreenull(twalk->envfile);
			xfreenull(twalk->envarea);
			xfreenull(twalk->onhostptn);
			xfreenull(twalk->cronstr);
			if (twalk->crondate) crondatefree(twalk->crondate);
			break;

		  case 0:
			/* Do nothing */
			break;

		  case 1:
			/* Bounce the task, if it is active */
			if (twalk->pid) {
				dbgprintf("Killing task %s PID %d\n", twalk->key, (int)twalk->pid);
				twalk->beingkilled = 1;
				kill(twalk->pid, SIGTERM);
			}
			break;
		}
	}

	/* First clean out dead tasks at the start of the list */
	while (taskhead && (taskhead->cfload == -1)) {
		tasklist_t *tmp;

		tmp = taskhead;
		taskhead = taskhead->next;
		xfree(tmp);
	}

	/* Then unlink and free those inside the list */
	twalk = taskhead;
	while (twalk && twalk->next) {
		tasklist_t *tmp;

		if (twalk->next->cfload == -1) {
			tmp = twalk->next;
			twalk->next = tmp->next;
			xfree(tmp);
		}
		else twalk = twalk->next;
	}

	if (taskhead == NULL) 
		tasktail = NULL;
	else {
		tasktail = taskhead;
		while (tasktail->next) tasktail = tasktail->next;
	}

	/* Make sure group usage counts are correct (groups can change) */
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		if (twalk->group) twalk->group->currentuse = 0;
	}
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		if (twalk->group && twalk->pid) twalk->group->currentuse++;
	}
}
Esempio n. 11
0
static void loadtests(void)
{
	static time_t lastupdate = 0;
	static char *fn = NULL;
	struct stat st;
	FILE *fd;
	strbuffer_t *inbuf;

	if (!fn) {
		fn = (char *)malloc(1024 + strlen(xgetenv("XYMONHOME")));
		*fn = '\0';
	}

	sprintf(fn, "%s/etc/combo.cfg", xgetenv("XYMONHOME"));
	if ((stat(fn, &st) == 0) && (st.st_mtime == lastupdate)) return;
	lastupdate = st.st_mtime;

	fd = stackfopen(fn, "r", NULL);
	if (fd == NULL) {
		errprintf("Cannot open %s/combo.cfg\n", xgetenv("XYMONHOME"));
		*fn = '\0';
		return;
	}

	flush_testlist();

	inbuf = newstrbuffer(0);
	while (stackfgets(inbuf, NULL)) {
		char *p, *comment;
		char *inp, *outp;

		p = strchr(STRBUF(inbuf), '\n'); if (p) *p = '\0';
		/* Strip whitespace */
		for (inp=outp=STRBUF(inbuf); ((*inp >= ' ') && (*inp != '#')); inp++) {
			if (isspace((int)*inp)) {
			}
			else {
				*outp = *inp;
				outp++;
			}
		}
		*outp = '\0';
		if (strlen(inp)) memmove(outp, inp, strlen(inp)+1);
		strbufferrecalc(inbuf);

		if (STRBUFLEN(inbuf) && (*STRBUF(inbuf) != '#') && (p = strchr(STRBUF(inbuf), '=')) ) {
			testspec_t *newtest;
			char *hname, *tname;

			hname = gethname(STRBUF(inbuf));
			tname = gettname(STRBUF(inbuf));

			if (hname && tname) {
				*p = '\0';
				comment = strchr(p+1, '#');
				if (comment) *comment = '\0';
				newtest = (testspec_t *) malloc(sizeof(testspec_t));
				newtest->reshostname = strdup(gethname(STRBUF(inbuf)));
				newtest->restestname = strdup(gettname(STRBUF(inbuf)));
				newtest->expression = strdup(p+1);
				newtest->comment = (comment ? strdup(comment+1) : NULL);
				newtest->resultexpr = NULL;
				newtest->valuelist = NULL;
				newtest->result = -1;
				newtest->errbuf = NULL;
				newtest->next = testhead;
				testhead = newtest;
				testcount++;
			}
			else {
				errprintf("Invalid combo test %s - missing host/test names. Perhaps you need to escape dashes?\n", STRBUF(inbuf));
			}
		}
	}

	stackfclose(fd);
	freestrbuffer(inbuf);
}
Esempio n. 12
0
char *init_tcp_services(void)
{
	static char *xymonnetsvcs = NULL;
	static void *svcflist = NULL;

	char filename[PATH_MAX];
	struct stat st;
	FILE *fd = NULL;
	strbuffer_t *inbuf;
	svclist_t *head, *tail, *first, *walk;
	char *searchstring;
	int svcnamebytes = 0;
	int svccount = 0;
	int i;

	MEMDEFINE(filename);

	filename[0] = '\0';
	if (xgetenv("XYMONHOME")) {
		sprintf(filename, "%s/etc/", xgetenv("XYMONHOME"));
	}
	strcat(filename, "protocols.cfg");

	if ((stat(filename, &st) == 0) && xymonnetsvcs) {
		/* See if we have already run and the file is unchanged - if so just pickup the result */
		if (svcflist && !stackfmodified(svcflist)) {
			return xymonnetsvcs;
		}

		/* File has changed - reload configuration. But clean up first so we dont leak memory. */
		if (svcinfo != default_svcinfo) {
			for (i=0; (svcinfo[i].svcname); i++) {
				if (svcinfo[i].svcname) xfree(svcinfo[i].svcname);
				if (svcinfo[i].sendtxt) xfree(svcinfo[i].sendtxt);
				if (svcinfo[i].exptext) xfree(svcinfo[i].exptext);
			}
			xfree(svcinfo);
			svcinfo = default_svcinfo;
		}

		xfree(xymonnetsvcs); xymonnetsvcs = NULL;
	}

	if (xgetenv("XYMONNETSVCS") == NULL) {
		putenv("XYMONNETSVCS=smtp telnet ftp pop pop3 pop-3 ssh imap ssh1 ssh2 imap2 imap3 imap4 pop2 pop-2 nntp");
	}

	fd = stackfopen(filename, "r", &svcflist);
	if (fd == NULL) {
		errprintf("Cannot open TCP service-definitions file %s - using defaults\n", filename);
		xymonnetsvcs = strdup(xgetenv("XYMONNETSVCS"));

		MEMUNDEFINE(filename);
		return xymonnetsvcs;
	}

	head = tail = first = NULL;

	inbuf = newstrbuffer(0);
	while (stackfgets(inbuf, NULL)) {
		char *l, *eol;

		sanitize_input(inbuf, 1, 0);
		l = STRBUF(inbuf);

		if (*l == '[') {
			char *svcname;

			eol = strchr(l, ']'); if (eol) *eol = '\0';
			l = skipwhitespace(l+1);

			svcname = strtok(l, "|"); first = NULL;
			while (svcname) {
				svclist_t *newitem;

				svccount++;
				svcnamebytes += (strlen(svcname) + 1);

				newitem = (svclist_t *) malloc(sizeof(svclist_t));
				newitem->rec = (svcinfo_t *)calloc(1, sizeof(svcinfo_t));
				newitem->rec->svcname = strdup(svcname);
				newitem->next = NULL;

				if (first == NULL) first = newitem;

				if (head == NULL) {
					head = tail = newitem;
				}
				else {
					tail->next = newitem;
					tail = newitem;
				}

				svcname = strtok(NULL, "|");
			}
		}
		else if (strncmp(l, "send ", 5) == 0) {
			if (first) {
				getescapestring(skipwhitespace(l+4), &first->rec->sendtxt, &first->rec->sendlen);
				for (walk = first->next; (walk); walk = walk->next) {
					walk->rec->sendtxt = strdup(first->rec->sendtxt);
					walk->rec->sendlen = first->rec->sendlen;
				}
			}
		}
		else if (strncmp(l, "expect ", 7) == 0) {
			if (first) {
				getescapestring(skipwhitespace(l+6), &first->rec->exptext, &first->rec->explen);
				for (walk = first->next; (walk); walk = walk->next) {
					walk->rec->exptext = strdup(first->rec->exptext);
					walk->rec->explen = first->rec->explen;
					walk->rec->expofs = 0; /* HACK - not used right now */
				}
			}
		}
		else if (strncmp(l, "options ", 8) == 0) {
			if (first) {
				char *opt;

				first->rec->flags = 0;
				l = skipwhitespace(l+7);
				opt = strtok(l, ",");
				while (opt) {
					if      (strcmp(opt, "ssl") == 0)    first->rec->flags |= TCP_SSL;
					else if (strcmp(opt, "banner") == 0) first->rec->flags |= TCP_GET_BANNER;
					else if (strcmp(opt, "telnet") == 0) first->rec->flags |= TCP_TELNET;
					else errprintf("Unknown option: %s\n", opt);

					opt = strtok(NULL, ",");
				}
				for (walk = first->next; (walk); walk = walk->next) {
					walk->rec->flags = first->rec->flags;
				}
			}
		}
		else if (strncmp(l, "port ", 5) == 0) {
			if (first) {
				first->rec->port = atoi(skipwhitespace(l+4));
				for (walk = first->next; (walk); walk = walk->next) {
					walk->rec->port = first->rec->port;
				}
			}
		}
	}

	if (fd) stackfclose(fd);
	freestrbuffer(inbuf);

	/* Copy from the svclist to svcinfo table */
	svcinfo = (svcinfo_t *) malloc((svccount+1) * sizeof(svcinfo_t));
	for (walk=head, i=0; (walk && (i < svccount)); walk = walk->next, i++) {
		svcinfo[i].svcname = walk->rec->svcname;
		svcinfo[i].sendtxt = walk->rec->sendtxt;
		svcinfo[i].sendlen = walk->rec->sendlen;
		svcinfo[i].exptext = walk->rec->exptext;
		svcinfo[i].explen  = walk->rec->explen;
		svcinfo[i].expofs  = walk->rec->expofs;
		svcinfo[i].flags   = walk->rec->flags;
		svcinfo[i].port    = walk->rec->port;
	}
	memset(&svcinfo[svccount], 0, sizeof(svcinfo_t));

	/* This should not happen */
	if (walk) {
		errprintf("Whoa - didnt copy all services! svccount=%d, next service '%s'\n", 
			svccount, walk->rec->svcname);
	}

	/* Free the temp. svclist list */
	while (head) {
		/*
		 * Note: Dont free the strings inside the records, 
		 * as they are now owned by the svcinfo records.
		 */
		walk = head;
		head = head->next;
		xfree(walk);
	}

	searchstring = strdup(xgetenv("XYMONNETSVCS"));
	xymonnetsvcs = (char *) malloc(strlen(xgetenv("XYMONNETSVCS")) + svcnamebytes + 1);
	strcpy(xymonnetsvcs, xgetenv("XYMONNETSVCS"));
	for (i=0; (svcinfo[i].svcname); i++) {
		char *p;

		strcpy(searchstring, xgetenv("XYMONNETSVCS"));
		p = strtok(searchstring, " ");
		while (p && (strcmp(p, svcinfo[i].svcname) != 0)) p = strtok(NULL, " ");

		if (p == NULL) {
			strcat(xymonnetsvcs, " ");
			strcat(xymonnetsvcs, svcinfo[i].svcname);
		}
	}
	xfree(searchstring);

	if (debug) {
		dump_tcp_services();
		dbgprintf("XYMONNETSVCS set to : %s\n", xymonnetsvcs);
	}

	MEMUNDEFINE(filename);
	return xymonnetsvcs;
}
Esempio n. 13
0
void load_config(char *conffn)
{
	static void *configfiles = NULL;
	tasklist_t *twalk, *curtask = NULL;
	FILE *fd;
	strbuffer_t *inbuf;
	char *p;
	char myhostname[256];

	/* First check if there were no modifications at all */
	if (configfiles) {
		if (!stackfmodified(configfiles)){
			dbgprintf("No files modified, skipping reload of %s\n", conffn);
			return;
		}
		else {
			stackfclist(&configfiles);
			configfiles = NULL;
		}
	}

	errprintf("Loading tasklist configuration from %s\n", conffn);
	if (gethostname(myhostname, sizeof(myhostname)) != 0) {
		errprintf("Cannot get the local hostname, using 'localhost' (error: %s)\n", strerror(errno));
		strcpy(myhostname, "localhost");
	}

	/* The cfload flag: -1=delete task, 0=old task unchanged, 1=new/changed task */
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		twalk->cfload = -1;
		twalk->group = NULL;
	}

	fd = stackfopen(conffn, "r", &configfiles);
	if (fd == NULL) {
		errprintf("Cannot open configuration file %s: %s\n", conffn, strerror(errno));
		return;
	}

	inbuf = newstrbuffer(0);
	while (stackfgets(inbuf, NULL)) {
		sanitize_input(inbuf, 1, 0); if (STRBUFLEN(inbuf) == 0) continue;

		p = STRBUF(inbuf);
		if (*p == '[') {
			/* New task */
			char *endp;

			if (curtask) {
				update_task(curtask);
				curtask = NULL;
			}

			p++; endp = strchr(p, ']');
			if (endp == NULL) continue;
			*endp = '\0';

			curtask = (tasklist_t *)calloc(1, sizeof(tasklist_t));
			curtask->key = strdup(p);
		}
		else if (curtask && (strncasecmp(p, "CMD ", 4) == 0)) {
			p += 3;
			p += strspn(p, " \t");
			curtask->cmd = strdup(p);
		}
		else if (strncasecmp(p, "GROUP ", 6) == 0) {
			/* Note: GROUP can be used by itself to define a group, or inside a task definition */
			char *groupname;
			int maxuse;
			grouplist_t *gwalk;

			p += 6;
			p += strspn(p, " \t");
			groupname = p;
			p += strcspn(p, " \t");
			if (isdigit((int) *p)) maxuse = atoi(p); else maxuse = 1;

			/* Find or create the grouplist entry */
			for (gwalk = grouphead; (gwalk && (strcmp(gwalk->groupname, groupname))); gwalk = gwalk->next);
			if (gwalk == NULL) {
				gwalk = (grouplist_t *)malloc(sizeof(grouplist_t));
				gwalk->groupname = strdup(groupname);
				gwalk->maxuse = maxuse;
				gwalk->currentuse = 0;
				gwalk->next = grouphead;
				grouphead = gwalk;
			}

			if (curtask) curtask->group = gwalk;
		}
		else if (curtask && (strncasecmp(p, "INTERVAL ", 9) == 0)) {
			char *tspec;
			p += 9;
			curtask->interval = atoi(p);
			tspec = p + strspn(p, "0123456789");
			switch (*tspec) {
			  case 'm': curtask->interval *= 60; break;	/* Minutes */
			  case 'h': curtask->interval *= 3600; break;	/* Hours */
			  case 'd': curtask->interval *= 86400; break;	/* Days */
			}
		}
		else if (curtask && (strncasecmp(p, "CRONDATE ", 9) == 0)) {
			p+= 9;
			curtask->cronstr = strdup(p);
			curtask->crondate = parse_cron_time(curtask->cronstr);
			if (!curtask->crondate) {
				errprintf("Can't parse cron date: %s->%s", curtask->key, curtask->cronstr);
				curtask->disabled = 1;
			}
			curtask->interval = -1; /* disable interval */
		}
		else if (curtask && (strncasecmp(p, "MAXTIME ", 8) == 0)) {
			char *tspec;
			p += 8;
			curtask->maxruntime = atoi(p);
			tspec = p + strspn(p, "0123456789");
			switch (*tspec) {
			  case 'm': curtask->maxruntime *= 60; break;	/* Minutes */
			  case 'h': curtask->maxruntime *= 3600; break;	/* Hours */
			  case 'd': curtask->maxruntime *= 86400; break;	/* Days */
			}
		}
		else if (curtask && (strncasecmp(p, "LOGFILE ", 8) == 0)) {
			p += 7;
			p += strspn(p, " \t");
			curtask->logfile = strdup(p);
		}
		else if (curtask && (strncasecmp(p, "NEEDS ", 6) == 0)) {
			p += 6;
			p += strspn(p, " \t");
			for (twalk = taskhead; (twalk && strcmp(twalk->key, p)); twalk = twalk->next);
			if (twalk) {
				curtask->depends = twalk;
			}
			else {
				errprintf("Configuration error, unknown dependency %s->%s", curtask->key, p);
			}
		}
		else if (curtask && (strncasecmp(p, "ENVFILE ", 8) == 0)) {
			p += 7;
			p += strspn(p, " \t");
			curtask->envfile = strdup(p);
		}
		else if (curtask && (strncasecmp(p, "ENVAREA ", 8) == 0)) {
			p += 7;
			p += strspn(p, " \t");
			curtask->envarea = strdup(p);
		}
		else if (curtask && (strcasecmp(p, "DISABLED") == 0)) {
			curtask->disabled = 1;
		}
		else if (curtask && (strncasecmp(p, "ONHOST ", 7) == 0)) {
			regex_t cpattern;
			int status;

			p += 7;
			p += strspn(p, " \t");

			curtask->onhostptn = strdup(p);

			/* Match the hostname against the pattern; if it doesnt match then disable the task */
			status = regcomp(&cpattern, curtask->onhostptn, REG_EXTENDED|REG_ICASE|REG_NOSUB);
			if (status == 0) {
				status = regexec(&cpattern, myhostname, 0, NULL, 0);
				if (status == REG_NOMATCH) curtask->disabled = 1;
			}
			else {
				errprintf("ONHOST pattern '%s' is invalid\n", p);
			}
		}
	}
	if (curtask) update_task(curtask);
	stackfclose(fd);
	freestrbuffer(inbuf);

	/* Running tasks that have been deleted or changed are killed off now. */
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		switch (twalk->cfload) {
		  case -1:
			/* Kill the task, if active */
			if (twalk->pid) {
				dbgprintf("Killing task %s PID %d\n", twalk->key, (int)twalk->pid);
				twalk->beingkilled = 1;
				kill(twalk->pid, SIGTERM);
			}
			/* And prepare to free this tasklist entry */
			xfree(twalk->key); 
			xfree(twalk->cmd); 
			if (twalk->logfile) xfree(twalk->logfile);
			if (twalk->envfile) xfree(twalk->envfile);
			if (twalk->envarea) xfree(twalk->envarea);
			if (twalk->onhostptn) xfree(twalk->onhostptn);
			if (twalk->cronstr) xfree(twalk->cronstr);
			if (twalk->crondate) crondatefree(twalk->crondate);
			break;

		  case 0:
			/* Do nothing */
			break;

		  case 1:
			/* Bounce the task, if it is active */
			if (twalk->pid) {
				dbgprintf("Killing task %s PID %d\n", twalk->key, (int)twalk->pid);
				twalk->beingkilled = 1;
				kill(twalk->pid, SIGTERM);
			}
			break;
		}
	}

	/* First clean out dead tasks at the start of the list */
	while (taskhead && (taskhead->cfload == -1)) {
		tasklist_t *tmp;

		tmp = taskhead;
		taskhead = taskhead->next;
		xfree(tmp);
	}

	/* Then unlink and free those inside the list */
	twalk = taskhead;
	while (twalk && twalk->next) {
		tasklist_t *tmp;

		if (twalk->next->cfload == -1) {
			tmp = twalk->next;
			twalk->next = tmp->next;
			xfree(tmp);
		}
		else twalk = twalk->next;
	}

	if (taskhead == NULL) 
		tasktail = NULL;
	else {
		tasktail = taskhead;
		while (tasktail->next) tasktail = tasktail->next;
	}

	/* Make sure group usage counts are correct (groups can change) */
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		if (twalk->group) twalk->group->currentuse = 0;
	}
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		if (twalk->group && twalk->pid) twalk->group->currentuse++;
	}
}
Esempio n. 14
0
int load_nkconfig(char *fn)
{
	static void *configfiles = NULL;
	static int firsttime = 1;
	FILE *fd;
	strbuffer_t *inbuf;

	/* Setup the default configuration filename */
	if (!fn) {
		if (!defaultfn) {
			char *bbhome = xgetenv("BBHOME");
			defaultfn = (char *)malloc(strlen(bbhome) + strlen(DEFAULTCONFIG) + 2);
			sprintf(defaultfn, "%s/%s", bbhome, DEFAULTCONFIG);
		}
		fn = defaultfn;
	}

	if (configfn) xfree(configfn);
	configfn = strdup(fn);

	/* First check if there were no modifications at all */
	if (configfiles) {
		if (!stackfmodified(configfiles)){
			dbgprintf("No files modified, skipping reload of %s\n", fn);
			return 0;
		}
		else {
			stackfclist(&configfiles);
			configfiles = NULL;
		}
	}

	if (!firsttime) {
		/* Clean up existing datatree */
		RbtHandle handle;
		void *k1, *k2;

		for (handle = rbtBegin(rbconf); (handle != rbtEnd(rbconf)); handle = rbtNext(rbconf, handle)) {
			rbtKeyValue(rbconf, handle, &k1, &k2);
			flushrec(k1, k2);
		}

		rbtDelete(rbconf);
	}

	firsttime = 0;
	rbconf = rbtNew(name_compare);

	fd = stackfopen(fn, "r", &configfiles);
	if (fd == NULL) return 1;

	inbuf = newstrbuffer(0);
	while (stackfgets(inbuf, NULL)) {
		/* Full record : Host  service  START  END  TIMESPEC  TTPrio TTGroup TTExtra */
		/* Clone record: Host  =HOST */
		char *ehost, *eservice, *estart, *eend, *etime, *ttgroup, *ttextra, *updinfo;
		int ttprio = 0;
		nkconf_t *newitem;
		RbtStatus status;
		int idx = 0;

		ehost = gettok(STRBUF(inbuf), "|\n"); if (!ehost) continue;
		eservice = gettok(NULL, "|\n"); if (!eservice) continue;

		if (*eservice == '=') {
			char *key = (char *)malloc(strlen(ehost) + 2);
			char *pointsto = strdup(eservice+1);

			sprintf(key, "%s=", ehost);
			status = rbtInsert(rbconf, key, pointsto);
		}
		else {
			estart = gettok(NULL, "|\n"); if (!estart) continue;
			eend = gettok(NULL, "|\n"); if (!eend) continue;
			etime = gettok(NULL, "|\n"); if (!etime) continue;
			ttprio = atoi(gettok(NULL, "|\n")); if (ttprio == 0) continue;
			ttgroup = gettok(NULL, "|\n");
			ttextra = gettok(NULL, "|\n");
			updinfo = gettok(NULL, "|\n");

			newitem = (nkconf_t *)malloc(sizeof(nkconf_t));
			newitem->key = (char *)malloc(strlen(ehost) + strlen(eservice) + 15);
			sprintf(newitem->key, "%s|%s", ehost, eservice);
			newitem->starttime= ((estart && *estart) ? atoi(estart) : 0);
			newitem->endtime  = ((eend && *eend) ? atoi(eend) : 0);
			newitem->nktime   = ((etime && *etime) ? strdup(etime) : NULL);
			newitem->priority = ttprio;
			newitem->ttgroup  = strdup(ttgroup);
			newitem->ttextra  = strdup(ttextra);
			newitem->updinfo  = strdup(updinfo);

			status = rbtInsert(rbconf, newitem->key, newitem);
			while (status == RBT_STATUS_DUPLICATE_KEY) {
				idx++;
				sprintf(newitem->key, "%s|%s|%d", ehost, eservice, idx);
				status = rbtInsert(rbconf, newitem->key, newitem);
			}
		}
	}

	stackfclose(fd);
	freestrbuffer(inbuf);

	if (debug) {
		RbtHandle handle;

		handle = rbtBegin(rbconf);
		while (handle != rbtEnd(rbconf)) {
			void *k1, *k2;
			rbtKeyValue(rbconf, handle, &k1, &k2);
			printf("%s\n", (char *)k1);
			handle = rbtNext(rbconf, handle);
		}
	}

	return 0;
}
Esempio n. 15
0
int load_hostnames(char *bbhostsfn, char *extrainclude, int fqdn)
{
	/* Return value: 0 for load OK, 1 for "No files changed since last load", -1 for error (file not found) */
	static void *bbhfiles = NULL;
	FILE *bbhosts;
	int ip1, ip2, ip3, ip4, groupid, pageidx;
	char hostname[4096];
	strbuffer_t *inbuf;
	pagelist_t *curtoppage, *curpage, *pgtail;
	namelist_t *nametail = NULL;
	RbtHandle htree;

	/* First check if there were no modifications at all */
	if (bbhfiles) {
		if (!stackfmodified(bbhfiles)){
			dbgprintf("No files modified, skipping reload of %s\n", bbhostsfn);
			return 1;
		}
		else {
			stackfclist(&bbhfiles);
			bbhfiles = NULL;
		}
	}

	MEMDEFINE(hostname);
	MEMDEFINE(l);

	configloaded = 1;
	initialize_hostlist();
	curpage = curtoppage = pgtail = pghead;
	pageidx = groupid = 0;

	bbhosts = stackfopen(bbhostsfn, "r", &bbhfiles);
	if (bbhosts == NULL) return -1;

	inbuf = newstrbuffer(0);
	htree = rbtNew(name_compare);
	while (stackfgets(inbuf, extrainclude)) {
		sanitize_input(inbuf, 0, 0);

		if (strncmp(STRBUF(inbuf), "page", 4) == 0) {
			pagelist_t *newp;
			char *name, *title;

			pageidx = groupid = 0;
			if (get_page_name_title(STRBUF(inbuf), "page", &name, &title) == 0) {
				newp = (pagelist_t *)malloc(sizeof(pagelist_t));
				newp->pagepath = strdup(name);
				newp->pagetitle = (title ? strdup(title) : NULL);
				newp->next = NULL;

				pgtail->next = newp;
				pgtail = newp;

				curpage = curtoppage = newp;
			}
		}
		else if (strncmp(STRBUF(inbuf), "subpage", 7) == 0) {
			pagelist_t *newp;
			char *name, *title;

			pageidx = groupid = 0;
			if (get_page_name_title(STRBUF(inbuf), "subpage", &name, &title) == 0) {
				newp = (pagelist_t *)malloc(sizeof(pagelist_t));
				newp->pagepath = malloc(strlen(curtoppage->pagepath) + strlen(name) + 2);
				sprintf(newp->pagepath, "%s/%s", curtoppage->pagepath, name);
				newp->pagetitle = malloc(strlen(curtoppage->pagetitle) + strlen(title) + 2);
				sprintf(newp->pagetitle, "%s/%s", curtoppage->pagetitle, title);
				newp->next = NULL;

				pgtail->next = newp;
				pgtail = newp;

				curpage = newp;
			}
		}
		else if (strncmp(STRBUF(inbuf), "subparent", 9) == 0) {
			pagelist_t *newp, *parent;
			char *pname, *name, *title;

			pageidx = groupid = 0;
			parent = NULL;
			if (get_page_name_title(STRBUF(inbuf), "subparent", &pname, &title) == 0) {
				for (parent = pghead; (parent && !pagematch(parent, pname)); parent = parent->next);
			}

			if (parent && (get_page_name_title(title, "", &name, &title) == 0)) {
				newp = (pagelist_t *)malloc(sizeof(pagelist_t));
				newp->pagepath = malloc(strlen(parent->pagepath) + strlen(name) + 2);
				sprintf(newp->pagepath, "%s/%s", parent->pagepath, name);
				newp->pagetitle = malloc(strlen(parent->pagetitle) + strlen(title) + 2);
				sprintf(newp->pagetitle, "%s/%s", parent->pagetitle, title);
				newp->next = NULL;

				pgtail->next = newp;
				pgtail = newp;

				curpage = newp;
			}
		}
		else if (strncmp(STRBUF(inbuf), "group", 5) == 0) {
			groupid++;
		}
		else if (sscanf(STRBUF(inbuf), "%d.%d.%d.%d %s", &ip1, &ip2, &ip3, &ip4, hostname) == 5) {
			char *startoftags, *tag, *delim;
			int elemidx, elemsize;
			char clientname[4096];
			char downtime[4096];
			char groupidstr[10];
			RbtIterator handle;

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

			MEMDEFINE(clientname);
			MEMDEFINE(downtime);

			/* Hostname beginning with '@' are "no-display" hosts. But we still want them. */
			if (*hostname == '@') memmove(hostname, hostname+1, strlen(hostname));

			if (!fqdn) {
				/* Strip any domain from the hostname */
				char *p = strchr(hostname, '.');
				if (p) *p = '\0';
			}

			sprintf(newitem->ip, "%d.%d.%d.%d", ip1, ip2, ip3, ip4);
			sprintf(groupidstr, "%d", groupid);
			newitem->groupid = strdup(groupidstr);
			newitem->pageindex = pageidx++;

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

			clientname[0] = downtime[0] = '\0';
			startoftags = strchr(STRBUF(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 */
			handle = rbtFind(htree, newitem->bbhostname);
			if (strcasecmp(newitem->bbhostname, ".default.") == 0) {
				/* The pseudo DEFAULT host */
				newitem->next = NULL;
				defaulthost = newitem;
			}
			else if (handle == rbtEnd(htree)) {
				/* New item, so add to end of list */
				newitem->next = NULL;
				if (namehead == NULL) 
					namehead = nametail = newitem;
				else {
					nametail->next = newitem;
					nametail = newitem;
				}
				rbtInsert(htree, newitem->bbhostname, newitem);
			}
			else {
				/* Find the existing record - compare the record pointer instead of the name */
				namelist_t *existingrec = (namelist_t *)gettreeitem(htree, handle);
				for (iwalk = namehead, iprev = NULL; ((iwalk != existingrec) && iwalk); iprev = iwalk, iwalk = iwalk->next) ;
 				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);
		}
	}
	stackfclose(bbhosts);
	freestrbuffer(inbuf);
	rbtDelete(htree);

	MEMUNDEFINE(hostname);
	MEMUNDEFINE(l);

	build_hosttree();

	return 0;
}
Esempio n. 16
0
void readconfig(char *cfgfn, int verbose)
{
	static void *cfgfiles = NULL;
	FILE *cfgfd;
	strbuffer_t *inbuf;

	struct req_t *reqitem = NULL;
	int tasksleep = atoi(xgetenv("TASKSLEEP"));

	mibdef_t *mib;

	/* Check if config was modified */
	if (cfgfiles) {
		if (!stackfmodified(cfgfiles)) {
			dbgprintf("No files changed, skipping reload\n");
			return;
		}
		else {
			stackfclist(&cfgfiles);
			cfgfiles = NULL;
		}
	}

	cfgfd = stackfopen(cfgfn, "r", &cfgfiles);
	if (cfgfd == NULL) {
		errprintf("Cannot open configuration files %s\n", cfgfn);
		return;
	}

	inbuf = newstrbuffer(0);
	while (stackfgets(inbuf, NULL)) {
		char *bot, *p, *mibidx;
		char savech;

		sanitize_input(inbuf, 0, 0);
		bot = STRBUF(inbuf) + strspn(STRBUF(inbuf), " \t");
		if ((*bot == '\0') || (*bot == '#')) continue;

		if (*bot == '[') {
			char *intvl = strchr(bot, '/');

			/*
			 * See if we're running a non-standard interval.
			 * If yes, then process only the records that match
			 * this TASKSLEEP setting.
			 */
			if (tasksleep != 300) {
				/* Non-default interval. Skip the host if it HASN'T got an interval setting */
				if (!intvl) continue;

				/* Also skip the hosts that have an interval different from the current */
				*intvl = '\0';	/* Clip the interval from the hostname */
				if (atoi(intvl+1) != tasksleep) continue;
			}
			else {
				/* Default interval. Skip the host if it HAS an interval setting */
				if (intvl) continue;
			}

			reqitem = (req_t *)calloc(1, sizeof(req_t));

			p = strchr(bot, ']'); if (p) *p = '\0';
			reqitem->hostname = strdup(bot + 1);
			if (p) *p = ']';

			reqitem->hostip[0] = reqitem->hostname;
			reqitem->version = SNMP_VERSION_1;
			reqitem->authmethod = SNMP_V3AUTH_MD5;
			reqitem->next = reqhead;
			reqhead = reqitem;

			continue;
		}

		/* If we have nowhere to put the data, then skip further processing */
		if (!reqitem) continue;

		if (strncmp(bot, "ip=", 3) == 0) {
			char *nextip = strtok(strdup(bot+3), ",");
			int i = 0;

			do {
				reqitem->hostip[i++] = nextip;
				nextip = strtok(NULL, ",");
			} while (nextip);
			continue;
		}

		if (strncmp(bot, "version=", 8) == 0) {
			switch (*(bot+8)) {
			  case '1': reqitem->version = SNMP_VERSION_1; break;
			  case '2': reqitem->version = SNMP_VERSION_2c; break;
			  case '3': reqitem->version = SNMP_VERSION_3; break;
			}
			continue;
		}

		if (strncmp(bot, "community=", 10) == 0) {
			reqitem->community = strdup(bot+10);
			continue;
		}

		if (strncmp(bot, "username="******"passphrase=", 10) == 0) {
			reqitem->passphrase = strdup(bot+10);
			continue;
		}

		if (strncmp(bot, "authmethod=", 10) == 0) {
			if (strcasecmp(bot+10, "md5") == 0)
				reqitem->authmethod = SNMP_V3AUTH_MD5;
			else if (strcasecmp(bot+10, "sha1") == 0)
				reqitem->authmethod = SNMP_V3AUTH_SHA1;
			else
				errprintf("Unknown SNMPv3 authentication method '%s'\n", bot+10);

			continue;
		}

		/* Custom mibs */
		p = bot + strcspn(bot, "= \t\r\n"); savech = *p; *p = '\0';
		mib = find_mib(bot);
		*p = savech; 
		p += strspn(p, "= \t");
		mibidx = p;
		if (mib) {
			int i;
			mibidx_t *iwalk = NULL;
			char *oid, *oidbuf;
			char *devname;
			oidset_t *swalk;

			setupmib(mib, verbose);
			if (mib->loadstatus != MIB_STATUS_LOADED) continue;	/* Cannot use this MIB */

			/* See if this is an entry where we must determine the index ourselves */
			if (*mibidx) {
				for (iwalk = mib->idxlist; (iwalk && (*mibidx != iwalk->marker)); iwalk = iwalk->next) ;
			}

			if ((*mibidx == '*') && !iwalk) {
				errprintf("Cannot do wildcard matching without an index (host %s, mib %s)\n",
					  reqitem->hostname, mib->mibname);
				continue;
			}

			if (!iwalk) {
				/* No key lookup */
				swalk = mib->oidlisthead;
				while (swalk) {
					reqitem->setnumber++;

					for (i=0; (i <= swalk->oidcount); i++) {
						if (*mibidx) {
							oid = oidbuf = (char *)malloc(strlen(swalk->oids[i].oid) + strlen(mibidx) + 2);
							sprintf(oidbuf, "%s.%s", swalk->oids[i].oid, mibidx);
							devname = mibidx;
						}
						else {
							oid = swalk->oids[i].oid;
							oidbuf = NULL;
							devname = "-";
						}

						make_oitem(mib, devname, &swalk->oids[i], oid, reqitem);
						if (oidbuf) xfree(oidbuf);
					}

					swalk = swalk->next;
				}

				reqitem->next_oid = reqitem->oidhead;
			}
			else {
				/* Add a key-record so we can try to locate the index */
				keyrecord_t *newitem = (keyrecord_t *)calloc(1, sizeof(keyrecord_t));
				char endmarks[6];

				mibidx++;	/* Skip the key-marker */
				sprintf(endmarks, "%s%c", ")]}>", iwalk->marker);
				p = mibidx + strcspn(mibidx, endmarks); *p = '\0';
				newitem->key = strdup(mibidx);
				newitem->indexmethod = iwalk;
				newitem->mib = mib;
				newitem->next = reqitem->keyrecords;
				reqitem->currentkey = reqitem->keyrecords = newitem;
			}

			continue;
		}
		else {
			errprintf("Unknown MIB (not in snmpmibs.cfg): '%s'\n", bot);
		}
	}

	stackfclose(cfgfd);
	freestrbuffer(inbuf);
}
Esempio n. 17
0
int load_holidays(int year)
{
	static void *configholidays = NULL;
	char fn[PATH_MAX];
	FILE *fd;
	strbuffer_t *inbuf;
	holiday_t newholiday;
	xtreePos_t handle, commonhandle;
	char *setname = NULL;
	holidayset_t *commonhols;

	MEMDEFINE(fn);

	if (year == 0) {
		time_t tnow;
		struct tm *now;
		tnow = getcurrenttime(NULL);
		now = localtime(&tnow);
		year = now->tm_year;
	}
	else if (year > 1000) {
		year -= 1900;
	}

	sprintf(fn, "%s/etc/holidays.cfg", xgetenv("XYMONHOME"));

	/* First check if there were no modifications at all */
	if (configholidays) {
		/* if the new year begins, the holidays have to be recalculated */
		if (!stackfmodified(configholidays) && (year == current_year)){
			dbgprintf("No files modified, skipping reload of %s\n", fn);
			MEMUNDEFINE(fn);
			return 0;
		}
		else {
			stackfclist(&configholidays);
			configholidays = NULL;
		}
	}

	reset_holidays();

	fd = stackfopen(fn, "r", &configholidays);
	if (!fd) {
		errprintf("Cannot open configuration file %s\n", fn);
		MEMUNDEFINE(fn);
		return 0;
	}

	memset(&newholiday,0,sizeof(holiday_t));
	inbuf = newstrbuffer(0);

	while (stackfgets(inbuf, NULL)) {
		char *p, *delim, *arg1, *arg2;

		sanitize_input(inbuf, 1, 0);
		if (STRBUFLEN(inbuf) == 0) continue;

		p = STRBUF(inbuf);
		if (strncasecmp(p, "HOLIDAYLIKEWEEKDAY=", 19) == 0)  {
			p+=19;
			holidays_like_weekday = atoi(p);
			if (holidays_like_weekday < -1 || holidays_like_weekday > 6) {
				holidays_like_weekday = -1;
				errprintf("Invalid HOLIDAYLIKEWEEKDAY in %s\n", fn);
			}

			continue;
		}

		if (*p == '[') {
			/* New set of holidays */
			if (setname) xfree(setname);
			delim = strchr(p, ']'); if (delim) *delim = '\0';
			setname = strdup(p+1);
			continue;
		}

		delim = strchr(p, ':');
		if (delim) {
			memset(&newholiday,0,sizeof(holiday_t));
			if (delim == p) {
				newholiday.desc = "untitled";
			}
			else {
				*delim = '\0';
				newholiday.desc = p;
				p=delim+1;
			}
		}

		arg1 = strtok(p, "=");
		while (arg1) {
			arg2=strtok(NULL," ,;\t\n\r");
			if (!arg2) break;
			if (strncasecmp(arg1, "TYPE", 4) == 0) {
				if      (strncasecmp(arg2, "STATIC", 6) == 0) newholiday.holtype = HOL_ABSOLUTE;
				else if (strncasecmp(arg2, "EASTER", 6) == 0) newholiday.holtype = HOL_EASTER;
				else if (strncasecmp(arg2, "4ADVENT", 7) == 0) newholiday.holtype = HOL_ADVENT;
				else if (strncasecmp(arg2, "MON", 3) == 0) newholiday.holtype = HOL_MON;
				else if (strncasecmp(arg2, "TUE", 3) == 0) newholiday.holtype = HOL_TUE;
				else if (strncasecmp(arg2, "WED", 3) == 0) newholiday.holtype = HOL_WED;
				else if (strncasecmp(arg2, "THU", 3) == 0) newholiday.holtype = HOL_THU;
				else if (strncasecmp(arg2, "FRI", 3) == 0) newholiday.holtype = HOL_FRI;
				else if (strncasecmp(arg2, "SAT", 3) == 0) newholiday.holtype = HOL_SAT;
				else if (strncasecmp(arg2, "SUN", 3) == 0) newholiday.holtype = HOL_SUN;
				else if (strncasecmp(arg2, "+MON", 4) == 0) newholiday.holtype = HOL_MON_AFTER;
				else if (strncasecmp(arg2, "+TUE", 4) == 0) newholiday.holtype = HOL_TUE_AFTER;
				else if (strncasecmp(arg2, "+WED", 4) == 0) newholiday.holtype = HOL_WED_AFTER;
				else if (strncasecmp(arg2, "+THU", 4) == 0) newholiday.holtype = HOL_THU_AFTER;
				else if (strncasecmp(arg2, "+FRI", 4) == 0) newholiday.holtype = HOL_FRI_AFTER;
				else if (strncasecmp(arg2, "+SAT", 4) == 0) newholiday.holtype = HOL_SAT_AFTER;
				else if (strncasecmp(arg2, "+SUN", 4) == 0) newholiday.holtype = HOL_SUN_AFTER;
			}
			else if (strncasecmp(arg1, "MONTH", 5) == 0) {
				newholiday.month=atoi(arg2);
			}
			else if (strncasecmp(arg1, "DAY", 3) == 0) {
				newholiday.day=atoi(arg2);
			}
			else if (strncasecmp(arg1, "OFFSET", 6) == 0) {
				newholiday.day=atoi(arg2);
			}
			else if (strncasecmp(arg1, "YEAR", 4) == 0) {
				newholiday.year=atoi(arg2);
				if (newholiday.year > 1000) {
			                newholiday.year -= 1900;
			        }
			}

			arg1 = strtok(NULL,"=");
		}

		add_holiday((setname ? setname : ""), year, &newholiday);
	}

	stackfclose(fd);
	freestrbuffer(inbuf);

	commonhandle = xtreeFind(holidays, "");
	commonhols = (commonhandle != xtreeEnd(holidays)) ? (holidayset_t *)xtreeData(holidays, commonhandle) : NULL;

	for (handle = xtreeFirst(holidays); (handle != xtreeEnd(holidays)); handle = xtreeNext(holidays, handle)) {
		holidayset_t *oneset = (holidayset_t *)xtreeData(holidays, handle);
		if (commonhols && (oneset != commonhols)) {
			/* Add the common holidays to this set */
			holiday_t *walk;

			for (walk = commonhols->head; (walk); walk = walk->next) add_holiday(oneset->key, year, walk);
		}

		oneset->head = msort(oneset->head, record_compare, record_getnext, record_setnext);
	}

	MEMUNDEFINE(fn);
	current_year = year;

	return 0;
}
Esempio n. 18
0
int load_alertconfig(char *configfn, int defcolors, int defaultinterval)
{
	/* (Re)load the configuration file without leaking memory */
	static void *configfiles = NULL;
	char fn[PATH_MAX];
	FILE *fd;
	strbuffer_t *inbuf;
	char *p;
	rule_t *currule = NULL;
	recip_t *currcp = NULL, *rcptail = NULL;

	MEMDEFINE(fn);

	if (configfn) strcpy(fn, configfn); else sprintf(fn, "%s/etc/alerts.cfg", xgetenv("XYMONHOME"));

	/* First check if there were no modifications at all */
	if (configfiles) {
		if (!stackfmodified(configfiles)){
			dbgprintf("No files modified, skipping reload of %s\n", fn);
			MEMUNDEFINE(fn); 
			return 0;
		}
		else {
			stackfclist(&configfiles);
			configfiles = NULL;
		}
	}

	fd = stackfopen(fn, "r", &configfiles);
	if (!fd) { 
		errprintf("Cannot open configuration file %s: %s\n", fn, strerror(errno));
		MEMUNDEFINE(fn); 
		return 0; 
	}

	/* First, clean out the old rule set */
	while (rulehead) {
		rule_t *trule;

		if (rulehead->criteria) {
			free_criteria(rulehead->criteria);
			xfree(rulehead->criteria);
		}

		while (rulehead->recipients) {
			recip_t *trecip = rulehead->recipients;

			if (trecip->criteria) {
				recip_t *rwalk;

				/* Clear out the duplicate criteria that may exist, to avoid double-free'ing them */
				for (rwalk = trecip->next; (rwalk); rwalk = rwalk->next) {
					if (rwalk->criteria == trecip->criteria) rwalk->criteria = NULL;
				}

				free_criteria(trecip->criteria);
				xfree(trecip->criteria);
			}

			if (trecip->recipient)  xfree(trecip->recipient);
			if (trecip->scriptname) xfree(trecip->scriptname);
			rulehead->recipients = rulehead->recipients->next;
			xfree(trecip);
		}
		trule = rulehead;
		rulehead = rulehead->next;
		xfree(trule);
	}

	while (tokhead) {
		token_t *ttok;

		if (tokhead->name)  xfree(tokhead->name);
		if (tokhead->value) xfree(tokhead->value);
		ttok = tokhead;
		tokhead = tokhead->next;
		xfree(ttok);
	}

	defaultcolors = defcolors;

	MEMDEFINE(cfline);

	cfid = 0;
	inbuf = newstrbuffer(0);
	while (stackfgets(inbuf, NULL)) {
		int firsttoken = 1;
		int mailcmdactive = 0, scriptcmdactive = 0;
		recip_t *curlinerecips = NULL;

		cfid++;
		sanitize_input(inbuf, 1, 0);

		/* Skip empty lines */
		if (STRBUFLEN(inbuf) == 0) continue;

		if ((*STRBUF(inbuf) == '$') && strchr(STRBUF(inbuf), '=')) {
			/* Define a macro */
			token_t *newtok = (token_t *) malloc(sizeof(token_t));
			char *delim;

			delim = strchr(STRBUF(inbuf), '=');
			*delim = '\0';
			newtok->name = strdup(STRBUF(inbuf)+1);	/* Skip the '$' */
			newtok->value = strdup(preprocess(delim+1));
			newtok->next = tokhead;
			tokhead = newtok;
			continue;
		}

		strncpy(cfline, STRBUF(inbuf), (sizeof(cfline)-1));
		cfline[sizeof(cfline)-1] = '\0';

		/* Expand macros inside the line before parsing */
		p = strtok(preprocess(STRBUF(inbuf)), " \t");
		while (p) {
			if ((strncasecmp(p, "PAGE=", 5) == 0) || (strncasecmp(p, "PAGES=", 6) == 0)) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->pagespec = strdup(val);
				if (*(crit->pagespec) == '%') crit->pagespecre = compileregex(crit->pagespec+1);
				firsttoken = 0;
			}
			else if ((strncasecmp(p, "EXPAGE=", 7) == 0) || (strncasecmp(p, "EXPAGES=", 8) == 0)) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->expagespec = strdup(val);
				if (*(crit->expagespec) == '%') crit->expagespecre = compileregex(crit->expagespec+1);
				firsttoken = 0;
			}
			else if ((strncasecmp(p, "DISPLAYGROUP=", 13) == 0) || (strncasecmp(p, "DISPLAYGROUPS=", 14) == 0)) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->dgspec = strdup(val);
				if (*(crit->dgspec) == '%') crit->dgspecre = compileregex(crit->dgspec+1);
				firsttoken = 0;
			}
			else if ((strncasecmp(p, "EXDISPLAYGROUP=", 15) == 0) || (strncasecmp(p, "EXDISPLAYGROUPS=", 16) == 0)) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->exdgspec = strdup(val);
				if (*(crit->exdgspec) == '%') crit->exdgspecre = compileregex(crit->exdgspec+1);
				firsttoken = 0;
			}
			else if ((strncasecmp(p, "HOST=", 5) == 0) || (strncasecmp(p, "HOSTS=", 6) == 0)) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->hostspec = strdup(val);
				if (*(crit->hostspec) == '%') crit->hostspecre = compileregex(crit->hostspec+1);
				firsttoken = 0;
			}
			else if ((strncasecmp(p, "EXHOST=", 7) == 0) || (strncasecmp(p, "EXHOSTS=", 8) == 0)) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->exhostspec = strdup(val);
				if (*(crit->exhostspec) == '%') crit->exhostspecre = compileregex(crit->exhostspec+1);
				firsttoken = 0;
			}
			else if ((strncasecmp(p, "SERVICE=", 8) == 0) || (strncasecmp(p, "SERVICES=", 9) == 0)) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->svcspec = strdup(val);
				if (*(crit->svcspec) == '%') crit->svcspecre = compileregex(crit->svcspec+1);
				firsttoken = 0;
			}
			else if ((strncasecmp(p, "EXSERVICE=", 10) == 0) || (strncasecmp(p, "EXSERVICES=", 11) == 0)) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->exsvcspec = strdup(val);
				if (*(crit->exsvcspec) == '%') crit->exsvcspecre = compileregex(crit->exsvcspec+1);
				firsttoken = 0;
			}
			else if (strncasecmp(p, "CLASS=", 6) == 0) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->classspec = strdup(val);
				if (*(crit->classspec) == '%') crit->classspecre = compileregex(crit->classspec+1);
				firsttoken = 0;
			}
			else if (strncasecmp(p, "EXCLASS=", 8) == 0) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->exclassspec = strdup(val);
				if (*(crit->exclassspec) == '%') crit->exclassspecre = compileregex(crit->exclassspec+1);
				firsttoken = 0;
			}
			else if (strncasecmp(p, "GROUP=", 6) == 0) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->groupspec = strdup(val);
				if (*(crit->groupspec) == '%') crit->groupspecre = compileregex(crit->groupspec+1);
				firsttoken = 0;
			}
			else if (strncasecmp(p, "EXGROUP=", 8) == 0) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->exgroupspec = strdup(val);
				if (*(crit->exgroupspec) == '%') crit->exgroupspecre = compileregex(crit->exgroupspec+1);
				firsttoken = 0;
			}
			else if ((strncasecmp(p, "COLOR=", 6) == 0) || (strncasecmp(p, "COLORS=", 7) == 0)) {
				criteria_t *crit;
				char *c1, *c2;
				int cval, reverse = 0;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				crit = setup_criteria(&currule, &currcp);

				/* Put a value in crit->colors so we know there is an explicit color setting */
				crit->colors = (1 << 30);
				c1 = strchr(p, '=')+1;

				/*
				 * If the first colorspec is "!color", then apply the default colors and
				 * subtract colors from that.
				 */
				if (*c1 == '!') crit->colors |= defaultcolors;

				do {
					c2 = strchr(c1, ',');
					if (c2) *c2 = '\0';

					if (*c1 == '!') { reverse=1; c1++; }
					cval = (1 << parse_color(c1));

					if (reverse)
						crit->colors &= (~cval);
					else 
						crit->colors |= cval;

					if (c2) c1 = (c2+1); else c1 = NULL;
				} while (c1);
				firsttoken = 0;
			}
			else if ((strncasecmp(p, "TIME=", 5) == 0) || (strncasecmp(p, "TIMES=", 6) == 0)) {
				char *val;
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				val = strchr(p, '=')+1;
				crit = setup_criteria(&currule, &currcp);
				crit->timespec = strdup(val);
				firsttoken = 0;
			}
			else if (strncasecmp(p, "DURATION", 8) == 0) {
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				crit = setup_criteria(&currule, &currcp);
				if (*(p+8) == '>') crit->minduration = 60*durationvalue(p+9);
				else if (*(p+8) == '<') crit->maxduration = 60*durationvalue(p+9);
				else errprintf("Ignoring invalid DURATION at line %d: %s\n",cfid, p);
				firsttoken = 0;
			}
			else if (strncasecmp(p, "RECOVERED", 9) == 0) {
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				crit = setup_criteria(&currule, &currcp);
				crit->sendrecovered = SR_WANTED;
				firsttoken = 0;
			}
			else if (strncasecmp(p, "NORECOVERED", 11) == 0) {
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				crit = setup_criteria(&currule, &currcp);
				crit->sendrecovered = SR_NOTWANTED;
				firsttoken = 0;
			}
			else if (strncasecmp(p, "NOTICE", 6) == 0) {
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				crit = setup_criteria(&currule, &currcp);
				crit->sendnotice = SR_WANTED;
				firsttoken = 0;
			}
			else if (strncasecmp(p, "NONOTICE", 8) == 0) {
				criteria_t *crit;

				if (firsttoken) { flush_rule(currule); currule = NULL; currcp = NULL; pstate = P_NONE; }
				crit = setup_criteria(&currule, &currcp);
				crit->sendnotice = SR_NOTWANTED;
				firsttoken = 0;
			}
			else if ((pstate == P_RECIP) && (strncasecmp(p, "FORMAT=", 7) == 0)) {
				if (!currcp) errprintf("FORMAT used without a recipient (line %d), ignored\n", cfid);
				else if (strcasecmp(p+7, "TEXT") == 0) currcp->format = ALERTFORM_TEXT;
				else if (strcasecmp(p+7, "PLAIN") == 0) currcp->format = ALERTFORM_PLAIN;
				else if (strcasecmp(p+7, "SMS") == 0) currcp->format = ALERTFORM_SMS;
				else if (strcasecmp(p+7, "PAGER") == 0) currcp->format = ALERTFORM_PAGER;
				else if (strcasecmp(p+7, "SCRIPT") == 0) currcp->format = ALERTFORM_SCRIPT;
				else errprintf("Unknown FORMAT setting '%s' ignored\n", p);
				firsttoken = 0;
			}
			else if ((pstate == P_RECIP) && (strncasecmp(p, "REPEAT=", 7) == 0)) {
				if (!currcp) errprintf("REPEAT used without a recipient (line %d), ignored\n", cfid);
				else currcp->interval = 60*durationvalue(p+7);
				firsttoken = 0;
			}
			else if ((pstate == P_RECIP) && (strcasecmp(p, "STOP") == 0)) {
				if (!currcp) errprintf("STOP used without a recipient (line %d), ignored\n", cfid);
				else currcp->stoprule = 1;
				firsttoken = 0;
			}
			else if ((pstate == P_RECIP) && (strcasecmp(p, "UNMATCHED") == 0)) {
				if (!currcp) errprintf("UNMATCHED used without a recipient (line %d), ignored\n", cfid);
				else currcp->unmatchedonly = 1;
				firsttoken = 0;
			}
			else if ((pstate == P_RECIP) && (strncasecmp(p, "NOALERT", 7) == 0)) {
				if (!currcp) errprintf("NOALERT used without a recipient (line %d), ignored\n", cfid);
				else currcp->noalerts = 1;
				firsttoken = 0;
			}
			else if (currule && ((strncasecmp(p, "MAIL", 4) == 0) || mailcmdactive) ) {
				recip_t *newrcp;

				mailcmdactive = 1;
				newrcp = (recip_t *)calloc(1, sizeof(recip_t));
				newrcp->cfid = cfid;
				newrcp->method = M_MAIL;
				newrcp->format = ALERTFORM_TEXT;

				if (strncasecmp(p, "MAIL=", 5) == 0) {
					p += 5;
				}
				else if (strcasecmp(p, "MAIL") == 0) {
					p = strtok(NULL, " \t");
				}
				else {
					/* Second recipient on a rule - do nothing */
				}

				if (p) {
					newrcp->recipient = strdup(p);
					newrcp->interval = defaultinterval;
					currcp = newrcp;
					if (curlinerecips == NULL) curlinerecips = newrcp;
					pstate = P_RECIP;

					if (currule->recipients == NULL)
						currule->recipients = rcptail = newrcp;
					else {
						rcptail->next = newrcp;
						rcptail = newrcp;
					}
				}
				else {
					errprintf("Ignoring MAIL with no recipient at line %d\n", cfid);
					xfree(newrcp);
				}
				firsttoken = 0;
			}
			else if (currule && ((strncasecmp(p, "SCRIPT", 6) == 0) || scriptcmdactive)) {
				recip_t *newrcp;

				scriptcmdactive = 1;
				newrcp = (recip_t *)calloc(1, sizeof(recip_t));
				newrcp->cfid = cfid;
				newrcp->method = M_SCRIPT;
				newrcp->format = ALERTFORM_SCRIPT;

				if (strncasecmp(p, "SCRIPT=", 7) == 0) {
					p += 7;
					newrcp->scriptname = strdup(p);
					p = strtok(NULL, " \t");
				}
				else if (strcasecmp(p, "SCRIPT") == 0) {
					p = strtok(NULL, " \t");
					if (p) {
						newrcp->scriptname = strdup(p);
						p = strtok(NULL, " \t");
					}
					else {
						errprintf("Invalid SCRIPT command at line %d\n", cfid);
					}
				}
				else {
					/* A second recipient for the same script as the previous one */
					newrcp->scriptname = strdup(currcp->scriptname);
				}

				if (p) {
					newrcp->recipient = strdup(p);
					newrcp->interval = defaultinterval;
					currcp = newrcp;
					if (curlinerecips == NULL) curlinerecips = newrcp;
					pstate = P_RECIP;

					if (currule->recipients == NULL)
						currule->recipients = rcptail = newrcp;
					else {
						rcptail->next = newrcp;
						rcptail = newrcp;
					}
				}
				else {
					errprintf("Ignoring SCRIPT with no recipient at line %d\n", cfid);
					if (newrcp->scriptname) xfree(newrcp->scriptname);
					xfree(newrcp);
				}
				firsttoken = 0;
			}
			else if (currule && (strncasecmp(p, "IGNORE", 6) == 0)) {
				recip_t *newrcp;

				newrcp = (recip_t *)calloc(1, sizeof(recip_t));
				newrcp->cfid = cfid;
				newrcp->method = M_IGNORE;
				newrcp->format = ALERTFORM_NONE;
				newrcp->interval = defaultinterval;
				newrcp->stoprule = 1;
				currcp = newrcp;
				if (curlinerecips == NULL) curlinerecips = newrcp;
				pstate = P_RECIP;

				if (currule->recipients == NULL)
					currule->recipients = rcptail = newrcp;
				else {
					rcptail->next = newrcp;
					rcptail = newrcp;
				}

				firsttoken = 0;
			}
			else {
				errprintf("Ignored unknown/unexpected token '%s' at line %d\n", p, cfid);
			}

			if (p) p = strtok(NULL, " \t");
		}

		if (curlinerecips && currcp && (curlinerecips != currcp)) {
			/* We have multiple recipients on one line. Make sure criteria etc. get copied */
			recip_t *rwalk;

			/* All criteria etc. have been set on the last recipient (currcp) */
			for (rwalk = curlinerecips; (rwalk != currcp); rwalk = rwalk->next) {
				rwalk->format = currcp->format;
				rwalk->interval = currcp->interval;
				rwalk->criteria = currcp->criteria;
				rwalk->noalerts = currcp->noalerts;
			}
		}
	}

	flush_rule(currule);
	stackfclose(fd);
	freestrbuffer(inbuf);

	MEMUNDEFINE(cfline);
	MEMUNDEFINE(fn);

	return 1;
}