int do_request(void) { int color = 0; char timesincechange[100]; time_t logtime = 0, acktime = 0, disabletime = 0; char *log = NULL, *firstline = NULL, *sender = NULL, *clientid = NULL, *flags = NULL; /* These are free'd */ char *restofmsg = NULL, *ackmsg = NULL, *dismsg = NULL, *acklist=NULL; /* These are just used */ int ishtmlformatted = 0; int clientavail = 0; char *ip, *displayname; if (parse_query() != 0) return 1; { char *s; s = xgetenv("CLIENTLOGS"); if (s) { hostdatadir = (char *)malloc(strlen(s) + strlen(hostname) + 12); sprintf(hostdatadir, "%s/%s", s, hostname); } else { s = xgetenv("BBVAR"); hostdatadir = (char *)malloc(strlen(s) + strlen(hostname) + 12); sprintf(hostdatadir, "%s/hostdata/%s", s, hostname); } } if (outform == FRM_CLIENT) { if (source == SRC_HOBBITD) { char *hobbitdreq; int hobbitdresult; hobbitdreq = (char *)malloc(1024 + strlen(hostname) + (service ? strlen(service) : 0)); sprintf(hobbitdreq, "clientlog %s", hostname); if (service && *service) sprintf(hobbitdreq + strlen(hobbitdreq), " section=%s", service); hobbitdresult = sendmessage(hobbitdreq, NULL, NULL, &log, 1, BBTALK_TIMEOUT); if (hobbitdresult != BB_OK) { char errtxt[4096]; sprintf(errtxt, "Status not available: Req=%s, result=%d\n", hobbitdreq, hobbitdresult); errormsg(errtxt); return 1; } } else if (source == SRC_HISTLOGS) { char logfn[PATH_MAX]; FILE *fd; sprintf(logfn, "%s/%s", hostdatadir, tstamp); fd = fopen(logfn, "r"); if (fd) { struct stat st; int n; fstat(fileno(fd), &st); log = (char *)malloc(st.st_size + 1); n = fread(log, 1, st.st_size, fd); if (n >= 0) *(log+n) = '\0'; else *log = '\0'; fclose(fd); } } restofmsg = (log ? log : strdup("<No data>\n")); } else if ((strcmp(service, xgetenv("TRENDSCOLUMN")) == 0) || (strcmp(service, xgetenv("INFOCOLUMN")) == 0)) { loadhostdata(hostname, &ip, &displayname); ishtmlformatted = 1; sethostenv(displayname, ip, service, colorname(COL_GREEN), hostname); sethostenv_refresh(600); color = COL_GREEN; logtime = time(NULL); strcpy(timesincechange, "0 minutes"); if (strcmp(service, xgetenv("TRENDSCOLUMN")) == 0) { log = restofmsg = generate_trends(hostname); } else if (strcmp(service, xgetenv("INFOCOLUMN")) == 0) { log = restofmsg = generate_info(hostname); } } else if (source == SRC_HOBBITD) { char hobbitdreq[1024]; int hobbitdresult; char *items[20]; int icount; time_t logage, clntstamp; char *sumline, *msg, *p; sprintf(hobbitdreq, "hobbitdlog host=%s test=%s fields=hostname,testname,color,flags,lastchange,logtime,validtime,acktime,disabletime,sender,cookie,ackmsg,dismsg,client,acklist,BBH_IP,BBH_DISPLAYNAME,clntstamp", hostname, service); hobbitdresult = sendmessage(hobbitdreq, NULL, NULL, &log, 1, BBTALK_TIMEOUT); if ((hobbitdresult != BB_OK) || (log == NULL) || (strlen(log) == 0)) { errormsg("Status not available\n"); return 1; } sumline = log; p = strchr(log, '\n'); *p = '\0'; msg = (p+1); p = strchr(msg, '\n'); if (!p) { firstline = strdup(msg); restofmsg = NULL; } else { *p = '\0'; firstline = strdup(msg); restofmsg = (p+1); *p = '\n'; } memset(items, 0, sizeof(items)); p = gettok(sumline, "|"); icount = 0; while (p && (icount < 20)) { items[icount++] = p; p = gettok(NULL, "|"); } /* * hostname, [0] * testname, [1] * color, [2] * flags, [3] * lastchange, [4] * logtime, [5] * validtime, [6] * acktime, [7] * disabletime, [8] * sender, [9] * cookie, [10] * ackmsg, [11] * dismsg, [12] * client, [13] * acklist [14] * BBH_IP [15] * BBH_DISPLAYNAME [16] * clienttstamp [17] */ color = parse_color(items[2]); flags = strdup(items[3]); logage = time(NULL) - atoi(items[4]); timesincechange[0] = '\0'; p = timesincechange; if (logage > 86400) p += sprintf(p, "%d days,", (int) (logage / 86400)); p += sprintf(p, "%d hours, %d minutes", (int) ((logage % 86400) / 3600), (int) ((logage % 3600) / 60)); logtime = atoi(items[5]); if (items[7] && strlen(items[7])) acktime = atoi(items[7]); if (items[8] && strlen(items[8])) disabletime = atoi(items[8]); sender = strdup(items[9]); if (items[11] && strlen(items[11])) ackmsg = items[11]; if (ackmsg) nldecode(ackmsg); if (items[12] && strlen(items[12])) dismsg = items[12]; if (dismsg) nldecode(dismsg); if (items[13]) clientavail = (*items[13] == 'Y'); acklist = ((items[14] && *items[14]) ? strdup(items[14]) : NULL); ip = (items[15] ? items[15] : ""); displayname = ((items[16] && *items[16]) ? items[16] : hostname); clntstamp = ((items[17] && *items[17]) ? atol(items[17]) : 0); sethostenv(displayname, ip, service, colorname(COL_GREEN), hostname); sethostenv_refresh(60); } else if (source == SRC_HISTLOGS) { char logfn[PATH_MAX]; struct stat st; int fd; /* * Some clients (Unix disk reports) dont have a newline before the * "Status unchanged in ..." text. Most do, but at least Solaris and * AIX do not. So just look for the text, not the newline. */ char *statusunchangedtext = "Status unchanged in "; char *receivedfromtext = "Message received from "; char *clientidtext = "Client data ID "; char *p, *unchangedstr, *receivedfromstr, *clientidstr, *hostnamedash; int n; if (!tstamp) errormsg("Invalid request"); loadhostdata(hostname, &ip, &displayname); hostnamedash = strdup(hostname); p = hostnamedash; while ((p = strchr(p, '.')) != NULL) *p = '_'; p = hostnamedash; while ((p = strchr(p, ',')) != NULL) *p = '_'; sprintf(logfn, "%s/%s/%s/%s", xgetenv("BBHISTLOGS"), hostnamedash, service, tstamp); xfree(hostnamedash); p = tstamp; while ((p = strchr(p, '_')) != NULL) *p = ' '; sethostenv_histlog(tstamp); if (stat(logfn, &st) == -1) { errormsg("Historical status log not available\n"); return 1; } fd = open(logfn, O_RDONLY); if (fd < 0) { errormsg("Unable to access historical logfile\n"); return 1; } log = (char *)malloc(st.st_size+1); n = read(fd, log, st.st_size); if (n >= 0) *(log+n) = '\0'; else *log = '\0'; close(fd); p = strchr(log, '\n'); if (!p) { firstline = strdup(log); restofmsg = NULL; } else { *p = '\0'; firstline = strdup(log); restofmsg = (p+1); *p = '\n'; } color = parse_color(log); p = strstr(log, "<!-- [flags:"); if (p) { p += strlen("<!-- [flags:"); n = strspn(p, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); flags = (char *)malloc(n+1); strncpy(flags, p, n); *(flags + n) = '\0'; } timesincechange[0] = '\0'; p = clientidstr = strstr(restofmsg, clientidtext); if (p) { p += strlen(clientidtext); n = strspn(p, "0123456789"); clientid = (char *)malloc(n+1); strncpy(clientid, p, n); *(clientid+n) = '\0'; } p = unchangedstr = strstr(restofmsg, statusunchangedtext); if (p) { p += strlen(statusunchangedtext); n = strcspn(p, "\n"); if (n >= sizeof(timesincechange)) n = sizeof(timesincechange); strncpy(timesincechange, p, n); timesincechange[n] = '\0'; } p = receivedfromstr = strstr(restofmsg, receivedfromtext); if (p) { p += strlen(receivedfromtext); n = strspn(p, "0123456789."); sender = (char *)malloc(n+1); strncpy(sender, p, n); *(sender+n) = '\0'; } /* Kill the "Status unchanged ..." and "Message received ..." lines */ if (unchangedstr) *unchangedstr = '\0'; if (receivedfromstr) *receivedfromstr = '\0'; } if (outform == FRM_CLIENT) { fprintf(stdout, "Content-type: text/plain\n\n"); fprintf(stdout, "%s", restofmsg); } else { if (clientid && (source == SRC_HISTLOGS)) { char logfn[PATH_MAX]; struct stat st; sprintf(logfn, "%s/%s", hostdatadir, clientid); clientavail = (stat(logfn, &st) == 0); if (clientavail) { sprintf(clienturi + strlen(clienturi), "&TIMEBUF=%s", clientid); } } fprintf(stdout, "Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); generate_html_log(hostname, displayname, service, ip, color, (sender ? sender : "Hobbit"), (flags ? flags : ""), logtime, timesincechange, (firstline ? firstline : ""), (restofmsg ? restofmsg : ""), acktime, ackmsg, acklist, disabletime, dismsg, (source == SRC_HISTLOGS), wantserviceid, ishtmlformatted, (source == SRC_HOBBITD), multigraphs, (clientavail ? clienturi : NULL), nkprio, nkttgroup, nkttextra, stdout); } /* Cleanup CGI params */ if (hostname) xfree(hostname); if (service) xfree(service); if (tstamp) xfree(tstamp); /* Cleanup main vars */ if (clientid) xfree(clientid); if (sender) xfree(sender); if (flags) xfree(flags); if (firstline) xfree(firstline); if (log) xfree(log); return 0; }
int loadstatus(int maxprio, time_t maxage, int mincolor, int wantacked) { char *board, *bol, *eol; time_t now; /* * We leak memory by dup'ing this and not freeing it. * But we cannot free it, because the tree holding the data * for later printing contains pointers into this string buffer. */ board = strdup(boardmaster); now = getcurrenttime(NULL); treecount++; if (treecount == 1) { rbstate = malloc(sizeof(void *)); hostsonpage = malloc(sizeof(void *)); } else { rbstate = realloc(rbstate, (treecount) * sizeof(void *)); hostsonpage = realloc(hostsonpage, (treecount) * sizeof(void *)); } rbstate[treecount-1] = xtreeNew(strcasecmp); hostsonpage[treecount-1] = xtreeNew(strcasecmp); bol = board; while (bol && (*bol)) { char *endkey; eol = strchr(bol, '\n'); if (eol) *eol = '\0'; /* Find the config entry */ endkey = strchr(bol, '|'); if (endkey) endkey = strchr(endkey+1, '|'); if (endkey) { critconf_t *cfg; char *ackstr, *ackrtimestr, *ackvtimestr, *acklevelstr, *ackbystr, *ackmsgstr; *endkey = '\0'; cfg = get_critconfig(bol, CRITCONF_TIMEFILTER, NULL); *endkey = '|'; if (cfg) { hstatus_t *newitem = (hstatus_t *)calloc(1, sizeof(hstatus_t)); newitem->config = cfg; newitem->hostname = gettok(bol, "|"); newitem->testname = gettok(NULL, "|"); newitem->color = parse_color(gettok(NULL, "|")); newitem->lastchange = atoi(gettok(NULL, "|")); newitem->logtime = atoi(gettok(NULL, "|")); newitem->validtime = atoi(gettok(NULL, "|")); ackstr = gettok(NULL, "|"); ackrtimestr = ackvtimestr = acklevelstr = ackbystr = ackmsgstr = NULL; if (ackstr) { nldecode(ackstr); ackrtimestr = strtok(ackstr, ":"); if (ackrtimestr) ackvtimestr = strtok(NULL, ":"); if (ackvtimestr) acklevelstr = strtok(NULL, ":"); if (acklevelstr) ackbystr = strtok(NULL, ":"); if (ackbystr) ackmsgstr = strtok(NULL, ":"); } if ( (hostinfo(newitem->hostname) == NULL) || ((newitem->config->priority > maxprio) && (newitem->config->priority != 99)) || ((now - newitem->lastchange) > maxage) || (newitem->color < mincolor) || (ackmsgstr && !wantacked) ) { xfree(newitem); } else { if (ackvtimestr && ackbystr && ackmsgstr) { newitem->acktime = atoi(ackvtimestr); newitem->ackedby = strdup(ackbystr); newitem->ackmsg = strdup(ackmsgstr); } newitem->key = (char *)malloc(strlen(newitem->hostname) + strlen(newitem->testname) + 2); sprintf(newitem->key, "%s|%s", newitem->hostname, newitem->testname); xtreeAdd(rbstate[treecount-1], newitem->key, newitem); } } } bol = (eol ? (eol+1) : NULL); } return 0; }
int main(int argc, char *argv[]) { char *msg; int running; int argi, seq; char newmsg[4096]; /* Handle program options. */ for (argi = 1; (argi < argc); argi++) { if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (strncmp(argv[argi], "--peer=", 7) == 0) { char *ip = strchr(argv[argi], '=') + 1; if (!peers) { peercount = 1; peers = (char **)calloc((peercount + 1), sizeof(char *)); peers[peercount-1] = strdup(ip); peers[peercount] = NULL; } else { peercount++; peers = (char **)realloc(peers, (peercount + 1)*sizeof(char *)); peers[peercount-1] = strdup(ip); peers[peercount] = NULL; } } else if (strncmp(argv[argi], "--channel=", 10) == 0) { channelname = strdup(strchr(argv[argi], '=') + 1); } } if (!peers) { errprintf("No peers specified, aborting\n"); return 1; } save_errbuf = 0; signal(SIGCHLD, SIG_IGN); running = 1; while (running) { char *eoln, *p; char *metadata[MAX_META+1]; int metacount; *newmsg = '\0'; msg = get_xymond_message(C_LAST, argv[0], &seq, NULL); /* Split the message in the first line (with meta-data), and the rest. We're only interested in the first line. */ eoln = strchr(msg, '\n'); if (eoln) *eoln = '\0'; metacount = 0; memset(&metadata, 0, sizeof(metadata)); p = gettok(msg, "|"); while (p && (metacount < MAX_META)) { metadata[metacount++] = p; p = gettok(NULL, "|"); } metadata[metacount] = NULL; if ((msg == NULL) || (strncmp(metadata[0], "@@shutdown", 10) == 0)) { printf("Shutting down\n"); running = 0; continue; } else if (strncmp(metadata[0], "@@logrotate", 11) == 0) { char *fn = xgetenv("XYMONCHANNEL_LOGFILENAME"); if (fn && strlen(fn)) { reopen_file(fn, "a", stdout); reopen_file(fn, "a", stderr); } continue; } else if ((metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) { snprintf(newmsg, sizeof(newmsg)-1, "drop %s", metadata[3]); } else if ((metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) { snprintf(newmsg, sizeof(newmsg)-1, "drop %s %s", metadata[3], metadata[4]); } else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) { snprintf(newmsg, sizeof(newmsg)-1, "rename %s %s", metadata[3], metadata[4]); } else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) { snprintf(newmsg, sizeof(newmsg)-1, "rename %s %s %s", metadata[3], metadata[4], metadata[5]); } else if ((metacount > 5) && (strncmp(metadata[0], "@@enadis", 8) == 0)) { /* @@enadis|timestamp|sender|hostname|testname|expiretime|message */ if (strcmp(metadata[5], "0") == 0) { snprintf(newmsg, sizeof(newmsg)-1, "enable %s.%s", metadata[3], metadata[4]); } else { long int distime; /* Disable until OK has time -1; normal disables has a count of minutes */ distime = (strcmp(metadata[5], "-1") == 0) ? -1 : ((atol(metadata[5]) - time(NULL)) / 60); snprintf(newmsg, sizeof(newmsg)-1, "disable %s.%s %ld", metadata[3], metadata[4], distime); if (metadata[6] && strlen(metadata[6])) { nldecode(metadata[6]); sprintf(newmsg + strlen(newmsg), " %s", metadata[6]); } dbgprintf("Disable: %s\n", newmsg); } } if (strlen(newmsg) > 0) { int i; for (i = 0; (i < peercount); i++) sendmessage(newmsg, peers[i], XYMON_TIMEOUT, NULL); } } return 0; }
void load_checkpoint(char *filename) { char *subfn; FILE *fd; strbuffer_t *inbuf; char statuscmd[1024]; char *statusbuf = NULL; sendreturn_t *sres; fd = fopen(filename, "r"); if (fd == NULL) return; sprintf(statuscmd, "xymondboard color=%s fields=hostname,testname,color", xgetenv("ALERTCOLORS")); sres = newsendreturnbuf(1, NULL); sendmessage(statuscmd, NULL, XYMON_TIMEOUT, sres); statusbuf = getsendreturnstr(sres, 1); freesendreturnbuf(sres); initfgets(fd); inbuf = newstrbuffer(0); while (unlimfgets(inbuf, fd)) { char *item[20], *p; int i; sanitize_input(inbuf, 0, 0); i = 0; p = gettok(STRBUF(inbuf), "|"); while (p && (i < 20)) { item[i++] = p; p = gettok(NULL, "|"); } if (i == 9) { /* There was no ack message */ item[i++] = ""; } if (i > 9) { char *valid = NULL; activealerts_t *newalert = (activealerts_t *)calloc(1, sizeof(activealerts_t)); newalert->hostname = find_name(hostnames, item[0]); newalert->testname = find_name(testnames, item[1]); newalert->location = find_name(locations, item[2]); newalert->ip = strdup(item[3]); newalert->color = newalert->maxcolor = parse_color(item[4]); newalert->eventstart = (time_t) atoi(item[5]); newalert->nextalerttime = (time_t) atoi(item[6]); newalert->state = A_PAGING; if (statusbuf) { char *key; key = (char *)malloc(strlen(newalert->hostname) + strlen(newalert->testname) + 100); sprintf(key, "\n%s|%s|%s\n", newalert->hostname, newalert->testname, colorname(newalert->color)); valid = strstr(statusbuf, key); if (!valid && (strncmp(statusbuf, key+1, strlen(key+1)) == 0)) valid = statusbuf; xfree(key); } if (!valid) { errprintf("Stale alert for %s:%s dropped\n", newalert->hostname, newalert->testname); xfree(newalert); continue; } while (strcmp(item[7], statename[newalert->state]) && (newalert->state < A_DEAD)) newalert->state++; /* Config might have changed while we were down */ if (newalert->state == A_NORECIP) newalert->state = A_PAGING; newalert->pagemessage = newalert->ackmessage = NULL; if (strlen(item[8])) { nldecode(item[8]); newalert->pagemessage = strdup(item[8]); } if (strlen(item[9])) { nldecode(item[9]); newalert->ackmessage = strdup(item[9]); } add_active(newalert->hostname, newalert); } } fclose(fd); freestrbuffer(inbuf); subfn = (char *)malloc(strlen(filename)+5); sprintf(subfn, "%s.sub", filename); load_state(subfn, statusbuf); xfree(subfn); if (statusbuf) xfree(statusbuf); }
int main(int argc, char *argv[]) { char *envarea = NULL; char *server = NULL; char *cookie, *pagefilter = ""; char *filter = NULL; char *heading = NULL; int showcolors = 1; int showcolumn = 0; int addlink = 0; int allhosts = 0; int summary = 0; int embedded = 0; char *req, *board, *l; int argi, res; sendreturn_t *sres; init_timestamp(); for (argi=1; (argi < argc); argi++) { 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); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if ( argnmatch(argv[argi], "--column=") || argnmatch(argv[argi], "--test=")) { char *p = strchr(argv[argi], '='); int needed; needed = 10 + strlen(p); if (filter) needed += strlen(filter); filter = (char *)(filter ? realloc(filter, needed) : calloc(1, needed)); sprintf(filter + strlen(filter), " test=%s", p+1); if (!heading) { heading = (char *)malloc(1024 + strlen(p) + strlen(timestamp)); sprintf(heading, "%s report on %s", p+1, timestamp); } } else if (argnmatch(argv[argi], "--filter=")) { char *p = strchr(argv[argi], '='); int needed; needed = 10 + strlen(p); if (filter) needed += strlen(filter); filter = (char *)(filter ? realloc(filter, needed) : calloc(1, needed)); sprintf(filter + strlen(filter), " %s", p+1); } else if (argnmatch(argv[argi], "--heading=")) { char *p = strchr(argv[argi], '='); heading = strdup(p+1); } else if (strcmp(argv[argi], "--show-column") == 0) { showcolumn = 1; } else if (strcmp(argv[argi], "--show-test") == 0) { showcolumn = 1; } else if (strcmp(argv[argi], "--show-colors") == 0) { showcolors = 1; } else if (strcmp(argv[argi], "--show-summary") == 0) { summary = 1; } else if (strcmp(argv[argi], "--show-message") == 0) { summary = 0; } else if (strcmp(argv[argi], "--link") == 0) { addlink = 1; } else if (strcmp(argv[argi], "--no-colors") == 0) { showcolors = 0; } else if (strcmp(argv[argi], "--all") == 0) { allhosts = 1; } else if (strcmp(argv[argi], "--embedded") == 0) { embedded = 1; } } if (!allhosts) { /* Setup the filter we use for the report */ cookie = get_cookie("pagepath"); if (cookie && *cookie) { pcre *dummy; char *re = (char *)malloc(8 + 2*strlen(cookie)); sprintf(re, "^%s$|^%s/.+", cookie, cookie); dummy = compileregex(re); if (dummy) { freeregex(dummy); pagefilter = malloc(10 + strlen(re)); sprintf(pagefilter, "page=%s", re); } } } sres = newsendreturnbuf(1, NULL); req = malloc(1024 + strlen(pagefilter) + strlen(filter)); sprintf(req, "xymondboard fields=hostname,testname,color,msg %s %s", pagefilter, filter); res = sendmessage(req, server, XYMON_TIMEOUT, sres); board = getsendreturnstr(sres, 1); freesendreturnbuf(sres); if (res != XYMONSEND_OK) return 1; if (!embedded) { printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); printf("<html><head><title>%s</title></head>\n", htmlquoted(heading)); printf("<body>"); printf("<table border=1 cellpadding=5><tr><th>%s</th><th align=left>Status</th></tr>\n", (showcolumn ? "Host/Column" : "Host")); } l = board; while (l && *l) { char *hostname, *testname = NULL, *colorstr = NULL, *msg = NULL, *p; char *eoln = strchr(l, '\n'); if (eoln) *eoln = '\0'; hostname = l; p = strchr(l, '|'); if (p) { *p = '\0'; l = testname = p+1; } p = strchr(l, '|'); if (p) { *p = '\0'; l = colorstr = p+1; } p = strchr(l, '|'); if (p) { *p = '\0'; l = msg = p+1; } if (hostname && testname && colorstr && msg) { char *msgeol; nldecode(msg); msgeol = strchr(msg, '\n'); if (msgeol) { /* Skip the first status line */ msg = msgeol + 1; } printf("<tr><td align=left valign=top><b>"); if (addlink) printf("<a href=\"%s\">%s</a>", hostsvcurl(hostname, xgetenv("INFOCOLUMN"), 1), htmlquoted(hostname)); else printf("%s", htmlquoted(hostname)); if (showcolumn) { printf("<br>"); if (addlink) printf("<a href=\"%s\">%s</a>", hostsvcurl(hostname, testname, 1), htmlquoted(testname)); else printf("%s", htmlquoted(testname)); } if (showcolors) printf(" - %s", colorstr); printf("</b></td>\n"); printf("<td><pre>\n"); if (summary) { int firstline = 1; char *bol, *eol; bol = msg; while (bol) { eol = strchr(bol, '\n'); if (eol) *eol = '\0'; if (firstline) { if (!isspace((int)*bol)) { printf("%s\n", bol); firstline = 0; } } else if ((*bol == '&') && (strncmp(bol, "&green", 6) != 0)) { printf("%s\n", bol); } bol = (eol ? eol+1 : NULL); } } else { printf("%s", msg); } printf("</pre></td></tr>\n"); } if (eoln) l = eoln+1; else l = NULL; } if (!embedded) printf("</table></body></html>\n"); return 0; }
int main(int argc, char *argv[]) { time_t starttime = time(NULL); char *histdir = NULL; char *histlogdir = NULL; char *msg; int argi, seq; int save_allevents = 1; int save_hostevents = 1; int save_statusevents = 1; int save_histlogs = 1; FILE *alleventsfd = NULL; int running = 1; struct sigaction sa; char newcol2[3]; char oldcol2[3]; MEMDEFINE(newcol2); MEMDEFINE(oldcol2); /* Dont save the error buffer */ save_errbuf = 0; if (xgetenv("BBALLHISTLOG")) save_allevents = (strcmp(xgetenv("BBALLHISTLOG"), "TRUE") == 0); if (xgetenv("BBHOSTHISTLOG")) save_hostevents = (strcmp(xgetenv("BBHOSTHISTLOG"), "TRUE") == 0); if (xgetenv("SAVESTATUSLOG")) save_histlogs = (strcmp(xgetenv("SAVESTATUSLOG"), "TRUE") == 0); for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--histdir=")) { histdir = strchr(argv[argi], '=')+1; } else if (argnmatch(argv[argi], "--histlogdir=")) { histlogdir = strchr(argv[argi], '=')+1; } else if (argnmatch(argv[argi], "--debug")) { debug = 1; } } if (xgetenv("BBHIST") && (histdir == NULL)) { histdir = strdup(xgetenv("BBHIST")); } if (histdir == NULL) { errprintf("No history directory given, aborting\n"); return 1; } if (save_histlogs && (histlogdir == NULL) && xgetenv("BBHISTLOGS")) { histlogdir = strdup(xgetenv("BBHISTLOGS")); } if (save_histlogs && (histlogdir == NULL)) { errprintf("No history-log directory given, aborting\n"); return 1; } if (save_allevents) { char alleventsfn[PATH_MAX]; MEMDEFINE(alleventsfn); sprintf(alleventsfn, "%s/allevents", histdir); alleventsfd = fopen(alleventsfn, "a"); if (alleventsfd == NULL) { errprintf("Cannot open the all-events file '%s'\n", alleventsfn); } setvbuf(alleventsfd, (char *)NULL, _IOLBF, 0); MEMUNDEFINE(alleventsfn); } /* For picking up lost children */ setup_signalhandler("hobbitd_history"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; sigaction(SIGCHLD, &sa, NULL); signal(SIGPIPE, SIG_DFL); while (running) { char *metadata[20] = { NULL, }; int metacount; char *p; char *statusdata = ""; char *hostname, *hostnamecommas, *testname, *dismsg; time_t tstamp, lastchg, disabletime, clienttstamp; int tstamp_i, lastchg_i; int newcolor, oldcolor; int downtimeactive; struct tm tstamptm; int trend; int childstat; /* Pickup any finished child processes to avoid zombies */ while (wait3(&childstat, WNOHANG, NULL) > 0) ; msg = get_hobbitd_message(C_STACHG, "hobbitd_history", &seq, NULL); if (msg == NULL) { running = 0; continue; } p = strchr(msg, '\n'); if (p) { *p = '\0'; statusdata = msg_data(p+1); } metacount = 0; memset(&metadata, 0, sizeof(metadata)); p = gettok(msg, "|"); while (p && (metacount < 20)) { metadata[metacount++] = p; p = gettok(NULL, "|"); } if ((metacount > 9) && (strncmp(metadata[0], "@@stachg", 8) == 0)) { /* @@stachg#seq|timestamp|sender|origin|hostname|testname|expiretime|color|prevcolor|changetime|disabletime|disablemsg|downtimeactive|clienttstamp */ sscanf(metadata[1], "%d.%*d", &tstamp_i); tstamp = tstamp_i; hostname = metadata[4]; testname = metadata[5]; newcolor = parse_color(metadata[7]); oldcolor = parse_color(metadata[8]); lastchg = atoi(metadata[9]); disabletime = atoi(metadata[10]); dismsg = metadata[11]; downtimeactive = (atoi(metadata[12]) > 0); clienttstamp = atoi(metadata[13]); if (newcolor == -1) { errprintf("Bad message: newcolor is unknown '%s'\n", metadata[7]); continue; } p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; if (save_statusevents) { char statuslogfn[PATH_MAX]; int logexists; FILE *statuslogfd; char oldcol[100]; char timestamp[40]; struct stat st; MEMDEFINE(statuslogfn); MEMDEFINE(oldcol); MEMDEFINE(timestamp); sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname); stat(statuslogfn, &st); statuslogfd = fopen(statuslogfn, "r+"); logexists = (statuslogfd != NULL); *oldcol = '\0'; if (logexists) { /* * There is a fair chance hobbitd has not been * running all the time while this system was monitored. * So get the time of the latest status change from the file, * instead of relying on the "lastchange" value we get * from hobbitd. This is also needed when migrating from * standard bbd to hobbitd. */ off_t pos = -1; char l[1024]; int gotit; MEMDEFINE(l); fseeko(statuslogfd, 0, SEEK_END); if (ftello(statuslogfd) > 512) { /* Go back 512 from EOF, and skip to start of a line */ fseeko(statuslogfd, -512, SEEK_END); gotit = (fgets(l, sizeof(l)-1, statuslogfd) == NULL); } else { /* Read from beginning of file */ fseeko(statuslogfd, 0, SEEK_SET); gotit = 0; } while (!gotit) { off_t tmppos = ftello(statuslogfd); time_t dur; int dur_i; if (fgets(l, sizeof(l)-1, statuslogfd)) { /* Sun Oct 10 06:49:42 2004 red 1097383782 602 */ if ((strlen(l) > 24) && (sscanf(l+24, " %s %d %d", oldcol, &lastchg_i, &dur_i) == 2) && (parse_color(oldcol) != -1)) { /* * Record the start location of the line */ pos = tmppos; lastchg = lastchg_i; dur = dur_i; } } else { gotit = 1; } } if (pos == -1) { /* * Couldnt find anything in the log. * Take lastchg from the timestamp of the logfile, * and just append the data. */ lastchg = st.st_mtime; fseeko(statuslogfd, 0, SEEK_END); } else { /* * lastchg was updated above. * Seek to where the last line starts. */ fseeko(statuslogfd, pos, SEEK_SET); } MEMUNDEFINE(l); } else { /* * Logfile does not exist. */ lastchg = tstamp; statuslogfd = fopen(statuslogfn, "a"); if (statuslogfd == NULL) { errprintf("Cannot open status historyfile '%s' : %s\n", statuslogfn, strerror(errno)); } } if (strcmp(oldcol, colorname(newcolor)) == 0) { /* We wont update history unless the color did change. */ if ((time(NULL) - starttime) > 300) { errprintf("Will not update %s - color unchanged (%s)\n", statuslogfn, oldcol); } if (hostnamecommas) xfree(hostnamecommas); if (statuslogfd) fclose(statuslogfd); MEMUNDEFINE(statuslogfn); MEMUNDEFINE(oldcol); MEMUNDEFINE(timestamp); continue; } if (statuslogfd) { if (logexists) { struct tm oldtm; /* Re-print the old record, now with the final duration */ memcpy(&oldtm, localtime(&lastchg), sizeof(oldtm)); strftime(timestamp, sizeof(timestamp), "%a %b %e %H:%M:%S %Y", &oldtm); fprintf(statuslogfd, "%s %s %d %d\n", timestamp, oldcol, (int)lastchg, (int)(tstamp - lastchg)); } /* And the new record. */ memcpy(&tstamptm, localtime(&tstamp), sizeof(tstamptm)); strftime(timestamp, sizeof(timestamp), "%a %b %e %H:%M:%S %Y", &tstamptm); fprintf(statuslogfd, "%s %s %d", timestamp, colorname(newcolor), (int)tstamp); fclose(statuslogfd); } MEMUNDEFINE(statuslogfn); MEMUNDEFINE(oldcol); MEMUNDEFINE(timestamp); } if (save_histlogs) { char *hostdash; char fname[PATH_MAX]; FILE *histlogfd; MEMDEFINE(fname); p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(fname, "%s/%s", histlogdir, hostdash); mkdir(fname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); p = fname + sprintf(fname, "%s/%s/%s", histlogdir, hostdash, testname); mkdir(fname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); p += sprintf(p, "/%s", histlogtime(tstamp)); histlogfd = fopen(fname, "w"); if (histlogfd) { /* * When a host gets disabled or goes purple, the status * message data is not changed - so it will include a * wrong color as the first word of the message. * Therefore we need to fixup this so it matches the * newcolor value. */ int txtcolor = parse_color(statusdata); char *origstatus = statusdata; if (txtcolor != -1) { fprintf(histlogfd, "%s", colorname(newcolor)); statusdata += strlen(colorname(txtcolor)); } if (dismsg && *dismsg) nldecode(dismsg); if (disabletime > 0) { fprintf(histlogfd, " Disabled until %s\n%s\n\n", ctime(&disabletime), (dismsg ? dismsg : "")); fprintf(histlogfd, "Status message when disabled follows:\n\n"); statusdata = origstatus; } else if (dismsg && *dismsg) { fprintf(histlogfd, " Planned downtime: %s\n\n", dismsg); fprintf(histlogfd, "Original status message follows:\n\n"); statusdata = origstatus; } fwrite(statusdata, strlen(statusdata), 1, histlogfd); fprintf(histlogfd, "Status unchanged in 0.00 minutes\n"); fprintf(histlogfd, "Message received from %s\n", metadata[2]); if (clienttstamp) fprintf(histlogfd, "Client data ID %d\n", (int) clienttstamp); fclose(histlogfd); } else { errprintf("Cannot create histlog file '%s' : %s\n", fname, strerror(errno)); } xfree(hostdash); MEMUNDEFINE(fname); } strncpy(oldcol2, ((oldcolor >= 0) ? colorname(oldcolor) : "-"), 2); strncpy(newcol2, colorname(newcolor), 2); newcol2[2] = oldcol2[2] = '\0'; if (oldcolor == -1) trend = -1; /* we dont know how bad it was */ else if (newcolor > oldcolor) trend = 2; /* It's getting worse */ else if (newcolor < oldcolor) trend = 1; /* It's getting better */ else trend = 0; /* Shouldn't happen ... */ if (save_hostevents) { char hostlogfn[PATH_MAX]; FILE *hostlogfd; MEMDEFINE(hostlogfn); sprintf(hostlogfn, "%s/%s", histdir, hostname); hostlogfd = fopen(hostlogfn, "a"); if (hostlogfd) { fprintf(hostlogfd, "%s %d %d %d %s %s %d\n", testname, (int)tstamp, (int)lastchg, (int)(tstamp - lastchg), newcol2, oldcol2, trend); fclose(hostlogfd); } else { errprintf("Cannot open host logfile '%s' : %s\n", hostlogfn, strerror(errno)); } MEMUNDEFINE(hostlogfn); } if (save_allevents) { fprintf(alleventsfd, "%s %s %d %d %d %s %s %d\n", hostname, testname, (int)tstamp, (int)lastchg, (int)(tstamp - lastchg), newcol2, oldcol2, trend); fflush(alleventsfd); } xfree(hostnamecommas); } else if ((metacount > 3) && ((strncmp(metadata[0], "@@drophost", 10) == 0))) { /* @@drophost|timestamp|sender|hostname */ hostname = metadata[3]; if (save_histlogs) { char *hostdash; char testdir[PATH_MAX]; MEMDEFINE(testdir); /* Remove all directories below the host-specific histlog dir */ p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(testdir, "%s/%s", histlogdir, hostdash); dropdirectory(testdir, 1); xfree(hostdash); MEMUNDEFINE(testdir); } if (save_hostevents) { char hostlogfn[PATH_MAX]; struct stat st; MEMDEFINE(hostlogfn); sprintf(hostlogfn, "%s/%s", histdir, hostname); if ((stat(hostlogfn, &st) == 0) && S_ISREG(st.st_mode)) { unlink(hostlogfn); } MEMUNDEFINE(hostlogfn); } if (save_statusevents) { DIR *dirfd; struct dirent *de; char *hostlead; char statuslogfn[PATH_MAX]; struct stat st; MEMDEFINE(statuslogfn); /* Remove bbvar/hist/host,name.* */ p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; hostlead = malloc(strlen(hostname) + 2); strcpy(hostlead, hostnamecommas); strcat(hostlead, "."); dirfd = opendir(histdir); if (dirfd) { while ((de = readdir(dirfd)) != NULL) { if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) { sprintf(statuslogfn, "%s/%s", histdir, de->d_name); if ((stat(statuslogfn, &st) == 0) && S_ISREG(st.st_mode)) { unlink(statuslogfn); } } } closedir(dirfd); } xfree(hostlead); xfree(hostnamecommas); MEMUNDEFINE(statuslogfn); } } else if ((metacount > 4) && ((strncmp(metadata[0], "@@droptest", 10) == 0))) { /* @@droptest|timestamp|sender|hostname|testname */ hostname = metadata[3]; testname = metadata[4]; if (save_histlogs) { char *hostdash; char testdir[PATH_MAX]; MEMDEFINE(testdir); p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(testdir, "%s/%s/%s", histlogdir, hostdash, testname); dropdirectory(testdir, 1); xfree(hostdash); MEMUNDEFINE(testdir); } if (save_statusevents) { char *hostnamecommas; char statuslogfn[PATH_MAX]; struct stat st; MEMDEFINE(statuslogfn); p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname); if ((stat(statuslogfn, &st) == 0) && S_ISREG(st.st_mode)) unlink(statuslogfn); xfree(hostnamecommas); MEMUNDEFINE(statuslogfn); } } else if ((metacount > 4) && ((strncmp(metadata[0], "@@renamehost", 12) == 0))) { /* @@renamehost|timestamp|sender|hostname|newhostname */ char *newhostname; hostname = metadata[3]; newhostname = metadata[4]; if (save_histlogs) { char *hostdash; char *newhostdash; char olddir[PATH_MAX]; char newdir[PATH_MAX]; MEMDEFINE(olddir); MEMDEFINE(newdir); p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; p = newhostdash = strdup(newhostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(olddir, "%s/%s", histlogdir, hostdash); sprintf(newdir, "%s/%s", histlogdir, newhostdash); rename(olddir, newdir); xfree(newhostdash); xfree(hostdash); MEMUNDEFINE(newdir); MEMUNDEFINE(olddir); } if (save_hostevents) { char hostlogfn[PATH_MAX]; char newhostlogfn[PATH_MAX]; MEMDEFINE(hostlogfn); MEMDEFINE(newhostlogfn); sprintf(hostlogfn, "%s/%s", histdir, hostname); sprintf(newhostlogfn, "%s/%s", histdir, newhostname); rename(hostlogfn, newhostlogfn); MEMUNDEFINE(hostlogfn); MEMUNDEFINE(newhostlogfn); } if (save_statusevents) { DIR *dirfd; struct dirent *de; char *hostlead; char *newhostnamecommas; char statuslogfn[PATH_MAX]; char newlogfn[PATH_MAX]; MEMDEFINE(statuslogfn); MEMDEFINE(newlogfn); p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; hostlead = malloc(strlen(hostname) + 2); strcpy(hostlead, hostnamecommas); strcat(hostlead, "."); p = newhostnamecommas = strdup(newhostname); while ((p = strchr(p, '.')) != NULL) *p = ','; dirfd = opendir(histdir); if (dirfd) { while ((de = readdir(dirfd)) != NULL) { if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) { char *testname = strchr(de->d_name, '.'); sprintf(statuslogfn, "%s/%s", histdir, de->d_name); sprintf(newlogfn, "%s/%s%s", histdir, newhostnamecommas, testname); rename(statuslogfn, newlogfn); } } closedir(dirfd); } xfree(newhostnamecommas); xfree(hostlead); xfree(hostnamecommas); MEMUNDEFINE(statuslogfn); MEMUNDEFINE(newlogfn); } } else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) { /* @@renametest|timestamp|sender|hostname|oldtestname|newtestname */ char *newtestname; hostname = metadata[3]; testname = metadata[4]; newtestname = metadata[5]; if (save_histlogs) { char *hostdash; char olddir[PATH_MAX]; char newdir[PATH_MAX]; MEMDEFINE(olddir); MEMDEFINE(newdir); p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_'; sprintf(olddir, "%s/%s/%s", histlogdir, hostdash, testname); sprintf(newdir, "%s/%s/%s", histlogdir, hostdash, newtestname); rename(olddir, newdir); xfree(hostdash); MEMUNDEFINE(newdir); MEMUNDEFINE(olddir); } if (save_statusevents) { char *hostnamecommas; char statuslogfn[PATH_MAX]; char newstatuslogfn[PATH_MAX]; MEMDEFINE(statuslogfn); MEMDEFINE(newstatuslogfn); p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ','; sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname); sprintf(newstatuslogfn, "%s/%s.%s", histdir, hostnamecommas, newtestname); rename(statuslogfn, newstatuslogfn); xfree(hostnamecommas); MEMUNDEFINE(newstatuslogfn); MEMUNDEFINE(statuslogfn); } } else if (strncmp(metadata[0], "@@shutdown", 10) == 0) { running = 0; } else if (strncmp(metadata[0], "@@logrotate", 11) == 0) { char *fn = xgetenv("HOBBITCHANNEL_LOGFILENAME"); if (fn && strlen(fn)) { freopen(fn, "a", stdout); freopen(fn, "a", stderr); } continue; } } MEMUNDEFINE(newcol2); MEMUNDEFINE(oldcol2); fclose(alleventsfd); return 0; }
int loadstatus(int maxprio, time_t maxage, int mincolor, int wantacked) { int xymondresult; char *board = NULL; char *bol, *eol; time_t now; char msg[1024]; int i; sendreturn_t *sres; sprintf(msg, "xymondboard acklevel=%d fields=hostname,testname,color,lastchange,logtime,validtime,acklist color=%s", critacklevel,colorname(mincolor)); for (i=mincolor+1; (i < COL_COUNT); i++) sprintf(msg+strlen(msg), ",%s", colorname(i)); sres = newsendreturnbuf(1, NULL); xymondresult = sendmessage(msg, NULL, XYMON_TIMEOUT, sres); if (xymondresult != XYMONSEND_OK) { freesendreturnbuf(sres); errormsg("Unable to fetch current status\n"); return 1; } else { board = getsendreturnstr(sres, 1); freesendreturnbuf(sres); } now = getcurrenttime(NULL); rbstate = rbtNew(name_compare); bol = board; while (bol && (*bol)) { char *endkey; RbtStatus status; eol = strchr(bol, '\n'); if (eol) *eol = '\0'; /* Find the config entry */ endkey = strchr(bol, '|'); if (endkey) endkey = strchr(endkey+1, '|'); if (endkey) { critconf_t *cfg; char *ackstr, *ackrtimestr, *ackvtimestr, *acklevelstr, *ackbystr, *ackmsgstr; *endkey = '\0'; cfg = get_critconfig(bol, CRITCONF_TIMEFILTER, NULL); *endkey = '|'; if (cfg) { hstatus_t *newitem = (hstatus_t *)calloc(1, sizeof(hstatus_t)); newitem->config = cfg; newitem->hostname = gettok(bol, "|"); newitem->testname = gettok(NULL, "|"); newitem->color = parse_color(gettok(NULL, "|")); newitem->lastchange = atoi(gettok(NULL, "|")); newitem->logtime = atoi(gettok(NULL, "|")); newitem->validtime = atoi(gettok(NULL, "|")); ackstr = gettok(NULL, "|"); ackrtimestr = ackvtimestr = acklevelstr = ackbystr = ackmsgstr = NULL; if (ackstr) { nldecode(ackstr); ackrtimestr = strtok(ackstr, ":"); if (ackrtimestr) ackvtimestr = strtok(NULL, ":"); if (ackvtimestr) acklevelstr = strtok(NULL, ":"); if (acklevelstr) ackbystr = strtok(NULL, ":"); if (ackbystr) ackmsgstr = strtok(NULL, ":"); } if ( (hostinfo(newitem->hostname) == NULL) || (newitem->config->priority > maxprio) || ((now - newitem->lastchange) > maxage) || (newitem->color < mincolor) || (ackmsgstr && !wantacked) ) { xfree(newitem); } else { if (ackvtimestr && ackbystr && ackmsgstr) { newitem->acktime = atoi(ackvtimestr); newitem->ackedby = strdup(ackbystr); newitem->ackmsg = strdup(ackmsgstr); } newitem->key = (char *)malloc(strlen(newitem->hostname) + strlen(newitem->testname) + 2); sprintf(newitem->key, "%s|%s", newitem->hostname, newitem->testname); status = rbtInsert(rbstate, newitem->key, newitem); } } } bol = (eol ? (eol+1) : NULL); } return 0; }
void do_acklog(FILE *output, int maxcount, int maxminutes) { FILE *acklog; char acklogfilename[PATH_MAX]; time_t cutoff; struct stat st; char l[MAX_LINE_LEN]; char title[200]; ack_t *acks; int num, ackintime_count; havedoneacklog = 1; cutoff = ( (maxminutes) ? (getcurrenttime(NULL) - maxminutes*60) : 0); if ((!maxcount) || (maxcount > 100)) maxcount = 100; sprintf(acklogfilename, "%s/acknowledge.log", xgetenv("BBSERVERLOGS")); acklog = fopen(acklogfilename, "r"); if (!acklog) { /* BB compatible naming */ sprintf(acklogfilename, "%s/acklog", xgetenv("BBACKS")); acklog = fopen(acklogfilename, "r"); } if (!acklog) { /* If no acklog, that is OK - some people dont use acks */ dbgprintf("Cannot open acklog\n"); return; } /* HACK ALERT! */ if (stat(acklogfilename, &st) == 0) { if (st.st_size != 0) { /* Assume a log entry is max 150 bytes */ if (150*maxcount < st.st_size) { fseeko(acklog, -150*maxcount, SEEK_END); fgets(l, sizeof(l), acklog); if (strchr(l, '\n') == NULL) { errprintf("Oops - couldnt find a newline in acklog\n"); } } } } acks = (ack_t *) calloc(maxcount, sizeof(ack_t)); ackintime_count = num = 0; while (fgets(l, sizeof(l), acklog)) { char ackedby[MAX_LINE_LEN], hosttest[MAX_LINE_LEN], color[10], ackmsg[MAX_LINE_LEN]; char ackfn[PATH_MAX]; char *testname; void *hinfo; int ok; if (atol(l) >= cutoff) { int c_used; char *p, *p1, *hobbitdacker = NULL; sscanf(l, "%u\t%d\t%d\t%d\t%s\t%s\t%s\t%n", (time_t *)&acks[num].acktime, &acks[num].acknum, &acks[num].duration, &acks[num].acknum2, ackedby, hosttest, color, &c_used); p1 = ackmsg; for (p=l+c_used, p1=ackmsg; (*p); ) { /* * Need to de-code the ackmsg - it may have been entered * via a web page that did "%asciival" encoding. */ if ((*p == '%') && (strlen(p) >= 3) && isxdigit((int)*(p+1)) && isxdigit((int)*(p+2))) { char hexnum[3]; hexnum[0] = *(p+1); hexnum[1] = *(p+2); hexnum[2] = '\0'; *p1 = (char) strtol(hexnum, NULL, 16); p1++; p += 3; } else { *p1 = *p; p1++; p++; } } *p1 = '\0'; /* Hobbit uses \n in the ack message, for the "acked by" data. Cut it off. */ nldecode(ackmsg); p = strchr(ackmsg, '\n'); if (p) { if (strncmp(p, "\nAcked by:", 10) == 0) hobbitdacker = p+10; *p = '\0'; } /* Show only the first 30 characters in message */ if (strlen(ackmsg) > 30) ackmsg[30] = '\0'; sprintf(ackfn, "%s/ack.%s", xgetenv("BBACKS"), hosttest); testname = strrchr(hosttest, '.'); if (testname) { *testname = '\0'; testname++; } else testname = "unknown"; ok = 1; /* Ack occurred within wanted timerange ? */ if (ok && (acks[num].acktime < cutoff)) ok = 0; /* Unknown host ? */ hinfo = hostinfo(hosttest); if (!hinfo) ok = 0; if (hinfo && bbh_item(hinfo, BBH_FLAG_NOBB2)) ok = 0; if (ok) { char *ackerp; /* If ack has expired or tag file is gone, the ack is no longer valid */ acks[num].ackvalid = 1; if ((acks[num].acktime + 60*acks[num].duration) < getcurrenttime(NULL)) acks[num].ackvalid = 0; if (acks[num].ackvalid && (stat(ackfn, &st) != 0)) acks[num].ackvalid = 0; if (strcmp(ackedby, "np_filename_not_used") != 0) { ackerp = ackedby; if (strncmp(ackerp, "np_", 3) == 0) ackerp += 3; p = strrchr(ackerp, '_'); if (p > ackerp) *p = '\0'; acks[num].ackedby = strdup(ackerp); } else if (hobbitdacker) { acks[num].ackedby = strdup(hobbitdacker); } else { acks[num].ackedby = ""; } acks[num].hostname = strdup(hosttest); acks[num].testname = strdup(testname); strcat(color, " "); acks[num].color = parse_color(color); acks[num].ackmsg = strdup(ackmsg); ackintime_count++; num = (num + 1) % maxcount; } } } if (ackintime_count > 0) { int firstack, lastack; int period = maxminutes; if (ackintime_count <= maxcount) { firstack = 0; lastack = ackintime_count-1; period = maxminutes; } else { firstack = num; lastack = ( (num == 0) ? maxcount : (num-1)); ackintime_count = maxcount; period = ((getcurrenttime(NULL)-acks[firstack].acktime) / 60); } sprintf(title, "%d events acknowledged in the past %u minutes", ackintime_count, period); fprintf(output, "<BR><BR>\n"); fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title); fprintf(output, "<TR BGCOLOR=\"#333333\">\n"); fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", title); for (num = lastack; (ackintime_count); ackintime_count--, num = ((num == 0) ? (maxcount-1) : (num - 1)) ) { fprintf(output, "<TR BGCOLOR=#000000>\n"); fprintf(output, "<TD ALIGN=CENTER><FONT COLOR=white>%s</FONT></TD>\n", ctime(&acks[num].acktime)); fprintf(output, "<TD ALIGN=CENTER BGCOLOR=%s><FONT COLOR=black>%s</FONT></TD>\n", colorname(acks[num].color), acks[num].hostname); fprintf(output, "<TD ALIGN=CENTER><FONT COLOR=white>%s</FONT></TD>\n", acks[num].testname); if (acks[num].color != -1) { fprintf(output, "<TD ALIGN=CENTER><IMG SRC=\"%s/%s\"></TD>\n", xgetenv("BBSKIN"), dotgiffilename(acks[num].color, acks[num].ackvalid, 1)); } else fprintf(output, "<TD ALIGN=CENTER><FONT COLOR=white> </FONT></TD>\n"); fprintf(output, "<TD ALIGN=LEFT BGCOLOR=#000033>%s</TD>\n", acks[num].ackedby); fprintf(output, "<TD ALIGN=LEFT>%s</TD></TR>\n", acks[num].ackmsg); } } else { sprintf(title, "No events acknowledged in the last %u minutes", maxminutes); fprintf(output, "<BR><BR>\n"); fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title); fprintf(output, "<TR BGCOLOR=\"#333333\">\n"); fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", title); } fprintf(output, "</TABLE>\n"); fclose(acklog); }
int main(int argc, char *argv[]) { char *filedir = NULL; char *htmldir = NULL; char *htmlextension = "html"; char *onlytests = NULL; char *msg; enum role_t role = ROLE_STATUS; enum msgchannels_t chnid = C_STATUS; int argi; int seq; int running = 1; /* Dont save the error buffer */ save_errbuf = 0; for (argi = 1; (argi < argc); argi++) { if (strcmp(argv[argi], "--status") == 0) { role = ROLE_STATUS; chnid = C_STATUS; if (!filedir) filedir = xgetenv("XYMONRAWSTATUSDIR"); } else if (strcmp(argv[argi], "--html") == 0) { role = ROLE_STATUS; chnid = C_STATUS; if (!htmldir) htmldir = xgetenv("XYMONHTMLSTATUSDIR"); } else if (strcmp(argv[argi], "--data") == 0) { role = ROLE_DATA; chnid = C_DATA; if (!filedir) filedir = xgetenv("XYMONDATADIR"); } else if (strcmp(argv[argi], "--notes") == 0) { role = ROLE_NOTES; chnid = C_NOTES; if (!filedir) filedir = xgetenv("XYMONNOTESDIR"); } else if (strcmp(argv[argi], "--enadis") == 0) { role = ROLE_ENADIS; chnid = C_ENADIS; if (!filedir) filedir = xgetenv("XYMONDISABLEDDIR"); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (argnmatch(argv[argi], "--dir=")) { filedir = strchr(argv[argi], '=')+1; } else if (argnmatch(argv[argi], "--htmldir=")) { htmldir = strchr(argv[argi], '=')+1; } else if (argnmatch(argv[argi], "--htmlext=")) { htmlextension = strchr(argv[argi], '=')+1; } else if (argnmatch(argv[argi], "--only=")) { char *p = strchr(argv[argi], '=') + 1; onlytests = (char *)malloc(3 + strlen(p)); sprintf(onlytests, ",%s,", p); } else if (argnmatch(argv[argi], "--multigraphs=")) { char *p = strchr(argv[argi], '='); multigraphs = (char *)malloc(strlen(p+1) + 3); sprintf(multigraphs, ",%s,", p+1); } else if (argnmatch(argv[argi], "--locator=")) { char *p = strchr(argv[argi], '='); locator_init(p+1); locatorbased = 1; } } if (filedir == NULL) { errprintf("No directory given, aborting\n"); return 1; } /* For picking up lost children */ setup_signalhandler("xymond_filestore"); signal(SIGPIPE, SIG_DFL); if (onlytests) dbgprintf("Storing tests '%s' only\n", onlytests); else dbgprintf("Storing all tests\n"); while (running) { char *metadata[20] = { NULL, }; char *statusdata = ""; char *p; int metacount; char *hostname, *testname; time_t expiretime = 0; char logfn[PATH_MAX]; MEMDEFINE(logfn); msg = get_xymond_message(chnid, "filestore", &seq, NULL); if (msg == NULL) { running = 0; MEMUNDEFINE(logfn); continue; } p = strchr(msg, '\n'); if (p) { *p = '\0'; statusdata = p+1; } metacount = 0; memset(&metadata, 0, sizeof(metadata)); p = gettok(msg, "|"); while (p && (metacount < 20)) { metadata[metacount++] = p; p = gettok(NULL, "|"); } if ((role == ROLE_STATUS) && (metacount >= 14) && (strncmp(metadata[0], "@@status", 8) == 0)) { /* @@status|timestamp|sender|origin|hostname|testname|expiretime|color|testflags|prevcolor|changetime|ackexpiretime|ackmessage|disableexpiretime|disablemessage|clientmsgtstamp|flapping */ int ltime, flapping = 0; time_t logtime = 0, timesincechange = 0, acktime = 0, disabletime = 0; hostname = metadata[4]; testname = metadata[5]; if (!wantedtest(onlytests, testname)) { dbgprintf("Status dropped - not wanted\n"); MEMUNDEFINE(logfn); continue; } sprintf(logfn, "%s/%s.%s", filedir, commafy(hostname), testname); expiretime = atoi(metadata[6]); statusdata = msg_data(statusdata); sscanf(metadata[1], "%d.%*d", <ime); logtime = ltime; timesincechange = logtime - atoi(metadata[10]); update_file(logfn, "w", statusdata, expiretime, metadata[2], timesincechange, seq); if (htmldir) { char *ackmsg = NULL; char *dismsg = NULL; char htmllogfn[PATH_MAX]; MEMDEFINE(htmllogfn); if (metadata[11]) acktime = atoi(metadata[11]); if (metadata[12] && strlen(metadata[12])) ackmsg = metadata[12]; if (ackmsg) nldecode(ackmsg); if (metadata[13]) disabletime = atoi(metadata[13]); if (metadata[14] && strlen(metadata[14]) && (disabletime > 0)) dismsg = metadata[14]; if (dismsg) nldecode(dismsg); flapping = (metadata[16] ? (*metadata[16] == '1') : 0); sprintf(htmllogfn, "%s/%s.%s.%s", htmldir, hostname, testname, htmlextension); update_htmlfile(htmllogfn, statusdata, hostname, testname, parse_color(metadata[7]), flapping, metadata[2], metadata[8], logtime, timesincechange, acktime, ackmsg, disabletime, dismsg); MEMUNDEFINE(htmllogfn); } } else if ((role == ROLE_DATA) && (metacount > 5) && (strncmp(metadata[0], "@@data", 6) == 0)) { /* @@data|timestamp|sender|hostname|testname */ p = hostname = metadata[4]; while ((p = strchr(p, '.')) != NULL) *p = ','; testname = metadata[5]; if (!wantedtest(onlytests, testname)) { dbgprintf("data dropped - not wanted\n"); MEMUNDEFINE(logfn); continue; } statusdata = msg_data(statusdata); if (*statusdata == '\n') statusdata++; sprintf(logfn, "%s/%s.%s", filedir, hostname, testname); expiretime = 0; update_file(logfn, "a", statusdata, expiretime, NULL, -1, seq); } else if ((role == ROLE_NOTES) && (metacount > 3) && (strncmp(metadata[0], "@@notes", 7) == 0)) { /* @@notes|timestamp|sender|hostname */ hostname = metadata[3]; statusdata = msg_data(statusdata); if (*statusdata == '\n') statusdata++; sprintf(logfn, "%s/%s", basename(filedir), hostname); expiretime = 0; update_file(logfn, "w", statusdata, expiretime, NULL, -1, seq); } else if ((role == ROLE_ENADIS) && (metacount > 5) && (strncmp(metadata[0], "@@enadis", 8) == 0)) { /* @@enadis|timestamp|sender|hostname|testname|expiretime */ p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ','; testname = metadata[4]; expiretime = atoi(metadata[5]); sprintf(logfn, "%s/%s.%s", filedir, hostname, testname); update_enable(logfn, expiretime); } else if (((role == ROLE_STATUS) || (role == ROLE_DATA) || (role == ROLE_ENADIS)) && (metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) { /* @@drophost|timestamp|sender|hostname */ DIR *dirfd; struct dirent *de; char *hostlead; p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ','; hostlead = malloc(strlen(hostname) + 2); strcpy(hostlead, hostname); strcat(hostlead, "."); dirfd = opendir(filedir); if (dirfd) { while ( (de = readdir(dirfd)) != NULL) { if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) { sprintf(logfn, "%s/%s", filedir, de->d_name); unlink(logfn); } } closedir(dirfd); } xfree(hostlead); } else if (((role == ROLE_STATUS) || (role == ROLE_DATA) || (role == ROLE_ENADIS)) && (metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) { /* @@droptest|timestamp|sender|hostname|testname */ p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ','; testname = metadata[4]; sprintf(logfn, "%s/%s.%s", filedir, hostname, testname); unlink(logfn); } else if (((role == ROLE_STATUS) || (role == ROLE_DATA) || (role == ROLE_ENADIS)) && (metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) { /* @@renamehost|timestamp|sender|hostname|newhostname */ DIR *dirfd; struct dirent *de; char *hostlead; char *newhostname; char newlogfn[PATH_MAX]; MEMDEFINE(newlogfn); p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ','; hostlead = malloc(strlen(hostname) + 2); strcpy(hostlead, hostname); strcat(hostlead, "."); p = newhostname = metadata[4]; while ((p = strchr(p, '.')) != NULL) *p = ','; dirfd = opendir(filedir); if (dirfd) { while ( (de = readdir(dirfd)) != NULL) { if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) { char *testname = strchr(de->d_name, '.'); sprintf(logfn, "%s/%s", filedir, de->d_name); sprintf(newlogfn, "%s/%s%s", filedir, newhostname, testname); rename(logfn, newlogfn); } } closedir(dirfd); } xfree(hostlead); MEMUNDEFINE(newlogfn); } else if (((role == ROLE_STATUS) || (role == ROLE_DATA) || (role == ROLE_ENADIS)) && (metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) { /* @@renametest|timestamp|sender|hostname|oldtestname|newtestname */ char *newtestname; char newfn[PATH_MAX]; MEMDEFINE(newfn); p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ','; testname = metadata[4]; newtestname = metadata[5]; sprintf(logfn, "%s/%s.%s", filedir, hostname, testname); sprintf(newfn, "%s/%s.%s", filedir, hostname, newtestname); rename(logfn, newfn); MEMUNDEFINE(newfn); } else if (strncmp(metadata[0], "@@shutdown", 10) == 0) { running = 0; } else if (strncmp(metadata[0], "@@logrotate", 11) == 0) { char *fn = xgetenv("XYMONCHANNEL_LOGFILENAME"); if (fn && strlen(fn)) { freopen(fn, "a", stdout); freopen(fn, "a", stderr); } continue; } else if (strncmp(metadata[0], "@@idle", 6) == 0) { /* Ignored */ } else { errprintf("Dropping message type %s, metacount=%d\n", metadata[0], metacount); } MEMUNDEFINE(logfn); } return 0; }