コード例 #1
0
hostinfo_t *register_host(char *hostname, enum locator_servicetype_t servicetype, char *servername)
{
	xtreePos_t handle;
	hostinfo_t *itm = NULL;

	handle = xtreeFind(hitree[servicetype], hostname);
	if (handle == xtreeEnd(hitree[servicetype])) {
		itm = (hostinfo_t *)calloc(1, sizeof(hostinfo_t));

		itm->hostname = strdup(hostname);
		xtreeAdd(hitree[servicetype], itm->hostname, itm);
	}
	else {
		itm = xtreeData(hitree[servicetype], handle);
	}

	/* If we dont know this server, then we must register it. If we do, just update the host record */
	handle = xtreeFind(sitree[servicetype], servername);
	if (handle == xtreeEnd(sitree[servicetype])) {
		dbgprintf("Registering default server '%s'\n", servername);
		itm->server = register_server(servername, servicetype, 1, 1, NULL);
	}
	else {
		serverinfo_t *newserver = xtreeData(sitree[servicetype], handle);

		if (itm->server && (itm->server != newserver)) {
			errprintf("Warning: Host %s:%s moved from %s to %s\n", 
				  hostname, servicetype_names[servicetype], itm->server->servername, newserver->servername);
		}

		itm->server = newserver;
	}

	return itm;
}
コード例 #2
0
ファイル: holidays.c プロジェクト: tjyang/cpam
static holiday_t *findholiday(char *key, int dayinyear)
{
	xtreePos_t handle;
	holidayset_t *hset;
	holiday_t *p;

	if (key && *key) {
		handle = xtreeFind(holidays, key);
		if (handle == xtreeEnd(holidays)) {
			key = NULL;
			handle = xtreeFind(holidays, "");
		}
	}
	else {
		key = NULL;
		handle = xtreeFind(holidays, "");
	}

	if (handle != xtreeEnd(holidays)) 
		hset = (holidayset_t *)xtreeData(holidays, handle);
	else
		return NULL;

	p = hset->head;
	while (p) {
		if (dayinyear == p->yday) {
			return p;
		}

		p = p->next;
	}

	return NULL;
}
コード例 #3
0
ファイル: locator.c プロジェクト: gvsurenderreddy/xymon-2
static void locator_updatecache(enum locator_servicetype_t svc, char *key, char *resp)
{
	xtreePos_t handle;
	cacheitm_t *newitm;

	if (!havecache[svc]) return;

	handle = xtreeFind(locatorcache[svc], key);
	if (handle == xtreeEnd(locatorcache[svc])) {
		newitm = (cacheitm_t *)calloc(1, sizeof(cacheitm_t));
		newitm->key = strdup(key);
		newitm->resp = strdup(resp);
		if (xtreeAdd(locatorcache[svc], newitm->key, newitm) != XTREE_STATUS_OK) {
			xfree(newitm->key);
			xfree(newitm->resp);
			xfree(newitm);
		}
	}
	else {
		newitm = (cacheitm_t *)xtreeData(locatorcache[svc], handle);
		if (newitm->resp) xfree(newitm->resp);
		newitm->resp = strdup(resp);
		newitm->tstamp = getcurrenttime(NULL);
	}
}
コード例 #4
0
serverinfo_t *register_server(char *servername, enum locator_servicetype_t servicetype, int weight, enum locator_sticky_t sticky, char *extras)
{
	xtreePos_t handle;
	serverinfo_t *itm = NULL;

	handle = xtreeFind(sitree[servicetype], servername);
	if (handle == xtreeEnd(sitree[servicetype])) {
		itm = (serverinfo_t *)calloc(1, sizeof(serverinfo_t));

		itm->servername = strdup(servername);
		xtreeAdd(sitree[servicetype], itm->servername, itm);
	}
	else {
		/* Update existing item */
		itm = xtreeData(sitree[servicetype], handle);
	}

	itm->serverconfweight = itm->serveractualweight = weight;
	itm->serverweightleft = 0;
	itm->sticky = sticky;

	if (itm->serverextras) xfree(itm->serverextras);
	itm->serverextras = (extras ? strdup(extras) : NULL);

	if (weight < 0) recalc_current(servicetype);

	return itm;
}
コード例 #5
0
ファイル: httpcookies.c プロジェクト: osvaldsson/xymon
void update_session_cookies(char *hostname, char *urlhost, char *headers)
{
	char *ckhdr, *onecookie;

	if (!headers) return;

	ckhdr = headers;
	do {
		ckhdr = strstr(ckhdr, "\nSet-Cookie:"); 
		if (ckhdr) {
			/* Set-Cookie: JSESSIONID=rKy8HZbLgT5W9N8; path=/ */
			char *eoln, *cknam, *ckval, *ckpath;

			cknam = ckval = ckpath = NULL;

			onecookie = strchr(ckhdr, ':') + 1; onecookie += strspn(onecookie, " \t");
			eoln = strchr(onecookie, '\n'); if (eoln) *eoln = '\0';
			ckhdr = (eoln ? eoln : NULL);
			onecookie = strdup(onecookie);
			if (eoln) *eoln = '\n';

			cknam = strtok(onecookie, "=");
			if (cknam) ckval = strtok(NULL, ";");
			if (ckval) {
				char *tok, *key;
				xtreePos_t h;
				hcookie_t *itm;

				do {
					tok = strtok(NULL, ";\r");
					if (tok) {
						tok += strspn(tok, " ");
						if (strncmp(tok, "path=", 5) == 0) {
							ckpath = tok+5;
						}
					}
				} while (tok);

				if (ckpath == NULL) ckpath = "/";
				key = (char *)malloc(strlen(urlhost) + strlen(cknam) + strlen(ckpath) + 3);
				sprintf(key, "%s\t%s\t%s", urlhost, cknam, ckpath);
				h = xtreeFind(cookietree, key);
				if (h == xtreeEnd(cookietree)) {
					itm = (hcookie_t *)malloc(sizeof(hcookie_t));
					itm->key = key;
					itm->val = strdup(ckval);
					xtreeAdd(cookietree, itm->key, itm);
				}
				else {
					itm = (hcookie_t *)xtreeData(cookietree, h);
					xfree(itm->val);
					itm->val = strdup(ckval);
					xfree(key);
				}
			}

			xfree(onecookie);
		}
	} while (ckhdr);
}
コード例 #6
0
activealerts_t *find_active(char *hostname, char *testname)
{
	xtreePos_t handle;
	alertanchor_t *anchor;
	char *twalk;
	activealerts_t *awalk;

	handle = xtreeFind(hostnames, hostname);
	if (handle == xtreeEnd(hostnames)) return NULL;
	anchor = (alertanchor_t *)xtreeData(hostnames, handle);

	handle = xtreeFind(testnames, testname);
	if (handle == xtreeEnd(testnames)) return NULL;
	twalk = (char *)xtreeData(testnames, handle);

	for (awalk = anchor->head; (awalk && (awalk->testname != twalk)); awalk=awalk->next) ;

	return awalk;
}
コード例 #7
0
ファイル: links.c プロジェクト: Kotty666/xymon
static link_t *find_link(char *key)
{
	link_t *l = NULL;
	xtreePos_t handle;

	handle = xtreeFind(linkstree, key);
	if (handle != xtreeEnd(linkstree)) l = (link_t *)xtreeData(linkstree, handle);

	return l;
}
コード例 #8
0
void add_active(char *hostname, activealerts_t *rec)
{
	xtreePos_t handle;
	alertanchor_t *anchor;

	handle = xtreeFind(hostnames, hostname);
	if (handle == xtreeEnd(hostnames)) return;
	anchor = (alertanchor_t *)xtreeData(hostnames, handle);
	rec->next = anchor->head;
	anchor->head = rec;
}
コード例 #9
0
hostinfo_t *rename_host(char *oldhostname, enum locator_servicetype_t servicetype, char *newhostname)
{
	xtreePos_t handle, newhandle;
	hostinfo_t *itm = NULL;

	handle = xtreeFind(hitree[servicetype], oldhostname);
	if (handle == xtreeEnd(hitree[servicetype])) return NULL;
	newhandle = xtreeFind(hitree[servicetype], newhostname);
	if (newhandle != xtreeEnd(hitree[servicetype])) {
		errprintf("Ignored rename of %s to %s - new name already exists\n", oldhostname, newhostname);
		return NULL;
	}

	itm = xtreeData(hitree[servicetype], handle);

	xtreeDelete(hitree[servicetype], oldhostname); xfree(itm->hostname);
	itm->hostname = strdup(newhostname);
	xtreeAdd(hitree[servicetype], itm->hostname, itm);

	return itm;
}
コード例 #10
0
char *get_clientconfig(char *hostname, char *hostclass, char *hostos)
{
	xtreePos_t handle;
	char *result = NULL;

	if (!clientconfigs) return NULL;

	/*
	 * Find the client config.  Search for a HOSTNAME entry first, 
	 * then the CLIENTCLASS, then CLIENTOS.
	 */
	handle = xtreeFind(rbconfigs, hostname);
	if ((handle == xtreeEnd(rbconfigs)) && hostclass && *hostclass)
		handle = xtreeFind(rbconfigs, hostclass);
	if ((handle == xtreeEnd(rbconfigs)) && hostos && *hostos)
		handle = xtreeFind(rbconfigs, hostos);

	if (handle != xtreeEnd(rbconfigs)) result = (char *)xtreeData(rbconfigs, handle);

	return result;
}
コード例 #11
0
serverinfo_t *find_server_by_host(enum locator_servicetype_t servicetype, char *hostname)
{
	xtreePos_t handle;
	hostinfo_t *hinfo;

	handle = xtreeFind(hitree[servicetype], hostname);
	if (handle == xtreeEnd(hitree[servicetype])) {
		return NULL;
	}

	hinfo = xtreeData(hitree[servicetype], handle);
	return hinfo->server;
}
コード例 #12
0
ファイル: locator.c プロジェクト: gvsurenderreddy/xymon-2
static char *locator_querycache(enum locator_servicetype_t svc, char *key)
{
	xtreePos_t handle;
	cacheitm_t *itm;

	if (!havecache[svc]) return NULL;

	handle = xtreeFind(locatorcache[svc], key);
	if (handle == xtreeEnd(locatorcache[svc])) return NULL;

	itm = (cacheitm_t *)xtreeData(locatorcache[svc], handle);
	return (itm->tstamp + cachetimeout[svc]) > getcurrenttime(NULL) ? itm->resp : NULL;
}
コード例 #13
0
ファイル: locator.c プロジェクト: gvsurenderreddy/xymon-2
void locator_flushcache(enum locator_servicetype_t svc, char *key)
{
	xtreePos_t handle;

	if (!havecache[svc]) return;

	if (key) {
		handle = xtreeFind(locatorcache[svc], key);
		if (handle != xtreeEnd(locatorcache[svc])) {
			cacheitm_t *itm = (cacheitm_t *)xtreeData(locatorcache[svc], handle);
			itm->tstamp = 0;
		}
	}
	else {
		for (handle = xtreeFirst(locatorcache[svc]); (handle != xtreeEnd(locatorcache[svc])); handle = xtreeNext(locatorcache[svc], handle)) {
			cacheitm_t *itm = (cacheitm_t *)xtreeData(locatorcache[svc], handle);
			itm->tstamp = 0;
		}
	}
}
コード例 #14
0
char *find_name(void * tree, char *name)
{
	char *result;
	xtreePos_t handle;

	handle = xtreeFind(tree, name);
	if (handle == xtreeEnd(tree)) {
		result = strdup(name);
		if (tree == hostnames) {
			alertanchor_t *anchor = malloc(sizeof(alertanchor_t));
			anchor->head = NULL;
			xtreeAdd(tree, result, anchor);
		}
		else {
			xtreeAdd(tree, result, result);
		}
	}
	else {
		result = (char *)xtreeKey(tree, handle);
	}
	
	return result;
}
コード例 #15
0
serverinfo_t *downup_server(char *servername, enum locator_servicetype_t servicetype, char action)
{
	xtreePos_t handle;
	serverinfo_t *itm = NULL;

	handle = xtreeFind(sitree[servicetype], servername);
	if (handle == xtreeEnd(sitree[servicetype])) return NULL;

	/* Update existing item */
	itm = xtreeData(sitree[servicetype], handle);
	switch (action) {
	  case 'F':
		/* Flag the hosts that point to this server as un-assigned */
		for (handle = xtreeFirst(hitree[servicetype]); (handle != xtreeEnd(hitree[servicetype])); handle = xtreeNext(hitree[servicetype], handle)) {
			hostinfo_t *hitm = (hostinfo_t *)xtreeData(hitree[servicetype], handle);
			if (hitm->server == itm) hitm->server = NULL;
		}
		/* Fall through */

	  case 'D':
		dbgprintf("Downing server '%s' type %s\n", servername, servicetype_names[servicetype]);
		itm->serveractualweight = 0;
		itm->serverweightleft = 0;
		if (itm->serverconfweight < 0) recalc_current(servicetype);
		break;

	  case 'U':
		dbgprintf("Upping server '%s' type %s to weight %d\n", servername, servicetype_names[servicetype], itm->serverconfweight);
		itm->serveractualweight = itm->serverconfweight;
		/* Dont mess with serverweightleft - this may just be an "i'm alive" message */
		if (itm->serverconfweight < 0) recalc_current(servicetype);
		break;
	}

	return itm;
}
コード例 #16
0
ファイル: do_la.c プロジェクト: Kotty666/xymon
int do_la_rrd(char *hostname, char *testname, char *classname, char *pagepaths, char *msg, time_t tstamp)
{
	static char *la_params[]          = { "DS:la:GAUGE:600:U:U", NULL };
	static void *la_tpl               = NULL;
	static char *clock_params[]       = { "DS:la:GAUGE:600:U:U", NULL }; /* "la" is a misnomer, but to stay compatiable with existing RRD files */
	static void *clock_tpl            = NULL;

	static pcre *as400_exp = NULL;
	static pcre *zVM_exp = NULL;
	static time_t starttime = 0;

	char *p, *eoln = NULL;
	int gotusers=0, gotprocs=0, gotload=0, gotclock=0;
	int users=0, procs=0, load=0, clockdiff=0;
	time_t now = getcurrenttime(NULL);

	if (la_tpl == NULL) la_tpl = setup_template(la_params);
	if (clock_tpl == NULL) clock_tpl = setup_template(clock_params);
	if (starttime == 0) starttime = now;

	if (strstr(msg, "bb-xsnmp")) {
		/*
		 * bb-xsnmp.pl script output.
		 *
		 * green Tue Apr  5 12:57:37 2005 up: 254.58 days, CPU Usage=  9%
		 *
		 * &green  CPU Time in Busy Mode:   9%
		 * &green  CPU Time in Idle Mode:  91%
		 *
		 * &yellow CPU Usage Threshold: 90%
		 * &red CPU Usage Threshold: 95%
		 *
		 * <!-- Enterprise: netapp , Version: 6.42 -->
		 * bb-xsnmp.pl Version: 1.78
		 */

		p = strstr(msg, "CPU Usage=");
		if (p) {
			p += strlen("CPU Usage=");
			gotload = 1;
			load = atoi(p);
		}

		goto done_parsing;
	}
	else if (strstr(msg, "z/VM") || strstr(msg, "VSE/ESA") || strstr(msg, "z/VSE") || strstr(msg, "z/OS")) {
		/* z/VM cpu message. Looks like this, from Rich Smrcina (client config mode):
		 * green 5 Apr 2005 20:07:34  CPU Utilization  7% z/VM Version 4 Release 4.0, service level 0402 (32-bit) AVGPROC-007% 01
		 * VSE/ESA or z/VSE cpu message.
		 * VSE/ESA 2.7.2 cr IPLed on ...
		 * or
		 * z/VSE 3.1.1 cr IPLed on ...
		 * In server (centralized) config mode or for z/OS (which is centralized config only)
		 * the operating system name is part of the message (as in the tests above).
		 */

		int ovector[30];
		char w[100];
		int res;

		if (zVM_exp == NULL) {
			const char *errmsg = NULL;
			int errofs = 0;

			zVM_exp = pcre_compile(".* CPU Utilization *([0-9]+)%", PCRE_CASELESS, &errmsg, &errofs, NULL);
		}

		res = pcre_exec(zVM_exp, NULL, msg, strlen(msg), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
		if (res >= 0) {
			/* We have a match - pick up the data. */
			*w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 1, w, sizeof(w));
			if (strlen(w)) {
				load = atoi(w); gotload = 1;
			}
		}

		goto done_parsing;
	}

	eoln = strchr(msg, '\n'); if (eoln) *eoln = '\0';
	p = strstr(msg, "up: ");
	if (!p) p = strstr(msg, "Uptime:");	/* Netapp filerstats2bb script */
	if (!p) p = strstr(msg, "uptime:");
	if (p) {
		/* First line of cpu report, contains "up: 159 days, 1 users, 169 procs, load=21" */
		p = strchr(p, ',');
		if (p) {
			gotusers = (sscanf(p, ", %d users", &users) == 1);
			p = strchr(p+1, ',');
		}

		if (p) {
			gotprocs = (sscanf(p, ", %d procs", &procs) == 1);
			p = strchr(p+1, ',');
		}

		/*
		 * Load can be either 
		 * -  "load=xx%"   (Windows)
		 * -  "load=xx.xx" (Unix, DISPREALLOADAVG=TRUE)
		 * -  "load=xx"    (Unix, DISPREALLOADAVG=FALSE)
		 *
		 * We want the load in percent (Windows), or LA*100 (Unix).
		 */
		p = strstr(msg, "load="); 
		if (p) { 
			p += 5;
			if (strchr(p, '%')) {
				gotload = 1; 
				load = atoi(p);
			}
			else if (strchr(p, '.')) {
				gotload = 1; 
				load = 100*atoi(p);
				/* Find the decimal part, and cut off at 2 decimals */
				p = strchr(p, '.'); if (strlen(p) > 3) *(p+3) = '\0';
				load += atoi(p+1);
			}
			else {
				gotload = 1; 
				load = atoi(p);
			}
		}
	}
	else {
		/* 
		 * No "uptime" in message - could be from an AS/400. They look like this:
		 * green March 21, 2005 12:33:24 PM EST deltacdc 108 users 45525 jobs(126 batch,0 waiting for message), load=26%
		 */
		int ovector[30];
		char w[100];
		int res;

		if (as400_exp == NULL) {
			const char *errmsg = NULL;
			int errofs = 0;

			as400_exp = pcre_compile(".* ([0-9]+) users ([0-9]+) jobs.* load=([0-9]+)\\%", 
						 PCRE_CASELESS, &errmsg, &errofs, NULL);
		}

		res = pcre_exec(as400_exp, NULL, msg, strlen(msg), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
		if (res >= 0) {
			/* We have a match - pick up the AS/400 data. */
			*w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 1, w, sizeof(w));
			if (strlen(w)) {
				users = atoi(w); gotusers = 1;
			}

			*w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 3, w, sizeof(w));
			if (strlen(w)) {
				load = atoi(w); gotload = 1;
			}
		}
	}

done_parsing:
	if (eoln) *eoln = '\n';

	p = strstr(msg, "System clock is ");
	if (p) {
		if (sscanf(p, "System clock is %d seconds off", &clockdiff) == 1) gotclock = 1;
	}

	if (!gotload) {
		/* See if it's a report from the ciscocpu.pl script. */
		p = strstr(msg, "<br>CPU 5 min average:");
		if (p) {
			/* It reports in % cpu utilization */
			p = strchr(p, ':');
			load = atoi(p+1);
			gotload = 1;
		}
	}

	if (gotload) {
		setupfn("%s.rrd", "la");
		snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, load);
		create_and_update_rrd(hostname, testname, classname, pagepaths, la_params, la_tpl);
	}

	if (gotprocs) {
		setupfn("%s.rrd", "procs");
		snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, procs);
		create_and_update_rrd(hostname, testname, classname, pagepaths, la_params, la_tpl);
	}

	if (gotusers) {
		setupfn("%s.rrd", "users");
		snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, users);
		create_and_update_rrd(hostname, testname, classname, pagepaths, la_params, la_tpl);
	}

	if (gotclock) {
		setupfn("%s.rrd", "clock");
		snprintf(rrdvalues, sizeof(rrdvalues), "%d:%d", (int)tstamp, clockdiff);
		create_and_update_rrd(hostname, testname, classname, pagepaths, clock_params, clock_tpl);
	}

	/*
	 * If we have run for less than 6 minutes, drop the memory updates here.
	 * We want to be sure not to use memory statistics from the CPU report
	 * if there is a memory add-on sending a separate memory statistics
	 */
	if ((now - starttime) < 360) return 0;

	if (!memhosts_init || (xtreeFind(memhosts, hostname) == xtreeEnd(memhosts))) {
		/* Pick up memory statistics */
		int found, overflow, realuse, swapuse;
		long long phystotal, physavail, pagetotal, pageavail;

		found = overflow = realuse = swapuse = 0;
		phystotal = physavail = pagetotal = pageavail = 0;

		p = strstr(msg, "Total Physical memory:");
		if (p) { 
			phystotal = str2ll(strchr(p, ':') + 1, NULL); 
			if (phystotal != LONG_MAX) found++; else overflow++;
		}

		if (found == 1) {
			p = strstr(msg, "Available Physical memory:");
			if (p) { 
				physavail = str2ll(strchr(p, ':') + 1, NULL); 
				if (physavail != LONG_MAX) found++; else overflow++;
			}
		}

		if (found == 2) {
			p = strstr(msg, "Total PageFile size:"); 
			if (p) { 
				pagetotal = str2ll(strchr(p, ':') + 1, NULL); 
				if (pagetotal != LONG_MAX) found++; else overflow++;
			}
		}

		if (found == 3) {
			p = strstr(msg, "Available PageFile size:"); 
			if (p) { 
				pageavail = str2ll(strchr(p, ':') + 1, NULL); 
				if (pageavail != LONG_MAX) found++; else overflow++;
			}
		}

		if (found == 4) {
			if (!phystotal || !pagetotal) { errprintf("Host %s cpu report had 0 total physical/pagefile memory listed\n", hostname); return 0; }
			phystotal = phystotal / 100;
			pagetotal = pagetotal / 100;
			realuse = 100 - (physavail / phystotal);
			swapuse = 100 - (pageavail / pagetotal);
			do_memory_rrd_update(tstamp, hostname, testname, classname, pagepaths, realuse, swapuse, -1);
		}
		else if (overflow) {
			errprintf("Host %s cpu report overflows in memory usage calculation\n", hostname);
		}
	}

	return 0;
}
コード例 #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;
}
コード例 #18
0
ファイル: webaccess.c プロジェクト: Kotty666/xymon
int web_access_allowed(char *username, char *hostname, char *testname, web_access_type_t acc)
{

	void *hinfo;
	char *pages, *onepg, *key;

	hinfo = hostinfo(hostname);
	if (!hinfo || !acctree || !username) return 0;

	/* Check for "root" access first */
	key = (char *)malloc(strlen(username) + 6);
	sprintf(key, "root %s", username);
	if (xtreeFind(acctree, key) != xtreeEnd(acctree)) {
		xfree(key);
		return 1;
	}
	xfree(key);

	pages = strdup(xmh_item(hinfo, XMH_ALLPAGEPATHS));
	onepg = strtok(pages, ",");
	while (onepg) {
		char *p;

		p = strchr(onepg, '/'); if (p) *p = '\0'; /* Will only look at the top-level path element */

		key = (char *)malloc(strlen(onepg) + strlen(username) + 2);
		sprintf(key, "%s %s", onepg, username);
		if (xtreeFind(acctree, key) != xtreeEnd(acctree)) {
			xfree(key);
			xfree(pages);
			return 1;
		}

		xfree(key);
		onepg = strtok(NULL, ",");
	}
	xfree(pages);

	if (hostname) {
		/* See if user is a member of a group named by the hostname */
		key = (char *)malloc(strlen(hostname) + strlen(username) + 2);
		sprintf(key, "%s %s", hostname, username);
		if (xtreeFind(acctree, key) != xtreeEnd(acctree)) {
			xfree(key);
			return 1;
		}
		xfree(key);
	}

	if (testname) {
		/* See if user is a member of a group named by the testname */
		key = (char *)malloc(strlen(testname) + strlen(username) + 2);
		sprintf(key, "%s %s", testname, username);
		if (xtreeFind(acctree, key) != xtreeEnd(acctree)) {
			xfree(key);
			return 1;
		}
		xfree(key);
	}

	return 0;
}
コード例 #19
0
int main(int argc, char *argv[])
{
	time_t starttime = gettimer();
	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, defaultsaveop = 1;
	FILE *alleventsfd = NULL;
	int running = 1;
	struct sigaction sa;
	char newcol2[3];
	char oldcol2[3];
	char alleventsfn[PATH_MAX];
	char pidfn[PATH_MAX];
	int logdirfull = 0;
	int minlogspace = 5;

	MEMDEFINE(pidfn);
	MEMDEFINE(alleventsfn);
	MEMDEFINE(newcol2);
	MEMDEFINE(oldcol2);

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

	sprintf(pidfn, "%s/xymond_history.pid", xgetenv("XYMONSERVERLOGS"));
	if (xgetenv("XYMONALLHISTLOG")) save_allevents = (strcmp(xgetenv("XYMONALLHISTLOG"), "TRUE") == 0);
	if (xgetenv("XYMONHOSTHISTLOG")) save_hostevents = (strcmp(xgetenv("XYMONHOSTHISTLOG"), "TRUE") == 0);
	if (xgetenv("SAVESTATUSLOG")) save_histlogs = (strncmp(xgetenv("SAVESTATUSLOG"), "FALSE", 5) != 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], "--pidfile=")) {
			strcpy(pidfn, strchr(argv[argi], '=')+1);
		}
		else if (argnmatch(argv[argi], "--minimum-free=")) {
			minlogspace = atoi(strchr(argv[argi], '=')+1);
		}
		else if (argnmatch(argv[argi], "--debug")) {
			debug = 1;
		}
	}

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

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

	columndefs = xtreeNew(strcmp);
	{
		char *defaultsave, *tok;
		char *savelist;
		columndef_t *newrec;

		savelist = strdup(xgetenv("SAVESTATUSLOG"));
		defaultsave = strtok(savelist, ","); 
		/*
		 * TRUE: Save everything by default; may list some that are not saved.
		 * ONLY: Save nothing by default; may list some that are saved.
		 * FALSE: Save nothing.
		 */
		defaultsaveop = (strcasecmp(defaultsave, "TRUE") == 0);
		tok = strtok(NULL, ",");
		while (tok) {
			newrec = (columndef_t *)malloc(sizeof(columndef_t));
			if (*tok == '!') {
				newrec->saveit = 0;
				newrec->name = strdup(tok+1);
			}
			else {
				newrec->saveit = 1;
				newrec->name = strdup(tok);
			}
			xtreeAdd(columndefs, newrec->name, newrec);

			tok = strtok(NULL, ",");
		}
		xfree(savelist);
	}

	{
		FILE *pidfd = fopen(pidfn, "w");
		if (pidfd) {
			fprintf(pidfd, "%lu\n", (unsigned long)getpid());
			fclose(pidfd);
		}
	}

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

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

	while (running) {
		char *metadata[20] = { NULL, };
		int metacount;
		char *p;
		char *statusdata = "";
		char *hostname, *hostnamecommas, *testname, *dismsg, *modifiers;
		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) ;

		if (rotatefiles && alleventsfd) {
			fclose(alleventsfd);
			alleventsfd = fopen(alleventsfn, "a");
			if (alleventsfd == NULL) {
				errprintf("Cannot re-open the all-events file '%s'\n", alleventsfn);
			}
			else {
				setvbuf(alleventsfd, (char *)NULL, _IOLBF, 0);
			}
		}

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

		if (nextfscheck < gettimer()) {
			logdirfull = (chkfreespace(histlogdir, minlogspace, minlogspace) != 0);
			if (logdirfull) errprintf("Historylog directory %s has less than %d%% free space - disabling save of data for 5 minutes\n", histlogdir, minlogspace);
			nextfscheck = gettimer() + 300;
		}

		p = strchr(msg, '\n'); 
		if (p) {
			*p = '\0'; 
			statusdata = msg_data(p+1, 0);
		}
		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)) {
			xtreePos_t handle;
			columndef_t *saveit = NULL;

			/* @@stachg#seq|timestamp|sender|origin|hostname|testname|expiretime|color|prevcolor|changetime|disabletime|disablemsg|downtimeactive|clienttstamp|modifiers */
			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]);
			modifiers = metadata[14];

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

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

			handle = xtreeFind(columndefs, testname);
			if (handle == xtreeEnd(columndefs)) {
				saveit = (columndef_t *)malloc(sizeof(columndef_t));
				saveit->name = strdup(testname);
				saveit->saveit = defaultsaveop;
				xtreeAdd(columndefs, saveit->name, saveit);
			}
			else {
				saveit = (columndef_t *) xtreeData(columndefs, handle);
			}

			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 xymond 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 xymond. This is also needed when migrating from 
					 * standard bbd to xymond.
					 */
					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);
						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;
							}
						}
						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 ((gettimer() - 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 && saveit->saveit && !logdirfull) {
				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;
					char *eoln, *restofdata;
					int written, closestatus, ok = 1;

					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;
					}

					restofdata = statusdata;
					if (modifiers && *modifiers) {
						char *modtxt;

						/* We must finish writing the first line before putting in the modifiers */
						eoln = strchr(restofdata, '\n');
						if (eoln) {
							restofdata = eoln+1;
							*eoln = '\0';
							fprintf(histlogfd, "%s\n", statusdata);
						}

						nldecode(modifiers);
						modtxt = strtok(modifiers, "\n");
						while (modtxt) {
							fprintf(histlogfd, "%s\n", modtxt);
							modtxt = strtok(NULL, "\n");
						}
					}

					written = fwrite(restofdata, 1, strlen(restofdata), histlogfd);
					if (written != strlen(restofdata)) {
						ok = 0;
						errprintf("Error writing to file %s: %s\n", fname, strerror(errno));
						closestatus = fclose(histlogfd); /* Ignore any errors on close */
					}
					else {
						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);
						closestatus = fclose(histlogfd);
						if (closestatus != 0) {
							ok = 0;
							errprintf("Error writing to file %s: %s\n", fname, strerror(errno));
						}
					}

					if (!ok) remove(fname);
				}
				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 $XYMONVAR/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], "@@idle", 6) == 0) {
			/* Nothing */
		}
		else if (strncmp(metadata[0], "@@shutdown", 10) == 0) {
			running = 0;
		}
		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);
			}
			continue;
		}
		else if (strncmp(metadata[0], "@@reload", 8) == 0) {
			/* Do nothing */
		}
	}

	MEMUNDEFINE(newcol2);
	MEMUNDEFINE(oldcol2);
	MEMUNDEFINE(alleventsfn);
	MEMUNDEFINE(pidfn);

	fclose(alleventsfd);
	unlink(pidfn);

	return 0;
}
コード例 #20
0
ファイル: tree.c プロジェクト: Kotty666/xymon
int main(int argc, char **argv)
{
	char buf[1024], key[1024], data[1024];
	void *th = NULL;
	xtreePos_t n;
	xtreeStatus_t stat;
	char *rec, *p;

	do {
		printf("New, Add, Find, Delete, dUmp, deStroy : "); fflush(stdout);
		if (fgets(buf, sizeof(buf), stdin) == NULL) return 0;

		switch (*buf) {
		  case 'N': case 'n':
			th = xtreeNew(strcasecmp);
			break;

		  case 'A': case 'a':
			printf("Key:");fflush(stdout); fgets(key, sizeof(key), stdin);
			p = strchr(key, '\n'); if (p) *p = '\0';
			printf("Data:");fflush(stdout); fgets(data, sizeof(data), stdin);
			p = strchr(data, '\n'); if (p) *p = '\0';
			stat = xtreeAdd(th, strdup(key), strdup(data));
			printf("Result: %d\n", stat);
			break;

		  case 'D': case 'd':
			printf("Key:");fflush(stdout); fgets(key, sizeof(key), stdin);
			p = strchr(key, '\n'); if (p) *p = '\0';
			rec = xtreeDelete(th, key);
			if (rec) {
				printf("Existing record deleted: Data was '%s'\n", rec);
			}
			else {
				printf("No record\n");
			}
			break;

		  case 'F': case 'f':
			printf("Key:");fflush(stdout); fgets(key, sizeof(key), stdin);
			p = strchr(key, '\n'); if (p) *p = '\0';
			n = xtreeFind(th, key);
			if (n != xtreeEnd(th)) {
				printf("Found record: Data was '%s'\n", (char *)xtreeData(th, n));
			}
			else {
				printf("No record\n");
			}
			break;

		  case 'U': case 'u':
			n = xtreeFirst(th);
			while (n != xtreeEnd(th)) {
				printf("Key '%s', data '%s'\n", (char *)xtreeKey(th, n), (char *)xtreeData(th, n));
				n = xtreeNext(th, n);
			}
			break;

		  case 'S': case 's':
			xtreeDestroy(th);
			th = NULL;
			break;
		}
	} while (1);

	return 0;
}
コード例 #21
0
ファイル: xymond_hostdata.c プロジェクト: Kotty666/xymon
int main(int argc, char *argv[])
{
	char *msg;
	int running;
	int argi, seq;
	int recentperiod = 3600;
	int maxrecentcount = 5;
	int logdirfull = 0;
	int minlogspace = 5;
	struct sigaction sa;

	/* Handle program options. */
	for (argi = 1; (argi < argc); argi++) {
                if (argnmatch(argv[argi], "--logdir=")) {
			clientlogdir = strchr(argv[argi], '=')+1;
		}
		else if (argnmatch(argv[argi], "--recent-period=")) {
			char *p = strchr(argv[argi], '=');
			recentperiod = 60*atoi(p+1);
		}
		else if (argnmatch(argv[argi], "--recent-count=")) {
			char *p = strchr(argv[argi], '=');
			maxrecentcount = atoi(p+1);
		}
		else if (argnmatch(argv[argi], "--minimum-free=")) {
			minlogspace = atoi(strchr(argv[argi], '=')+1);
		}
		else if (strcmp(argv[argi], "--debug") == 0) {
			/*
			 * A global "debug" variable is available. If
			 * it is set, then "dbgprintf()" outputs debug messages.
			 */
			debug = 1;
		}
		else if (net_worker_option(argv[argi])) {
			/* Handled in the subroutine */
		}
	}

	if (clientlogdir == NULL) clientlogdir = xgetenv("CLIENTLOGS");
	if (clientlogdir == NULL) {
		clientlogdir = (char *)malloc(strlen(xgetenv("XYMONVAR")) + 10);
		sprintf(clientlogdir, "%s/hostdata", xgetenv("XYMONVAR"));
	}

	save_errbuf = 0;

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

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

	savetimes = xtreeNew(strcasecmp);

	running = 1;
	while (running) {
		char *eoln, *restofmsg, *p;
		char *metadata[MAX_META+1];
		int metacount;

		msg = get_xymond_message(C_CLICHG, "xymond_hostdata", &seq, NULL);
		if (msg == NULL) {
			/*
			 * get_xymond_message will return NULL if xymond_channel closes
			 * the input pipe. We should shutdown when that happens.
			 */
			running = 0;
			continue;
		}

		if (nextfscheck < gettimer()) {
			logdirfull = (chkfreespace(clientlogdir, minlogspace, minlogspace) != 0);
			if (logdirfull) errprintf("Hostdata directory %s has less than %d%% free space - disabling save of data for 5 minutes\n", clientlogdir, minlogspace);
			nextfscheck = gettimer() + 300;
		}

		/* 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 = "";
		}

		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 (strncmp(metadata[0], "@@clichg", 8) == 0) {
			xtreePos_t handle;
			savetimes_t *itm;
			int i, recentcount;
			time_t now = gettimer();
			char hostdir[PATH_MAX];
			char fn[PATH_MAX];
			FILE *fd;

			/* metadata[3] is the hostname */
			handle = xtreeFind(savetimes, metadata[3]);
			if (handle != xtreeEnd(savetimes)) {
				itm = (savetimes_t *)xtreeData(savetimes, handle);
			}
			else {
				itm = (savetimes_t *)calloc(1, sizeof(savetimes_t));
				itm->hostname = strdup(metadata[3]);
				xtreeAdd(savetimes, itm->hostname, itm);
			}

			/* See how many times we've saved the hostdata recently (within the past 'recentperiod' seconds) */
			for (i=0, recentcount=0; ((i < 12) && (itm->tstamp[i] > (now - recentperiod))); i++) recentcount++;
			/* If it's been saved less than 'maxrecentcount' times, then save it. Otherwise just drop it */
			if (!logdirfull && (recentcount < maxrecentcount)) {
				int written, closestatus, ok = 1;

				for (i = 10; (i > 0); i--) itm->tstamp[i+1] = itm->tstamp[i];
				itm->tstamp[0] = now;

				sprintf(hostdir, "%s/%s", clientlogdir, metadata[3]);
				mkdir(hostdir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
				sprintf(fn, "%s/%s", hostdir, metadata[4]);
				fd = fopen(fn, "w");
				if (fd == NULL) {
					errprintf("Cannot create file %s: %s\n", fn, strerror(errno));
					continue;
				}
				written = fwrite(restofmsg, 1, strlen(restofmsg), fd);
				if (written != strlen(restofmsg)) {
					errprintf("Cannot write hostdata file %s: %s\n", fn, strerror(errno));
					closestatus = fclose(fd);	/* Ignore any close errors */
					ok = 0;
				}
				else {
					closestatus = fclose(fd);
					if (closestatus != 0) {
						errprintf("Cannot write hostdata file %s: %s\n", fn, strerror(errno));
						ok = 0;
					}
				}

				if (!ok) remove(fn);
			}
		}

		/*
		 * A "shutdown" message is sent when the master daemon
		 * terminates. The child workers should shutdown also.
		 */
		else if (strncmp(metadata[0], "@@shutdown", 10) == 0) {
			running = 0;
			continue;
		}
		else if (strncmp(metadata[0], "@@idle", 6) == 0) {
			/* Ignored */
			continue;
		}

		/*
		 * A "logrotate" message is sent when the Xymon logs are
		 * rotated. The child workers must re-open their logfiles,
		 * typically stdin and stderr - the filename is always
		 * provided in the XYMONCHANNEL_LOGFILENAME environment.
		 */
		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);
			}
			continue;
		}

		else if ((metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) {
			/* @@drophost|timestamp|sender|hostname */
			char hostdir[PATH_MAX];
			snprintf(hostdir, sizeof(hostdir), "%s/%s", clientlogdir, basename(metadata[3]));
			dropdirectory(hostdir, 1);
		}

		else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) {
			/* @@renamehost|timestamp|sender|hostname|newhostname */
			char oldhostdir[PATH_MAX], newhostdir[PATH_MAX];
			snprintf(oldhostdir, sizeof(oldhostdir), "%s/%s", clientlogdir, basename(metadata[3]));
			snprintf(newhostdir, sizeof(newhostdir), "%s/%s", clientlogdir, basename(metadata[4]));
			rename(oldhostdir, newhostdir);

			if (net_worker_locatorbased()) locator_rename_host(metadata[3], metadata[4], ST_HOSTDATA);
		}
		else if (strncmp(metadata[0], "@@reload", 8) == 0) {
			/* Do nothing */
		}
	}

	return 0;
}
コード例 #22
0
ファイル: criticalview.c プロジェクト: Kotty666/xymon
static int ev_included(char *hostname)
{
	/* Callback function for filtering eventlog-hosts */
	return (xtreeFind(evhopfilter, hostname) == xtreeEnd(evhopfilter)) ? 0 : 1;
}
コード例 #23
0
ファイル: xymond_rrd.c プロジェクト: osvaldsson/xymon
static void load_rrddefs(void)
{
	char fn[PATH_MAX];
	FILE *fd;
	strbuffer_t *inbuf = newstrbuffer(0);
	char *key = NULL, *p;
	char **defs = NULL;
	int defcount = 0;
	rrddeftree_t *newrec;

	rrddeftree = xtreeNew(strcasecmp);

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

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

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

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

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

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

	stackfclose(fd);

loaddone:
	freestrbuffer(inbuf);

	/* Check if the default record exists */
	if (xtreeFind(rrddeftree, "") == xtreeEnd(rrddeftree)) {
		/* Create the default record */
		newrec = (rrddeftree_t *)malloc(sizeof(rrddeftree_t));
		newrec->key = strdup("");
		newrec->defs = (char **)malloc(4 * sizeof(char *));;
		newrec->defs[0] = strdup("RRA:AVERAGE:0.5:1:576");
		newrec->defs[1] = strdup("RRA:AVERAGE:0.5:6:576");
		newrec->defs[2] = strdup("RRA:AVERAGE:0.5:24:576");
		newrec->defs[3] = strdup("RRA:AVERAGE:0.5:288:576");
		newrec->count = 4;
		xtreeAdd(rrddeftree, newrec->key, newrec);
	}
}
コード例 #24
0
ファイル: criticalview.c プロジェクト: Kotty666/xymon
void print_hoststatus(FILE *output, hstatus_t *itm, void * statetree, void * columns, int prio, int firsthost, int firsthostever)
{
	char *key;
	time_t now;
	xtreePos_t colhandle;

	now = getcurrenttime(NULL);

	fprintf(output, "<TR>\n");

	/* Print the priority */
	fprintf(output, "<TD ALIGN=LEFT VALIGN=TOP WIDTH=10%% NOWRAP>");
	if (firsthost) 
		if (prio == 99) {
			if (firsthostever)
				/* Only non-prioritised hosts, so just drop that text */
				fprintf(output, "&nbsp;");
			else
				fprintf(output, "<FONT %s>No priority</FONT>", xgetenv("XYMONPAGEROWFONT"));
		}
		else {
			fprintf(output, "<FONT %s>PRIO %d</FONT>", xgetenv("XYMONPAGEROWFONT"), prio);
		}

	else 
		fprintf(output, "&nbsp;");
	fprintf(output, "</TD>\n");

	/* Print the hostname with a link to the critical systems info page */
	fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", hostnamehtml(itm->hostname, NULL, usetooltips));

	key = (char *)malloc(1024);
	for (colhandle = xtreeFirst(columns); (colhandle != xtreeEnd(columns)); colhandle = xtreeNext(columns, colhandle)) {
		char *colname;
		xtreePos_t sthandle;

		fprintf(output, "<TD ALIGN=CENTER>");

		colname = (char *)xtreeKey(columns, colhandle);
		key = (char *)realloc(key, 2 + strlen(itm->hostname) + strlen(colname));
		sprintf(key, "%s|%s", itm->hostname, colname);
		sthandle = xtreeFind(statetree, key);
		if (sthandle == xtreeEnd(statetree)) {
			fprintf(output, "-");
		}
		else {
			hstatus_t *column;
			char *htmlalttag;
			char *htmlackstr;

			column = (hstatus_t *)xtreeData(statetree, sthandle);
			if (column->config->priority != prio) 
				fprintf(output, "-");
			else {
				time_t age = now - column->lastchange;
				char *htmlgroupstr;
				char *htmlextrastr;

				htmlalttag = alttag(colname, column->color, 0, 1, agestring(age));
				htmlackstr = (column->ackmsg ? column->ackmsg : "");
				htmlgroupstr = strdup(urlencode(column->config->ttgroup ? column->config->ttgroup : ""));
				htmlextrastr = strdup(urlencode(column->config->ttextra ? column->config->ttextra : ""));
				fprintf(output, "<A HREF=\"%s&amp;NKPRIO=%d&amp;NKTTGROUP=%s&amp;NKTTEXTRA=%s\">",
					hostsvcurl(itm->hostname, colname, 1),
					prio, 
					htmlgroupstr, htmlextrastr);
				fprintf(output, "<IMG SRC=\"%s/%s\" ALT=\"%s\" TITLE=\"%s %s\" HEIGHT=\"%s\" WIDTH=\"%s\" BORDER=0></A>",
					xgetenv("XYMONSKIN"), 
					dotgiffilename(column->color, (column->acktime > 0), (age > oldlimit)),
					colorname(column->color), htmlalttag, htmlackstr,
					xgetenv("DOTHEIGHT"), xgetenv("DOTWIDTH"));
				xfree(htmlgroupstr);
				xfree(htmlextrastr);
			}
		}

		fprintf(output, "</TD>\n");
	}
	xfree(key);

	fprintf(output, "</TR>\n");
}
コード例 #25
0
ファイル: holidays.c プロジェクト: tjyang/cpam
static void add_holiday(char *key, int year, holiday_t *newhol)
{
	int isOK = 0;
	struct tm *t;
	time_t day;
	holiday_t *newitem;
	xtreePos_t handle;
	holidayset_t *hset;

	switch (newhol->holtype) {
	  case HOL_ABSOLUTE:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <=31) && (!newhol->year || (newhol->year == year)) );
		if (!isOK) break;
		day = mkday(year, newhol->month, newhol->day);
		t = localtime(&day);
		newhol->yday = t->tm_yday;
		break;

	  case HOL_EASTER:
		isOK = (newhol->month == 0); if (!isOK) break;
		day = getEasterDate(year);
		t = localtime(&day);
		newhol->yday = t->tm_yday + newhol->day;
		break;

	  case HOL_ADVENT:
		isOK = (newhol->month == 0); if (!isOK) break;
		day = get4AdventDate(year);
		t = localtime(&day);
		newhol->yday = t->tm_yday + newhol->day;
		break;

	  case HOL_MON:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) );
		if (!isOK) break;
		newhol->yday = getnumberedweekday(1, newhol->day, newhol->month, year);
		break;

	  case HOL_TUE:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) );
		if (!isOK) break;
		newhol->yday = getnumberedweekday(2, newhol->day, newhol->month, year);
		break;

	  case HOL_WED:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) );
		if (!isOK) break;
		newhol->yday = getnumberedweekday(3, newhol->day, newhol->month, year);
		break;

	  case HOL_THU:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) );
		if (!isOK) break;
		newhol->yday = getnumberedweekday(4, newhol->day, newhol->month, year);
		break;

	  case HOL_FRI:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) );
		if (!isOK) break;
		newhol->yday = getnumberedweekday(5, newhol->day, newhol->month, year);
		break;

	  case HOL_SAT:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) );
		if (!isOK) break;
		newhol->yday = getnumberedweekday(6, newhol->day, newhol->month, year);
		break;

	  case HOL_SUN:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 5) );
		if (!isOK) break;
		newhol->yday = getnumberedweekday(0, newhol->day, newhol->month, year);
		break;

	  case HOL_MON_AFTER:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) );
		if (!isOK) break;
		newhol->yday = getweekdayafter(1, newhol->day, newhol->month, year);
		break;

	  case HOL_TUE_AFTER:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) );
		if (!isOK) break;
		newhol->yday = getweekdayafter(2, newhol->day, newhol->month, year);
		break;

	  case HOL_WED_AFTER:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) );
		if (!isOK) break;
		newhol->yday = getweekdayafter(3, newhol->day, newhol->month, year);
		break;

	  case HOL_THU_AFTER:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) );
		if (!isOK) break;
		newhol->yday = getweekdayafter(4, newhol->day, newhol->month, year);
		break;

	  case HOL_FRI_AFTER:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) );
		if (!isOK) break;
		newhol->yday = getweekdayafter(5, newhol->day, newhol->month, year);
		break;

	  case HOL_SAT_AFTER:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) );
		if (!isOK) break;
		newhol->yday = getweekdayafter(6, newhol->day, newhol->month, year);
		break;

	  case HOL_SUN_AFTER:
		isOK = ( (newhol->month >= 1 && newhol->month <=12) && (newhol->day >=1 && newhol->day <= 31) );
		if (!isOK) break;
		newhol->yday = getweekdayafter(0, newhol->day, newhol->month, year);
		break;

	}

	if (!isOK) {
		errprintf("Error in holiday definition %s\n", newhol->desc);
		return;
	}

	newitem = (holiday_t *)calloc(1, sizeof(holiday_t));
	newitem->holtype = newhol->holtype;
	newitem->day = newhol->day;
	newitem->month = newhol->month;
	newitem->desc = strdup(newhol->desc);
	newitem->yday = newhol->yday;

	handle = xtreeFind(holidays, key);
	if (handle == xtreeEnd(holidays)) {
		hset = (holidayset_t *)calloc(1, sizeof(holidayset_t));
		hset->key = strdup(key);
		xtreeAdd(holidays, hset->key, hset);
	}
	else {
		hset = (holidayset_t *)xtreeData(holidays, handle);
	}

	if (hset->head == NULL) {
		hset->head = hset->tail = newitem;
	}
	else {
		hset->tail->next = newitem; hset->tail = hset->tail->next;
	}
}
コード例 #26
0
ファイル: holidays.c プロジェクト: tjyang/cpam
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;
}
コード例 #27
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;
}
コード例 #28
0
ファイル: sendresults.c プロジェクト: gvsurenderreddy/xymon-2
void send_test_results(listhead_t *head, char *collector, int issubmodule, char *location, int usebackfeed)
{
	char msgline[4096];
	listitem_t *walk;
	xtreePos_t handle;
	void *hostresults = xtreeNew(strcasecmp);

	if (usebackfeed) combo_start_local(); else combo_start();
	for (walk = head->head; (walk); walk = walk->next) {
		hostresult_t *hres;
		myconn_t *rec = (myconn_t *)walk->data;
		char *s;

		if (rec->ignoreresult) continue;

		switch (rec->talkprotocol) {
		  case TALK_PROTO_PING:
			if (!issubmodule && (rec->talkresult == TALK_OK)) {
				add_to_sub_queue(rec, "ping", location, NULL);
				continue;
			}
			break;

#ifdef HAVE_LDAP
		  case TALK_PROTO_LDAP:
			if (!issubmodule && (rec->talkresult == TALK_OK)) {
				char *creds = xmh_item(rec->hostinfo, XMH_LDAPLOGIN);

				add_to_sub_queue(rec, "ldap", location, creds, NULL);
				continue;
			}
			break;
#endif

		  case TALK_PROTO_EXTERNAL:
			if (!issubmodule && (rec->talkresult == TALK_OK)) {
				if (strncmp(rec->testspec, "rpc=", 4) == 0)
					add_to_sub_queue(rec, "rpc", location, NULL);
				else
					add_to_sub_queue(rec, rec->testspec, location, NULL);
				continue;
			}
			break;

		  default:
			break;
		}

		handle = xtreeFind(hostresults, xmh_item(rec->hostinfo, XMH_HOSTNAME));
		if (handle == xtreeEnd(hostresults)) {
			hres = (hostresult_t *)calloc(1, sizeof(hostresult_t));
			hres->hinfo = rec->hostinfo;
			hres->txt = newstrbuffer(0);
			xtreeAdd(hostresults, xmh_item(rec->hostinfo, XMH_HOSTNAME), hres);

			snprintf(msgline, sizeof(msgline), "client/%s %s.netcollect netcollect\n", 
				collector, xmh_item(rec->hostinfo, XMH_HOSTNAME));
			addtobuffer(hres->txt, msgline);
		}
		else {
			hres = xtreeData(hostresults, handle);
		}

		switch (rec->talkprotocol) {
		  case TALK_PROTO_DNSQUERY:
			snprintf(msgline, sizeof(msgline), "\n[dns=%s]\n", rec->testspec);
			addtobuffer(hres->txt, msgline);
			break;
		  case TALK_PROTO_PING:
			snprintf(msgline, sizeof(msgline), "\n[ping=%s]\n", rec->netparams.destinationip);
			addtobuffer(hres->txt, msgline);
			snprintf(msgline, sizeof(msgline), "SourceSpec: %s\n", rec->testspec);
			addtobuffer(hres->txt, msgline);
			break;
		  default:
			snprintf(msgline, sizeof(msgline), "\n[%s]\n", rec->testspec);
			addtobuffer(hres->txt, msgline);
			break;
		}

		snprintf(msgline, sizeof(msgline), "Handler: %s\n", talkproto_names[rec->talkprotocol]);
		addtobuffer(hres->txt, msgline);

		snprintf(msgline, sizeof(msgline), "StartTime: %d\nEndTime: %d\n", (int)rec->teststarttime, (int)rec->testendtime);
		addtobuffer(hres->txt, msgline);

		if (rec->netparams.lookupstring) {
			snprintf(msgline, sizeof(msgline), "TargetHostname: %s\n", rec->netparams.lookupstring);
			addtobuffer(hres->txt, msgline);
		}
		snprintf(msgline, sizeof(msgline), "TargetIP: %s\n", rec->netparams.destinationip);
		addtobuffer(hres->txt, msgline);
		snprintf(msgline, sizeof(msgline), "TargetPort: %d\n", rec->netparams.destinationport);
		addtobuffer(hres->txt, msgline);
		if (rec->netparams.sourceip) {
			snprintf(msgline, sizeof(msgline), "SourceIP: %s\n", rec->netparams.sourceip);
			addtobuffer(hres->txt, msgline);
		}

		if (location) {
			snprintf(msgline, sizeof(msgline), "Location: %s\n", location);
			addtobuffer(hres->txt, msgline);
		}

		if (rec->talkprotocol == TALK_PROTO_PING)
			s = "ICMP";
		else {
			switch (rec->netparams.socktype) {
			  case CONN_SOCKTYPE_STREAM: s = "TCP"; break;
			  case CONN_SOCKTYPE_DGRAM: s = "UDP"; break;
			  default: s = "UNKNOWN"; break;
			}
		}
		snprintf(msgline, sizeof(msgline), "Protocol: %s\n", s);
		addtobuffer(hres->txt, msgline);

		switch (rec->netparams.sslhandling) {
		  case CONN_SSL_NO: s = "NO"; break;
		  case CONN_SSL_YES: s = "YES"; break;
		  case CONN_SSL_STARTTLS_CLIENT: s = "STARTTLS_CLIENT"; break;
		  case CONN_SSL_STARTTLS_SERVER: s = "STARTTLS_SERVER"; break;
		  default: s = "UNKNOWN"; break;
		}
		snprintf(msgline, sizeof(msgline), "SSL: %s\n", s);
		addtobuffer(hres->txt, msgline);

		switch (rec->talkresult) {
		  case TALK_CONN_FAILED: s = "CONN_FAILED"; break;
		  case TALK_CONN_TIMEOUT: s = "CONN_TIMEOUT"; break;
		  case TALK_OK: s = "OK"; break;
		  case TALK_BADDATA: s = "BADDATA"; break;
		  case TALK_BADSSLHANDSHAKE: s = "BADSSLHANDSHAKE"; break;
		  case TALK_INTERRUPTED: s = "INTERRUPTED"; break;
		  case TALK_CANNOT_RESOLVE: s = "CANNOT_RESOLVE"; break;
		  case TALK_MODULE_FAILED: s = "MODULE_FAILED"; break;
		  default: s = "UNKNOWN"; break;
		}
		snprintf(msgline, sizeof(msgline), "Status: %s\n", s);
		addtobuffer(hres->txt, msgline);

		snprintf(msgline, sizeof(msgline), "TestID: %lu\nElapsedMS: %d.%02d\nDNSMS: %d.%02d\nTimeoutMS: %d\nIntervalMS: %d\n",
			rec->testid,
			(rec->elapsedus / 1000), (rec->elapsedus % 1000), 
			(rec->dnselapsedus / 1000), (rec->dnselapsedus % 1000), 
			rec->timeout*1000, rec->interval*1000);
		addtobuffer(hres->txt, msgline);

		snprintf(msgline, sizeof(msgline), "BytesRead: %u\nBytesWritten: %u\n", rec->bytesread, rec->byteswritten);
		addtobuffer(hres->txt, msgline);

		if (rec->peercertificate) {
			char exps[50];

			addtobuffer(hres->txt, "PeerCertificateSubject: ");
			addtobuffer(hres->txt, rec->peercertificate);
			addtobuffer(hres->txt, "\n");
			addtobuffer(hres->txt, "PeerCertificateIssuer: ");
			addtobuffer(hres->txt, rec->peercertificateissuer);
			addtobuffer(hres->txt, "\n");

			strftime(exps, sizeof(exps), "%Y-%m-%d %H:%M:%S UTC", gmtime(&rec->peercertificatestart));
			snprintf(msgline, sizeof(msgline), "PeerCertificateStart: %d %s\n", (int)rec->peercertificatestart, exps);
			addtobuffer(hres->txt, msgline);

			strftime(exps, sizeof(exps), "%Y-%m-%d %H:%M:%S UTC", gmtime(&rec->peercertificateexpiry));
			snprintf(msgline, sizeof(msgline), "PeerCertificateExpiry: %d %s\n", (int)rec->peercertificateexpiry, exps);
			addtobuffer(hres->txt, msgline);

			snprintf(msgline, sizeof(msgline), "PeerCertificateKeysize: %d\n", (int)rec->peercertificatekeysize);
			addtobuffer(hres->txt, msgline);

			snprintf(msgline, sizeof(msgline), "PeerCertificateDetails: %d\n", (int)strlen(rec->peercertificatedetails)+1);
			addtobuffer(hres->txt, msgline);
			addtobuffer(hres->txt, rec->peercertificatedetails);
			addtobuffer(hres->txt, "\n");
		}

		switch (rec->talkprotocol) {
		  case TALK_PROTO_PLAIN: result_plain(rec, hres->txt); break;
		  case TALK_PROTO_NTP: result_ntp(rec, hres->txt); break;
		  case TALK_PROTO_HTTP: result_http(rec, hres->txt); break;
		  case TALK_PROTO_DNSQUERY: result_dns(rec, hres->txt); break;
		  case TALK_PROTO_PING: result_subqueue("PING", rec, hres->txt); break;
#ifdef HAVE_LDAP
		  case TALK_PROTO_LDAP: result_subqueue("LDAP", rec, hres->txt); break;
#endif
		  case TALK_PROTO_EXTERNAL: result_subqueue(rec->testspec, rec, hres->txt); break;
		  default: break;
		}
	}

	for (handle = xtreeFirst(hostresults); handle != xtreeEnd(hostresults); handle = xtreeNext(hostresults, handle)) {
		hostresult_t *hres = xtreeData(hostresults, handle);

		combo_add(hres->txt);
		freestrbuffer(hres->txt);
		xtreeDelete(hostresults, xmh_item(hres->hinfo, XMH_HOSTNAME));
		xfree(hres);
	}

	xtreeDestroy(hostresults);
	combo_end();
}