Example #1
0
char *histlogtime(time_t histtime)
{
	static char *result = NULL;
	char d1[40],d2[3],d3[40];

	if (result == NULL) result = (char *)malloc(30);
	MEMDEFINE(d1); MEMDEFINE(d2); MEMDEFINE(d3);

	/*
	 * Historical logs use a filename like "Fri_Nov_7_16:01:08_2002 
	 * But apparently there is no simple way to generate a day-of-month 
	 * with no leading 0.
	 */

        strftime(d1, sizeof(d1), "%a_%b_", localtime(&histtime));
        strftime(d2, sizeof(d2), "%d", localtime(&histtime));
	if (d2[0] == '0') { d2[0] = d2[1]; d2[1] = '\0'; }
        strftime(d3, sizeof(d3), "_%H:%M:%S_%Y", localtime(&histtime));

	snprintf(result, 29, "%s%s%s", d1, d2, d3);

	MEMUNDEFINE(d1); MEMUNDEFINE(d2); MEMUNDEFINE(d3);

	return result;
}
Example #2
0
static void load_links(char *directory, char *urlprefix)
{
	DIR		*linkdir;
	struct dirent 	*d;
	char		fn[PATH_MAX];

	dbgprintf("load_links(%s, %s)\n", textornull(directory), textornull(urlprefix));

	linkdir = opendir(directory);
	if (!linkdir) {
		errprintf("Cannot read links in directory %s\n", directory);
		return;
	}

	MEMDEFINE(fn);

	while ((d = readdir(linkdir))) {
		link_t *newlink;

		if (*(d->d_name) == '.') continue;

		strcpy(fn, d->d_name);
		newlink = init_link(fn, urlprefix);
		rbtInsert(linkstree, newlink->key, newlink);
	}
	closedir(linkdir);

	MEMUNDEFINE(fn);
}
Example #3
0
static char *message_subject(activealerts_t *alert, recip_t *recip)
{
    static char subj[250];
    static char *sevtxt[COL_COUNT] = {
        "is GREEN",
        "has no data (CLEAR)",
        "is disabled (BLUE)",
        "stopped reporting (PURPLE)",
        "warning (YELLOW)",
        "CRITICAL (RED)"
    };
    char *sev = "";
    char *subjfmt = NULL;

    /* Only subjects on ALERTFORM_TEXT and ALERTFORM_PLAIN messages */
    if ((recip->format != ALERTFORM_TEXT) && (recip->format != ALERTFORM_PLAIN)) return NULL;

    MEMDEFINE(subj);

    if ((alert->color >= 0) && (alert->color < COL_COUNT)) sev = sevtxt[alert->color];

    switch (alert->state) {
    case A_PAGING:
    case A_ACKED:
        subjfmt = (include_configid ? "Xymon [%d] %s:%s %s [cfid:%d]" :  "Xymon [%d] %s:%s %s");
        snprintf(subj, sizeof(subj), subjfmt,
                 alert->cookie, alert->hostname, alert->testname, sev, recip->cfid);
        break;

    case A_NOTIFY:
        subjfmt = (include_configid ? "Xymon %s:%s NOTICE [cfid:%d]" :  "Xymon %s:%s NOTICE");
        snprintf(subj, sizeof(subj), subjfmt,
                 alert->hostname, alert->testname, recip->cfid);
        break;

    case A_RECOVERED:
        subjfmt = (include_configid ? "Xymon %s:%s recovered [cfid:%d]" :  "Xymon %s:%s recovered");
        snprintf(subj, sizeof(subj), subjfmt,
                 alert->hostname, alert->testname, recip->cfid);
        break;

    case A_DISABLED:
        subjfmt = (include_configid ? "Xymon %s:%s disabled [cfid:%d]" :  "Xymon %s:%s disabled");
        snprintf(subj, sizeof(subj), subjfmt,
                 alert->hostname, alert->testname, recip->cfid);
        break;

    case A_NORECIP:
    case A_DEAD:
        /* Cannot happen */
        break;
    }

    *(subj + sizeof(subj) - 1) = '\0';

    MEMUNDEFINE(subj);
    return subj;
}
Example #4
0
void do_extensions(FILE *output, char *extenv, char *family)
{
	/*
	 * Extension scripts. These are ad-hoc, and implemented as a
	 * simple pipe. So we do a fork here ...
	 */

	char *exts, *p;
	FILE *inpipe;
	char extfn[PATH_MAX];
	strbuffer_t *inbuf;

	p = xgetenv(extenv);
	if (p == NULL) {
		/* No extension */
		return;
	}

	MEMDEFINE(extfn);

	exts = strdup(p);
	p = strtok(exts, "\t ");
	inbuf = newstrbuffer(0);

	while (p) {
		/* Dont redo the eventlog or acklog things */
		if ((strcmp(p, "eventlog.sh") != 0) &&
		    (strcmp(p, "acklog.sh") != 0)) {
			sprintf(extfn, "%s/ext/%s/%s", xgetenv("XYMONHOME"), family, p);
			inpipe = popen(extfn, "r");
			if (inpipe) {
				initfgets(inpipe);
				while (unlimfgets(inbuf, inpipe)) fputs(STRBUF(inbuf), output);
				pclose(inpipe);
				freestrbuffer(inbuf);
			}
		}
		p = strtok(NULL, "\t ");
	}

	xfree(exts);

	MEMUNDEFINE(extfn);
	MEMUNDEFINE(buf);
}
Example #5
0
void update_htmlfile(char *fn, char *msg, 
		     char *hostname, char *service, int color, int flapping,
		     char *sender, char *flags,
		     time_t logtime, time_t timesincechange,
		     time_t acktime, char *ackmsg,
                     time_t disabletime, char *dismsg)
{
	FILE *output;
	char *tmpfn;
	char *firstline, *restofmsg;
	char *displayname = hostname;
	char *ip = "";
	char timestr[100];

	MEMDEFINE(timestr);

	tmpfn = (char *) malloc(strlen(fn)+5);
	sprintf(tmpfn, "%s.tmp", fn);
	output = fopen(tmpfn, "w");

	if (output) {
		firstline = msg;
		restofmsg = strchr(msg, '\n');
		if (restofmsg) {
			*restofmsg = '\0';
			restofmsg++;
		}
		else {
			restofmsg = "";
		}

		if (timesincechange >= 0) {
			char *p = timestr;
			if (timesincechange > 86400) p += sprintf(p, "%ld days, ", (timesincechange / 86400));
			p += sprintf(p, "%ld hours, %ld minutes", 
					((timesincechange % 86400) / 3600), ((timesincechange % 3600) / 60));
		}

		generate_html_log(hostname, displayname, service, ip,
			color, flapping, sender, flags,
			logtime, timestr,
			firstline, restofmsg, NULL,
			acktime, ackmsg, NULL,
			disabletime, dismsg,
			0, 1, 0, locatorbased, multigraphs, NULL, 
			NULL, NULL, NULL,
			0,
			output);

		fclose(output);
		rename(tmpfn, fn);
	}

	xfree(tmpfn);
	MEMUNDEFINE(timestr);
}
Example #6
0
FILE *stackfopen(char *filename, char *mode, void **v_listhead)
{
	FILE *newfd;
	stackfd_t *newitem;
	char stackfd_filename[PATH_MAX];
	filelist_t **listhead = (filelist_t **)v_listhead;

	MEMDEFINE(stackfd_filename);

	if (fdhead == NULL) {
		char *p;

		stackfd_base = strdup(filename);
		p = strrchr(stackfd_base, '/'); if (p) *(p+1) = '\0';

		stackfd_mode = strdup(mode);

		strcpy(stackfd_filename, filename);
	}
	else {
		if (*filename == '/')
			strcpy(stackfd_filename, filename);
		else
			sprintf(stackfd_filename, "%s/%s", stackfd_base, filename);
	}

	dbgprintf("Opening file %s\n", stackfd_filename);
	newfd = fopen(stackfd_filename, stackfd_mode);
	if (newfd != NULL) {
		newitem = (stackfd_t *) malloc(sizeof(stackfd_t));
		newitem->fd = newfd;
		newitem->listhead = listhead;
		newitem->next = fdhead;
		fdhead = newitem;
		initfgets(newfd);

		if (listhead) {
			struct filelist_t *newlistitem;
			struct stat st;

			fstat(fileno(newfd), &st);
			newlistitem = (filelist_t *)malloc(sizeof(filelist_t));
			newlistitem->filename = strdup(stackfd_filename);
			newlistitem->mtime = st.st_mtime;
			newlistitem->fsize = st.st_size;
			newlistitem->next = *listhead;
			*listhead = newlistitem;
		}
	}

	MEMUNDEFINE(stackfd_filename);

	return newfd;
}
Example #7
0
void close_channel(hobbitd_channel_t *chn, int role)
{
	if (chn == NULL) return;

	/* No need to de-register, this happens automatically because we registered with SEM_UNDO */

	if (role == CHAN_MASTER) semctl(chn->semid, 0, IPC_RMID);

	MEMUNDEFINE(chn->channelbuf);
	shmdt(chn->channelbuf);
	if (role == CHAN_MASTER) shmctl(chn->shmid, IPC_RMID, NULL);
}
Example #8
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);
}
Example #9
0
void errprintf(const char *fmt, ...)
{
	char timestr[30];
	char msg[4096];
	va_list args;

	time_t now = getcurrenttime(NULL);

	MEMDEFINE(timestr);
	MEMDEFINE(msg);

	strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now));
	fprintf(stderr, "%s ", timestr);
	if (errappname) fprintf(stderr, "%s ", errappname);

	va_start(args, fmt);
	vsnprintf(msg, sizeof(msg), fmt, args);
	va_end(args);

	fprintf(stderr, "%s", msg);
	fflush(stderr);

	if (save_errbuf) {
		if (errbuf == NULL) {
			errbufsize = 8192;
			errbuf = (char *) malloc(errbufsize);
			*errbuf = '\0';
		}
		else if ((strlen(errbuf) + strlen(msg)) > errbufsize) {
			errbufsize += 8192;
			errbuf = (char *) realloc(errbuf, errbufsize);
		}

		strcat(errbuf, msg);
	}

	MEMUNDEFINE(timestr);
	MEMUNDEFINE(msg);
}
Example #10
0
void show_timestamps(char **buffer)
{
	timestamp_t *s;
	struct timespec dif;
	char *outbuf = (char *) malloc(4096);
	int outbuflen = 4096;
	char buf1[80];

	if (!timing || (stamphead == NULL)) return;

	MEMDEFINE(buf1);

	strcpy(outbuf, "\n\nTIME SPENT\n");
	strcat(outbuf, "Event                                   ");
	strcat(outbuf, "        Start time");
	strcat(outbuf, "          Duration\n");

	for (s=stamphead; (s); s=s->next) {
		sprintf(buf1, "%-40s ", s->eventtext);
		strcat(outbuf, buf1);
		sprintf(buf1, "%10u.%06u ", (unsigned int)s->eventtime.tv_sec, (unsigned int)s->eventtime.tv_nsec / 1000);
		strcat(outbuf, buf1);
		if (s->prev) {
			tvdiff(&((timestamp_t *)s->prev)->eventtime, &s->eventtime, &dif);
			sprintf(buf1, "%10u.%06u ", (unsigned int)dif.tv_sec, (unsigned int)dif.tv_nsec / 1000);
			strcat(outbuf, buf1);
		}
		else strcat(outbuf, "                -");
		strcat(outbuf, "\n");

		if ((outbuflen - strlen(outbuf)) < 200) {
			outbuflen += 4096;
			outbuf = (char *) realloc(outbuf, outbuflen);
		}
	}

	tvdiff(&stamphead->eventtime, &stamptail->eventtime, &dif);
	sprintf(buf1, "%-40s ", "TIME TOTAL"); strcat(outbuf, buf1);
	sprintf(buf1, "%-18s", ""); strcat(outbuf, buf1);
	sprintf(buf1, "%10u.%06u ", (unsigned int)dif.tv_sec, (unsigned int)dif.tv_nsec / 1000); strcat(outbuf, buf1);
	strcat(outbuf, "\n");

	if (buffer == NULL) {
		printf("%s", outbuf);
		xfree(outbuf);
	}
	else *buffer = outbuf;

	MEMUNDEFINE(buf1);
}
Example #11
0
void dropdirectory(char *dirfn, int background)
{
	DIR *dirfd;
	struct dirent *de;
	char fn[PATH_MAX];
	struct stat st;
	pid_t childpid = 0;

	if (background) {
		/* Caller wants us to run as a background task. */
		childpid = fork();
	}

	MEMDEFINE(fn);

	if (childpid == 0) {
		dbgprintf("Starting to remove directory %s\n", dirfn);
		dirfd = opendir(dirfn);
		if (dirfd) {
			while ( (de = readdir(dirfd)) != NULL ) {
				sprintf(fn, "%s/%s", dirfn, de->d_name);
				if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..") && (stat(fn, &st) == 0)) {
					if (S_ISREG(st.st_mode)) {
						dbgprintf("Removing file %s\n", fn);
						unlink(fn);
					}
					else if (S_ISDIR(st.st_mode)) {
						dbgprintf("Recurse into %s\n", fn);
						dropdirectory(fn, 0); /* Don't background the recursive calls! */
					}
				}
			}
			closedir(dirfd);
		}
		dbgprintf("Removing directory %s\n", dirfn);
		rmdir(dirfn);
		if (background) {
			/* Background task just exits */
			exit(0);
		}
	}
	else if (childpid < 0) {
		errprintf("Could not fork child to remove directory %s\n", dirfn);
	}

	MEMUNDEFINE(fn);
}
Example #12
0
void load_all_links(void)
{
	char dirname[PATH_MAX];
	char *p;

	MEMDEFINE(dirname);

	dbgprintf("load_all_links()\n");

	linkstree = xtreeNew(strcasecmp);

	if (notesskin) { xfree(notesskin); notesskin = NULL; }
	if (helpskin) { xfree(helpskin); helpskin = NULL; }
	if (columndocurl) { xfree(columndocurl); columndocurl = NULL; }
	if (hostdocurl) { xfree(hostdocurl); hostdocurl = NULL; }

	if (xgetenv("XYMONNOTESSKIN")) notesskin = strdup(xgetenv("XYMONNOTESSKIN"));
	else { 
		notesskin = (char *) malloc(strlen(xgetenv("XYMONWEB")) + strlen("/notes") + 1);
		sprintf(notesskin, "%s/notes", xgetenv("XYMONWEB"));
	}

	if (xgetenv("XYMONHELPSKIN")) helpskin = strdup(xgetenv("XYMONHELPSKIN"));
	else { 
		helpskin = (char *) malloc(strlen(xgetenv("XYMONWEB")) + strlen("/help") + 1);
		sprintf(helpskin, "%s/help", xgetenv("XYMONWEB"));
	}

	if (xgetenv("COLUMNDOCURL")) columndocurl = strdup(xgetenv("COLUMNDOCURL"));
	if (xgetenv("HOSTDOCURL")) hostdocurl = strdup(xgetenv("HOSTDOCURL"));

	if (!hostdocurl || (strlen(hostdocurl) == 0)) {
		strcpy(dirname, xgetenv("XYMONNOTESDIR"));
		load_links(dirname, notesskin);
	}

	/* Change xxx/xxx/xxx/notes into xxx/xxx/xxx/help */
	strcpy(dirname, xgetenv("XYMONNOTESDIR"));
	p = strrchr(dirname, '/'); *p = '\0'; strcat(dirname, "/help");
	load_links(dirname, helpskin);

	linksloaded = 1;

	MEMUNDEFINE(dirname);
}
Example #13
0
void update_file(char *fn, char *mode, char *msg, time_t expire, char *sender, time_t timesincechange, int seq)
{
	FILE *logfd;
	char tmpfn[PATH_MAX];
	char *p;

	MEMDEFINE(tmpfn);

	dbgprintf("Updating seq %d file %s\n", seq, fn);

	p = strrchr(fn, '/');
	if (p) {
		*p = '\0';
		sprintf(tmpfn, "%s/.%s", fn, p+1);
		*p = '/';
	}
	else {
		sprintf(tmpfn, ".%s", fn);
	}

	logfd = fopen(tmpfn, mode);
	fwrite(msg, strlen(msg), 1, logfd);
	if (sender) fprintf(logfd, "\n\nMessage received from %s\n", sender);
	if (timesincechange >= 0) {
		char timestr[100];
		char *p = timestr;
		if (timesincechange > 86400) p += sprintf(p, "%ld days, ", (timesincechange / 86400));
		p += sprintf(p, "%ld hours, %ld minutes", 
				((timesincechange % 86400) / 3600), ((timesincechange % 3600) / 60));
		fprintf(logfd, "Status unchanged in %s\n", timestr);
	}
	fclose(logfd);

	if (expire) {
		struct utimbuf logtime;
		logtime.actime = logtime.modtime = expire;
		utime(tmpfn, &logtime);
	}

	rename(tmpfn, fn);

	MEMUNDEFINE(tmpfn);
}
Example #14
0
static criteria_t *setup_criteria(rule_t **currule, recip_t **currcp)
{
	criteria_t *crit = NULL;

	MEMDEFINE(cfline);

	switch (pstate) {
	  case P_NONE:
		*currule = (rule_t *)calloc(1, sizeof(rule_t));
		(*currule)->cfid = cfid;
		pstate = P_RULE;
		/* Fall through */

	  case P_RULE:
		if (!(*currule)->criteria) 
			(*currule)->criteria = (criteria_t *)calloc(1, sizeof(criteria_t));
		crit = (*currule)->criteria;
		crit->cfid = cfid;
		if (crit->cfline == NULL) crit->cfline = strdup(cfline);
		*currcp = NULL;
		break;

	  case P_RECIP:
		if (!(*currcp)->criteria) {
			recip_t *rwalk;

			(*currcp)->criteria = (criteria_t *)calloc(1, sizeof(criteria_t));

			/* Make sure other recipients on the same rule also get these criteria */
			for (rwalk = (*currule)->recipients; (rwalk); rwalk = rwalk->next) {
				if (rwalk->cfid == cfid) rwalk->criteria = (*currcp)->criteria;
			}
		}
		crit = (*currcp)->criteria;
		crit->cfid = cfid;
		if (crit->cfline == NULL) crit->cfline = strdup(cfline);
		break;
	}

	MEMUNDEFINE(cfline);
	return crit;
}
Example #15
0
void traceprintf(const char *fmt, ...)
{
	va_list args;

	if (tracefd) {
		char timestr[40];
		time_t now = getcurrenttime(NULL);

		MEMDEFINE(timestr);

		strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now));
		fprintf(tracefd, "%08u %s ", (unsigned int)getpid(), timestr);

		va_start(args, fmt);
		vfprintf(tracefd, fmt, args);
		va_end(args);
		fflush(tracefd);

		MEMUNDEFINE(timestr);
	}
}
Example #16
0
void dbgprintf(const char *fmt, ...)
{
	va_list args;

	if (debug) {
		char timestr[30];
		time_t now = getcurrenttime(NULL);

		MEMDEFINE(timestr);

		if (!debugfd) debugfd = stdout;

		strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S",
			 localtime(&now));
		fprintf(debugfd, "%s ", timestr);

		va_start(args, fmt);
		vfprintf(debugfd, fmt, args);
		va_end(args);
		fflush(debugfd);

		MEMUNDEFINE(timestr);
	}
}
Example #17
0
int load_hostnames(char *hostsfn, char *extrainclude, int fqdn)
{
	/* Return value: 0 for load OK, 1 for "No files changed since last load", -1 for error (file not found) */
	int prepresult;
	int ip1, ip2, ip3, ip4, groupid, pageidx;
	char hostname[4096], *dgname;
	pagelist_t *curtoppage, *curpage, *pgtail;
	namelist_t *nametail = NULL;
	void * htree;
	char *cfgdata, *inbol, *ineol, insavchar = '\0';

	load_hostinfo(NULL);

	if (*hostsfn == '!')
		prepresult = prepare_fromfile(hostsfn+1, extrainclude);
	else if (extrainclude)
		prepresult = prepare_fromfile(hostsfn, extrainclude);
	else if ((*hostsfn == '@') || (strcmp(hostsfn, xgetenv("HOSTSCFG")) == 0)) {
		prepresult = prepare_fromnet();
		if (prepresult == -1) {
			errprintf("Failed to load from xymond, reverting to file-load\n");
			prepresult = prepare_fromfile(xgetenv("HOSTSCFG"), extrainclude);
		}
	}
	else
		prepresult = prepare_fromfile(hostsfn, extrainclude);

	/* Did we get the data ? */
	if (prepresult == -1) {
		errprintf("Cannot load host data\n");
		return -1;
	}

	/* Any modifications at all ? */
	if (prepresult == 1) {
		dbgprintf("No files modified, skipping reload of %s\n", hostsfn);
		return 1;
	}

	MEMDEFINE(hostname);
	MEMDEFINE(l);

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

	htree = xtreeNew(strcasecmp);
	inbol = cfgdata = hostscfg_content();
	while (inbol && *inbol) {
		inbol += strspn(inbol, " \t");
		ineol = strchr(inbol, '\n'); 
		if (ineol) {
			while ((ineol > inbol) && (isspace(*ineol) || (*ineol == '\n'))) ineol--;
			if (*ineol != '\n') ineol++;

			insavchar = *ineol;
			*ineol = '\0';
		}

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

			pageidx = groupid = 0;
			if (dgname) xfree(dgname); dgname = NULL;
			if (get_page_name_title(inbol, "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(inbol, "subpage", 7) == 0) {
			pagelist_t *newp;
			char *name, *title;

			pageidx = groupid = 0;
			if (dgname) xfree(dgname); dgname = NULL;
			if (get_page_name_title(inbol, "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(inbol, "subparent", 9) == 0) {
			pagelist_t *newp, *parent;
			char *pname, *name, *title;

			pageidx = groupid = 0;
			if (dgname) xfree(dgname); dgname = NULL;
			parent = NULL;
			if (get_page_name_title(inbol, "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(inbol, "group", 5) == 0) {
			char *tok;

			groupid++;
			if (dgname) xfree(dgname); dgname = NULL;

			tok = strtok(inbol, " \t");
			if ((strcmp(tok, "group-only") == 0) || (strcmp(tok, "group-except") == 0)) {
				tok = strtok(NULL, " \t");
			}
			if (tok) tok = strtok(NULL, "\r\n");

			if (tok) {
				char *inp;

				/* Strip HTML tags from the string */
				dgname = (char *)malloc(strlen(tok) + 1);
				*dgname = '\0';

				inp = tok;
				while (*inp) {
					char *tagstart, *tagend;

					tagstart = strchr(inp, '<');
					if (tagstart) {
						tagend = strchr(tagstart, '>');

						*tagstart = '\0';
						if (*inp) strcat(dgname, inp);
						if (tagend) {
							inp = tagend+1;
						}
						else {
							/* Unmatched '<', keep all of the string */
							*tagstart = '<';
							strcat(dgname, tagstart);
							inp += strlen(inp);
						}
					}
					else {
						strcat(dgname, inp);
						inp += strlen(inp);
					}
				}
			}
		}
		else if (sscanf(inbol, "%d.%d.%d.%d %s", &ip1, &ip2, &ip3, &ip4, hostname) == 5) {
			char *startoftags, *tag, *delim;
			int elemidx, elemsize;
			char groupidstr[10];
			xtreePos_t handle;
			namelist_t *newitem, *iwalk, *iprev;

			if ( (ip1 < 0) || (ip1 > 255) ||
			     (ip2 < 0) || (ip2 > 255) ||
			     (ip3 < 0) || (ip3 > 255) ||
			     (ip4 < 0) || (ip4 > 255)) {
				errprintf("Invalid IPv4-address for host %s (nibble outside 0-255 range): %d.%d.%d.%d\n",
					  hostname, ip1, ip2, ip3, ip4);
				goto nextline;
			}

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

			/* 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->dgname = (dgname ? strdup(dgname) : strdup("NONE"));
			newitem->pageindex = pageidx++;

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

			startoftags = strchr(inbol, '#');
			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 = xtreeFind(htree, newitem->hostname);
			if (strcasecmp(newitem->hostname, ".default.") == 0) {
				/* The pseudo DEFAULT host */
				newitem->next = NULL;
				defaulthost = newitem;
			}
			else if (handle == xtreeEnd(htree)) {
				/* New item, so add to end of list */
				newitem->next = NULL;
				if (namehead == NULL) 
					namehead = nametail = newitem;
				else {
					nametail->next = newitem;
					nametail = newitem;
				}
				xtreeAdd(htree, newitem->hostname, newitem);
			}
			else {
				/* Find the existing record - compare the record pointer instead of the name */
				namelist_t *existingrec = (namelist_t *)xtreeData(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 = xmh_find_item(newitem, XMH_CLIENTALIAS);
			if (newitem->clientname == NULL) newitem->clientname = newitem->hostname;
			newitem->downtime = xmh_find_item(newitem, XMH_DOWNTIME);
		}


nextline:
		if (ineol) {
			*ineol = insavchar;
			if (*ineol != '\n') ineol = strchr(ineol, '\n');

			inbol = (ineol ? ineol+1 : NULL);
		}
		else
			inbol = NULL;
	}

	xfree(cfgdata);
	if (dgname) xfree(dgname);
	xtreeDestroy(htree);

	MEMUNDEFINE(hostname);
	MEMUNDEFINE(l);

	build_hosttree();

	return 0;
}
Example #18
0
char *init_tcp_services(void)
{
	static char *xymonnetsvcs = NULL;
	static time_t lastupdate = 0;

	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 (st.st_mtime == lastupdate) 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 = fopen(filename, "r");
	if (fd == NULL) {
		errprintf("Cannot open TCP service-definitions file %s - using defaults\n", filename);
		xymonnetsvcs = strdup(xgetenv("XYMONNETSVCS"));

		MEMUNDEFINE(filename);
		return xymonnetsvcs;
	}

	lastupdate = st.st_mtime;
	head = tail = first = NULL;

	inbuf = newstrbuffer(0);
	initfgets(fd);
	while (unlimfgets(inbuf, fd)) {
		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) fclose(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;
}
Example #19
0
int main(int argc, char *argv[])
{
	char *msg;
	int argi;
	struct sigaction sa;
	char *exthandler = NULL;
	char *extids = NULL;
	char *processor = NULL;
	struct sockaddr_un ctlsockaddr;
	int ctlsocket;

	/* Handle program options. */
	for (argi = 1; (argi < argc); argi++) {
		if (strcmp(argv[argi], "--debug") == 0) {
			debug = 1;
		}
		else if (argnmatch(argv[argi], "--rrddir=")) {
			char *p = strchr(argv[argi], '=');
			rrddir = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--extra-script=")) {
			char *p = strchr(argv[argi], '=');
			exthandler = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--extra-tests=")) {
			char *p = strchr(argv[argi], '=');
			extids = strdup(p+1);
		}
		else if (argnmatch(argv[argi], "--processor=")) {
			char *p = strchr(argv[argi], '=');
			processor = strdup(p+1);
		}
		else if (strcmp(argv[argi], "--no-cache") == 0) {
			use_rrd_cache = 0;
		}
		else if (net_worker_option(argv[argi])) {
			/* Handled in the subroutine */
		}
	}

	save_errbuf = 0;

	if ((rrddir == NULL) && xgetenv("XYMONRRDS")) {
		rrddir = strdup(xgetenv("XYMONRRDS"));
	}

	if (exthandler && extids) setup_exthandler(exthandler, extids);

	/* Do the network stuff if needed */
	net_worker_run(ST_RRD, LOC_STICKY, update_locator_hostdata);

	setup_signalhandler("xymond_rrd");
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sig_handler;
	sigaction(SIGHUP, &sa, NULL);
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT, &sa, NULL);
	signal(SIGPIPE, SIG_DFL);

	/* Setup the control socket that receives cache-flush commands */
	memset(&ctlsockaddr, 0, sizeof(ctlsockaddr));
	sprintf(ctlsockaddr.sun_path, "%s/rrdctl.%d", xgetenv("XYMONTMP"), getpid());
	unlink(ctlsockaddr.sun_path);     /* In case it was accidentally left behind */
	ctlsockaddr.sun_family = AF_UNIX;
	ctlsocket = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (ctlsocket == -1) {
		errprintf("Cannot create cache-control socket (%s)\n", strerror(errno));
		return 1;
	}
	fcntl(ctlsocket, F_SETFL, O_NONBLOCK);
	if (bind(ctlsocket, (struct sockaddr *)&ctlsockaddr, sizeof(ctlsockaddr)) == -1) {
		errprintf("Cannot bind to cache-control socket (%s)\n", strerror(errno));
		return 1;
	}
	/* Linux obeys filesystem permissions on the socket file, so make it world-accessible */
	if (chmod(ctlsockaddr.sun_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) {
		errprintf("Setting permissions on cache-control socket failed: %s\n", strerror(errno));
	}

	/* Load the RRD definitions */
	load_rrddefs();

	/* If we are passing data to an external processor, create the pipe to it */
	setup_extprocessor(processor);

	running = 1;
	while (running) {
		char *eoln, *restofmsg = NULL;
		char *metadata[MAX_META+1];
		int metacount;
		char *p;
		char *hostname = NULL, *testname = NULL, *sender = NULL, *classname = NULL, *pagepaths = NULL;
		xymonrrd_t *ldef = NULL;
		time_t tstamp;
		int childstat;
                ssize_t n;
		char ctlbuf[PATH_MAX];
		int gotcachectlmessage;
		time_t now;

		/* See if we have any cache-control messages pending */
		do {
			n = recv(ctlsocket, ctlbuf, sizeof(ctlbuf), 0);
			gotcachectlmessage = (n > 0);
			if (gotcachectlmessage) {
				/* We have a control message */
				char *bol, *eol;

				ctlbuf[n] = '\0';
				bol = ctlbuf;
				do {
					eol = strchr(bol, '\n'); if (eol) *eol = '\0';
					rrdcacheflushhost(bol);
					if (eol) { bol = eol+1; } else bol = NULL;
				} while (bol && *bol);
			}
		} while (gotcachectlmessage);

		/* Get next message */
		msg = get_xymond_message(C_LAST, argv[0], &seq, NULL);
		if (msg == NULL) {
			running = 0;
			continue;
		}

		now = gettimer();
		if (reloadtime < now) {
			/* Reload configuration files */
			load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn());
			load_client_config(NULL);
			reloadtime = now + 600;
		}

		/* Split the message in the first line (with meta-data), and the rest */
 		eoln = strchr(msg, '\n');
		if (eoln) {
			*eoln = '\0';
			restofmsg = eoln+1;
		}

		/* Parse the meta-data */
		metacount = 0; 
		memset(&metadata, 0, sizeof(metadata));
		p = gettok(msg, "|");
		while (p && (metacount < MAX_META)) {
			metadata[metacount++] = p;
			p = gettok(NULL, "|");
		}
		metadata[metacount] = NULL;

		if ((metacount >= 14) && (strncmp(metadata[0], "@@status", 8) == 0)) {
			/*
			 * @@status|timestamp|sender|origin|hostname|testname|expiretime|color|testflags|\
			 * prevcolor|changetime|ackexpiretime|ackmessage|disableexpiretime|disablemessage|\
			 * clienttstamp|flapping|classname|pagepaths
			 */
			int color = parse_color(metadata[7]);

			switch (color) {
			  case COL_GREEN:
			  case COL_YELLOW:
			  case COL_RED:
			  case COL_BLUE: /* Blue is OK, because it only arrives here when an update is sent */
				tstamp = atoi(metadata[1]);
				sender = metadata[2];
				hostname = metadata[4]; 
				testname = metadata[5];
				classname = (metadata[17] ? metadata[17] : "");
				pagepaths = (metadata[18] ? metadata[18] : "");
				ldef = find_xymon_rrd(testname, metadata[8]);
				update_rrd(hostname, testname, restofmsg, tstamp, sender, ldef, classname, pagepaths);
				break;

			  default:
				/* Ignore reports with purple, blue or clear - they have no data we want. */
				break;
			}
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@data", 6) == 0)) {
			/* @@data|timestamp|sender|origin|hostname|testname|classname|pagepaths */
			tstamp = atoi(metadata[1]);
			sender = metadata[2];
			hostname = metadata[4]; 
			testname = metadata[5];
			classname = (metadata[6] ? metadata[6] : "");
			pagepaths = (metadata[7] ? metadata[7] : "");
			ldef = find_xymon_rrd(testname, "");
			update_rrd(hostname, testname, restofmsg, tstamp, sender, ldef, classname, pagepaths);
		}
		else if (strncmp(metadata[0], "@@shutdown", 10) == 0) {
			running = 0;
			continue;
		}
		else if (strncmp(metadata[0], "@@idle", 6) == 0) {
			/* Ignored */
			continue;
		}
		else if (strncmp(metadata[0], "@@logrotate", 11) == 0) {
			char *fn = xgetenv("XYMONCHANNEL_LOGFILENAME");
			if (fn && strlen(fn)) {
				freopen(fn, "a", stdout);
				freopen(fn, "a", stderr);
			}
			continue;
		}
		else if (strncmp(metadata[0], "@@reload", 8) == 0) {
			reloadtime = 0;
		}
		else if ((metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) {
			char hostdir[PATH_MAX];
			hostname = metadata[3];

			MEMDEFINE(hostdir);

			sprintf(hostdir, "%s/%s", rrddir, hostname);
			dropdirectory(hostdir, 1);

			MEMUNDEFINE(hostdir);
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) {
			/*
			 * Not implemented. Mappings of testnames -> rrd files is
			 * too complex, so on the rare occasion that a single test
			 * is deleted, they will have to delete the rrd files themselves.
			 */
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) {
			char oldhostdir[PATH_MAX];
			char newhostdir[PATH_MAX];
			char *newhostname;

			MEMDEFINE(oldhostdir);
			MEMDEFINE(newhostdir);

			hostname = metadata[3];
			newhostname = metadata[4];
			sprintf(oldhostdir, "%s/%s", rrddir, hostname);
			sprintf(newhostdir, "%s/%s", rrddir, newhostname);
			rename(oldhostdir, newhostdir);

			if (net_worker_locatorbased()) locator_rename_host(hostname, newhostname, ST_RRD);

			MEMUNDEFINE(newhostdir);
			MEMUNDEFINE(oldhostdir);
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) {
			/* Not implemented. See "droptest". */
		}

		/* 
		 * We fork a subprocess when processing drophost requests.
		 * Pickup any finished child processes to avoid zombies
		 */
		while (wait3(&childstat, WNOHANG, NULL) > 0) ;
	}

	/* Flush all cached updates to disk */
	errprintf("Shutting down, flushing cached updates to disk\n");
	rrdcacheflushall();
	errprintf("Cache flush completed\n");

	/* Close the external processor */
	shutdown_extprocessor();

	/* Close the control socket */
	close(ctlsocket);
	unlink(ctlsockaddr.sun_path);

	return 0;
}
Example #20
0
/*
 * Load the $HOME/.netrc file with authentication tokens for HTTP tests.
 */
static void load_netrc(void)
{

#define WANT_TOKEN   0
#define MACHINEVAL   1
#define LOGINVAL     2
#define PASSVAL      3
#define OTHERVAL     4

	static int loaded = 0;

	char netrcfn[MAXPATHLEN];
	FILE *fd;
	strbuffer_t *inbuf;
	char *host, *login, *password, *p;
	int state = WANT_TOKEN;

	if (loaded) return;
	loaded = 1;

	MEMDEFINE(netrcfn);

	/* Look for $BBHOME/etc/netrc first, then the default ~/.netrc */
	sprintf(netrcfn, "%s/etc/netrc", xgetenv("BBHOME"));
	fd = fopen(netrcfn, "r");
	/* Can HOME be undefined ? Yes, on Solaris when started during boot */
	if ((fd == NULL) && getenv("HOME")) {
		sprintf(netrcfn, "%s/.netrc", xgetenv("HOME"));
		fd = fopen(netrcfn, "r");
	}

	if (fd == NULL) {
		MEMUNDEFINE(netrcfn);
		return;
	}

	host = login = password = NULL;
	initfgets(fd);
	inbuf = newstrbuffer(0);
	while (unlimfgets(inbuf, fd)) {
		sanitize_input(inbuf, 0, 0);

		if (STRBUFLEN(inbuf) != 0) {
			p = strtok(STRBUF(inbuf), " \t");
			while (p) {
				switch (state) {
				  case WANT_TOKEN:
					if (strcmp(p, "machine") == 0) state = MACHINEVAL;
					else if (strcmp(p, "login") == 0) state = LOGINVAL;
					else if (strcmp(p, "password") == 0) state = PASSVAL;
					else if (strcmp(p, "account") == 0) state = OTHERVAL;
					else if (strcmp(p, "macdef") == 0) state = OTHERVAL;
					else if (strcmp(p, "default") == 0) { host = ""; state = WANT_TOKEN; }
					else state = WANT_TOKEN;
					break;

				  case MACHINEVAL:
					host = strdup(p); state = WANT_TOKEN; break;

				  case LOGINVAL:
					login = strdup(p); state = WANT_TOKEN; break;

				  case PASSVAL:
					password = strdup(p); state = WANT_TOKEN; break;

				  case OTHERVAL:
				  	state = WANT_TOKEN; break;
				}

				if (host && login && password) {
					loginlist_t *item = (loginlist_t *) malloc(sizeof(loginlist_t));

					item->host = host;
					item->auth = (char *) malloc(strlen(login) + strlen(password) + 2);
					sprintf(item->auth, "%s:%s", login, password);
					item->next = loginhead;
					loginhead = item;
					host = login = password = NULL;
				}

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

	fclose(fd);
	freestrbuffer(inbuf);

	MEMUNDEFINE(netrcfn);
}
Example #21
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;
}
Example #22
0
int main(int argc, char *argv[])
{
	char *msg;
	int seq;
	int argi;
	int alertcolors, alertinterval;
	char *configfn = NULL;
	char *checkfn = NULL;
	int checkpointinterval = 900;
	char acklogfn[PATH_MAX];
	FILE *acklogfd = NULL;
	char notiflogfn[PATH_MAX];
	FILE *notiflogfd = NULL;
	char *tracefn = NULL;
	struct sigaction sa;
	int configchanged;
	time_t lastxmit = 0;

	MEMDEFINE(acklogfn);
	MEMDEFINE(notiflogfn);

	libxymon_init(argv[0]);

	/* Dont save the error buffer */
	save_errbuf = 0;

	/* Load alert config */
	alertcolors = colorset(xgetenv("ALERTCOLORS"), ((1 << COL_GREEN) | (1 << COL_BLUE)));
	alertinterval = 60*atoi(xgetenv("ALERTREPEAT"));

	/* Create our loookup-trees */
	hostnames = xtreeNew(strcasecmp);
	testnames = xtreeNew(strcasecmp);
	locations = xtreeNew(strcasecmp);

	for (argi=1; (argi < argc); argi++) {
		if (argnmatch(argv[argi], "--config=")) {
			configfn = strdup(strchr(argv[argi], '=')+1);
		}
		else if (argnmatch(argv[argi], "--checkpoint-file=")) {
			checkfn = strdup(strchr(argv[argi], '=')+1);
		}
		else if (argnmatch(argv[argi], "--checkpoint-interval=")) {
			char *p = strchr(argv[argi], '=') + 1;
			checkpointinterval = atoi(p);
		}
		else if (argnmatch(argv[argi], "--dump-config")) {
			load_alertconfig(configfn, alertcolors, alertinterval);
			dump_alertconfig(1);
			return 0;
		}
		else if (argnmatch(argv[argi], "--cfid")) {
			include_configid = 1;
		}
		else if (argnmatch(argv[argi], "--test")) {
			char *testhost = NULL, *testservice = NULL, *testpage = NULL, 
			     *testcolor = "red", *testgroups = NULL;
			void *hinfo;
			int testdur = 0;
			FILE *logfd = NULL;
			activealerts_t *awalk = NULL;
			int paramno = 0;

			argi++; if (argi < argc) testhost = argv[argi];
			argi++; if (argi < argc) testservice = argv[argi];
			argi++; 
			while (argi < argc) {
				if (strncasecmp(argv[argi], "--duration=", 11) == 0) {
					testdur = durationvalue(strchr(argv[argi], '=')+1);
				}
				else if (strncasecmp(argv[argi], "--color=", 8) == 0) {
					testcolor = strchr(argv[argi], '=')+1;
				}
				else if (strncasecmp(argv[argi], "--group=", 8) == 0) {
					testgroups = strchr(argv[argi], '=')+1;
				}
				else if (strncasecmp(argv[argi], "--time=", 7) == 0) {
					fakestarttime = (time_t)atoi(strchr(argv[argi], '=')+1);
				}
				else {
					paramno++;
					if (paramno == 1) testdur = atoi(argv[argi]);
					else if (paramno == 2) testcolor = argv[argi];
					else if (paramno == 3) fakestarttime = (time_t) atoi(argv[argi]);
				}

				argi++;
			}

			if ((testhost == NULL) || (testservice == NULL)) {
				printf("Usage: xymond_alert --test HOST SERVICE [options]\n");
				printf("Possible options:\n\t[--duration=MINUTES]\n\t[--color=COLOR]\n\t[--group=GROUPNAME]\n\t[--time=TIMESPEC]\n");

				return 1;
			}

			load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn());
			hinfo = hostinfo(testhost);
			if (hinfo) {
				testpage = strdup(xmh_item(hinfo, XMH_ALLPAGEPATHS));
			}
			else {
				errprintf("Host not found in hosts.cfg - assuming it is on the top page\n");
				testpage = "";
			}

			awalk = (activealerts_t *)calloc(1, sizeof(activealerts_t));
			awalk->hostname = find_name(hostnames, testhost);
			awalk->testname = find_name(testnames, testservice);
			awalk->location = find_name(locations, testpage);
			awalk->ip = strdup("127.0.0.1");
			awalk->color = awalk->maxcolor = parse_color(testcolor);
			awalk->pagemessage = "Test of the alert configuration";
			awalk->eventstart = getcurrenttime(NULL) - testdur*60;
			awalk->groups = (testgroups ? strdup(testgroups) : NULL);
			awalk->state = A_PAGING;
			awalk->cookie = 12345;
			awalk->next = NULL;

			logfd = fopen("/dev/null", "w");
			starttrace(NULL);
			testonly = 1;

			load_alertconfig(configfn, alertcolors, alertinterval);
			load_holidays(0);
			send_alert(awalk, logfd);
			return 0;
		}
		else if (argnmatch(argv[argi], "--trace=")) {
			tracefn = strdup(strchr(argv[argi], '=')+1);
			starttrace(tracefn);
		}
		else if (net_worker_option(argv[argi])) {
			/* Handled in the subroutine */
		}
		else if (standardoption(argv[argi])) {
			if (showhelp) return 0;
		}
		else {
			errprintf("Unknown option '%s'\n", argv[argi]);
		}
	}

	/* Do the network stuff if needed */
	net_worker_run(ST_ALERT, LOC_SINGLESERVER, NULL);

	if (checkfn) {
		load_checkpoint(checkfn);
		nextcheckpoint = gettimer() + checkpointinterval;
		dbgprintf("Next checkpoint at %d, interval %d\n", (int) nextcheckpoint, checkpointinterval);
	}

	setup_signalhandler("xymond_alert");
	/* Need to handle these ourselves, so we can shutdown and save state-info */
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sig_handler;
	sigaction(SIGPIPE, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGUSR1, &sa, NULL);
	sigaction(SIGHUP,  &sa, NULL);

	if (xgetenv("XYMONSERVERLOGS")) {
		sprintf(acklogfn, "%s/acknowledge.log", xgetenv("XYMONSERVERLOGS"));
		acklogfd = fopen(acklogfn, "a");
		sprintf(notiflogfn, "%s/notifications.log", xgetenv("XYMONSERVERLOGS"));
		notiflogfd = fopen(notiflogfn, "a");
	}

	/*
	 * The general idea here is that this loop handles receiving of alert-
	 * and ack-messages from the master daemon, and maintains a list of 
	 * host+test combinations that may have alerts going out.
	 *
	 * This module does not deal with any specific alert-configuration, 
	 * it just picks up the alert messages, maintains the list of 
	 * known tests that are in some sort of critical condition, and
	 * periodically pushes alerts to the do_alert.c module for handling.
	 *
	 * The only modification of alerts that happen here is the handling
	 * of when the next alert is due. It calls into the next_alert() 
	 * routine to learn when an alert should be repeated, and also 
	 * deals with Acknowledgments that stop alerts from going out for
	 * a period of time.
	 */
	while (running) {
		char *eoln, *restofmsg;
		char *metadata[20];
		char *p;
		int metacount;
		char *hostname = NULL, *testname = NULL;
		struct timespec timeout;
		time_t now, nowtimer;
		int anytogo;
		activealerts_t *awalk;
		int childstat;

		nowtimer = gettimer();
		if (checkfn && (nowtimer > nextcheckpoint)) {
			dbgprintf("Saving checkpoint\n");
			nextcheckpoint = nowtimer + checkpointinterval;
			save_checkpoint(checkfn);

			if (acklogfd) acklogfd = freopen(acklogfn, "a", acklogfd);
			if (notiflogfd) notiflogfd = freopen(notiflogfn, "a", notiflogfd);
		}

		timeout.tv_sec = 60; timeout.tv_nsec = 0;
		msg = get_xymond_message(C_PAGE, "xymond_alert", &seq, &timeout);
		if (msg == NULL) {
			running = 0;
			continue;
		}

		/* See what time it is - must happen AFTER the timeout */
		now = getcurrenttime(NULL);

		/* Split the message in the first line (with meta-data), and the rest */
 		eoln = strchr(msg, '\n');
		if (eoln) {
			*eoln = '\0';
			restofmsg = eoln+1;
		}
		else {
			restofmsg = "";
		}

		/* 
		 * Now parse the meta-data into elements.
		 * We use our own "gettok()" routine which works
		 * like strtok(), but can handle empty elements.
		 */
		metacount = 0; 
		memset(&metadata, 0, sizeof(metadata));
		p = gettok(msg, "|");
		while (p && (metacount < 19)) {
			metadata[metacount] = p;
			metacount++;
			p = gettok(NULL, "|");
		}
		metadata[metacount] = NULL;

		if (metacount > 3) hostname = metadata[3];
		if (metacount > 4) testname = metadata[4];

		if ((metacount > 10) && (strncmp(metadata[0], "@@page", 6) == 0)) {
			/* @@page|timestamp|sender|hostname|testname|hostip|expiretime|color|prevcolor|changetime|location|cookie|osname|classname|grouplist|modifiers */

			int newcolor, newalertstatus, oldalertstatus;

			dbgprintf("Got page message from %s:%s\n", hostname, testname);
			traceprintf("@@page %s:%s:%s=%s\n", hostname, testname, metadata[10], metadata[7]);

			awalk = find_active(hostname, testname);
			if (awalk == NULL) {
				char *hwalk = find_name(hostnames, hostname);
				char *twalk = find_name(testnames, testname);
				char *pwalk = find_name(locations, metadata[10]);

				awalk = (activealerts_t *)calloc(1, sizeof(activealerts_t));
				awalk->hostname = hwalk;
				awalk->testname = twalk;
				awalk->location = pwalk;
				awalk->cookie = -1;
				awalk->state = A_DEAD;
				/*
				 * Use changetime here, if we restart the alert module then
				 * this gets the duration values more right than using "now".
				 * Also, define this only when a new alert arrives - we should
				 * NOT clear this when a status goes yellow->red, or if it
				 * flaps between yellow and red.
				 */
				awalk->eventstart = atoi(metadata[9]);
				add_active(awalk->hostname, awalk);
				traceprintf("New record\n");
			}

			newcolor = parse_color(metadata[7]);
			oldalertstatus = ((alertcolors & (1 << awalk->color)) != 0);
			newalertstatus = ((alertcolors & (1 << newcolor)) != 0);

			traceprintf("state %d->%d\n", oldalertstatus, newalertstatus);

			if (newalertstatus) {
				/* It's in an alert state. */
				awalk->color = newcolor;
				awalk->state = A_PAGING;

				if (newcolor > awalk->maxcolor) {
					if (awalk->maxcolor != 0) {
						/*
						 * Severity has increased (yellow -> red).
						 * Clear the repeat-interval, and set maxcolor to
						 * the new color. If it drops to yellow again,
						 * maxcolor stays at red, so a test that flaps
						 * between yellow and red will only alert on red
						 * the first time, and then follow the repeat
						 * interval.
						 */
						dbgprintf("Severity increased, cleared repeat interval: %s/%s %s->%s\n",
							awalk->hostname, awalk->testname,
							colorname(awalk->maxcolor), colorname(newcolor));
						clear_interval(awalk);
					}

					awalk->maxcolor = newcolor;
				}
			}
			else {
				/* 
				 * Send one "recovered" message out now, then go to A_DEAD.
				 * Dont update the color here - we want recoveries to go out 
				 * only if the alert color triggered an alert
				 */
				awalk->state = (newcolor == COL_BLUE) ? A_DISABLED : A_RECOVERED;
			}

			if (oldalertstatus != newalertstatus) {
				dbgprintf("Alert status changed from %d to %d\n", oldalertstatus, newalertstatus);
				clear_interval(awalk);
			}

			if (awalk->ip) xfree(awalk->ip);
			awalk->ip = strdup(metadata[5]);
			awalk->cookie = atoi(metadata[11]);
			if (awalk->osname) xfree(awalk->osname);
			awalk->osname    = (metadata[12] ? strdup(metadata[12]) : NULL);
			if (awalk->classname) xfree(awalk->classname);
			awalk->classname = (metadata[13] ? strdup(metadata[13]) : NULL);
			if (awalk->groups) xfree(awalk->groups);
			awalk->groups    = (metadata[14] ? strdup(metadata[14]) : NULL);
			if (awalk->pagemessage) xfree(awalk->pagemessage);
			if (metadata[15]) {
				/* Modifiers are more interesting than the message itself */
				awalk->pagemessage = (char *)malloc(strlen(awalk->hostname) + strlen(awalk->testname) + strlen(colorname(awalk->color)) + strlen(metadata[15]) + strlen(restofmsg) + 10);
				sprintf(awalk->pagemessage, "%s:%s %s\n%s\n%s",
					awalk->hostname, awalk->testname, colorname(awalk->color), metadata[15], restofmsg);
			}
			else {
				awalk->pagemessage = strdup(restofmsg);
			}
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@ack", 5) == 0)) {
 			/* @@ack|timestamp|sender|hostname|testname|hostip|expiretime */

			/*
			 * An ack is handled simply by setting the next
			 * alert-time to when the ack expires.
			 */
			time_t nextalert = atoi(metadata[6]);

			dbgprintf("Got ack message from %s:%s\n", hostname, testname);
			traceprintf("@@ack: %s:%s now=%d, ackeduntil %d\n",
				     hostname, testname, (int)now, (int)nextalert);

			awalk = find_active(hostname, testname);

			if (acklogfd) {
				int cookie = (awalk ? awalk->cookie : -1);
				int color  = (awalk ? awalk->color : 0);

				fprintf(acklogfd, "%d\t%d\t%d\t%d\t%s\t%s.%s\t%s\t%s\n",
					(int)now, cookie, 
					(int)((nextalert - now) / 60), cookie,
					"np_filename_not_used", 
					hostname, testname, 
					colorname(color),
					nlencode(restofmsg));
				fflush(acklogfd);
			}

			if (awalk && (awalk->state == A_PAGING)) {
				traceprintf("Record updated\n");
				awalk->state = A_ACKED;
				awalk->nextalerttime = nextalert;
				if (awalk->ackmessage) xfree(awalk->ackmessage);
				awalk->ackmessage = strdup(restofmsg);
			}
			else {
				traceprintf("No record\n");
			}
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@notify", 5) == 0)) {
			/* @@notify|timestamp|sender|hostname|testname|pagepath */

			char *hwalk = find_name(hostnames, hostname);
			char *twalk = find_name(testnames, testname);
			char *pwalk = find_name(locations, (metadata[5] ? metadata[5] : ""));

			awalk = (activealerts_t *)calloc(1, sizeof(activealerts_t));
			awalk->hostname = hwalk;
			awalk->testname = twalk;
			awalk->location = pwalk;
			awalk->cookie = -1;
			awalk->pagemessage = strdup(restofmsg);
			awalk->eventstart = getcurrenttime(NULL);
			awalk->state = A_NOTIFY;
			add_active(awalk->hostname, awalk);
		}
		else if ((metacount > 3) && 
			 ((strncmp(metadata[0], "@@drophost", 10) == 0) || (strncmp(metadata[0], "@@dropstate", 11) == 0))) {
			/* @@drophost|timestamp|sender|hostname */
			/* @@dropstate|timestamp|sender|hostname */
			xtreePos_t handle;

			handle = xtreeFind(hostnames, hostname);
			if (handle != xtreeEnd(hostnames)) {
				alertanchor_t *anchor = (alertanchor_t *)xtreeData(hostnames, handle);
				for (awalk = anchor->head; (awalk); awalk = awalk->next) awalk->state = A_DEAD;
			}
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) {
			/* @@droptest|timestamp|sender|hostname|testname */

			awalk = find_active(hostname, testname);
			if (awalk) awalk->state = A_DEAD;
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) {
			/* @@renamehost|timestamp|sender|hostname|newhostname */

			/* 
			 * We handle rename's simply by dropping the alert. If there is still an
			 * active alert for the host, it will have to be dealt with when the next
			 * status update arrives.
			 */
			xtreePos_t handle;

			handle = xtreeFind(hostnames, hostname);
			if (handle != xtreeEnd(hostnames)) {
				alertanchor_t *anchor = (alertanchor_t *)xtreeData(hostnames, handle);
				for (awalk = anchor->head; (awalk); awalk = awalk->next) awalk->state = A_DEAD;
			}
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) {
			/* @@renametest|timestamp|sender|hostname|oldtestname|newtestname */

			/* 
			 * We handle rename's simply by dropping the alert. If there is still an
			 * active alert for the host, it will have to be dealt with when the next
			 * status update arrives.
			 */
			awalk = find_active(hostname, testname);
			if (awalk) awalk->state = A_DEAD;
		}
		else if (strncmp(metadata[0], "@@shutdown", 10) == 0) {
			running = 0;
			errprintf("Got a shutdown message\n");
			continue;
		}
		else if (strncmp(metadata[0], "@@logrotate", 11) == 0) {
			char *fn = xgetenv("XYMONCHANNEL_LOGFILENAME");
			if (fn && strlen(fn)) {
				reopen_file(fn, "a", stdout);
				reopen_file(fn, "a", stderr);

				if (tracefn) {
					stoptrace();
					starttrace(tracefn);
				}
			}
			continue;
		}
		else if (strncmp(metadata[0], "@@reload", 8) == 0) {
			/* Nothing ... right now */
		}
		else if (strncmp(metadata[0], "@@idle", 6) == 0) {
			/* Timeout */
		}

		/*
		 * When a burst of alerts happen, we get lots of alert messages
		 * coming in quickly. So lets handle them in bunches and only 
		 * do the full alert handling once every 10 secs - that lets us
		 * combine a bunch of alerts into one transmission process.
		 */
		if (nowtimer < (lastxmit+10)) continue;
		lastxmit = nowtimer;

		/* 
		 * Loop through the activealerts list and see if anything is pending.
		 * This is an optimization, we could just as well just fork off the
		 * notification child and let it handle all of it. But there is no
		 * reason to fork a child process unless it is going to do something.
		 */
		configchanged = load_alertconfig(configfn, alertcolors, alertinterval);
		configchanged += load_holidays(0);
		anytogo = 0;
		for (awalk = alistBegin(); (awalk); awalk = alistNext()) {
			int anymatch = 0;

			switch (awalk->state) {
			  case A_NORECIP:
				if (!configchanged) break;

				/* The configuration has changed - switch NORECIP -> PAGING */
				awalk->state = A_PAGING;
				clear_interval(awalk);
				/* Fall through */

			  case A_PAGING:
				if (have_recipient(awalk, &anymatch)) {
					if (awalk->nextalerttime <= now) anytogo++;
				}
				else {
					if (!anymatch) {
						awalk->state = A_NORECIP;
						cleanup_alert(awalk);
					}
				}
				break;

			  case A_ACKED:
				if (awalk->nextalerttime <= now) {
					/* An ack has expired, so drop the ack message and switch to A_PAGING */
					anytogo++;
					if (awalk->ackmessage) xfree(awalk->ackmessage);
					awalk->state = A_PAGING;
				}
				break;

			  case A_RECOVERED:
			  case A_DISABLED:
			  case A_NOTIFY:
				anytogo++;
				break;

			  case A_DEAD:
				break;
			}
		}
		dbgprintf("%d alerts to go\n", anytogo);

		if (anytogo) {
			pid_t childpid;

			childpid = fork();
			if (childpid == 0) {
				/* The child */
				start_alerts();
				for (awalk = alistBegin(); (awalk); awalk = alistNext()) {
					switch (awalk->state) {
					  case A_PAGING:
						if (awalk->nextalerttime <= now) {
							send_alert(awalk, notiflogfd);
						}
						break;

					  case A_ACKED:
						/* Cannot be A_ACKED unless the ack is still valid, so no alert. */
						break;

					  case A_RECOVERED:
					  case A_DISABLED:
					  case A_NOTIFY:
						send_alert(awalk, notiflogfd);
						break;

					  case A_NORECIP:
					  case A_DEAD:
						break;
					}
				}
				finish_alerts();

				/* Child does not continue */
				exit(0);
			}
			else if (childpid < 0) {
				errprintf("Fork failed, cannot send alerts: %s\n", strerror(errno));
			}
		}

		/* Update the state flag and the next-alert timestamp */
		for (awalk = alistBegin(); (awalk); awalk = alistNext()) {
			switch (awalk->state) {
			  case A_PAGING:
				if (awalk->nextalerttime <= now) awalk->nextalerttime = next_alert(awalk);
				break;

			  case A_NORECIP:
				break;

			  case A_ACKED:
				/* Still cannot get here except if ack is still valid */
				break;

			  case A_RECOVERED:
			  case A_DISABLED:
			  case A_NOTIFY:
				awalk->state = A_DEAD;
				/* Fall through */

			  case A_DEAD:
				cleanup_alert(awalk); 
				break;
			}
		}

		clean_all_active();

		/* Pickup any finished child processes to avoid zombies */
		while (wait3(&childstat, WNOHANG, NULL) > 0) ;
	}

	if (checkfn) save_checkpoint(checkfn);
	if (acklogfd) fclose(acklogfd);
	if (notiflogfd) fclose(notiflogfd);
	stoptrace();

	MEMUNDEFINE(notiflogfn);
	MEMUNDEFINE(acklogfn);

	if (termsig >= 0) {
		errprintf("Terminated by signal %d\n", termsig);
	}

	return 0;
}
Example #23
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;
}
Example #24
0
static char *message_text(activealerts_t *alert, recip_t *recip)
{
    static strbuffer_t *buf = NULL;
    char *eoln, *bom, *p;
    char info[4096];

    MEMDEFINE(info);

    if (!buf) buf = newstrbuffer(0);
    else clearstrbuffer(buf);

    if (alert->state == A_NOTIFY) {
        sprintf(info, "%s:%s INFO\n", alert->hostname, alert->testname);
        addtobuffer(buf, info);
        addtobuffer(buf, alert->pagemessage);
        MEMUNDEFINE(info);
        return STRBUF(buf);
    }

    switch (recip->format) {
    case ALERTFORM_TEXT:
    case ALERTFORM_PLAIN:
        bom = msg_data(alert->pagemessage);
        eoln = strchr(bom, '\n');
        if (eoln) *eoln = '\0';

        /* If there's a "<-- flags:.... -->" then remove it from the message */
        if ((p = strstr(bom, "<!--")) != NULL) {
            /* Add the part of line 1 before the flags ... */
            *p = '\0';
            addtobuffer(buf, bom);
            *p = '<';

            /* And the part of line 1 after the flags ... */
            p = strstr(p, "-->");
            if (p) addtobuffer(buf, p+3);

            /* And if there is more than line 1, add it as well */
            if (eoln) {
                *eoln = '\n';
                addtobuffer(buf, eoln);
            }
        }
        else {
            if (eoln) *eoln = '\n';
            addtobuffer(buf, bom);
        }

        addtobuffer(buf, "\n");

        if (recip->format == ALERTFORM_TEXT) {
            sprintf(info, "See %s%s\n",
                    xgetenv("XYMONWEBHOST"),
                    hostsvcurl(alert->hostname, alert->testname, 0));
            addtobuffer(buf, info);
        }

        MEMUNDEFINE(info);
        return STRBUF(buf);

    case ALERTFORM_SMS:
        /*
         * Send a report containing a brief alert
         * and any lines that begin with a "&COLOR"
         */
        switch (alert->state) {
        case A_PAGING:
        case A_ACKED:
            sprintf(info, "%s:%s %s [%d]",
                    alert->hostname, alert->testname,
                    colorname(alert->color), alert->cookie);
            break;

        case A_RECOVERED:
            sprintf(info, "%s:%s RECOVERED",
                    alert->hostname, alert->testname);
            break;

        case A_DISABLED:
            sprintf(info, "%s:%s DISABLED",
                    alert->hostname, alert->testname);
            break;

        case A_NOTIFY:
            sprintf(info, "%s:%s NOTICE",
                    alert->hostname, alert->testname);
            break;

        case A_NORECIP:
        case A_DEAD:
            break;
        }

        addtobuffer(buf, info);
        bom = msg_data(alert->pagemessage);
        eoln = strchr(bom, '\n');
        if (eoln) {
            bom = eoln;
            while ((bom = strstr(bom, "\n&")) != NULL) {
                eoln = strchr(bom+1, '\n');
                if (eoln) *eoln = '\0';
                if ((strncmp(bom+1, "&red", 4) == 0) || (strncmp(bom+1, "&yellow", 7) == 0))
                    addtobuffer(buf, bom);
                if (eoln) *eoln = '\n';
                bom = (eoln ? eoln+1 : "");
            }
        }
        MEMUNDEFINE(info);
        return STRBUF(buf);

    case ALERTFORM_SCRIPT:
        sprintf(info, "%s:%s %s [%d]\n",
                alert->hostname, alert->testname, colorname(alert->color), alert->cookie);
        addtobuffer(buf, info);
        addtobuffer(buf, msg_data(alert->pagemessage));
        addtobuffer(buf, "\n");
        sprintf(info, "See %s%s\n",
                xgetenv("XYMONWEBHOST"),
                hostsvcurl(alert->hostname, alert->testname, 0));
        addtobuffer(buf, info);
        MEMUNDEFINE(info);
        return STRBUF(buf);

    case ALERTFORM_PAGER:
    case ALERTFORM_NONE:
        MEMUNDEFINE(info);
        return "";
    }

    MEMUNDEFINE(info);
    return alert->pagemessage;
}
Example #25
0
int do_xymond_rrd(char *hostname, char *testname, char *classname, char *pagepaths, char *msg, time_t tstamp) 
{ 
	static char *xymond_params[] = { "DS:inmessages:DERIVE:600:0:U", 
					 "DS:statusmessages:DERIVE:600:0:U", 
					 "DS:combomessages:DERIVE:600:0:U", 
					 "DS:pagemessages:DERIVE:600:0:U", 
					 "DS:summarymessages:DERIVE:600:0:U", 
					 "DS:datamessages:DERIVE:600:0:U", 
					 "DS:notesmessages:DERIVE:600:0:U", 
					 "DS:enablemessages:DERIVE:600:0:U", 
					 "DS:disablemessages:DERIVE:600:0:U", 
					 "DS:ackmessages:DERIVE:600:0:U", 
					 "DS:configmessages:DERIVE:600:0:U", 
					 "DS:querymessages:DERIVE:600:0:U", 
					 "DS:boardmessages:DERIVE:600:0:U", 
					 "DS:listmessages:DERIVE:600:0:U", 
					 "DS:logmessages:DERIVE:600:0:U", 
					 "DS:dropmessages:DERIVE:600:0:U", 
					 "DS:renamemessages:DERIVE:600:0:U", 
					 "DS:statuschmsgs:DERIVE:600:0:U", 
					 "DS:stachgchmsgs:DERIVE:600:0:U", 
					 "DS:pagechmsgs:DERIVE:600:0:U", 
					 "DS:datachmsgs:DERIVE:600:0:U", 
					 "DS:noteschmsgs:DERIVE:600:0:U", 
					 "DS:enadischmsgs:DERIVE:600:0:U", 
					 NULL };
	static void *xymond_tpl        = NULL;

	struct {
		char *marker;
		unsigned long val;
	} xymond_data[] = {
		{ "\nIncoming messages", 0 },
		{ "\n- status", 0 },
		{ "\n- combo", 0 },
		{ "\n- page", 0 },
		{ "\n- summary", 0 },
		{ "\n- data", 0 },
		{ "\n- notes", 0 },
		{ "\n- enable", 0 },
		{ "\n- disable", 0 },
		{ "\n- ack", 0 },
		{ "\n- config", 0 },
		{ "\n- query", 0 },
		{ "\n- xymondboard", 0 },
		{ "\n- xymondlist", 0 },
		{ "\n- xymondlog", 0 },
		{ "\n- drop", 0 },
		{ "\n- rename", 0 },
		{ "\nstatus channel messages", 0 },
		{ "\nstachg channel messages", 0 },
		{ "\npage   channel messages", 0 },
		{ "\ndata   channel messages", 0 },
		{ "\nnotes  channel messages", 0 },
		{ "\nenadis channel messages", 0 },
		{ NULL, 0 }
	};

	int	i, gotany = 0;
	char	*p;
	char	valstr[10];

	MEMDEFINE(valstr);

	if (xymond_tpl == NULL) xymond_tpl = setup_template(xymond_params);

	sprintf(rrdvalues, "%d", (int)tstamp);
	i = 0;
	while (xymond_data[i].marker) {
		p = strstr(msg, xymond_data[i].marker);
		if (p) {
			if (*p == '\n') p++;
			p += strcspn(p, ":\r\n");
			if (*p == ':') {
				xymond_data[i].val = atol(p+1);
				gotany++;
				sprintf(valstr, ":%lu", xymond_data[i].val);
				strcat(rrdvalues, valstr);
			}
			else strcat(rrdvalues, ":U");
		}
		else strcat(rrdvalues, ":U");

		i++;
	}

	if (gotany) {
		if (strcmp("xymond", testname) != 0) {
			setupfn2("%s.%s.rrd", "xymond", testname);
		}
		else {
			setupfn("%s.rrd", "xymond");
		}

		MEMUNDEFINE(valstr);
		return create_and_update_rrd(hostname, testname, classname, pagepaths, xymond_params, xymond_tpl);
	}

	MEMUNDEFINE(valstr);
	return 0;
}
Example #26
0
void send_alert(activealerts_t *alert, FILE *logfd)
{
    recip_t *recip;
    int first = 1;
    int alertcount = 0;
    time_t now = getcurrenttime(NULL);
    /* A_PAGING, A_NORECIP, A_ACKED, A_RECOVERED, A_DISABLED, A_NOTIFY, A_DEAD */
    char *alerttxt[A_DEAD+1] = { "Paging", "Norecip", "Acked", "Recovered", "Disabled", "Notify", "Dead" };

    dbgprintf("send_alert %s:%s state %d\n", alert->hostname, alert->testname, (int)alert->state);
    traceprintf("send_alert %s:%s state %s\n",
                alert->hostname, alert->testname, alerttxt[alert->state]);

    stoprulefound = 0;

    while (!stoprulefound && ((recip = next_recipient(alert, &first, NULL, NULL)) != NULL)) {
        /* If this is an "UNMATCHED" rule, ignore it if we have already sent out some alert */
        if (recip->unmatchedonly && (alertcount != 0)) {
            traceprintf("Recipient '%s' dropped, not unmatched (count=%d)\n", recip->recipient, alertcount);
            continue;
        }

        if (recip->noalerts && ((alert->state == A_PAGING) || (alert->state == A_RECOVERED) || (alert->state == A_DISABLED))) {
            traceprintf("Recipient '%s' dropped (NOALERT)\n", recip->recipient);
            continue;
        }

        if (recip->method == M_IGNORE) {
            traceprintf("IGNORE rule found\n");
            continue;
        }

        if (alert->state == A_PAGING) {
            repeat_t *rpt = NULL;

            /*
             * This runs in a child-process context, so the record we
             * might create here is NOT used later on.
             */
            rpt = find_repeatinfo(alert, recip, 1);
            if (!rpt) continue;	/* Happens for e.g. M_IGNORE recipients */

            dbgprintf("  repeat %s at %d\n", rpt->recipid, rpt->nextalert);
            if (rpt->nextalert > now) {
                traceprintf("Recipient '%s' dropped, next alert due at %ld > %ld\n",
                            rpt->recipid, (long)rpt->nextalert, (long)now);
                continue;
            }
            alertcount++;
        }
        else if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
            /* RECOVERED messages require that we've sent out an alert before */
            repeat_t *rpt = NULL;

            rpt = find_repeatinfo(alert, recip, 0);
            if (!rpt) continue;
            alertcount++;
        }

        dbgprintf("  Alert for %s:%s to %s\n", alert->hostname, alert->testname, recip->recipient);
        switch (recip->method) {
        case M_IGNORE:
            break;

        case M_MAIL:
        {
            char cmd[32768];
            char *mailsubj;
            char *mailrecip;
            FILE *mailpipe;

            MEMDEFINE(cmd);

            mailsubj = message_subject(alert, recip);
            mailrecip = message_recipient(recip->recipient, alert->hostname, alert->testname, colorname(alert->color));

            if (mailsubj) {
                if (xgetenv("MAIL"))
                    sprintf(cmd, "%s \"%s\" ", xgetenv("MAIL"), mailsubj);
                else if (xgetenv("MAILC"))
                    sprintf(cmd, "%s -s \"%s\" ", xgetenv("MAILC"), mailsubj);
                else
                    sprintf(cmd, "mail -s \"%s\" ", mailsubj);
            }
            else {
                if (xgetenv("MAILC"))
                    sprintf(cmd, "%s ", xgetenv("MAILC"));
                else
                    sprintf(cmd, "mail ");
            }
            strcat(cmd, mailrecip);

            traceprintf("Mail alert with command '%s'\n", cmd);
            if (testonly) {
                MEMUNDEFINE(cmd);
                break;
            }

            mailpipe = popen(cmd, "w");
            if (mailpipe) {
                fprintf(mailpipe, "%s", message_text(alert, recip));
                pclose(mailpipe);
                if (logfd) {
                    init_timestamp();
                    fprintf(logfd, "%s %s.%s (%s) %s[%d] %ld %d",
                            timestamp, alert->hostname, alert->testname,
                            alert->ip, mailrecip, recip->cfid,
                            (long)now, servicecode(alert->testname));
                    if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
                        fprintf(logfd, " %ld\n", (long)(now - alert->eventstart));
                    }
                    else {
                        fprintf(logfd, "\n");
                    }
                    fflush(logfd);
                }
            }
            else {
                errprintf("ERROR: Cannot open command pipe for '%s' - alert lost!\n", cmd);
                traceprintf("Mail pipe failed - alert lost\n");
            }

            MEMUNDEFINE(cmd);
        }
        break;

        case M_SCRIPT:
        {
            pid_t scriptpid;
            char *scriptrecip;

            traceprintf("Script alert with command '%s' and recipient %s\n", recip->scriptname, recip->recipient);
            if (testonly) break;

            scriptrecip = message_recipient(recip->recipient, alert->hostname, alert->testname, colorname(alert->color));
            scriptpid = fork();
            if (scriptpid == 0) {
                /* Setup all of the environment for a paging script */
                void *hinfo;
                char *p;
                int ip1=0, ip2=0, ip3=0, ip4=0;
                char *bbalphamsg, *ackcode, *rcpt, *bbhostname, *bbhostsvc, *bbhostsvccommas, *bbnumeric, *machip, *bbsvcname, *bbsvcnum, *bbcolorlevel, *recovered, *downsecs, *eventtstamp, *downsecsmsg, *cfidtxt;
                char *alertid, *alertidenv;
                int msglen;

                cfidtxt = (char *)malloc(strlen("CFID=") + 10);
                sprintf(cfidtxt, "CFID=%d", recip->cfid);
                putenv(cfidtxt);

                p = message_text(alert, recip);
                msglen = strlen(p);
                if (msglen > MAX_ALERTMSG_SCRIPTS) {
                    dbgprintf("Cropping large alert message from %d to %d bytes\n", msglen, MAX_ALERTMSG_SCRIPTS);
                    msglen = MAX_ALERTMSG_SCRIPTS;
                }
                msglen += strlen("BBALPHAMSG=");
                bbalphamsg = (char *)malloc(msglen + 1);
                snprintf(bbalphamsg, msglen+1, "BBALPHAMSG=%s", p);
                putenv(bbalphamsg);

                ackcode = (char *)malloc(strlen("ACKCODE=") + 10);
                sprintf(ackcode, "ACKCODE=%d", alert->cookie);
                putenv(ackcode);

                rcpt = (char *)malloc(strlen("RCPT=") + strlen(scriptrecip) + 1);
                sprintf(rcpt, "RCPT=%s", scriptrecip);
                putenv(rcpt);

                bbhostname = (char *)malloc(strlen("BBHOSTNAME=") + strlen(alert->hostname) + 1);
                sprintf(bbhostname, "BBHOSTNAME=%s", alert->hostname);
                putenv(bbhostname);

                bbhostsvc = (char *)malloc(strlen("BBHOSTSVC=") + strlen(alert->hostname) + 1 + strlen(alert->testname) + 1);
                sprintf(bbhostsvc, "BBHOSTSVC=%s.%s", alert->hostname, alert->testname);
                putenv(bbhostsvc);

                bbhostsvccommas = (char *)malloc(strlen("BBHOSTSVCCOMMAS=") + strlen(alert->hostname) + 1 + strlen(alert->testname) + 1);
                sprintf(bbhostsvccommas, "BBHOSTSVCCOMMAS=%s.%s", commafy(alert->hostname), alert->testname);
                putenv(bbhostsvccommas);

                bbnumeric = (char *)malloc(strlen("BBNUMERIC=") + 22 + 1);
                p = bbnumeric;
                p += sprintf(p, "BBNUMERIC=");
                p += sprintf(p, "%03d", servicecode(alert->testname));
                sscanf(alert->ip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
                p += sprintf(p, "%03d%03d%03d%03d", ip1, ip2, ip3, ip4);
                p += sprintf(p, "%d", alert->cookie);
                putenv(bbnumeric);

                machip = (char *)malloc(strlen("MACHIP=") + 13);
                sprintf(machip, "MACHIP=%03d%03d%03d%03d", ip1, ip2, ip3, ip4);
                putenv(machip);

                bbsvcname = (char *)malloc(strlen("BBSVCNAME=") + strlen(alert->testname) + 1);
                sprintf(bbsvcname, "BBSVCNAME=%s", alert->testname);
                putenv(bbsvcname);

                bbsvcnum = (char *)malloc(strlen("BBSVCNUM=") + 10);
                sprintf(bbsvcnum, "BBSVCNUM=%d", servicecode(alert->testname));
                putenv(bbsvcnum);

                bbcolorlevel = (char *)malloc(strlen("BBCOLORLEVEL=") + strlen(colorname(alert->color)) + 1);
                sprintf(bbcolorlevel, "BBCOLORLEVEL=%s", colorname(alert->color));
                putenv(bbcolorlevel);

                recovered = (char *)malloc(strlen("RECOVERED=") + 2);
                switch (alert->state) {
                case A_RECOVERED:
                    strcpy(recovered, "RECOVERED=1");
                    break;
                case A_DISABLED:
                    strcpy(recovered, "RECOVERED=2");
                    break;
                default:
                    strcpy(recovered, "RECOVERED=0");
                    break;
                }
                putenv(recovered);

                downsecs = (char *)malloc(strlen("DOWNSECS=") + 20);
                sprintf(downsecs, "DOWNSECS=%ld", (long)(getcurrenttime(NULL) - alert->eventstart));
                putenv(downsecs);

                eventtstamp = (char *)malloc(strlen("EVENTSTART=") + 20);
                sprintf(eventtstamp, "EVENTSTART=%ld", (long)alert->eventstart);
                putenv(eventtstamp);

                if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
                    downsecsmsg = (char *)malloc(strlen("DOWNSECSMSG=Event duration :") + 20);
                    sprintf(downsecsmsg, "DOWNSECSMSG=Event duration : %ld", (long)(getcurrenttime(NULL) - alert->eventstart));
                }
                else {
                    downsecsmsg = strdup("DOWNSECSMSG=");
                }
                putenv(downsecsmsg);

                alertid = make_alertid(alert->hostname, alert->testname, alert->eventstart);
                alertidenv = (char *)malloc(strlen("ALERTID=") + strlen(alertid) + 10);
                sprintf(alertidenv, "ALERTID=%s", alertid);
                putenv(alertidenv);

                hinfo = hostinfo(alert->hostname);
                if (hinfo) {
                    enum xmh_item_t walk;
                    char *itm, *id, *bbhenv;

                    for (walk = 0; (walk < XMH_LAST); walk++) {
                        itm = xmh_item(hinfo, walk);
                        id = xmh_item_id(walk);
                        if (itm && id) {
                            bbhenv = (char *)malloc(strlen(id) + strlen(itm) + 2);
                            sprintf(bbhenv, "%s=%s", id, itm);
                            putenv(bbhenv);
                        }
                    }
                }

                /* The child starts the script */
                execlp(recip->scriptname, recip->scriptname, NULL);
                errprintf("Could not launch paging script %s: %s\n",
                          recip->scriptname, strerror(errno));
                exit(0);
            }
            else if (scriptpid > 0) {
                /* Parent waits for child to complete */
                int childstat;

                wait(&childstat);
                if (WIFEXITED(childstat) && (WEXITSTATUS(childstat) != 0)) {
                    errprintf("Paging script %s terminated with status %d\n",
                              recip->scriptname, WEXITSTATUS(childstat));
                }
                else if (WIFSIGNALED(childstat)) {
                    errprintf("Paging script %s terminated by signal %d\n",
                              recip->scriptname, WTERMSIG(childstat));
                }

                if (logfd) {
                    init_timestamp();
                    fprintf(logfd, "%s %s.%s (%s) %s %ld %d",
                            timestamp, alert->hostname, alert->testname,
                            alert->ip, scriptrecip, (long)now,
                            servicecode(alert->testname));
                    if ((alert->state == A_RECOVERED) || (alert->state == A_DISABLED)) {
                        fprintf(logfd, " %ld\n", (long)(now - alert->eventstart));
                    }
                    else {
                        fprintf(logfd, "\n");
                    }
                    fflush(logfd);
                }
            }
            else {
                errprintf("ERROR: Fork failed to launch script '%s' - alert lost\n", recip->scriptname);
                traceprintf("Script fork failed - alert lost\n");
            }
        }
        break;
        }
    }
}
Example #27
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;
}
Example #28
0
int main(int argc, char *argv[])
{
	time_t starttime = time(NULL);
	char *histdir = NULL;
	char *histlogdir = NULL;
	char *msg;
	int argi, seq;
	int save_allevents = 1;
	int save_hostevents = 1;
	int save_statusevents = 1;
	int save_histlogs = 1;
	FILE *alleventsfd = NULL;
	int running = 1;
	struct sigaction sa;
	char newcol2[3];
	char oldcol2[3];

	MEMDEFINE(newcol2);
	MEMDEFINE(oldcol2);

	/* Dont save the error buffer */
	save_errbuf = 0;

	if (xgetenv("BBALLHISTLOG")) save_allevents = (strcmp(xgetenv("BBALLHISTLOG"), "TRUE") == 0);
	if (xgetenv("BBHOSTHISTLOG")) save_hostevents = (strcmp(xgetenv("BBHOSTHISTLOG"), "TRUE") == 0);
	if (xgetenv("SAVESTATUSLOG")) save_histlogs = (strcmp(xgetenv("SAVESTATUSLOG"), "TRUE") == 0);

	for (argi = 1; (argi < argc); argi++) {
		if (argnmatch(argv[argi], "--histdir=")) {
			histdir = strchr(argv[argi], '=')+1;
		}
		else if (argnmatch(argv[argi], "--histlogdir=")) {
			histlogdir = strchr(argv[argi], '=')+1;
		}
		else if (argnmatch(argv[argi], "--debug")) {
			debug = 1;
		}
	}

	if (xgetenv("BBHIST") && (histdir == NULL)) {
		histdir = strdup(xgetenv("BBHIST"));
	}
	if (histdir == NULL) {
		errprintf("No history directory given, aborting\n");
		return 1;
	}

	if (save_histlogs && (histlogdir == NULL) && xgetenv("BBHISTLOGS")) {
		histlogdir = strdup(xgetenv("BBHISTLOGS"));
	}
	if (save_histlogs && (histlogdir == NULL)) {
		errprintf("No history-log directory given, aborting\n");
		return 1;
	}

	if (save_allevents) {
		char alleventsfn[PATH_MAX];

		MEMDEFINE(alleventsfn);

		sprintf(alleventsfn, "%s/allevents", histdir);
		alleventsfd = fopen(alleventsfn, "a");
		if (alleventsfd == NULL) {
			errprintf("Cannot open the all-events file '%s'\n", alleventsfn);
		}
		setvbuf(alleventsfd, (char *)NULL, _IOLBF, 0);

		MEMUNDEFINE(alleventsfn);
	}

	/* For picking up lost children */
	setup_signalhandler("hobbitd_history");
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sig_handler;
	sigaction(SIGCHLD, &sa, NULL);
	signal(SIGPIPE, SIG_DFL);

	while (running) {
		char *metadata[20] = { NULL, };
		int metacount;
		char *p;
		char *statusdata = "";
		char *hostname, *hostnamecommas, *testname, *dismsg;
		time_t tstamp, lastchg, disabletime, clienttstamp;
		int tstamp_i, lastchg_i;
		int newcolor, oldcolor;
		int downtimeactive;
		struct tm tstamptm;
		int trend;
		int childstat;

		/* Pickup any finished child processes to avoid zombies */
		while (wait3(&childstat, WNOHANG, NULL) > 0) ;

		msg = get_hobbitd_message(C_STACHG, "hobbitd_history", &seq, NULL);
		if (msg == NULL) {
			running = 0;
			continue;
		}

		p = strchr(msg, '\n'); 
		if (p) {
			*p = '\0'; 
			statusdata = msg_data(p+1);
		}
		metacount = 0;
		memset(&metadata, 0, sizeof(metadata));
		p = gettok(msg, "|");
		while (p && (metacount < 20)) {
			metadata[metacount++] = p;
			p = gettok(NULL, "|");
		}

		if ((metacount > 9) && (strncmp(metadata[0], "@@stachg", 8) == 0)) {
			/* @@stachg#seq|timestamp|sender|origin|hostname|testname|expiretime|color|prevcolor|changetime|disabletime|disablemsg|downtimeactive|clienttstamp */
			sscanf(metadata[1], "%d.%*d", &tstamp_i); tstamp = tstamp_i;
			hostname = metadata[4];
			testname = metadata[5];
			newcolor = parse_color(metadata[7]);
			oldcolor = parse_color(metadata[8]);
			lastchg  = atoi(metadata[9]);
			disabletime = atoi(metadata[10]);
			dismsg   = metadata[11];
			downtimeactive = (atoi(metadata[12]) > 0);
			clienttstamp = atoi(metadata[13]);

			if (newcolor == -1) {
				errprintf("Bad message: newcolor is unknown '%s'\n", metadata[7]);
				continue;
			}

			p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';

			if (save_statusevents) {
				char statuslogfn[PATH_MAX];
				int logexists;
				FILE *statuslogfd;
				char oldcol[100];
				char timestamp[40];
				struct stat st;

				MEMDEFINE(statuslogfn);
				MEMDEFINE(oldcol);
				MEMDEFINE(timestamp);

				sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname);
				stat(statuslogfn, &st);
				statuslogfd = fopen(statuslogfn, "r+");
				logexists = (statuslogfd != NULL);
				*oldcol = '\0';

				if (logexists) {
					/*
					 * There is a fair chance hobbitd has not been
					 * running all the time while this system was monitored.
					 * So get the time of the latest status change from the file,
					 * instead of relying on the "lastchange" value we get
					 * from hobbitd. This is also needed when migrating from 
					 * standard bbd to hobbitd.
					 */
					off_t pos = -1;
					char l[1024];
					int gotit;

					MEMDEFINE(l);

					fseeko(statuslogfd, 0, SEEK_END);
					if (ftello(statuslogfd) > 512) {
						/* Go back 512 from EOF, and skip to start of a line */
						fseeko(statuslogfd, -512, SEEK_END);
						gotit = (fgets(l, sizeof(l)-1, statuslogfd) == NULL);
					}
					else {
						/* Read from beginning of file */
						fseeko(statuslogfd, 0, SEEK_SET);
						gotit = 0;
					}


					while (!gotit) {
						off_t tmppos = ftello(statuslogfd);
						time_t dur;
						int dur_i;

						if (fgets(l, sizeof(l)-1, statuslogfd)) {
							/* Sun Oct 10 06:49:42 2004 red   1097383782 602 */

							if ((strlen(l) > 24) && 
							    (sscanf(l+24, " %s %d %d", oldcol, &lastchg_i, &dur_i) == 2) &&
							    (parse_color(oldcol) != -1)) {
								/* 
								 * Record the start location of the line
								 */
								pos = tmppos;
								lastchg = lastchg_i;
								dur = dur_i;
							}
						}
						else {
							gotit = 1;
						}
					}

					if (pos == -1) {
						/* 
						 * Couldnt find anything in the log.
						 * Take lastchg from the timestamp of the logfile,
						 * and just append the data.
						 */
						lastchg = st.st_mtime;
						fseeko(statuslogfd, 0, SEEK_END);
					}
					else {
						/*
						 * lastchg was updated above.
						 * Seek to where the last line starts.
						 */
						fseeko(statuslogfd, pos, SEEK_SET);
					}

					MEMUNDEFINE(l);
				}
				else {
					/*
					 * Logfile does not exist.
					 */
					lastchg = tstamp;
					statuslogfd = fopen(statuslogfn, "a");
					if (statuslogfd == NULL) {
						errprintf("Cannot open status historyfile '%s' : %s\n", 
							statuslogfn, strerror(errno));
					}
				}

				if (strcmp(oldcol, colorname(newcolor)) == 0) {
					/* We wont update history unless the color did change. */
					if ((time(NULL) - starttime) > 300) {
						errprintf("Will not update %s - color unchanged (%s)\n", 
							  statuslogfn, oldcol);
					}

					if (hostnamecommas) xfree(hostnamecommas);
					if (statuslogfd) fclose(statuslogfd);

					MEMUNDEFINE(statuslogfn);
					MEMUNDEFINE(oldcol);
					MEMUNDEFINE(timestamp);

					continue;
				}

				if (statuslogfd) {
					if (logexists) {
						struct tm oldtm;

						/* Re-print the old record, now with the final duration */
						memcpy(&oldtm, localtime(&lastchg), sizeof(oldtm));
						strftime(timestamp, sizeof(timestamp), "%a %b %e %H:%M:%S %Y", &oldtm);
						fprintf(statuslogfd, "%s %s %d %d\n", 
							timestamp, oldcol, (int)lastchg, (int)(tstamp - lastchg));
					}

					/* And the new record. */
					memcpy(&tstamptm, localtime(&tstamp), sizeof(tstamptm));
					strftime(timestamp, sizeof(timestamp), "%a %b %e %H:%M:%S %Y", &tstamptm);
					fprintf(statuslogfd, "%s %s %d", timestamp, colorname(newcolor), (int)tstamp);

					fclose(statuslogfd);
				}

				MEMUNDEFINE(statuslogfn);
				MEMUNDEFINE(oldcol);
				MEMUNDEFINE(timestamp);
			}

			if (save_histlogs) {
				char *hostdash;
				char fname[PATH_MAX];
				FILE *histlogfd;

				MEMDEFINE(fname);

				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(fname, "%s/%s", histlogdir, hostdash);
				mkdir(fname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
				p = fname + sprintf(fname, "%s/%s/%s", histlogdir, hostdash, testname);
				mkdir(fname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
				p += sprintf(p, "/%s", histlogtime(tstamp));

				histlogfd = fopen(fname, "w");
				if (histlogfd) {
					/*
					 * When a host gets disabled or goes purple, the status
					 * message data is not changed - so it will include a
					 * wrong color as the first word of the message.
					 * Therefore we need to fixup this so it matches the
					 * newcolor value.
					 */
					int txtcolor = parse_color(statusdata);
					char *origstatus = statusdata;

					if (txtcolor != -1) {
						fprintf(histlogfd, "%s", colorname(newcolor));
						statusdata += strlen(colorname(txtcolor));
					}

					if (dismsg && *dismsg) nldecode(dismsg);
					if (disabletime > 0) {
						fprintf(histlogfd, " Disabled until %s\n%s\n\n", 
							ctime(&disabletime), (dismsg ? dismsg : ""));
						fprintf(histlogfd, "Status message when disabled follows:\n\n");
						statusdata = origstatus;
					}
					else if (dismsg && *dismsg) {
						fprintf(histlogfd, " Planned downtime: %s\n\n", dismsg);
						fprintf(histlogfd, "Original status message follows:\n\n");
						statusdata = origstatus;
					}

					fwrite(statusdata, strlen(statusdata), 1, histlogfd);
					fprintf(histlogfd, "Status unchanged in 0.00 minutes\n");
					fprintf(histlogfd, "Message received from %s\n", metadata[2]);
					if (clienttstamp) fprintf(histlogfd, "Client data ID %d\n", (int) clienttstamp);
					fclose(histlogfd);
				}
				else {
					errprintf("Cannot create histlog file '%s' : %s\n", fname, strerror(errno));
				}
				xfree(hostdash);

				MEMUNDEFINE(fname);
			}

			strncpy(oldcol2, ((oldcolor >= 0) ? colorname(oldcolor) : "-"), 2);
			strncpy(newcol2, colorname(newcolor), 2);
			newcol2[2] = oldcol2[2] = '\0';

			if (oldcolor == -1)           trend = -1;	/* we dont know how bad it was */
			else if (newcolor > oldcolor) trend = 2;	/* It's getting worse */
			else if (newcolor < oldcolor) trend = 1;	/* It's getting better */
			else                          trend = 0;	/* Shouldn't happen ... */

			if (save_hostevents) {
				char hostlogfn[PATH_MAX];
				FILE *hostlogfd;

				MEMDEFINE(hostlogfn);

				sprintf(hostlogfn, "%s/%s", histdir, hostname);
				hostlogfd = fopen(hostlogfn, "a");
				if (hostlogfd) {
					fprintf(hostlogfd, "%s %d %d %d %s %s %d\n",
						testname, (int)tstamp, (int)lastchg, (int)(tstamp - lastchg),
						newcol2, oldcol2, trend);
					fclose(hostlogfd);
				}
				else {
					errprintf("Cannot open host logfile '%s' : %s\n", hostlogfn, strerror(errno));
				}

				MEMUNDEFINE(hostlogfn);
			}

			if (save_allevents) {
				fprintf(alleventsfd, "%s %s %d %d %d %s %s %d\n",
					hostname, testname, (int)tstamp, (int)lastchg, (int)(tstamp - lastchg),
					newcol2, oldcol2, trend);
				fflush(alleventsfd);
			}

			xfree(hostnamecommas);
		}
		else if ((metacount > 3) && ((strncmp(metadata[0], "@@drophost", 10) == 0))) {
			/* @@drophost|timestamp|sender|hostname */

			hostname = metadata[3];

			if (save_histlogs) {
				char *hostdash;
				char testdir[PATH_MAX];

				MEMDEFINE(testdir);

				/* Remove all directories below the host-specific histlog dir */
				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(testdir, "%s/%s", histlogdir, hostdash);
				dropdirectory(testdir, 1);
				xfree(hostdash);

				MEMUNDEFINE(testdir);
			}

			if (save_hostevents) {
				char hostlogfn[PATH_MAX];
				struct stat st;

				MEMDEFINE(hostlogfn);

				sprintf(hostlogfn, "%s/%s", histdir, hostname);
				if ((stat(hostlogfn, &st) == 0) && S_ISREG(st.st_mode)) {
					unlink(hostlogfn);
				}

				MEMUNDEFINE(hostlogfn);
			}

			if (save_statusevents) {
				DIR *dirfd;
				struct dirent *de;
				char *hostlead;
				char statuslogfn[PATH_MAX];
				struct stat st;

				MEMDEFINE(statuslogfn);

				/* Remove bbvar/hist/host,name.* */
				p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';
				hostlead = malloc(strlen(hostname) + 2);
				strcpy(hostlead, hostnamecommas); strcat(hostlead, ".");

				dirfd = opendir(histdir);
				if (dirfd) {
					while ((de = readdir(dirfd)) != NULL) {
						if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) {
							sprintf(statuslogfn, "%s/%s", histdir, de->d_name);
							if ((stat(statuslogfn, &st) == 0) && S_ISREG(st.st_mode)) {
								unlink(statuslogfn);
							}
						}
					}
					closedir(dirfd);
				}

				xfree(hostlead);
				xfree(hostnamecommas);

				MEMUNDEFINE(statuslogfn);
			}
		}
		else if ((metacount > 4) && ((strncmp(metadata[0], "@@droptest", 10) == 0))) {
			/* @@droptest|timestamp|sender|hostname|testname */

			hostname = metadata[3];
			testname = metadata[4];

			if (save_histlogs) {
				char *hostdash;
				char testdir[PATH_MAX];

				MEMDEFINE(testdir);

				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(testdir, "%s/%s/%s", histlogdir, hostdash, testname);
				dropdirectory(testdir, 1);
				xfree(hostdash);

				MEMUNDEFINE(testdir);
			}

			if (save_statusevents) {
				char *hostnamecommas;
				char statuslogfn[PATH_MAX];
				struct stat st;

				MEMDEFINE(statuslogfn);

				p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';
				sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname);
				if ((stat(statuslogfn, &st) == 0) && S_ISREG(st.st_mode)) unlink(statuslogfn);
				xfree(hostnamecommas);

				MEMUNDEFINE(statuslogfn);
			}
		}
		else if ((metacount > 4) && ((strncmp(metadata[0], "@@renamehost", 12) == 0))) {
			/* @@renamehost|timestamp|sender|hostname|newhostname */
			char *newhostname;

			hostname = metadata[3];
			newhostname = metadata[4];

			if (save_histlogs) {
				char *hostdash;
				char *newhostdash;
				char olddir[PATH_MAX];
				char newdir[PATH_MAX];

				MEMDEFINE(olddir); MEMDEFINE(newdir);

				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				p = newhostdash = strdup(newhostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(olddir, "%s/%s", histlogdir, hostdash);
				sprintf(newdir, "%s/%s", histlogdir, newhostdash);
				rename(olddir, newdir);
				xfree(newhostdash);
				xfree(hostdash);

				MEMUNDEFINE(newdir); MEMUNDEFINE(olddir);
			}

			if (save_hostevents) {
				char hostlogfn[PATH_MAX];
				char newhostlogfn[PATH_MAX];

				MEMDEFINE(hostlogfn); MEMDEFINE(newhostlogfn);

				sprintf(hostlogfn, "%s/%s", histdir, hostname);
				sprintf(newhostlogfn, "%s/%s", histdir, newhostname);
				rename(hostlogfn, newhostlogfn);

				MEMUNDEFINE(hostlogfn); MEMUNDEFINE(newhostlogfn);
			}

			if (save_statusevents) {
				DIR *dirfd;
				struct dirent *de;
				char *hostlead;
				char *newhostnamecommas;
				char statuslogfn[PATH_MAX];
				char newlogfn[PATH_MAX];

				MEMDEFINE(statuslogfn); MEMDEFINE(newlogfn);

				p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';
				hostlead = malloc(strlen(hostname) + 2);
				strcpy(hostlead, hostnamecommas); strcat(hostlead, ".");

				p = newhostnamecommas = strdup(newhostname); while ((p = strchr(p, '.')) != NULL) *p = ',';


				dirfd = opendir(histdir);
				if (dirfd) {
					while ((de = readdir(dirfd)) != NULL) {
						if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) {
							char *testname = strchr(de->d_name, '.');
							sprintf(statuslogfn, "%s/%s", histdir, de->d_name);
							sprintf(newlogfn, "%s/%s%s", histdir, newhostnamecommas, testname);
							rename(statuslogfn, newlogfn);
						}
					}
					closedir(dirfd);
				}

				xfree(newhostnamecommas);
				xfree(hostlead);
				xfree(hostnamecommas);

				MEMUNDEFINE(statuslogfn); MEMUNDEFINE(newlogfn);
			}
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) {
			/* @@renametest|timestamp|sender|hostname|oldtestname|newtestname */
			char *newtestname;

			hostname = metadata[3];
			testname = metadata[4];
			newtestname = metadata[5];

			if (save_histlogs) {
				char *hostdash;
				char olddir[PATH_MAX];
				char newdir[PATH_MAX];

				MEMDEFINE(olddir); MEMDEFINE(newdir);

				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(olddir, "%s/%s/%s", histlogdir, hostdash, testname);
				sprintf(newdir, "%s/%s/%s", histlogdir, hostdash, newtestname);
				rename(olddir, newdir);
				xfree(hostdash);

				MEMUNDEFINE(newdir); MEMUNDEFINE(olddir);
			}

			if (save_statusevents) {
				char *hostnamecommas;
				char statuslogfn[PATH_MAX];
				char newstatuslogfn[PATH_MAX];

				MEMDEFINE(statuslogfn); MEMDEFINE(newstatuslogfn);

				p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';
				sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname);
				sprintf(newstatuslogfn, "%s/%s.%s", histdir, hostnamecommas, newtestname);
				rename(statuslogfn, newstatuslogfn);
				xfree(hostnamecommas);

				MEMUNDEFINE(newstatuslogfn); MEMUNDEFINE(statuslogfn);
			}
		}
		else if (strncmp(metadata[0], "@@shutdown", 10) == 0) {
			running = 0;
		}
		else if (strncmp(metadata[0], "@@logrotate", 11) == 0) {
			char *fn = xgetenv("HOBBITCHANNEL_LOGFILENAME");
			if (fn && strlen(fn)) {
				freopen(fn, "a", stdout);
				freopen(fn, "a", stderr);
			}
			continue;
		}
	}

	MEMUNDEFINE(newcol2);
	MEMUNDEFINE(oldcol2);

	fclose(alleventsfd);
	return 0;
}
Example #29
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);
}
Example #30
0
int do_iostat_rrd(char *hostname, char *testname, char *classname, char *pagepaths, char *msg, time_t tstamp)
{
	/*
	 * BEGINKEY
	 * d0 /
	 * d5 /var
	 * d6 /export
	 * ENDKEY
	 * BEGINDATA
	 *     r/s    w/s   kr/s   kw/s wait actv wsvc_t asvc_t  %w  %b s/w h/w trn tot device
	 *     0.9    2.8    7.3    1.8  0.0  0.0    2.7    9.3   1   2   0   0   0   0 d0
	 *     0.1    0.3    0.8    0.5  0.0  0.0    5.2   11.0   0   0   0   0   0   0 d5
	 *     0.1    0.2    1.0    1.1  0.0  0.0    6.9   12.9   0   0   0   0   0   0 d6
	 * ENDDATA
	 */

	typedef struct iostatkey_t { 
		char *key; 
		char *value; 
		struct iostatkey_t *next;
	} iostatkey_t;

	enum { S_NONE, S_KEYS, S_DATA } state;
	iostatkey_t *keyhead = NULL;
	iostatkey_t *newkey;
	char *eoln, *curline;
	char *buf, *p;
	float v[14];
	char marker[MAX_LINE_LEN];

	MEMDEFINE(marker);

	if (iostat_tpl == NULL) iostat_tpl = setup_template(iostat_params);

	curline = msg; state = S_NONE;
	while (curline) {
		eoln = strchr(curline, '\n'); if (eoln) *eoln = '\0';

		if (strncmp(curline, "BEGINKEY", 8) == 0) { state = S_KEYS; }
		else if (strncmp(curline, "ENDKEY", 6) == 0) { state = S_NONE; }
		else if (strncmp(curline, "BEGINDATA", 9) == 0) { state = S_DATA; }
		else if (strncmp(curline, "ENDDATA", 7) == 0) { state = S_NONE; }
		else {
			switch (state) {
			  case S_NONE:
				break;

			  case S_KEYS:
				buf = xstrdup(curline);
				newkey = (iostatkey_t *)xcalloc(1, sizeof(iostatkey_t));

				p = strtok(buf, " "); 
				if (p) newkey->key = xstrdup(p);

				p = strtok(NULL, " "); 
				if (p) {
					if (strcmp(p, "/") == 0) newkey->value = xstrdup(",root");
					else {
						newkey->value = xstrdup(p);
						p = newkey->value; while ((p = strchr(p, '/')) != NULL) *p = ',';
					}
				}
				xfree(buf);

				if (newkey->key && newkey->value) {
					newkey->next = keyhead; keyhead = newkey;
				}
				else {
					if (newkey->key) xfree(newkey->key);
					if (newkey->value) xfree(newkey->value);
					xfree(newkey);
				}
				break;

			  case S_DATA:
				buf = xstrdup(curline);
				if (sscanf(buf, "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %s",
					   &v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6],
					   &v[7], &v[8], &v[9], &v[10], &v[11], &v[12], &v[13], marker) == 15) {

					/* Find the disk name */
					for (newkey = keyhead; (newkey && strcmp(newkey->key, marker)); newkey = newkey->next) ;

					if (newkey) {
						setupfn2("%s.%s.rrd", "iostat", newkey->value);
						sprintf(rrdvalues, "%d:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f",
							(int) tstamp, 
							v[0], v[1], v[2], v[3], v[4], v[5], v[6],
							v[7], v[8], v[9], v[10], v[11], v[12], v[13]);
						create_and_update_rrd(hostname, testname, classname, pagepaths, iostat_params, iostat_tpl);
					}
				}
				xfree(buf);
				break;
			}
		}

		if (eoln) { *eoln = '\n'; curline = eoln + 1; }
		else { curline = NULL; }
	}

	/* Free the keylist */
	while (keyhead) {
		newkey = keyhead;
		keyhead = keyhead->next;
		if (newkey->key) xfree(newkey->key);
		if (newkey->value) xfree(newkey->value);
		xfree(newkey);
	}

	MEMUNDEFINE(marker);

	return 0;
}