Exemple #1
0
void senddata(conn_t *conn)
{
	/* Write data to a peer connection (client or server) */
	int n, togo;
	char *startp;

	togo = STRBUFLEN(conn->msgbuf) - conn->sentbytes;
	startp = STRBUF(conn->msgbuf) + conn->sentbytes;
	n = write(conn->sockfd, startp, togo);

	if (n == -1) {
		/* Write failure. Also happens if connecting to peer fails */
		time_t now = time(NULL);
		if (debug || (conn->client->nexterrortxt < now)) {
			errprintf("Connection lost during connect/write to %s (req %lu): %s\n", 
				  addrstring(&conn->caddr), conn->seq, strerror(errno));
			conn->client->nexterrortxt = now + errorloginterval;
		}
		flag_cleanup(conn);
	}
	else if (n >= 0) {
		dbgprintf("Sent %d bytes to %s (req %lu)\n", n, addrstring(&conn->caddr), conn->seq);
		conn->sentbytes += n;
		if (conn->sentbytes == STRBUFLEN(conn->msgbuf)) {
			/* Everything has been sent, so switch to READ mode */
			clearstrbuffer(conn->msgbuf);
			shutdown(conn->sockfd, SHUT_WR);
			conn->action = C_READING;
		}
	}
}
static void result_http(myconn_t *rec,  strbuffer_t *txt)
{
	char msgline[4096];

	snprintf(msgline, sizeof(msgline), "HTTPstatus: %d\n", rec->httpstatus);
	addtobuffer(txt, msgline);

	if (dontsendmessages >= 2) {
		if (rec->textlog) clearstrbuffer(rec->textlog);
		if (rec->httpheaders) clearstrbuffer(rec->httpheaders);
		if (rec->httpbody) clearstrbuffer(rec->httpbody);
		return;
	}

	if (rec->redircount) {
		snprintf(msgline, sizeof(msgline), "Redirects: %d\n", rec->redircount);
		addtobuffer(txt, msgline);
	}

	if (rec->textlog) {
		char *authtoken;
		snprintf(msgline, sizeof(msgline), "HTTPrequest: %d\n", STRBUFLEN(rec->textlog));
		addtobuffer(txt, msgline);
		/*
		 * If there is an authentication header, it is best to obscure it here.
		 * Otherwise, anyone who can view the "client data" will be able to see
		 * the login.
		 */
		authtoken = strstr(STRBUF(rec->textlog), "\nAuthorization:");
		if (authtoken) {
			authtoken += 15;
			while (*authtoken != '\r') {
				*authtoken = '*'; authtoken++;
			}
		}
		addtostrbuffer(txt, rec->textlog);
		addtobuffer(txt, "\n");
		clearstrbuffer(rec->textlog);
	}
	if (rec->httpheaders) {
		snprintf(msgline, sizeof(msgline), "HTTPheaders: %d\n", STRBUFLEN(rec->httpheaders));
		addtobuffer(txt, msgline);
		addtostrbuffer(txt, rec->httpheaders);
		addtobuffer(txt, "\n");
		clearstrbuffer(rec->httpheaders);
	}
	if (rec->httpbody) {
		snprintf(msgline, sizeof(msgline), "HTTPbody: %d\n", STRBUFLEN(rec->httpbody));
		addtobuffer(txt, msgline);
		addtostrbuffer(txt, rec->httpbody);
		addtobuffer(txt, "\n");
		clearstrbuffer(rec->httpbody);
	}
}
Exemple #3
0
static void zvse_paging_report(char *hostname, char *clientclass, enum ostype_t os,
                     void *hinfo, char *fromline, char *timestr, char *pagingstr)
{
	char *p;
        int ipagerate, pagingyellow, pagingred;
        float fpagerate=0.0;
        char pagingresult[100];

        int pagingcolor = COL_GREEN;
        char msgline[4096];
        strbuffer_t *upmsg;

        if (!pagingstr) return;
        /*
         *  Looking for Paging rate in message
         *  Page Rate=0.00 /sec
         */
        *pagingresult = '\0';

	ipagerate=0;
	p = strstr(pagingstr, "Page Rate=") + 10; 
	if (p) {
        	if (sscanf(p, "%f", &fpagerate) == 1) {
			ipagerate=fpagerate + 0.5;   /*  Rounding up */
                	sprintf(pagingresult, "z/VSE Paging Rate %d per second\n", ipagerate);
                	}
		}
	else
		sprintf(pagingresult, "Can not find page rate value in:\n%s\n", pagingstr);

        get_paging_thresholds(hinfo, clientclass, &pagingyellow, &pagingred);

        upmsg = newstrbuffer(0);

        if (ipagerate > pagingred) {
                pagingcolor = COL_RED;
                addtobuffer(upmsg, "&red Paging Rate is CRITICAL\n");
        }
        else if (ipagerate > pagingyellow) {
                pagingcolor = COL_YELLOW;
                addtobuffer(upmsg, "&yellow Paging Rate is HIGH\n");
        }

        init_status(pagingcolor);
        sprintf(msgline, "status %s.paging %s %s %s %s\n",
                commafy(hostname), colorname(pagingcolor),
                (timestr ? timestr : "<no timestamp data>"),
                pagingresult, pagingstr);
        addtostatus(msgline);
        if (STRBUFLEN(upmsg)) {
                addtostrstatus(upmsg);
                addtostatus("\n");
        }

        if (fromline && !localmode) addtostatus(fromline);
        finish_status();

        freestrbuffer(upmsg);
}
Exemple #4
0
void senddata(conn_t *conn)
{
	int n, togo;
	char *startp;

	/* Send data on the connection socket */
	togo = STRBUFLEN(conn->msgbuf) - conn->sentbytes;
	startp = STRBUF(conn->msgbuf) + conn->sentbytes;
	n = write(conn->sockfd, startp, togo);

	if (n <= -1) {
		/* Write failure */
		errprintf("Connection lost during write to %s\n", inet_ntoa(conn->caddr.sin_addr));
		conn->action = C_DONE;
	}
	else {
		conn->sentbytes += n;
		if (conn->sentbytes == STRBUFLEN(conn->msgbuf)) conn->action = C_DONE;
	}
}
static void result_subqueue(char *id, myconn_t *rec,  strbuffer_t *txt)
{
	char msgline[4096];

	if (rec->textlog) {
		snprintf(msgline, sizeof(msgline), "%slog: %d\n", id, STRBUFLEN(rec->textlog));
		addtobuffer(txt, msgline);
		addtostrbuffer(txt, rec->textlog);
		addtobuffer(txt, "\n");
		clearstrbuffer(rec->textlog);
	}
}
Exemple #6
0
void loadenv(char *envfile, char *area)
{
	FILE *fd;
	strbuffer_t *inbuf;
	char *p, *oneenv;
	int n;

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

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

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

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

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

	freestrbuffer(inbuf);
	MEMUNDEFINE(l);
}
Exemple #7
0
static void zvm_paging_report(char *hostname, char *clientclass, enum ostype_t os,
                     void *hinfo, char *fromline, char *timestr, char *cpuutilstr)
{
        char *p;
        int pagerate, pagingyellow, pagingred;
        char pagingresult[100];

        int pagingcolor = COL_GREEN;
        char msgline[256];
        strbuffer_t *upmsg;

        if (!cpuutilstr) return;
        /*
         *  Looking for Paging rate info in 'IND' command response
         *  PAGING-0000/SEC
         */
        *pagingresult = '\0';
	/*  Skip past three newlines in message to the PAGING text  */
	p=strstr(cpuutilstr,"PAGING-") + 7;
	if (sscanf(p, "%d/SEC", &pagerate) == 1) {
               	sprintf(pagingresult, "z/VM Paging Rate %d per second\n", pagerate);
        }

        get_paging_thresholds(hinfo, clientclass, &pagingyellow, &pagingred);

        upmsg = newstrbuffer(0);

        if (pagerate > pagingred) {
                pagingcolor = COL_RED;
                addtobuffer(upmsg, "&red Paging Rate is CRITICAL\n");
        }
        else if (pagerate > pagingyellow) {
                pagingcolor = COL_YELLOW;
                addtobuffer(upmsg, "&yellow Paging Rate is HIGH\n");
        }

        init_status(pagingcolor);
        sprintf(msgline, "status %s.paging %s %s %s %s\n",
                commafy(hostname), colorname(pagingcolor),
                (timestr ? timestr : "<no timestamp data>"),
                pagingresult,
                cpuutilstr);
        addtostatus(msgline);
        if (STRBUFLEN(upmsg)) {
                addtostrstatus(upmsg);
                addtostatus("\n");
        }

        if (fromline && !localmode) addtostatus(fromline);
        finish_status();

        freestrbuffer(upmsg);
}
static void result_plain(myconn_t *rec,  strbuffer_t *txt)
{
	char msgline[4096];

	if (dontsendmessages >= 1) {
		if (rec->textlog) clearstrbuffer(rec->textlog);
		return;
	}

	if (rec->textlog) {
		snprintf(msgline, sizeof(msgline), "PLAINlog: %d\n", STRBUFLEN(rec->textlog));
		addtobuffer(txt, msgline);
		addtostrbuffer(txt, rec->textlog);
		addtobuffer(txt, "\n");
		clearstrbuffer(rec->textlog);
	}
}
static void add_to_sub_queue(myconn_t *rec, char *moduleid, char *location, ...)
{
	va_list extraparams;
	char *s;
	strbuffer_t *extrastr = newstrbuffer(0);

	if (!rec || !moduleid) return;

	va_start(extraparams, location);
	while ((s = va_arg(extraparams, char *)) != NULL) {
		if (STRBUFLEN(extrastr) > 0) addtobuffer(extrastr, "\t");
		addtobuffer(extrastr, s);
	}
	va_end(extraparams);

	xymon_sqldb_netmodule_additem(moduleid, location, xmh_item(rec->hostinfo, XMH_HOSTNAME), rec->netparams.destinationip, rec->testspec, STRBUF(extrastr), rec->interval*1000, rec->timeout*1000);
	freestrbuffer(extrastr);
}
Exemple #10
0
int do_external_rrd(char *hostname, char *testname, char *msg, time_t tstamp) 
{ 
	pid_t childpid;

	dbgprintf("-> do_external(%s, %s)\n", hostname, testname);

	childpid = fork();
	if (childpid == 0) {
		FILE *fd;
		char fn[PATH_MAX];
		enum { R_DEFS, R_FN, R_DATA, R_NEXT } pstate;
		FILE *extfd;
		char extcmd[2*PATH_MAX];
		strbuffer_t *inbuf;
		char *p;
		char **params = NULL;
		int paridx = 1;
		pid_t mypid = getpid();
		
		MEMDEFINE(fn); MEMDEFINE(extcmd);

		sprintf(fn, "%s/rrd_msg_%d", xgetenv("BBTMP"), (int) getpid());
		dbgprintf("%09d : Saving msg to file %s\n", (int)mypid, fn);

		fd = fopen(fn, "w");
		if (fd == NULL) {
			errprintf("Cannot create temp file %s\n", fn);
			exit(1);
		}
		if (fwrite(msg, strlen(msg), 1, fd) != 1) {
			errprintf("Error writing to file %s: %s\n", fn, strerror(errno));
			exit(1) ;
		}
		if (fclose(fd)) errprintf("Error closing file %s: %s\n", fn, strerror(errno));

		inbuf = newstrbuffer(0);

		/* Now call the external helper */
		sprintf(extcmd, "%s %s %s %s", exthandler, hostname, testname, fn);
		dbgprintf("%09d : Calling helper script %s\n", (int)mypid, extcmd);
		extfd = popen(extcmd, "r");
		if (extfd) {
			pstate = R_DEFS;
			initfgets(extfd);

			while (unlimfgets(inbuf, extfd)) {
				p = strchr(STRBUF(inbuf), '\n'); if (p) *p = '\0';
				dbgprintf("%09d : Helper input '%s'\n", (int)mypid, STRBUF(inbuf));
				if (STRBUFLEN(inbuf) == 0) continue;

				if (pstate == R_NEXT) {
					/* After doing one set of data, allow script to re-use the same DS defs */
					if (strncasecmp(STRBUF(inbuf), "DS:", 3) == 0) {
						/* New DS definitions, scratch the old ones */
						pstate = R_DEFS;

						if (params) {
							for (paridx=2; (params[paridx] != NULL); paridx++) 
								xfree(params[paridx]);
						}
						xfree(params);
						params = NULL;
						pstate = R_DEFS;
					}
					else pstate = R_FN;
				}

				switch (pstate) {
				  case R_DEFS:
					if (params == NULL) {
						params = (char **)calloc(8, sizeof(char *));
						params[0] = "rrdcreate";
						params[1] = rrdfn;
						paridx = 1;
					}

					if (strncasecmp(STRBUF(inbuf), "DS:", 3) == 0) {
						/* Dataset definition */
						paridx++;
						params = (char **)realloc(params, (7 + paridx)*sizeof(char *));
						params[paridx] = strdup(STRBUF(inbuf));
						params[paridx+1] = NULL;
						break;
					}
					else {
						/* No more DS defs - put in the RRA's last. */
						params[++paridx] = strdup(rra1);
						params[++paridx] = strdup(rra2);
						params[++paridx] = strdup(rra3);
						params[++paridx] = strdup(rra4);
						params[++paridx] = NULL;
						pstate = R_FN;
					}
					/* Fall through */
				  case R_FN:
					strncpy(rrdfn, STRBUF(inbuf), sizeof(rrdfn)-1);
					rrdfn[sizeof(rrdfn)-1] = '\0';
					pstate = R_DATA;
					break;

				  case R_DATA:
					snprintf(rrdvalues, sizeof(rrdvalues)-1, "%d:%s", (int)tstamp, STRBUF(inbuf));
					rrdvalues[sizeof(rrdvalues)-1] = '\0';
					create_and_update_rrd(hostname, rrdfn, params, NULL);
					pstate = R_NEXT;
					break;

				  case R_NEXT:
					/* Should not happen */
					break;
				}
			}
			pclose(extfd);
		}
		else {
			errprintf("Pipe open of RRD handler failed: %s\n", strerror(errno));
		}

		if (params) {
			for (paridx=2; (params[paridx] != NULL); paridx++) xfree(params[paridx]);
			xfree(params);
		}

		dbgprintf("%09d : Unlinking temp file\n", (int)mypid);
		unlink(fn);
		freestrbuffer(inbuf);

		exit(0);
	}
	else if (childpid > 0) {
		/* Parent continues */
	}
	else {
		errprintf("Fork failed in RRD handler: %s\n", strerror(errno));
	}

	dbgprintf("<- do_external(%s, %s)\n", hostname, testname);
	return 0;
}
Exemple #11
0
static void load_rrddefs(void)
{
	char fn[PATH_MAX];
	FILE *fd;
	strbuffer_t *inbuf = newstrbuffer(0);
	char *key = NULL, *p;
	char **defs = NULL;
	int defcount = 0;
	rrddeftree_t *newrec;

	rrddeftree = xtreeNew(strcasecmp);

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

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

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

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

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

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

	stackfclose(fd);

loaddone:
	freestrbuffer(inbuf);

	/* Check if the default record exists */
	if (xtreeFind(rrddeftree, "") == xtreeEnd(rrddeftree)) {
		/* Create the default record */
		newrec = (rrddeftree_t *)malloc(sizeof(rrddeftree_t));
		newrec->key = strdup("");
		newrec->defs = (char **)malloc(4 * sizeof(char *));;
		newrec->defs[0] = strdup("RRA:AVERAGE:0.5:1:576");
		newrec->defs[1] = strdup("RRA:AVERAGE:0.5:6:576");
		newrec->defs[2] = strdup("RRA:AVERAGE:0.5:24:576");
		newrec->defs[3] = strdup("RRA:AVERAGE:0.5:288:576");
		newrec->count = 4;
		xtreeAdd(rrddeftree, newrec->key, newrec);
	}
}
Exemple #12
0
int main(int argc, char *argv[])
{
        void *hwalk;
	int argi;
	strbuffer_t *statusmsg, *jrockout, *qout;

	for (argi = 1; (argi < argc); argi++) {
		if ((strcmp(argv[argi], "--help") == 0)) {
			printf("beastat version %s\n\n", VERSION);
			printf("Usage:\n%s [--debug] [--no-update] [--port=SNMPPORT] [--community=SNMPCOMMUNITY]\n", 
				argv[0]);
			exit(0);
		}
		else if ((strcmp(argv[argi], "--version") == 0)) {
			printf("beastat version %s\n", VERSION);
			exit(0);
		}
		else if ((strcmp(argv[argi], "--debug") == 0)) {
			debug = 1;
		}
		else if ((strcmp(argv[argi], "--no-update") == 0)) {
			dontsendmessages = 1;
		}
		else if (argnmatch(argv[argi], "--timeout=")) {
			char *p = strchr(argv[argi], '=');
			extcmdtimeout = atoi(p+1);
		}
		else if (argnmatch(argv[argi], "--port=")) {
			char *p = strchr(argv[argi], '=');
			default_port = atoi(p+1);
		}
		else if (argnmatch(argv[argi], "--community=")) {
			char *p = strchr(argv[argi], '=');
			default_community = strdup(p+1);
		}
	}

        load_hostnames(xgetenv("BBHOSTS"), "netinclude", get_fqdn());
        if (first_host() == NULL) {
                errprintf("Cannot load bb-hosts\n");
                return 1;
        }

        if (xgetenv("BBLOCATION")) location = strdup(xgetenv("BBLOCATION"));

	init_timestamp();
	combo_start();
	statusmsg = newstrbuffer(0);
	jrockout = newstrbuffer(0);
	qout = newstrbuffer(0);

	for (hwalk = first_host(); (hwalk); hwalk = next_host(hwalk, 0)) {
		char *tspec = bbh_custom_item(hwalk, "bea=");
		char *snmpcommunity = default_community;
		char *beadomain = "";
		int snmpport = default_port;
		char *p;
		char pipecmd[4096];
		int jrockres, qres;

		clearstrbuffer(statusmsg);
		clearstrbuffer(jrockout);
		clearstrbuffer(qout);

		/* Check if we have a "bea" test for this host, and it is a host we want to test */
                if (!tspec || !wanted_host(hwalk, location)) continue;

		/* Parse the testspec: bea=[SNMPCOMMUNITY@]BEADOMAIN[:SNMPPORT] */
		tspec = strdup(tspec+strlen("bea="));

		p = strchr(tspec, ':');
		if (p) {
			*p = '\0';
			snmpport = atoi(p+1);
		}

		p = strchr(tspec, '@');
		if (p) {
			*p = '\0';
			snmpcommunity = strdup(tspec);
			beadomain = strdup(p+1);
		}
		else {
			beadomain = strdup(tspec);
		}

		/* Prepare for the host status */
		statuscolor = COL_GREEN;

		/* Setup the snmpwalk pipe-command for jrockit stats */
		sprintf(pipecmd, "snmpwalk -m BEA-WEBLOGIC-MIB -c %s@%s -v 1 %s:%d enterprises.140.625.302.1",
			snmpcommunity, beadomain, bbh_item(hwalk, BBH_IP), snmpport);
		jrockres = run_command(pipecmd, NULL, jrockout, 0, extcmdtimeout);
		if (jrockres == 0) {
			find_idxes(STRBUF(jrockout), "BEA-WEBLOGIC-MIB::jrockitRuntimeIndex.");
			send_data(hwalk, beadomain, STRBUF(jrockout), jrockitems);
		}
		else {
			if (statuscolor < COL_YELLOW) statuscolor = COL_YELLOW;
			sprintf(msgline, "Could not retrieve BEA jRockit statistics from %s:%d domain %s (code %d)\n",
				bbh_item(hwalk, BBH_IP), snmpport, beadomain, jrockres);
			addtobuffer(statusmsg, msgline);
		}

		/* Setup the snmpwalk pipe-command for executeQueur stats */
		sprintf(pipecmd, "snmpwalk -m BEA-WEBLOGIC-MIB -c %s@%s -v 1 %s:%d enterprises.140.625.180.1",
			snmpcommunity, beadomain, bbh_item(hwalk, BBH_IP), snmpport);
		qres = run_command(pipecmd, NULL, qout, 0, extcmdtimeout);
		if (qres == 0) {
			find_idxes(STRBUF(qout), "BEA-WEBLOGIC-MIB::executeQueueRuntimeIndex.");
			send_data(hwalk, beadomain, STRBUF(qout), qitems);
		}
		else {
			if (statuscolor < COL_YELLOW) statuscolor = COL_YELLOW;
			sprintf(msgline, "Could not retrieve BEA executeQueue statistics from %s:%d domain %s (code %d)\n",
				bbh_item(hwalk, BBH_IP), snmpport, beadomain, qres);
			addtobuffer(statusmsg, msgline);
		}

		/* FUTURE: Have the statuscolor/statusmsg be updated to check against thresholds */
		/* Right now, the "bea" status is always green */
		init_status(statuscolor);
		sprintf(msgline, "status %s.%s %s %s\n\n", commafy(bbh_item(hwalk, BBH_HOSTNAME)), "bea", colorname(statuscolor), timestamp);
		addtostatus(msgline);
		if (STRBUFLEN(statusmsg) == 0) addtobuffer(statusmsg, "All BEA monitors OK\n");
		addtostrstatus(statusmsg);
		finish_status();
	}

	combo_end();
	freestrbuffer(statusmsg);
	freestrbuffer(jrockout);
	freestrbuffer(qout);

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

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

	static int loaded = 0;

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

	if (loaded) return;
	loaded = 1;

	MEMDEFINE(netrcfn);

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

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

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

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

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

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

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

				  case OTHERVAL:
				  	state = WANT_TOKEN; break;
				}

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

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

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

	fclose(fd);
	freestrbuffer(inbuf);

	MEMUNDEFINE(netrcfn);
}
Exemple #14
0
static void zvm_users_report(char *hostname, char *clientclass, enum ostype_t os,
                         void *hinfo, char *fromline, char *timestr,
		         char *psstr)
{
        int pscolor = COL_GREEN;

        int pchecks;
        int cmdofs = -1;
        char msgline[4096];
        strbuffer_t *monmsg;
        static strbuffer_t *countdata = NULL;
        int anycountdata = 0;
        char *group;

        if (!want_msgtype(hinfo, MSG_PROCS)) return;
        if (!psstr) return;

        if (!countdata) countdata = newstrbuffer(0);

        clearalertgroups();
        monmsg = newstrbuffer(0);

        sprintf(msgline, "data %s.proccounts\n", commafy(hostname));
        addtobuffer(countdata, msgline);

	cmdofs = 0;   /*  Command offset for z/VM isn't necessary  */

        pchecks = clear_process_counts(hinfo, clientclass);

        if (pchecks == 0) {
                /* Nothing to check */
                sprintf(msgline, "&%s No process checks defined\n", colorname(noreportcolor));
                addtobuffer(monmsg, msgline);
                pscolor = noreportcolor;
        }
        else if (cmdofs >= 0) {
                /* Count how many instances of each monitored process is running */
                char *pname, *pid, *bol, *nl;
                int pcount, pmin, pmax, pcolor, ptrack;

                bol = psstr;
                while (bol) {
                        nl = strchr(bol, '\n');

                        /* Take care - the ps output line may be shorter than what we look at */
                        if (nl) {
                                *nl = '\0';

                                if ((nl-bol) > cmdofs) add_process_count(bol+cmdofs);

                                *nl = '\n';
                                bol = nl+1;
                        }
                        else {
                                if (strlen(bol) > cmdofs) add_process_count(bol+cmdofs);

                                bol = NULL;
                        }
                }

                /* Check the number found for each monitored process */
                while ((pname = check_process_count(&pcount, &pmin, &pmax, &pcolor, &pid, &ptrack, &group)) != NULL) {
                        char limtxt[1024];

                        if (pmax == -1) {
                                if (pmin > 0) sprintf(limtxt, "%d or more", pmin);
                                else if (pmin == 0) sprintf(limtxt, "none");
                        }
                        else {
                                if (pmin > 0) sprintf(limtxt, "between %d and %d", pmin, pmax);
                                else if (pmin == 0) sprintf(limtxt, "at most %d", pmax);
                        }

                        if (pcolor == COL_GREEN) {
                                sprintf(msgline, "&green %s (found %d, req. %s)\n", pname, pcount, limtxt);
                                addtobuffer(monmsg, msgline);
                        }
                        else {
                                if (pcolor > pscolor) pscolor = pcolor;
                                sprintf(msgline, "&%s %s (found %d, req. %s)\n",
                                        colorname(pcolor), pname, pcount, limtxt);
                                addtobuffer(monmsg, msgline);
                                addalertgroup(group);
                        }

                        if (ptrack) {
                                /* Save the count data for later DATA message to track process counts */
                                if (!pid) pid = "default";
                                sprintf(msgline, "%s:%u\n", pid, pcount);
                                addtobuffer(countdata, msgline);
                                anycountdata = 1;
                        }
                }
        }
        else {
                pscolor = COL_YELLOW;
                sprintf(msgline, "&yellow Expected string not found in ps output header\n");
                addtobuffer(monmsg, msgline);
        }

        /* Now we know the result, so generate a status message */
        init_status(pscolor);

        group = getalertgroups();
        if (group) sprintf(msgline, "status/group:%s ", group); else strcpy(msgline, "status ");
        addtostatus(msgline);

        sprintf(msgline, "%s.procs %s %s - Processes %s\n",
                commafy(hostname), colorname(pscolor),
                (timestr ? timestr : "<No timestamp data>"),
                ((pscolor == COL_GREEN) ? "OK" : "NOT ok"));
        addtostatus(msgline);

        /* And add the info about what's wrong */
        if (STRBUFLEN(monmsg)) {
                addtostrstatus(monmsg);
                addtostatus("\n");
        }

        /* And the full virtual machine names output for those who want it */
        if (pslistinprocs) {
                /*
                 * Format the list of virtual machines into four per line, 
                 * this list could be fairly long.
                 */
                char *tmpstr, *tok, *nm[4];
		int nmidx = 0;

		/*  Make a copy of psstr, strtok() will be changing it  */
		tmpstr = strdup(psstr);

		/*  Use strtok() to split string into pieces delimited by newline  */
		tok = strtok(tmpstr, "\n");

		while (tok) {
                        nm[nmidx++] = tok;

			if (nmidx == 4) {
				sprintf(msgline, "%-8s %-8s %-8s %-8s\n", nm[0], nm[1], nm[2], nm[3]);
				addtostatus(msgline);
				nmidx = 0;
				nm[0] = nm[1] = nm[2] = nm[3] = " ";
			}
			tok = strtok(NULL, "\n");
		}
		/*  Print any remaining names  */
		if (nmidx > 0) {
			sprintf(msgline, "%-8s %-8s %-8s %-8s\n", nm[0], nm[1], nm[2], nm[3]);
			addtostatus(msgline);
		}

		free(tmpstr);
        }

        if (fromline && !localmode) addtostatus(fromline);
        finish_status();

        freestrbuffer(monmsg);

        if (anycountdata) sendmessage(STRBUF(countdata), NULL, BBTALK_TIMEOUT, NULL);
        clearstrbuffer(countdata);
}
Exemple #15
0
int main(int argc, char *argv[])
{
	char *msg;
	int running;
	int argi, seq;
	struct timespec *timeout = NULL;
	pcre *hostexp = NULL;
	pcre *exhostexp = NULL;
	pcre *testexp = NULL;
	pcre *extestexp = NULL;
	pcre *colorexp = NULL;
        const char *errmsg = NULL;
	int errofs = 0;
	FILE *logfd = stdout;
	int batchtimeout = 30;
	char *batchcmd = NULL;
	strbuffer_t *batchbuf = NULL;
	time_t lastmsgtime = 0;

	/* Handle program options. */
	for (argi = 1; (argi < argc); argi++) {
		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 (strncmp(argv[argi], "--timeout=", 10) == 0) {
			/*
			 * You can have a timeout when waiting for new
			 * messages. If it happens, you will get a "@@idle\n"
			 * message with sequence number 0.
			 * If you dont want a timeout, just pass a NULL for the timeout parameter.
			 */
			timeout = (struct timespec *)(malloc(sizeof(struct timespec)));
			timeout->tv_sec = (atoi(argv[argi]+10));
			timeout->tv_nsec = 0;
		}
		else if (argnmatch(argv[argi], "--hosts=")) {
			char *exp = strchr(argv[argi], '=') + 1;
			hostexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
			if (hostexp == NULL) printf("Invalid expression '%s'\n", exp);
		}
		else if (argnmatch(argv[argi], "--exhosts=")) {
			char *exp = strchr(argv[argi], '=') + 1;
			exhostexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
			if (exhostexp == NULL) printf("Invalid expression '%s'\n", exp);
		}
		else if (argnmatch(argv[argi], "--tests=")) {
			char *exp = strchr(argv[argi], '=') + 1;
			testexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
			if (testexp == NULL) printf("Invalid expression '%s'\n", exp);
		}
		else if (argnmatch(argv[argi], "--extests=")) {
			char *exp = strchr(argv[argi], '=') + 1;
			extestexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
			if (extestexp == NULL) printf("Invalid expression '%s'\n", exp);
		}
		else if (argnmatch(argv[argi], "--colors=")) {
			char *exp = strchr(argv[argi], '=') + 1;
			colorexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL);
			if (colorexp == NULL) printf("Invalid expression '%s'\n", exp);
		}
		else if (argnmatch(argv[argi], "--outfile=")) {
			char *fn = strchr(argv[argi], '=') + 1;
			logfd = fopen(fn, "a");
			if (logfd == NULL) {
				printf("Cannot open logfile %s: %s\n", fn, strerror(errno));
				logfd = stdout;
			}
		}
		else if (argnmatch(argv[argi], "--batch-timeout=")) {
			char *p = strchr(argv[argi], '=');
			batchtimeout = atoi(p+1);
			timeout = (struct timespec *)(malloc(sizeof(struct timespec)));
			timeout->tv_sec = batchtimeout;
			timeout->tv_nsec = 0;
		}
		else if (argnmatch(argv[argi], "--batch-command=")) {
			char *p = strchr(argv[argi], '=');
			batchcmd = strdup(p+1);
			batchbuf = newstrbuffer(0);
		}
		else {
			printf("Unknown option %s\n", argv[argi]);
			printf("Usage: %s [--hosts=EXP] [--tests=EXP] [--exhosts=EXP] [--extests=EXP] [--color=EXP] [--outfile=FILENAME] [--batch-timeout=N] [--batch-command=COMMAND]\n", argv[0]);
			return 0;
		}
	}

	signal(SIGCHLD, SIG_IGN);

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

		msg = get_hobbitd_message(C_LAST, argv[0], &seq, timeout);
		if (msg == NULL) {
			/*
			 * get_hobbitd_message will return NULL if hobbitd_channel closes
			 * the input pipe. We should shutdown when that happens.
			 */
			running = 0;
			continue;
		}

		/*
		 * Now we have a message. So do something with it.
		 *
		 * The first line of the message is always a '|' separated
		 * list of meta-data about the message. After the first
		 * line, the content varies by channel.
		 */

		/* 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 < MAX_META)) {
			metadata[metacount++] = p;
			p = gettok(NULL, "|");
		}
		metadata[metacount] = NULL;

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

		/*
		 * A "logrotate" message is sent when the Hobbit logs are
		 * rotated. The child workers must re-open their logfiles,
		 * typically stdin and stderr - the filename is always
		 * provided in the HOBBITCHANNEL_LOGFILENAME environment.
		 */
		else if (strncmp(metadata[0], "@@logrotate", 11) == 0) {
			char *fn = xgetenv("HOBBITCHANNEL_LOGFILENAME");
			if (fn && strlen(fn)) {
				freopen(fn, "a", stdout);
				freopen(fn, "a", stderr);
			}
			continue;
		}

		/*
		 * An "idle" message appears when get_hobbitd_message() 
		 * exceeds the timeout setting (ie. you passed a timeout
		 * value). This allows your worker module to perform
		 * some internal processing even though no messages arrive.
		 */
		else if (strncmp(metadata[0], "@@idle", 6) == 0) {
			dbgprintf("Got an 'idle' message\n");
		}

		/*
		 * The "drophost", "droptest", "renamehost" and "renametst"
		 * indicates that a host/test was deleted or renamed. If the
		 * worker module maintains some internal storage (in memory
		 * or persistent file-storage), it should act on these
		 * messages to maintain data consistency.
		 */
		else if ((metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) {
			dbgprintf("Got a 'drophost' message for host '%s'\n", metadata[3]);
		}
		else if ((metacount > 3) && (strncmp(metadata[0], "@@dropstate", 11) == 0)) {
			dbgprintf("Got a 'dropstate' message for host '%s'\n", metadata[3]);
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) {
			dbgprintf("Got a 'droptest' message for host '%s' test '%s'\n", metadata[3], metadata[4]);
		}
		else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) {
			dbgprintf("Got a 'renamehost' message for host '%s' -> '%s'\n", metadata[3], metadata[4]);
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) {
			dbgprintf("Got a 'renametest' message for host '%s' test '%s' -> '%s'\n", 
				metadata[3], metadata[4], metadata[5]);
		}

		/*
		 * Process this message.
		 */
		else {
			int ovector[30];
			int match, i;
			char *hostname = metadata[4];
			char *testname = metadata[5];
			char *color = metadata[7];

			/* See if we should handle the batched messages we've got */
			if (batchcmd && ((lastmsgtime + batchtimeout) < gettimer()) && (STRBUFLEN(batchbuf) > 0)) {
				pid_t childpid = fork();
				int childres = 0;

				if (childpid < 0) {
					/* Fork failed! */
					errprintf("Fork failed: %s\n", strerror(errno));
				}
				else if (childpid == 0) {
					/* Child */
					FILE *cmdpipe = popen(batchcmd, "w");
					if (cmdpipe) {
						/* Write the data to the batch command pipe */
						int n, bytesleft = STRBUFLEN(batchbuf);
						char *outp = STRBUF(batchbuf);

						while (bytesleft) {
							n = fwrite(outp, 1, bytesleft, cmdpipe);
							if (n >= 0) {
								bytesleft -= n;
								outp += n;
							}
							else {
								errprintf("Error while writing data to batch command\n");
								bytesleft = 0;
							}
						}

						childres = pclose(cmdpipe);
					}
					else {
						errprintf("Could not open pipe to batch command '%s'\n", batchcmd);
						childres = 127;
					}

					exit(childres);
				}
				else if (childpid > 0) {
					/* Parent continues */
				}

				clearstrbuffer(batchbuf);
			}


			if (hostexp) {
				match = (pcre_exec(hostexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
				if (!match) continue;
			}
			if (exhostexp) {
				match = (pcre_exec(exhostexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
				if (match) continue;
			}
			if (testexp) {
				match = (pcre_exec(testexp, NULL, testname, strlen(testname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
				if (!match) continue;
			}
			if (exhostexp) {
				match = (pcre_exec(extestexp, NULL, testname, strlen(testname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
				if (match) continue;
			}
			if (colorexp) {
				match = (pcre_exec(colorexp, NULL, color, strlen(color), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0);
				if (!match) continue;
			}

			lastmsgtime = gettimer();

			if (batchcmd) {
				addtobuffer(batchbuf, "## ");
				for (i=0; (i < metacount); i++) {
					addtobuffer(batchbuf, metadata[i]);
					addtobuffer(batchbuf, " ");
				}
				addtobuffer(batchbuf, "\n");
				addtobuffer(batchbuf, restofmsg);
				addtobuffer(batchbuf, "\n");
			}
			else {
				fprintf(logfd, "## ");
				for (i=0; (i < metacount); i++) fprintf(logfd, "%s ", metadata[i]);
				fprintf(logfd, "\n");
				fprintf(logfd, "%s\n", restofmsg);
			}
		}
	}

	return 0;
}
Exemple #16
0
void load_config(char *conffn)
{
	static void *configfiles = NULL;
	tasklist_t *twalk, *curtask = NULL;
	FILE *fd;
	strbuffer_t *inbuf;
	char *p;
	char myhostname[256];

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

			xfreedup(curtask->onhostptn,p);

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

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

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

		  case 0:
			/* Do nothing */
			break;

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

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

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

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

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

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

	/* Make sure group usage counts are correct (groups can change) */
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		if (twalk->group) twalk->group->currentuse = 0;
	}
	for (twalk = taskhead; (twalk); twalk = twalk->next) {
		if (twalk->group && twalk->pid) twalk->group->currentuse++;
	}
}
Exemple #17
0
int main(int argc, char *argv[])
{
	strbuffer_t *inbuf;
	char *ackbuf;
	char *subjectline = NULL;
	char *returnpathline = NULL;
	char *fromline = NULL;
	char *firsttxtline = NULL;
	int inheaders = 1;
	char *p;
	pcre *subjexp;
	const char *errmsg;
	int errofs, result;
	int ovector[30];
	char cookie[10];
	int duration = 0;
	int argi;
	char *envarea = NULL;

	for (argi=1; (argi < argc); argi++) {
		if (strcmp(argv[argi], "--debug") == 0) {
			debug = 1;
		}
		else if (argnmatch(argv[argi], "--env=")) {
			char *p = strchr(argv[argi], '=');
			loadenv(p+1, envarea);
		}
		else if (argnmatch(argv[argi], "--area=")) {
			char *p = strchr(argv[argi], '=');
			envarea = strdup(p+1);
		}
	}

	initfgets(stdin);
	inbuf = newstrbuffer(0);
	while (unlimfgets(inbuf, stdin)) {
		sanitize_input(inbuf, 0, 0);

		if (!inheaders) {
			/* We're in the message body. Look for a "delay=N" line here. */
			if ((strncasecmp(STRBUF(inbuf), "delay=", 6) == 0) || (strncasecmp(STRBUF(inbuf), "delay ", 6) == 0)) {
				duration = durationvalue(STRBUF(inbuf)+6);
				continue;
			}
			else if ((strncasecmp(STRBUF(inbuf), "ack=", 4) == 0) || (strncasecmp(STRBUF(inbuf), "ack ", 4) == 0)) {
				/* Some systems cannot generate a subject. Allow them to ack
				 * via text in the message body. */
				subjectline = (char *)malloc(STRBUFLEN(inbuf) + 1024);
				sprintf(subjectline, "Subject: Xymon [%s]", STRBUF(inbuf)+4);
			}
			else if (*STRBUF(inbuf) && !firsttxtline) {
				/* Save the first line of the message body, but ignore blank lines */
				firsttxtline = strdup(STRBUF(inbuf));
			}

			continue;	/* We don't care about the rest of the message body */
		}

		/* See if we're at the end of the mail headers */
		if (inheaders && (STRBUFLEN(inbuf) == 0)) { inheaders = 0; continue; }

		/* Is it one of those we want to keep ? */
		if (strncasecmp(STRBUF(inbuf), "return-path:", 12) == 0) returnpathline = strdup(skipwhitespace(STRBUF(inbuf)+12));
		else if (strncasecmp(STRBUF(inbuf), "from:", 5) == 0)    fromline = strdup(skipwhitespace(STRBUF(inbuf)+5));
		else if (strncasecmp(STRBUF(inbuf), "subject:", 8) == 0) subjectline = strdup(skipwhitespace(STRBUF(inbuf)+8));
	}
	freestrbuffer(inbuf);

	/* No subject ? No deal */
	if (subjectline == NULL) {
		dbgprintf("Subject-line not found\n");
		return 1;
	}

	/* Get the alert cookie */
	subjexp = pcre_compile(".*(Xymon|Hobbit|BB)[ -]* \\[*(-*[0-9]+)[\\]!]*", PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (subjexp == NULL) {
		dbgprintf("pcre compile failed - 1\n");
		return 2;
	}
	result = pcre_exec(subjexp, NULL, subjectline, strlen(subjectline), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
	if (result < 0) {
		dbgprintf("Subject line did not match pattern\n");
		return 3; /* Subject did not match what we expected */
	}
	if (pcre_copy_substring(subjectline, ovector, result, 2, cookie, sizeof(cookie)) <= 0) {
		dbgprintf("Could not find cookie value\n");
		return 4; /* No cookie */
	}
	pcre_free(subjexp);

	/* See if there's a "DELAY=" delay-value also */
	subjexp = pcre_compile(".*DELAY[ =]+([0-9]+[mhdw]*)", PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (subjexp == NULL) {
		dbgprintf("pcre compile failed - 2\n");
		return 2;
	}
	result = pcre_exec(subjexp, NULL, subjectline, strlen(subjectline), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
	if (result >= 0) {
		char delaytxt[4096];
		if (pcre_copy_substring(subjectline, ovector, result, 1, delaytxt, sizeof(delaytxt)) > 0) {
			duration = durationvalue(delaytxt);
		}
	}
	pcre_free(subjexp);

	/* See if there's a "msg" text also */
	subjexp = pcre_compile(".*MSG[ =]+(.*)", PCRE_CASELESS, &errmsg, &errofs, NULL);
	if (subjexp == NULL) {
		dbgprintf("pcre compile failed - 3\n");
		return 2;
	}
	result = pcre_exec(subjexp, NULL, subjectline, strlen(subjectline), 0, 0, ovector, (sizeof(ovector)/sizeof(int)));
	if (result >= 0) {
		char msgtxt[4096];
		if (pcre_copy_substring(subjectline, ovector, result, 1, msgtxt, sizeof(msgtxt)) > 0) {
			firsttxtline = strdup(msgtxt);
		}
	}
	pcre_free(subjexp);

	/* Use the "return-path:" header if we didn't see a From: line */
	if ((fromline == NULL) && returnpathline) fromline = returnpathline;
	if (fromline) {
		/* Remove '<' and '>' from the fromline - they mess up HTML */
		while ((p = strchr(fromline, '<')) != NULL) *p = ' ';
		while ((p = strchr(fromline, '>')) != NULL) *p = ' ';
	}

	/* Setup the acknowledge message */
	if (duration == 0) duration = 60;	/* Default: Ack for 60 minutes */
	if (firsttxtline == NULL) firsttxtline = "<No cause specified>";
	ackbuf = (char *)malloc(4096 + strlen(firsttxtline) + (fromline ? strlen(fromline) : 0));
	p = ackbuf;
	p += sprintf(p, "xymondack %s %d %s", cookie, duration, firsttxtline);
	if (fromline) {
		p += sprintf(p, "\nAcked by: %s", fromline);
	}

	if (debug) {
		printf("%s\n", ackbuf);
		return 0;
	}

	sendmessage(ackbuf, NULL, XYMON_TIMEOUT, NULL);
	return 0;
}
Exemple #18
0
void grabdata(conn_t *conn)
{
	int n;
	char buf[8192];
	int pollid = 0;

	/* Get data from the connection socket - we know there is some */
	n = read(conn->sockfd, buf, sizeof(buf)-1);
	if (n <= -1) {
		/* Read failure */
		errprintf("Connection lost during read: %s\n", strerror(errno));
		conn->action = C_DONE;
		return;
	}

	if (n > 0) {
		/* Got some data - store it */
		buf[n] = '\0';
		addtobuffer(conn->msgbuf, buf);
		return;
	}

	/* Done reading - process the data */
	if (STRBUFLEN(conn->msgbuf) == 0) {
		/* No data ? We're done */
		conn->action = C_DONE;
		return;
	}

	/* 
	 * See what kind of message this is. If it's a "pullclient" message,
	 * save the contents of the message - this is the client configuration
	 * that we'll return the next time a client sends us the "client" message.
	 */

	if (strncmp(STRBUF(conn->msgbuf), "pullclient", 10) == 0) {
		char *clientcfg;
		int idnum;

		/* Access check */
		if (!oksender(serverlist, NULL, conn->caddr.sin_addr, STRBUF(conn->msgbuf))) {
			errprintf("Rejected pullclient request from %s\n",
				  inet_ntoa(conn->caddr.sin_addr));
			conn->action = C_DONE;
			return;
		}

		dbgprintf("Got pullclient request: %s\n", STRBUF(conn->msgbuf));

		/*
		 * The pollid is unique for each Xymon server. It is to allow
		 * multiple servers to pick up the same message, for resiliance.
		 */
		idnum = atoi(STRBUF(conn->msgbuf) + 10);
		if ((idnum <= 0) || (idnum > 31)) {
			pollid = 0;
		}
		else {
			pollid = (1 << idnum);
		}

		conn->ctype = C_SERVER;
		conn->action = C_WRITING;

		/* Save any client config sent to us */
		clientcfg = strchr(STRBUF(conn->msgbuf), '\n');
		if (clientcfg) {
			clientcfg++;
			if (client_response) xfree(client_response);
			client_response = strdup(clientcfg);
			dbgprintf("Saved client response: %s\n", client_response);
		}
	}
	else if (strncmp(STRBUF(conn->msgbuf), "client ", 7) == 0) {
		/*
		 * Got a "client" message. Return the client-response saved from
		 * earlier, if there is any. If not, then we're done.
		 */
		conn->ctype = C_CLIENT_CLIENT;
		conn->action = (client_response ? C_WRITING : C_DONE);
	}
	else {
		/* Message from a client, but not the "client" message. So no response. */
		conn->ctype = C_CLIENT_OTHER;
		conn->action = C_DONE;
	}

	/*
	 * Messages we receive from clients are stored on our outbound queue.
	 * If it's a local "client" message, respond with the queued response
	 * from the Xymon server. Other client messages get no response.
	 *
	 * Server messages get our outbound queue back in response.
	 */
	if (conn->ctype != C_SERVER) {
		/* Messages from clients go on the outbound queue */
		msgqueue_t *newq = calloc(1, sizeof(msgqueue_t));
		dbgprintf("Queuing outbound message\n");
		newq->tstamp = conn->tstamp;
		newq->msgbuf = conn->msgbuf;
		conn->msgbuf = NULL;
		if (qtail) {
			qtail->next = newq;
			qtail = newq;
		}
		else {
			qhead = qtail = newq;
		}

		if ((conn->ctype == C_CLIENT_CLIENT) && (conn->action == C_WRITING)) {
			/* Send the response back to the client */
			conn->msgbuf = newstrbuffer(0);
			addtobuffer(conn->msgbuf, client_response);

			/* 
			 * Dont drop the client response data. If for some reason
			 * the "client" request is repeated, he should still get
			 * the right answer that we have.
			 */
		}
	}
	else {
		/* A server has asked us for our list of messages */
		time_t now = getcurrenttime(NULL);
		msgqueue_t *mwalk;

		if (!qhead) {
			/* No queued messages */
			conn->action = C_DONE;
		}
		else {
			/* Build a message of all the queued data */
			clearstrbuffer(conn->msgbuf);

			/* Index line first */
			for (mwalk = qhead; (mwalk); mwalk = mwalk->next) {
				if ((mwalk->sentto & pollid) == 0) {
					char idx[20];
					sprintf(idx, "%d:%ld ", 
						STRBUFLEN(mwalk->msgbuf), (long)(now - mwalk->tstamp));
					addtobuffer(conn->msgbuf, idx);
				}
			}

			if (STRBUFLEN(conn->msgbuf) > 0) addtobuffer(conn->msgbuf, "\n");

			/* Then the stream of messages */
			for (mwalk = qhead; (mwalk); mwalk = mwalk->next) {
				if ((mwalk->sentto & pollid) == 0) {
					if (pollid) mwalk->sentto |= pollid;
					addtostrbuffer(conn->msgbuf, mwalk->msgbuf);
				}
			}

			if (STRBUFLEN(conn->msgbuf) == 0) {
				/* No data for this server */
				conn->action = C_DONE;
			}
		}
	}
}
Exemple #19
0
void loadenv(char *envfile, char *area)
{
	FILE *fd;
	strbuffer_t *inbuf;
	char *p, *oneenv;

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

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

			sanitize_input(inbuf, 1, 1);

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

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

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

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

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

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

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

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

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

	freestrbuffer(inbuf);
	MEMUNDEFINE(l);
}
Exemple #20
0
void show_topchanges(FILE *output, 
		     countlist_t *hostcounthead, countlist_t *svccounthead, event_t *eventhead, 
		     int topcount, time_t firstevent, time_t lastevent)
{
	fprintf(output, "<p><font size=+1>%s</font></p>\n", periodstring);

	fprintf(output, "<table summary=\"Top changing hosts and services\" border=1>\n");
	fprintf(output, "<tr>\n");
	if (hostcounthead && (output != NULL)) {
		countlist_t *cwalk;
		int i;
		unsigned long others = 0, totalcount = 0;
		strbuffer_t *s = newstrbuffer(0);
		strbuffer_t *othercriteria = newstrbuffer(0);

		if (hostregex) {
			addtobuffer(othercriteria, "&amp;HOSTMATCH=");
			addtobuffer(othercriteria, hostregex);
		}
		if (exhostregex) addtobuffer(s, exhostregex);
		if (testregex) {
			addtobuffer(othercriteria, "&amp;TESTMATCH=");
			addtobuffer(othercriteria, testregex);
		}
		if (extestregex) {
			addtobuffer(othercriteria, "&amp;EXTESTMATCH=");
			addtobuffer(othercriteria, extestregex);
		}
		if (pageregex) {
			addtobuffer(othercriteria, "&amp;PAGEMATCH=");
			addtobuffer(othercriteria, pageregex);
		}
		if (expageregex) {
			addtobuffer(othercriteria, "&amp;EXPAGEMATCH=");
			addtobuffer(othercriteria, expageregex);
		}
		if (colorregex) {
			addtobuffer(othercriteria, "&amp;COLORMATCH=");
			addtobuffer(othercriteria, colorregex);
		}
		if (ignoredialups) {
			addtobuffer(othercriteria, "&amp;NODIALUPS=on");
		}
		addtobuffer(othercriteria, "&amp;SUMMARY=services");
		addtobuffer(othercriteria, "&amp;TIMETXT=");
		addtobuffer(othercriteria, periodstring);
		if (counttype == XYMON_COUNT_EVENTS) addtobuffer(othercriteria, "&amp;COUNTTYPE=events");
		else if (counttype == XYMON_COUNT_DURATION) addtobuffer(othercriteria, "&amp;COUNTTYPE=duration");

		fprintf(output, "<td width=40%% align=center valign=top>\n");
		fprintf(output, "   <table summary=\"Top %d hosts\" border=0>\n", topcount);
		fprintf(output, "      <tr><th colspan=3>Top %d hosts</th></tr>\n", topcount);
		fprintf(output, "      <tr><th align=left>Host</th><th align=left colspan=2>%s</th></tr>\n",
			(counttype == XYMON_COUNT_EVENTS) ? "State changes" : "Seconds red/yellow");

		/* Compute the total count */
		for (i=0, cwalk=hostcounthead; (cwalk); i++, cwalk=cwalk->next) totalcount += cwalk->total;

		for (i=0, cwalk=hostcounthead; (cwalk && (cwalk->total > 0)); i++, cwalk=cwalk->next) {
			if (i < topcount) {
				fprintf(output, "      <tr><td align=left><a href=\"eventlog.sh?HOSTMATCH=^%s$&amp;MAXCOUNT=-1&amp;MAXTIME=-1&amp;FROMTIME=%lu&amp;TOTIME=%lu%s\">%s</a></td><td align=right>%lu</td><td align=right>(%6.2f %%)</td></tr>\n", 
					xmh_item(cwalk->src, XMH_HOSTNAME), 
					(unsigned long)firstevent, (unsigned long)lastevent,
					STRBUF(othercriteria),
					xmh_item(cwalk->src, XMH_HOSTNAME), 
					cwalk->total, ((100.0 * cwalk->total) / totalcount));
				if (STRBUFLEN(s) > 0) addtobuffer(s, "|"); 
				addtobuffer(s, "^");
				addtobuffer(s, xmh_item(cwalk->src, XMH_HOSTNAME));
				addtobuffer(s, "$");
			}
			else {
				others += cwalk->total;
			}
		}
		fprintf(output, "      <tr><td align=left><a href=\"eventlog.sh?EXHOSTMATCH=%s&amp;MAXCOUNT=-1&amp;MAXTIME=-1&amp;FROMTIME=%lu&amp;TOTIME=%lu%s\">%s</a></td><td align=right>%lu</td><td align=right>(%6.2f %%)</td></tr>\n", 
			STRBUF(s),
			(unsigned long)firstevent, (unsigned long)lastevent,
			STRBUF(othercriteria),
			"Other hosts", 
			others, ((100.0 * others) / totalcount));
		fprintf(output, "      <tr><td colspan=3><hr width=\"100%%\"></td></tr>\n");
		fprintf(output, "      <tr><th>Total</th><th>%lu</th><th>&nbsp;</th></tr>\n", totalcount);
		fprintf(output, "   </table>\n");
		fprintf(output, "</td>\n");

		freestrbuffer(s);
		freestrbuffer(othercriteria);
	}
	if (svccounthead && (output != NULL)) {
		countlist_t *cwalk;
		int i;
		unsigned long others = 0, totalcount = 0;
		strbuffer_t *s = newstrbuffer(0);
		strbuffer_t *othercriteria = newstrbuffer(0);

		if (hostregex) {
			addtobuffer(othercriteria, "&amp;HOSTMATCH=");
			addtobuffer(othercriteria, hostregex);
		}
		if (exhostregex) {
			addtobuffer(othercriteria, "&amp;EXHOSTMATCH=");
			addtobuffer(othercriteria, exhostregex);
		}
		if (testregex) {
			addtobuffer(othercriteria, "&amp;TESTMATCH=");
			addtobuffer(othercriteria, testregex);
		}
		if (extestregex) addtobuffer(s, extestregex);
		if (pageregex) {
			addtobuffer(othercriteria, "&amp;PAGEMATCH=");
			addtobuffer(othercriteria, pageregex);
		}
		if (expageregex) {
			addtobuffer(othercriteria, "&amp;EXPAGEMATCH=");
			addtobuffer(othercriteria, expageregex);
		}
		if (colorregex) {
			addtobuffer(othercriteria, "&amp;COLORMATCH=");
			addtobuffer(othercriteria, colorregex);
		}
		if (ignoredialups) {
			addtobuffer(othercriteria, "&amp;NODIALUPS=on");
		}
		addtobuffer(othercriteria, "&amp;SUMMARY=hosts");
		addtobuffer(othercriteria, "&amp;TIMETXT=");
		addtobuffer(othercriteria, periodstring);
		if (counttype == XYMON_COUNT_EVENTS) addtobuffer(othercriteria, "&amp;COUNTTYPE=events");
		else if (counttype == XYMON_COUNT_DURATION) addtobuffer(othercriteria, "&amp;COUNTTYPE=duration");


		fprintf(output, "<td width=40%% align=center valign=top>\n");
		fprintf(output, "   <table summary=\"Top %d services\" border=0>\n", topcount);
		fprintf(output, "      <tr><th colspan=3>Top %d services</th></tr>\n", topcount);
		fprintf(output, "      <tr><th align=left>Service</th><th align=left colspan=2>%s</th></tr>\n",
			(counttype == XYMON_COUNT_EVENTS) ? "State changes" : "Seconds red/yellow");

		/* Compute the total count */
		for (i=0, cwalk=svccounthead; (cwalk); i++, cwalk=cwalk->next) totalcount += cwalk->total;

		for (i=0, cwalk=svccounthead; (cwalk && (cwalk->total > 0)); i++, cwalk=cwalk->next) {
			if (i < topcount) {
				fprintf(output, "      <tr><td align=left><a href=\"eventlog.sh?TESTMATCH=^%s$&amp;MAXCOUNT=-1&amp;MAXTIME=-1&amp;FROMTIME=%lu&amp;TOTIME=%lu%s\">%s</a></td><td align=right>%lu</td><td align=right>(%6.2f %%)</td></tr>\n", 
					((htnames_t *)cwalk->src)->name, 
					(unsigned long)firstevent, (unsigned long)lastevent,
					STRBUF(othercriteria),
					((htnames_t *)cwalk->src)->name, 
					cwalk->total, ((100.0 * cwalk->total) / totalcount));
				if (STRBUFLEN(s) > 0) addtobuffer(s, "|"); 
				addtobuffer(s, "^");
				addtobuffer(s, ((htnames_t *)cwalk->src)->name);
				addtobuffer(s, "$");
			}
			else {
				others += cwalk->total;
			}
		}
		fprintf(output, "      <tr><td align=left><a href=\"eventlog.sh?EXTESTMATCH=%s&amp;MAXCOUNT=-1&amp;MAXTIME=-1&amp;FROMTIME=%lu&amp;TOTIME=%lu%s\">%s</td><td align=right>%lu</td><td align=right>(%6.2f %%)</td></tr>\n", 
			STRBUF(s),
			(unsigned long)firstevent, (unsigned long)lastevent,
			STRBUF(othercriteria),
			"Other services", 
			others, ((100.0 * others) / totalcount));
		fprintf(output, "      <tr><td colspan=3><hr width=\"100%%\"></td></tr>\n");
		fprintf(output, "      <tr><th>Total</th><th>%lu</th><th>&nbsp;</th></tr>\n", totalcount);
		fprintf(output, "   </table>\n");
		fprintf(output, "</td>\n");

		freestrbuffer(s);
		freestrbuffer(othercriteria);
	}
	fprintf(output, "</tr>\n");
	fprintf(output, "</table>\n");
}
Exemple #21
0
void process_clientdata(conn_t *conn)
{
	/* 
	 * Handle data we received while talking to the Hobbit client.
	 * This will be a list of messages we must send to the server.
	 * Each of the messages are pushed to the server through
	 * new C_SERVER requests.
	 */

	char *mptr, *databegin, *msgbegin;
	int portnum = atoi(xgetenv("BBPORT"));

	databegin = strchr(STRBUF(conn->msgbuf), '\n');
	if (!databegin || (STRBUFLEN(conn->msgbuf) == 0)) {
		/* No data - we're done */
		flag_cleanup(conn);
		return;
	}
	*databegin = '\0'; /* End the first line, and point msgbegin at start of data */
	msgbegin = (databegin+1);

	/*
	 * First line of the message is a list of numbers, telling 
	 * us the size of each of the individual messages we got from 
	 * the client, and how long ago they were received.
	 */
	mptr = strtok(STRBUF(conn->msgbuf), " \t");
	while (mptr) {
		int msgbytes, msgago;
		char savech;
		strbuffer_t *req;

		if (sscanf(mptr, "%d:%d", &msgbytes, &msgago) == 2) {
			msgbytes = atoi(mptr);
			if ((msgbytes <= 0) || ((msgbegin + msgbytes) - STRBUF(conn->msgbuf)) > STRBUFLEN(conn->msgbuf)) {
				/* Someone is playing games with us */
				errprintf("Invalid message data from %s (req %lu): Current offset %d, msgbytes %d, msglen %d\n",
					  addrstring(&conn->caddr), conn->seq,
					  (msgbegin - STRBUF(conn->msgbuf)), msgbytes, STRBUFLEN(conn->msgbuf));
				return;
			}

			savech = *(msgbegin + msgbytes);
			*(msgbegin + msgbytes) = '\0';
			req = newstrbuffer(msgbytes+100);
			addtobuffer(req, msgbegin);

			if (strncmp(msgbegin, "client ", 7) == 0) {
				/*
				 * It's a client message. See when it was received in
				 * msgcache, and adjust our next poll time accordingly.
				 */
				char msgcachesection[100];

				conn->client->suggestpoll = time(NULL) - (msgago % 300) + 300 + 10;
				dbgprintf("Client %s (req %lu) received a client message %d secs ago, poll again at %lu\n",
					addrstring(&conn->caddr), conn->seq, msgago,
					conn->client->suggestpoll);

				/* Add a section to the client message with cache delay info */
				snprintf(msgcachesection, sizeof(msgcachesection),
					 "[msgcache]\nCachedelay: %d\n[proxy]\nClientIP:%s", 
					 msgago, addrstring(&conn->caddr));
				addtobuffer(req, msgcachesection);
			}
			else if ( (strncmp(msgbegin, "status", 6) == 0) ||
				  (strncmp(msgbegin, "data", 4) == 0) ) {
				char sourcemsg[100];

				/* Add a line to the message showing where it came from */
				sprintf(sourcemsg, "\nStatus message received from %s\n", 
					addrstring(&conn->caddr));
				addtobuffer(req, sourcemsg);
			}

			addrequest(C_SERVER, serverip, portnum, req, conn->client);

			*(msgbegin + msgbytes) = savech;

			msgbegin += msgbytes;
			mptr = strtok(NULL, " \t");
		}
		else {
			errprintf("Garbled pullclient response from %s (req %lu), token %s\n",
				  addrstring(&conn->caddr), conn->seq, mptr);
			mptr = NULL;
		}
	}
}
Exemple #22
0
void send_http_results(service_t *httptest, testedhost_t *host, testitem_t *firsttest,
		       char *nonetpage, int failgoesclear)
{
	testitem_t *t;
	int	color = -1;
	char    *svcname;
	strbuffer_t *msgtext;
	char    *nopagename;
	int     nopage = 0;
	int	anydown = 0, totalreports = 0;

	if (firsttest == NULL) return;

	svcname = strdup(httptest->testname);
	if (httptest->namelen) svcname[httptest->namelen] = '\0';

	/* Check if this service is a NOPAGENET service. */
	nopagename = (char *) malloc(strlen(svcname)+3);
	sprintf(nopagename, ",%s,", svcname);
	nopage = (strstr(nonetpage, svcname) != NULL);
	xfree(nopagename);

	dbgprintf("Calc http color host %s : ", host->hostname);

	msgtext = newstrbuffer(0);
	for (t=firsttest; (t && (t->host == host)); t = t->next) {
		http_data_t *req = (http_data_t *) t->privdata;

		/* Skip the data-reports for now */
		if (t->senddata) continue;

		/* Grab session cookies */
		update_session_cookies(host->hostname, req->bburl.desturl->host, req->headers);

		totalreports++;
		if (req->bburl.okcodes || req->bburl.badcodes) {
			req->httpcolor = statuscolor_by_set(host, req->httpstatus, req->bburl.okcodes, req->bburl.badcodes);
		}
		else {
			req->httpcolor = statuscolor(host, req->httpstatus);
		}
		if (req->httpcolor == COL_RED) anydown++;

		/* Dialup hosts and dialup tests report red as clear */
		if ((req->httpcolor != COL_GREEN) && (host->dialup || t->dialup)) req->httpcolor = COL_CLEAR;

		/* If ping failed, report CLEAR unless alwaystrue */
		if ( ((req->httpcolor == COL_RED) || (req->httpcolor == COL_YELLOW)) && /* Test failed */
		     (host->downcount > 0)                   && /* The ping check did fail */
		     (!host->noping && !host->noconn)        && /* We are doing a ping test */
		     (failgoesclear)                         &&
		     (!t->alwaystrue)                           )  /* No "~testname" flag */ {
			req->httpcolor = COL_CLEAR;
		}

		/* If test we depend on has failed, report CLEAR unless alwaystrue */
		if ( ((req->httpcolor == COL_RED) || (req->httpcolor == COL_YELLOW)) && /* Test failed */
		      failgoesclear && !t->alwaystrue )  /* No "~testname" flag */ {
			char *faileddeps = deptest_failed(host, t->service->testname);

			if (faileddeps) {
				req->httpcolor = COL_CLEAR;
				req->faileddeps = strdup(faileddeps);
			}
		}

		dbgprintf("%s(%s) ", t->testspec, colorname(req->httpcolor));
		if (req->httpcolor > color) color = req->httpcolor;

		/* Build the short msgtext which goes on line 1 of the status message. */
		addtobuffer(msgtext, (STRBUFLEN(msgtext) ? " ; " : ": ") );
		if (req->tcptest->errcode != CONTEST_ENOERROR) {
			switch (req->tcptest->errcode) {
			  case CONTEST_ETIMEOUT: 
				  req->errorcause = "Server timeout"; break;
			  case CONTEST_ENOCONN : 
				  req->errorcause =  strdup(strerror(req->tcptest->connres)); break;
			  case CONTEST_EDNS    : 
				  switch (req->parsestatus) {
					  case 1 : req->errorcause =  "Invalid URL"; break;
					  case 2 : req->errorcause =  "Hostname not in DNS"; break;
					  default: req->errorcause =  "DNS error"; break;
				  }
				  break;
			  case CONTEST_EIO     : 
				  req->errorcause =  "I/O error"; break;
			  case CONTEST_ESSL    : 
				  req->errorcause =  "SSL error"; break;
			  default: 
				  req->errorcause =  "Xfer failed";
			}

			addtobuffer(msgtext, req->errorcause);
		} 
		else if (req->tcptest->open == 0) {
			req->errorcause = "Connect failed";
			addtobuffer(msgtext, req->errorcause);
		}
		else if ((req->httpcolor == COL_RED) || (req->httpcolor == COL_YELLOW)) {
			char m1[100];

			if (req->bburl.okcodes || req->bburl.badcodes) {
				sprintf(m1, "Unwanted HTTP status %ld", req->httpstatus);
			}
			else if (req->headers) {
				char *p = req->headers;

				/* Skip past "HTTP/1.x 200 " and pick up the explanatory text, if any */
				if (strncasecmp(p, "http/", 5) == 0) {
					p += 5;
					p += strspn(p, "0123456789. ");
				}

				strncpy(m1, p, sizeof(m1)-1);
				m1[sizeof(m1)-1] = '\0';

				/* Only show the first line of the HTTP status description */
				p = strchr(m1, '\n'); if (p) *p = '\0';
			}
			else {
				sprintf(m1, "HTTP error %ld", req->httpstatus);
			}
			addtobuffer(msgtext, m1);
			req->errorcause = strdup(m1);
		}
		else {
			addtobuffer(msgtext, "OK");
			if (req->bburl.okcodes || req->bburl.badcodes) {
				char m1[100];

				sprintf(m1, " (HTTP status %ld)", req->httpstatus);
				addtobuffer(msgtext, m1);
			}
		}
	}

	/* It could be that we have 0 http tests - if we only do the apache one */
	if (totalreports > 0) {
		char msgline[4096];

		if (anydown) {
			firsttest->downcount++; 
			if(firsttest->downcount == 1) firsttest->downstart = getcurrenttime(NULL);
		} 
		else firsttest->downcount = 0;

		/* Handle the "badtest" stuff for http tests */
		if ((color == COL_RED) && (firsttest->downcount < firsttest->badtest[2])) {
			if      (firsttest->downcount >= firsttest->badtest[1]) color = COL_YELLOW;
			else if (firsttest->downcount >= firsttest->badtest[0]) color = COL_CLEAR;
			else                                                    color = COL_GREEN;
		}

		if (nopage && (color == COL_RED)) color = COL_YELLOW;
		dbgprintf(" --> %s\n", colorname(color));

		/* Send off the http status report */
		init_status(color);
		sprintf(msgline, "status+%d %s.%s %s %s", 
			validity, commafy(host->hostname), svcname, colorname(color), timestamp);
		addtostatus(msgline);
		addtostrstatus(msgtext);
		addtostatus("\n");

		for (t=firsttest; (t && (t->host == host)); t = t->next) {
			char *urlmsg;
			http_data_t *req = (http_data_t *) t->privdata;

			/* Skip the "data" reports */
			if (t->senddata) continue;

			urlmsg = (char *)malloc(1024 + strlen(req->url));
			sprintf(urlmsg, "\n&%s %s - ", colorname(req->httpcolor), req->url);
			addtostatus(urlmsg);

			if (req->httpcolor == COL_GREEN) addtostatus("OK");
			else {
				if (req->errorcause) addtostatus(req->errorcause);
				else addtostatus("failed");
			}
			if (req->bburl.okcodes || req->bburl.badcodes) {
				char m1[100];

				sprintf(m1, " (HTTP status %ld)", req->httpstatus);
				addtostatus(m1);
			}
			addtostatus("\n");

			if (req->headers) {
				addtostatus("\n");
				addtostatus(req->headers);
			}
			if (req->faileddeps) addtostatus(req->faileddeps);

			sprintf(urlmsg, "\nSeconds: %5d.%02d\n\n", 
				(unsigned int)req->tcptest->totaltime.tv_sec, 
				(unsigned int)req->tcptest->totaltime.tv_nsec / 10000000 );
			addtostatus(urlmsg);
			xfree(urlmsg);
		}
		addtostatus("\n\n");
		finish_status();
	}

	/* Send of any HTTP status tests in separate columns */
	for (t=firsttest; (t && (t->host == host)); t = t->next) {
		int color;
		char msgline[4096];
		char *urlmsg;
		http_data_t *req = (http_data_t *) t->privdata;

		if ((t->senddata) || (!req->bburl.columnname) || (req->contentcheck != CONTENTCHECK_NONE)) continue;

		/* Handle the "badtest" stuff */
		color = req->httpcolor;
		if ((color == COL_RED) && (t->downcount < t->badtest[2])) {
			if      (t->downcount >= t->badtest[1]) color = COL_YELLOW;
			else if (t->downcount >= t->badtest[0]) color = COL_CLEAR;
			else                                    color = COL_GREEN;
		}

		if (nopage && (color == COL_RED)) color = COL_YELLOW;

		/* Send off the http status report */
		init_status(color);
		sprintf(msgline, "status+%d %s.%s %s %s", 
			validity, commafy(host->hostname), req->bburl.columnname, colorname(color), timestamp);
		addtostatus(msgline);

		addtostatus(" : ");
		addtostatus(req->errorcause ? req->errorcause : "OK");
		if (req->bburl.okcodes || req->bburl.badcodes) {
			char m1[100];

			sprintf(m1, " (HTTP status %ld)", req->httpstatus);
			addtostatus(m1);
		}
		addtostatus("\n");

		urlmsg = (char *)malloc(1024 + strlen(req->url));
		sprintf(urlmsg, "\n&%s %s - ", colorname(req->httpcolor), req->url);
		addtostatus(urlmsg);
		xfree(urlmsg);

		if (req->httpcolor == COL_GREEN) addtostatus("OK");
		else {
			if (req->errorcause) addtostatus(req->errorcause);
			else addtostatus("failed");
		}
		addtostatus("\n");

		if (req->headers) {
			addtostatus("\n");
			addtostatus(req->headers);
		}
		if (req->faileddeps) addtostatus(req->faileddeps);

		sprintf(msgline, "\nSeconds: %5d.%02d\n\n", 
			(unsigned int)req->tcptest->totaltime.tv_sec, 
			(unsigned int)req->tcptest->totaltime.tv_nsec / 10000000 );
		addtostatus(msgline);

		addtostatus("\n\n");
		finish_status();
	}

	/* Send off any "data" messages now */
	for (t=firsttest; (t && (t->host == host)); t = t->next) {
		http_data_t *req;
		char *data = "";
		char *msg;

		if (!t->senddata) continue;

		req = (http_data_t *) t->privdata;
		if (req->output) data = req->output;

		msg = (char *)malloc(1024 + strlen(host->hostname) + strlen(req->bburl.columnname) + strlen(data));
		sprintf(msg, "data %s.%s\n%s", commafy(host->hostname), req->bburl.columnname, data);
		sendmessage(msg, NULL, BBTALK_TIMEOUT, NULL);
		xfree(msg);
	}

	xfree(svcname);
	freestrbuffer(msgtext);
}
Exemple #23
0
static void print_host(hostlist_t *host, htnames_t *testnames[], int testcount)
{
    int testi, rowcount, netcount;
    void *hinfo = hostinfo(host->hostname);
    char *dispname = NULL, *clientalias = NULL, *comment = NULL, *description = NULL, *pagepathtitle = NULL;
    char *net = NULL, *nkalerts = NULL;
    char *nktime = NULL, *downtime = NULL, *reporttime = NULL;
    char *itm;
    tag_t *taghead = NULL;
    int contidx = 0, haveping = 0;
    char contcol[1024];
    activealerts_t *alert;
    strbuffer_t *buf = newstrbuffer(0);

    fprintf(stdout, "<p style=\"page-break-before: always\">\n");
    fprintf(stdout, "<table width=\"100%%\" border=1 summary=\"%s configuration\">\n", host->hostname);

    pagepathtitle = bbh_item(hinfo, BBH_PAGEPATHTITLE);
    if (!pagepathtitle || (strlen(pagepathtitle) == 0)) pagepathtitle = "Top page";
    dispname = bbh_item(hinfo, BBH_DISPLAYNAME);
    if (dispname && (strcmp(dispname, host->hostname) == 0)) dispname = NULL;
    clientalias = bbh_item(hinfo, BBH_CLIENTALIAS);
    if (clientalias && (strcmp(clientalias, host->hostname) == 0)) clientalias = NULL;
    comment = bbh_item(hinfo, BBH_COMMENT);
    description = bbh_item(hinfo, BBH_DESCRIPTION);
    net = bbh_item(hinfo, BBH_NET);
    nkalerts = bbh_item(hinfo, BBH_NK);
    nktime = bbh_item(hinfo, BBH_NKTIME);
    if (!nktime) nktime = "24x7";
    else nktime = strdup(timespec_text(nktime));
    downtime = bbh_item(hinfo, BBH_DOWNTIME);
    if (downtime) downtime = strdup(timespec_text(downtime));
    reporttime = bbh_item(hinfo, BBH_REPORTTIME);
    if (!reporttime) reporttime = "24x7";
    else reporttime = strdup(timespec_text(reporttime));

    rowcount = 1;
    if (pagepathtitle) rowcount++;
    if (dispname || clientalias) rowcount++;
    if (comment) rowcount++;
    if (description) rowcount++;
    if (!newnkconfig && nktime) rowcount++;
    if (downtime) rowcount++;
    if (reporttime) rowcount++;

    fprintf(stdout, "<tr>\n");
    fprintf(stdout, "<th rowspan=%d align=left width=\"25%%\" valign=top>Basics</th>\n", rowcount);
    fprintf(stdout, "<th align=center>%s (%s)</th>\n",
            (dispname ? dispname : host->hostname), bbh_item(hinfo, BBH_IP));
    fprintf(stdout, "</tr>\n");

    if (dispname || clientalias) {
        fprintf(stdout, "<tr><td>Aliases:");
        if (dispname) fprintf(stdout, " %s", dispname);
        if (clientalias) fprintf(stdout, " %s", clientalias);
        fprintf(stdout, "</td></tr>\n");
    }
    if (pagepathtitle) fprintf(stdout, "<tr><td>Monitoring location: %s</td></tr>\n", pagepathtitle);
    if (comment) fprintf(stdout, "<tr><td>Comment: %s</td></tr>\n", comment);
    if (description) fprintf(stdout, "<tr><td>Description: %s</td></tr>\n", description);
    if (!newnkconfig && nktime) fprintf(stdout, "<tr><td>NK monitoring period: %s</td></tr>\n", nktime);
    if (downtime) fprintf(stdout, "<tr><td>Planned downtime: %s</td></tr>\n", downtime);
    if (reporttime) fprintf(stdout, "<tr><td>SLA Reporting Period: %s</td></tr>\n", reporttime);


    /* Build a list of the network tests */
    itm = bbh_item_walk(hinfo);
    while (itm) {
        char *visdata = NULL, *colname = NULL, *expdata = NULL;
        bburl_t bu;
        int dialuptest = 0, reversetest = 0, alwaystruetest = 0, httpextra = 0;

        if (*itm == '?') {
            dialuptest=1;
            itm++;
        }
        if (*itm == '!') {
            reversetest=1;
            itm++;
        }
        if (*itm == '~') {
            alwaystruetest=1;
            itm++;
        }

        if ( argnmatch(itm, "http")         ||
                argnmatch(itm, "content=http") ||
                argnmatch(itm, "cont;http")    ||
                argnmatch(itm, "cont=")        ||
                argnmatch(itm, "nocont;http")  ||
                argnmatch(itm, "nocont=")      ||
                argnmatch(itm, "post;http")    ||
                argnmatch(itm, "post=")        ||
                argnmatch(itm, "nopost;http")  ||
                argnmatch(itm, "nopost=")      ||
                argnmatch(itm, "type;http")    ||
                argnmatch(itm, "type=")        ) {
            visdata = decode_url(itm, &bu);
            colname = bu.columnname;
            if (!colname) {
                if (bu.expdata) {
                    httpextra = 1;
                    if (contidx == 0) {
                        colname = "content";
                        contidx++;
                    }
                    else {
                        sprintf(contcol, "content%d", contidx);
                        colname = contcol;
                        contidx++;
                    }
                }
                else {
                    colname = "http";
                }
            }
            expdata = bu.expdata;
        }
        else if (strncmp(itm, "rpc=", 4) == 0) {
            colname = "rpc";
            visdata = strdup(itm+4);
        }
        else if (strncmp(itm, "dns=", 4) == 0) {
            colname = "dns";
            visdata = strdup(itm+4);
        }
        else if (strncmp(itm, "dig=", 4) == 0) {
            colname = "dns";
            visdata = strdup(itm+4);
        }
        else if (strncmp(itm, pingplus, strlen(pingplus)) == 0) {
            haveping = 1;
            colname = pingcolumn;
            visdata = strdup(itm+strlen(pingplus));
        }
        else if (is_net_test(itm)) {
            colname = strdup(itm);
        }


        if (colname) {
            tag_t *newitem;

addtolist:
            for (newitem = taghead; (newitem && strcmp(newitem->columnname, colname)); newitem = newitem->next);

            if (!newitem) {
                newitem = (tag_t *)calloc(1, sizeof(tag_t));
                newitem->columnname = strdup(colname);
                newitem->visualdata = (visdata ? strdup(visdata) : NULL);
                newitem->expdata = (expdata ? strdup(expdata) : NULL);
                newitem->next = taghead;
                taghead = newitem;
            }
            else {
                /* Multiple tags for one column - must be http */
                newitem->visualdata = (char *)realloc(newitem->visualdata, strlen(newitem->visualdata) + strlen(visdata) + 5);
                strcat(newitem->visualdata, "<br>");
                strcat(newitem->visualdata, visdata);
            }

            if (httpextra) {
                httpextra = 0;
                colname = "http";
                expdata = NULL;
                goto addtolist;
            }
        }

        itm = bbh_item_walk(NULL);
    }

    if (!haveping && !bbh_item(hinfo, BBH_FLAG_NOCONN)) {
        for (testi = 0; (testi < testcount); testi++) {
            if (strcmp(testnames[testi]->name, pingcolumn) == 0) {
                tag_t *newitem = (tag_t *)calloc(1, sizeof(tag_t));
                newitem->columnname = strdup(pingcolumn);
                newitem->next = taghead;
                taghead = newitem;
            }
        }
    }

    /* Add the "badFOO" settings */
    itm = bbh_item_walk(hinfo);
    while (itm) {
        if (strncmp(itm, "bad", 3) == 0) {
            char *tname, *p;
            int b1, b2, b3, n = -1;
            tag_t *tag = NULL;

            tname = itm+3;
            p = strchr(tname, ':');
            if (p) {
                *p = '\0';
                n = sscanf(p+1, "%d:%d:%d", &b1, &b2, &b3);
                for (tag = taghead; (tag && strcmp(tag->columnname, tname)); tag = tag->next);
                *p = ':';
            }

            if (tag && (n == 3)) {
                tag->b1 = b1;
                tag->b2 = b2;
                tag->b3 = b3;
            }
        }

        itm = bbh_item_walk(NULL);
    }

    if (taghead) {
        fprintf(stdout, "<tr>\n");
        fprintf(stdout, "<th align=left valign=top>Network tests");
        if (net) fprintf(stdout, "<br>(from %s)", net);
        fprintf(stdout, "</th>\n");

        fprintf(stdout, "<td><table border=0 cellpadding=\"3\" cellspacing=\"5\" summary=\"%s network tests\">\n", host->hostname);
        fprintf(stdout, "<tr><th align=left valign=top>Service</th><th align=left valign=top>NK</th><th align=left valign=top>C/Y/R limits</th><th align=left valign=top>Specifics</th></tr>\n");
    }
    for (testi = 0, netcount = 0; (testi < testcount); testi++) {
        tag_t *twalk;

        for (twalk = taghead; (twalk && strcasecmp(twalk->columnname, testnames[testi]->name)); twalk = twalk->next);
        if (!twalk) continue;

        use_columndoc(testnames[testi]->name);
        fprintf(stdout, "<tr>");
        fprintf(stdout, "<td valign=top>%s</td>", testnames[testi]->name);
        fprintf(stdout, "<td valign=top>%s</td>", nkval(host->hostname, testnames[testi]->name, nkalerts));

        fprintf(stdout, "<td valign=top>");
        if (twalk->b1 || twalk->b2 || twalk->b3) {
            fprintf(stdout, "%d/%d/%d", twalk->b1, twalk->b2, twalk->b3);
        }
        else {
            fprintf(stdout, "-/-/-");
        }
        fprintf(stdout, "</td>");

        fprintf(stdout, "<td valign=top>");
        fprintf(stdout, "<i>%s</i>", (twalk->visualdata ? twalk->visualdata : "&nbsp;"));
        if (twalk->expdata) fprintf(stdout, " must return <i>'%s'</i>", twalk->expdata);
        fprintf(stdout, "</td>");

        fprintf(stdout, "</tr>");
        netcount++;
    }
    if (taghead) {
        fprintf(stdout, "</table></td>\n");
        fprintf(stdout, "</tr>\n");
    }


    if (netcount != testcount) {
        fprintf(stdout, "<tr>\n");
        fprintf(stdout, "<th align=left valign=top>Local tests</th>\n");
        fprintf(stdout, "<td><table border=0 cellpadding=\"3\" cellspacing=\"5\" summary=\"%s local tests\">\n", host->hostname);
        fprintf(stdout, "<tr><th align=left valign=top>Service</th><th align=left valign=top>NK</th><th align=left valign=top>C/Y/R limits</th><th align=left valign=top>Configuration <i>(NB: Thresholds on client may differ)</i></th></tr>\n");
    }
    for (testi = 0; (testi < testcount); testi++) {
        tag_t *twalk;

        for (twalk = taghead; (twalk && strcasecmp(twalk->columnname, testnames[testi]->name)); twalk = twalk->next);
        if (twalk) continue;

        use_columndoc(testnames[testi]->name);
        fprintf(stdout, "<tr>");
        fprintf(stdout, "<td valign=top>%s</td>", testnames[testi]->name);
        fprintf(stdout, "<td valign=top>%s</td>", nkval(host->hostname, testnames[testi]->name, nkalerts));
        fprintf(stdout, "<td valign=top>-/-/-</td>");

        /* Make up some default configuration data */
        fprintf(stdout, "<td valign=top>");
        if (strcmp(testnames[testi]->name, "cpu") == 0) {
            fprintf(stdout, "UNIX - Yellow: Load average > 1.5, Red: Load average > 3.0<br>");
            fprintf(stdout, "Windows - Yellow: CPU utilisation > 80%%, Red: CPU utilisation > 95%%");
        }
        else if (strcmp(testnames[testi]->name, "disk") == 0) {
            fprintf(stdout, "Default limits: Yellow 90%% full, Red 95%% full<br>\n");
            print_disklist(host->hostname);
        }
        else if (strcmp(testnames[testi]->name, "memory") == 0) {
            fprintf(stdout, "Yellow: swap/pagefile use > 80%%, Red: swap/pagefile use > 90%%");
        }
        else if (strcmp(testnames[testi]->name, "procs") == 0) {
            htnames_t *walk;

            if (!host->procs) fprintf(stdout, "No processes monitored<br>\n");

            for (walk = host->procs; (walk); walk = walk->next) {
                fprintf(stdout, "%s<br>\n", walk->name);
            }
        }
        else if (strcmp(testnames[testi]->name, "svcs") == 0) {
            htnames_t *walk;

            if (!host->svcs) fprintf(stdout, "No services monitored<br>\n");

            for (walk = host->svcs; (walk); walk = walk->next) {
                fprintf(stdout, "%s<br>\n", walk->name);
            }
        }
        else {
            fprintf(stdout, "&nbsp;");
        }
        fprintf(stdout, "</td>");

        fprintf(stdout, "</tr>");
    }
    if (netcount != testcount) {
        fprintf(stdout, "</table></td>\n");
        fprintf(stdout, "</tr>\n");
    }

    /* Do the alerts */
    alert = (activealerts_t *)calloc(1, sizeof(activealerts_t));
    alert->hostname = host->hostname;
    alert->location = bbh_item(hinfo, BBH_ALLPAGEPATHS);
    strcpy(alert->ip, "127.0.0.1");
    alert->color = COL_RED;
    alert->pagemessage = "";
    alert->state = A_PAGING;
    alert->cookie = 12345;
    alert_printmode(2);
    for (testi = 0; (testi < testcount); testi++) {
        alert->testname = testnames[testi]->name;
        if (have_recipient(alert, NULL)) print_alert_recipients(alert, buf);
    }
    xfree(alert);

    if (STRBUFLEN(buf) > 0) {
        fprintf(stdout, "<tr>\n");
        fprintf(stdout, "<th align=left valign=top>Alerts</th>\n");
        fprintf(stdout, "<td><table border=0 cellpadding=\"3\" cellspacing=\"5\" summary=\"%s alerts\">\n", host->hostname);
        fprintf(stdout, "<tr><th>Service</th><th>Recipient</th><th>1st Delay</th><th>Stop after</th><th>Repeat</th><th>Time of Day</th><th>Colors</th></tr>\n");

        fprintf(stdout, "%s", STRBUF(buf));

        fprintf(stdout, "</table></td>\n");
        fprintf(stdout, "</tr>\n");
    }

    /* Finish off this host */
    fprintf(stdout, "</table>\n");

    freestrbuffer(buf);
}
Exemple #24
0
static void zvm_cpu_report(char *hostname, char *clientclass, enum ostype_t os,
                     void *hinfo, char *fromline, char *timestr,
                     char *cpuutilstr, char *uptimestr)
{
        char *p;
        float load1, loadyellow, loadred;
        int recentlimit, ancientlimit, maxclockdiff;
        int  uphour, upmin;
        char loadresult[100];
        char myupstr[100];
        long uptimesecs = -1;
        long upday;

        int cpucolor = COL_GREEN;

        char msgline[1024];
        strbuffer_t *upmsg;

	if (!want_msgtype(hinfo, MSG_CPU)) return;

        if (!cpuutilstr) return;
        if (!uptimestr) return;

        uptimesecs = 0;

        /*
         * z/VM: "Uptime: 1 Days, 13 Hours, 38 Minutes"
         */

	sscanf(uptimestr,"Uptime: %ld Days, %d Hours, %d Minutes", &upday, &uphour, &upmin);
        uptimesecs = upday * 86400;
        uptimesecs += 60*(60*uphour + upmin);
        sprintf(myupstr, "%s\n", uptimestr);

        /*
         *  Looking for average CPU Utilization in 'IND' command response
         *  AVGPROC-000% 
         */
        *loadresult = '\0';
        p = strstr(cpuutilstr, "AVGPROC-") + 8 ;
        if (p) {
                if (sscanf(p, "%f%%", &load1) == 1) {
                        sprintf(loadresult, "z/VM CPU Utilization %3.0f%%\n", load1);
                }
        }

        get_cpu_thresholds(hinfo, clientclass, &loadyellow, &loadred, &recentlimit, &ancientlimit, &maxclockdiff);

        upmsg = newstrbuffer(0);

        if (load1 > loadred) {
                cpucolor = COL_RED;
                addtobuffer(upmsg, "&red Load is CRITICAL\n");
        }
        else if (load1 > loadyellow) {
                cpucolor = COL_YELLOW;
                addtobuffer(upmsg, "&yellow Load is HIGH\n");
        }

        if ((uptimesecs != -1) && (recentlimit != -1) && (uptimesecs < recentlimit)) {
                if (cpucolor == COL_GREEN) cpucolor = COL_YELLOW;
                addtobuffer(upmsg, "&yellow Machine recently rebooted\n");
        }
        if ((uptimesecs != -1) && (ancientlimit != -1) && (uptimesecs > ancientlimit)) {
                if (cpucolor == COL_GREEN) cpucolor = COL_YELLOW;
                sprintf(msgline, "&yellow Machine has been up more than %d days\n", (ancientlimit / 86400));
                addtobuffer(upmsg, msgline);
        }

        init_status(cpucolor);
        sprintf(msgline, "status %s.cpu %s %s %s %s %s\n",
                commafy(hostname), colorname(cpucolor),
                (timestr ? timestr : "<no timestamp data>"),
                loadresult,
		myupstr,
		cpuutilstr); 
        addtostatus(msgline);
        if (STRBUFLEN(upmsg)) {
                addtostrstatus(upmsg);
                addtostatus("\n");
        }

        if (fromline && !localmode) addtostatus(fromline);
        finish_status();

        freestrbuffer(upmsg);
}
Exemple #25
0
char *unlimfgets(strbuffer_t *buffer, FILE *fd)
{
	fgetsbuf_t *fg;
	size_t n;
	char *eoln = NULL;

	for (fg = fgetshead; (fg && (fg->fd != fd)); fg = fg->next) ;
	if (!fg) {
		errprintf("umlimfgets() called with bad input FD\n"); 
		return NULL;
	}

	/* End of file ? */
	if (!(fg->moretoread) && (*(fg->inbufp) == '\0')) {
		if (fg == fgetshead) {
			fgetshead = fgetshead->next;
			free(fg);
		}
		else {
			fgetsbuf_t *prev;
			for (prev = fgetshead; (prev->next != fg); prev = prev->next) ;
			prev->next = fg->next;
			free(fg);
		}
		return NULL;
	}

	/* Make sure the output buffer is empty */
	clearstrbuffer(buffer);

	while (!eoln && (fg->moretoread || *(fg->inbufp))) {
		int continued = 0;

		if (*(fg->inbufp)) {
			/* Have some data in the buffer */
			eoln = strchr(fg->inbufp, '\n');
			if (eoln) { 
				/* See if there's a continuation character just before the eoln */
				char *contchar = eoln-1;
				while ((contchar > fg->inbufp) && isspace((int)*contchar) && (*contchar != '\\')) contchar--;
				continued = (*contchar == '\\');

				if (continued) {
					*contchar = '\0';
					addtobuffer(buffer, fg->inbufp);
					fg->inbufp = eoln+1; 
					eoln = NULL;
				}
				else {
					char savech = *(eoln+1); 
					*(eoln+1) = '\0';
					addtobuffer(buffer, fg->inbufp);
					*(eoln+1) = savech; 
					fg->inbufp = eoln+1; 
				}
			}
			else {
				/* No newline in buffer, so add all of it to the output buffer */
				addtobuffer(buffer, fg->inbufp);

				/* Input buffer is now empty */
				*(fg->inbuf) = '\0';
				fg->inbufp = fg->inbuf;
			}
		}

		if (!eoln && !continued) {
			/* Get data for the input buffer */
			char *inpos = fg->inbuf;
			size_t insize = sizeof(fg->inbuf);

			/* If the last byte we read was a continuation char, we must do special stuff.
			 *
			 * Mike Romaniw discovered that if we hit an input with a newline exactly at
			 * the point of a buffer refill, then strlen(*buffer) is 0, and contchar then
			 * points before the start of the buffer. Bad. But this can only happen when
			 * the previous char WAS a newline, and hence it is not a continuation line.
			 * So the simple fix is to only do the cont-char stuff if **buffer is not NUL.
			 * Hence the test for both *buffer and **buffer.
			 */
			if (STRBUF(buffer) && *STRBUF(buffer)) {
				char *contchar = STRBUF(buffer) + STRBUFLEN(buffer) - 1;
				while ((contchar > STRBUF(buffer)) && isspace((int)*contchar) && (*contchar != '\\')) contchar--;

				if (*contchar == '\\') {
					/*
					 * Remove the cont. char from the output buffer, and stuff it into
					 * the input buffer again - so we can check if there's a new-line coming.
					 */
					strbufferchop(buffer, 1);
					*(fg->inbuf) = '\\';
					inpos++;
					insize--;
				}
			}

			n = fread(inpos, 1, insize-1, fd);
			*(inpos + n) = '\0';
			fg->inbufp = fg->inbuf;
			if (n < insize-1) fg->moretoread = 0;
		}
	}

	return STRBUF(buffer);
}
Exemple #26
0
int load_holidays(int year)
{
	static void *configholidays = NULL;
	char fn[PATH_MAX];
	FILE *fd;
	strbuffer_t *inbuf;
	holiday_t newholiday;
	xtreePos_t handle, commonhandle;
	char *setname = NULL;
	holidayset_t *commonhols;

	MEMDEFINE(fn);

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

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

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

	reset_holidays();

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

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

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

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

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

			continue;
		}

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

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

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

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

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

	stackfclose(fd);
	freestrbuffer(inbuf);

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

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

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

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

	MEMUNDEFINE(fn);
	current_year = year;

	return 0;
}
Exemple #27
0
static int http_datahandler(myconn_t *rec, int iobytes, int startoffset, int *advancestep)
{
	char *endofhdrs;
	int httpmajorver, httpminorver;
	char *xferencoding;
	int len = iobytes;
	char *bol, *buf;
	int hdrbytes, bodybytes = 0, bodyoffset, initialhdrbuflen, n;

	*advancestep = 0;

	switch (rec->httpdatastate) {
	  case HTTPDATA_HEADERS:
		initialhdrbuflen = STRBUFLEN(rec->httpheaders);
		addtobufferraw(rec->httpheaders, rec->readbuf+startoffset, (iobytes - startoffset));

check_for_endofheaders:
		/* 
		 * Now see if we have the end-of-headers delimiter.
		 * This SHOULD be <cr><lf><cr><lf>, but RFC 2616 says
		 * you SHOULD recognize just plain <lf><lf>.
		 * So try the second form, if the first one is not there.
		 */
		endofhdrs = strstr(STRBUF(rec->httpheaders), "\r\n\r\n");
		if (endofhdrs) {
			endofhdrs += 4;
		}
		else {
			endofhdrs = strstr(STRBUF(rec->httpheaders), "\n\n");
			if (endofhdrs) {
				endofhdrs += 2;
			}
		}

		if (!endofhdrs) {
			/* No more to do for now, but pass the databyte-count back to the caller for further processing. */
			return iobytes;
		}
		else {
			/* Chop the non-header section of data from the headers */
			strbufferchop(rec->httpheaders, strlen(endofhdrs));
		}


		/* We have an end-of-header delimiter, but it could be just a "100 Continue" response */
		sscanf(STRBUF(rec->httpheaders), "HTTP/%d.%d %d", &httpmajorver, &httpminorver, &rec->httpstatus);
		if (rec->httpstatus == 100) {
			/* 
			 * It's a "100"  continue-status.
			 * Just drop this set of headers, and re-do the end-of-headers check.
			 */
			strbuffer_t *newhdrbuf = newstrbuffer(0);
			addtobuffer(newhdrbuf, endofhdrs);
			freestrbuffer(rec->httpheaders);
			rec->httpheaders = newhdrbuf;
			goto check_for_endofheaders;
		}

		/* Have all the http headers now */
		rec->httpdatastate = HTTPDATA_BODY;


		/* 
		 * Find the "Transfer-encoding: " header (if there is one) to see if the transfer uses chunks,
		 * and grab "Content-Length:" to get the length of the body.
		 */
		xferencoding = NULL;
		bol = STRBUF(rec->httpheaders);
		while (bol && !xferencoding && !rec->httpcontentleft) {
			if (strncasecmp(bol, "Transfer-encoding:", 18) == 0) {
				bol += 18; bol += strspn(bol, " ");
				xferencoding = bol;
			}
			else if (strncasecmp(bol, "Content-Length:", 15) == 0) {
				bol += 15; bol += strspn(bol, " ");
				rec->httpcontentleft = atoi(bol);
			}
			else {
				bol = strchr(bol, '\n'); if (bol) bol++;
			}
		}

		if (xferencoding && (strncasecmp(xferencoding, "chunked", 7) == 0)) 
			rec->httpchunkstate = HTTP_CHUNK_INIT;
		else {
			rec->httpchunkstate = (rec->httpcontentleft > 0) ? HTTP_CHUNK_NOTCHUNKED : HTTP_CHUNK_NOTCHUNKED_NOCLEN;
		}

		/* Done with all the http header processing. Call ourselves to handle any remaining data we got after the headers */

		/* 
		 * To figure out how this works, here is the layout of rec->httpheaders. The first 
		 * (initialhdrbuflen) part is what we had before this call to http_datahandler, the 
		 * last (iobytes) part has been copied over from the current rec->buf. 
		 * endofhdrs points into rec->httpheaders. bodyoffset and bodybytes are relative,
		 * so even though the body data is in rec->buf and NOT in rec->httpheaders, we can
		 * calculate the offset and length of the body data.
		 *
		 *                                         endofhdrs
		 *                                              !
		 * !-----------------------------!----------------------------!
		 *
		 * <......initialhdrbuflen.......>
		 *                               <.........iobytes............>
		 * <...............hdrbytes.....................>
		 *                               <..bodyoffset..>
		 *                                              <..bodybytes..>
		 */
		hdrbytes = (endofhdrs - STRBUF(rec->httpheaders));
		bodyoffset = hdrbytes - initialhdrbuflen;
		bodybytes = iobytes - bodyoffset;
		http_datahandler(rec, bodybytes, bodyoffset, advancestep); 
		break;


	  case HTTPDATA_BODY:
		buf = rec->readbuf+startoffset;
		while (len > 0) {
			bodybytes = 0;

			switch (rec->httpchunkstate) {
			  case HTTP_CHUNK_NOTCHUNKED:
			  case HTTP_CHUNK_NOTCHUNKED_NOCLEN:
				bodybytes = len;
				break;

			  case HTTP_CHUNK_INIT:
				/* We're about to pick up a chunk length */
				rec->httpleftinchunk = 0;
				rec->httpchunkstate = HTTP_CHUNK_GETLEN;
				break;

			  case HTTP_CHUNK_GETLEN:
				/* We are collecting the length of the chunk */
				n = hexvalue(*buf);
				if (n == -1) {
					rec->httpchunkstate = HTTP_CHUNK_SKIPLENCR;
				}
				else {
					rec->httpleftinchunk = rec->httpleftinchunk*16 + n;
					buf++; len--;
				}
				break;
				
			  case HTTP_CHUNK_SKIPLENCR:
				/* We've got the length, now skip to the next LF */
				if (*buf == '\n') {
					buf++; len--; 
					rec->httpchunkstate = ((rec->httpleftinchunk > 0) ? HTTP_CHUNK_DATA : HTTP_CHUNK_NOMORE);
				}
				else if ((*buf == '\r') || (*buf == ' ')) {
					buf++; len--;
				}
				else {
					errprintf("Yikes - strange data following chunk len. Saw a '%c'\n", *buf);
					buf++; len--;
				}
				break;

			  case HTTP_CHUNK_DATA:
				/* Passing off the data */
				bodybytes = (len > rec->httpleftinchunk) ? rec->httpleftinchunk : len;
				rec->httpleftinchunk -= bodybytes;
				if (rec->httpleftinchunk == 0) rec->httpchunkstate = HTTP_CHUNK_SKIPENDCR;
				break;

			  case HTTP_CHUNK_SKIPENDCR:
				/* Skip CR/LF after a chunk */
				if (*buf == '\n') {
					buf++; len--; rec->httpchunkstate = HTTP_CHUNK_DONE;
				}
				else if (*buf == '\r') {
					buf++; len--;
				}
				else {
					errprintf("Yikes - strange data following chunk data. Saw a '%c'\n", *buf);
					buf++; len--;
				}
				break;

			  case HTTP_CHUNK_DONE:
				/* One chunk is done, continue with the next */
				rec->httpchunkstate = HTTP_CHUNK_GETLEN;
				break;

			  case HTTP_CHUNK_NOMORE:
				/* All chunks done. Skip the rest (trailers) */
				len = 0;
				break;
			}

			/* bodybytes holds the number of bytes data from buf that should go to userspace */
			if (bodybytes > 0) {
				addtobufferraw(rec->httpbody, buf, bodybytes);
				buf += bodybytes;
				len -= bodybytes;
				if ((rec->httpcontentleft > 0) && (rec->httpcontentleft >= bodybytes)) rec->httpcontentleft -= bodybytes;
				dbgprintf("HTTP bodybytes %d, %d bytes left\n", bodybytes, rec->httpcontentleft);
			}
		}

		/* Done processing body content. Now see if we have all of it - if we do, then proceed to next step. */
		dbgprintf("http chunkstate: %d\n",rec->httpchunkstate);
		switch (rec->httpchunkstate) {
		  case HTTP_CHUNK_NOTCHUNKED:
			if (rec->httpcontentleft <= 0) *advancestep = 1;
			break;

		  case HTTP_CHUNK_NOTCHUNKED_NOCLEN:
			/* We have no content-length: header, so keep going until we do two NULL-reads */
			if ((rec->httplastbodyread == 0) && (bodybytes == 0))
				*advancestep = 1;
			else
				rec->httplastbodyread = bodybytes;
			break;

		  case HTTP_CHUNK_NOMORE:
			*advancestep = 1;
			break;

		  default:
			break;
		}

		break;
	}


	return iobytes;
}
Exemple #28
0
static void loadtests(void)
{
	static time_t lastupdate = 0;
	static char *fn = NULL;
	struct stat st;
	FILE *fd;
	strbuffer_t *inbuf;

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

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

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

	flush_testlist();

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

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

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

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

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

	stackfclose(fd);
	freestrbuffer(inbuf);
}
Exemple #29
0
int do_external_rrd(char *hostname, char *testname, char *classname, char *pagepaths, char *msg, time_t tstamp) 
{ 
	pid_t childpid;

	dbgprintf("-> do_external(%s, %s)\n", hostname, testname);

	childpid = fork();
	if (childpid == 0) {
		FILE *fd;
		char fn[PATH_MAX];
		enum { R_DEFS, R_FN, R_DATA, R_NEXT } pstate;
		FILE *extfd;
		char extcmd[2*PATH_MAX];
		strbuffer_t *inbuf;
		char *p;
		char **params = NULL;
		int paridx = 0;
		pid_t mypid = getpid();
		
		MEMDEFINE(fn); MEMDEFINE(extcmd);

		sprintf(fn, "%s/rrd_msg_%d", xgetenv("XYMONTMP"), (int) getpid());
		dbgprintf("%09d : Saving msg to file %s\n", (int)mypid, fn);

		fd = fopen(fn, "w");
		if (fd == NULL) {
			errprintf("Cannot create temp file %s\n", fn);
			exit(1);
		}
		if (fwrite(msg, strlen(msg), 1, fd) != 1) {
			errprintf("Error writing to file %s: %s\n", fn, strerror(errno));
			exit(1) ;
		}
		if (fclose(fd)) errprintf("Error closing file %s: %s\n", fn, strerror(errno));

		/* 
		 * Disable the RRD update cache.
		 * We cannot use the cache, because this child
		 * process terminates without flushing the cache,
		 * and it cannot feed the update-data back to the
		 * parent process which owns the cache. So using
		 * an external handler means the updates will be
		 * sync'ed to disk immediately.
		 *
		 * NB: It is OK to do this now and not re-enable it,
		 * since we're running in the external helper
		 * child process - so this only affects the current
		 * update.
		 *
		 * Thanks to Graham Nayler for the analysis.
		 */
		use_rrd_cache = 0;

		inbuf = newstrbuffer(0);

		/* Now call the external helper */
		sprintf(extcmd, "%s %s %s %s", exthandler, hostname, testname, fn);
		dbgprintf("%09d : Calling helper script %s\n", (int)mypid, extcmd);
		extfd = popen(extcmd, "r");
		if (extfd) {
			pstate = R_DEFS;
			initfgets(extfd);

			while (unlimfgets(inbuf, extfd)) {
				p = strchr(STRBUF(inbuf), '\n'); if (p) *p = '\0';
				dbgprintf("%09d : Helper input '%s'\n", (int)mypid, STRBUF(inbuf));
				if (STRBUFLEN(inbuf) == 0) continue;

				if (pstate == R_NEXT) {
					/* After doing one set of data, allow script to re-use the same DS defs */
					if (strncasecmp(STRBUF(inbuf), "DS:", 3) == 0) {
						/* New DS definitions, scratch the old ones */
						if (params) {
							for (paridx=0; (params[paridx] != NULL); paridx++) 
								xfree(params[paridx]);
							xfree(params);
							params = NULL;
						}
						pstate = R_DEFS;
					}
					else pstate = R_FN;
				}

				switch (pstate) {
				  case R_DEFS:
					if (params == NULL) {
						params = (char **)calloc(1, sizeof(char *));
						paridx = 0;
					}

					if (strncasecmp(STRBUF(inbuf), "DS:", 3) == 0) {
						/* Dataset definition */
						params[paridx] = strdup(STRBUF(inbuf));
						paridx++;
						params = (char **)realloc(params, (1 + paridx)*sizeof(char *));
						params[paridx] = NULL;
						break;
					}
					else {
						/* No more DS defs */
						pstate = R_FN;
					}
					/* Fall through */
				  case R_FN:
					setupfn("%s", STRBUF(inbuf));
					pstate = R_DATA;
					break;

				  case R_DATA:
					snprintf(rrdvalues, sizeof(rrdvalues)-1, "%d:%s", (int)tstamp, STRBUF(inbuf));
					rrdvalues[sizeof(rrdvalues)-1] = '\0';
					create_and_update_rrd(hostname, testname, classname, pagepaths, params, NULL);
					pstate = R_NEXT;
					break;

				  case R_NEXT:
					/* Should not happen */
					break;
				}
			}
			pclose(extfd);
		}
		else {
			errprintf("Pipe open of RRD handler failed: %s\n", strerror(errno));
		}

		if (params) {
			for (paridx=0; (params[paridx] != NULL); paridx++) xfree(params[paridx]);
			xfree(params);
		}

		dbgprintf("%09d : Unlinking temp file\n", (int)mypid);
		unlink(fn);
		freestrbuffer(inbuf);

		exit(0);
	}
	else if (childpid > 0) {
		/* Parent continues */
	}
	else {
		errprintf("Fork failed in RRD handler: %s\n", strerror(errno));
	}

	dbgprintf("<- do_external(%s, %s)\n", hostname, testname);
	return 0;
}
Exemple #30
0
char *bbh_item(void *hostin, enum bbh_item_t item)
{
	static char *result;
	static char intbuf[10];
	static char *inttxt = NULL;
	static strbuffer_t *rawtxt = NULL;
	char *p;
	namelist_t *host = (namelist_t *)hostin;
	namelist_t *hwalk;

	if (rawtxt == NULL) rawtxt = newstrbuffer(0);
	if (inttxt == NULL) inttxt = (char *)malloc(10);

	if (host == NULL) return NULL;

	switch (item) {
	  case BBH_CLIENTALIAS: 
		  return host->clientname;

	  case BBH_IP:
		  return host->ip;

	  case BBH_CLASS:
		  if (host->classname) return host->classname;
		  else return bbh_find_item(host, item);
		  break;

	  case BBH_OS:
		  if (host->osname) return host->osname;
		  else return bbh_find_item(host, item);
		  break;

	  case BBH_HOSTNAME: 
		  return host->bbhostname;

	  case BBH_PAGENAME:
		  p = strrchr(host->page->pagepath, '/');
		  if (p) return (p+1); else return host->page->pagepath;

	  case BBH_PAGEPATH:
		  return host->page->pagepath;

	  case BBH_PAGETITLE:
		  p = strrchr(host->page->pagetitle, '/');
		  if (p) return (p+1);
		  /* else: Fall through */

	  case BBH_PAGEPATHTITLE:
		  if (strlen(host->page->pagetitle)) return host->page->pagetitle;
		  return "Top Page";

	  case BBH_PAGEINDEX:
		  sprintf(intbuf, "%d", host->pageindex);
		  return intbuf;

	  case BBH_ALLPAGEPATHS:
		  if (rawtxt) clearstrbuffer(rawtxt);
		  hwalk = host;
		  while (hwalk && (strcmp(hwalk->bbhostname, host->bbhostname) == 0)) {
			if (STRBUFLEN(rawtxt) > 0) addtobuffer(rawtxt, ",");
			addtobuffer(rawtxt, hwalk->page->pagepath);
			hwalk = hwalk->next;
		  }
		  return STRBUF(rawtxt);

	  case BBH_GROUPID:
		  return host->groupid;

	  case BBH_DOCURL:
		  p = bbh_find_item(host, item);
		  if (p) {
			if (result) xfree(result);
			result = (char *)malloc(strlen(p) + strlen(host->bbhostname) + 1);
			sprintf(result, p, host->bbhostname);
		  	return result;
		  }
		  else
			return NULL;

	  case BBH_DOWNTIME:
		  if (host->downtime)
			  return host->downtime;
		  else if (host->defaulthost)
			  return host->defaulthost->downtime;
		  else
			  return NULL;

	  case BBH_RAW:
		  if (rawtxt) clearstrbuffer(rawtxt);
		  p = bbh_item_walk(host);
		  while (p) {
			  addtobuffer(rawtxt, nlencode(p));
			  p = bbh_item_walk(NULL);
			  if (p) addtobuffer(rawtxt, "|");
		  }
		  return STRBUF(rawtxt);

	  case BBH_HOLIDAYS:
		  p = bbh_find_item(host, item);
		  if (!p) p = getenv("HOLIDAYS");
		  return p;

	  case BBH_DATA:
		  return host->data;

	  default:
		  return bbh_find_item(host, item);
	}

	return NULL;
}