static void combo_flush(void) { if (!xymonmsgqueued) { dbgprintf("Flush, but xymonmsg is empty\n"); return; } if (debug) { char *p1, *p2; dbgprintf("Flushing combo message\n"); p1 = p2 = STRBUF(xymonmsg); do { p2++; p1 = strstr(p2, "\nstatus "); if (p1) { p1++; /* Skip the newline */ p2 = strchr(p1, '\n'); if (p2) *p2='\0'; printf(" %s\n", p1); if (p2) *p2='\n'; } } while (p1 && p2); } sendmessage(STRBUF(xymonmsg), NULL, XYMON_TIMEOUT, NULL); combo_start(); /* Get ready for the next */ }
void finish_status(void) { if (debug) { char *p = strchr(STRBUF(msgbuf), '\n'); if (p) *p = '\0'; dbgprintf("Adding to combo msg: %s\n", STRBUF(msgbuf)); if (p) *p = '\n'; } combo_add(msgbuf); }
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); }
void load_state(char *filename, char *statusbuf) { FILE *fd = fopen(filename, "r"); strbuffer_t *inbuf; char *p; if (fd == NULL) return; initfgets(fd); inbuf = newstrbuffer(0); while (unlimfgets(inbuf, fd)) { sanitize_input(inbuf, 0, 0); p = strchr(STRBUF(inbuf), '|'); if (p) { repeat_t *newrpt; *p = '\0'; if (atoi(STRBUF(inbuf)) > getcurrenttime(NULL)) { char *found = NULL; if (statusbuf) { char *htend; /* statusbuf contains lines with "HOSTNAME|TESTNAME|COLOR" */ htend = strchr(p+1, '|'); if (htend) htend = strchr(htend+1, '|'); if (htend) { *htend = '\0'; *p = '\n'; found = strstr(statusbuf, p); if (!found && (strncmp(statusbuf, p+1, strlen(p+1)) == 0)) found = statusbuf; *htend = '|'; } } if (!found) continue; newrpt = (repeat_t *)malloc(sizeof(repeat_t)); newrpt->recipid = strdup(p+1); newrpt->nextalert = atoi(STRBUF(inbuf)); newrpt->next = rpthead; rpthead = newrpt; } } } fclose(fd); freestrbuffer(inbuf); }
void *load_web_access_config(char *accessfn) { FILE *fd; strbuffer_t *buf; if (acctree) return 0; acctree = xtreeNew(strcasecmp); fd = stackfopen(accessfn, "r", NULL); if (fd == NULL) return NULL; buf = newstrbuffer(0); while (stackfgets(buf, NULL)) { char *group, *member; char *key; group = strtok(STRBUF(buf), ": \n"); if (!group) continue; member = strtok(NULL, ", \n"); while (member) { key = (char *)malloc(strlen(group) + strlen(member) + 2); sprintf(key, "%s %s", group, member); xtreeAdd(acctree, key, NULL); member = strtok(NULL, ", \n"); } } stackfclose(fd); return acctree; }
void send_data(void *host, char *beadomain, char *databuf, char **items) { bea_idx_t *idxwalk; strbuffer_t *msgbuf; char *p; int i; msgbuf = newstrbuffer(0); for (idxwalk = bea_idxhead; (idxwalk); idxwalk = idxwalk->next) { sprintf(msgline, "data %s.bea\n\n", commafy(bbh_item(host, BBH_HOSTNAME))); addtobuffer(msgbuf, msgline); if (beadomain && *beadomain) { sprintf(msgline, "DOMAIN:%s\n", beadomain); addtobuffer(msgbuf, msgline); } for (i=0; (items[i]); i++) { p = getstring(databuf, idxwalk->idx, items[i]); sprintf(msgline, "%s\n", p); addtobuffer(msgbuf, msgline); } sendmessage(STRBUF(msgbuf), NULL, BBTALK_TIMEOUT, NULL); clearstrbuffer(msgbuf); } freestrbuffer(msgbuf); }
char *htmlquoted(char *s) { /* * This routine converts a plain string into an html-quoted string */ static strbuffer_t *result = NULL; char *inp, *endp; char c; if (!result) result = newstrbuffer(4096); clearstrbuffer(result); inp = s; do { endp = inp + strcspn(inp, "\"&<> "); c = *endp; if (endp > inp) addtobufferraw(result, inp, endp-inp); switch (c) { case '"': addtobuffer(result, """); break; case '&': addtobuffer(result, "&"); break; case '<': addtobuffer(result, "<"); break; case '>': addtobuffer(result, ">"); break; case ' ': addtobuffer(result, " "); break; default: break; } inp = (c == '\0') ? NULL : endp+1; } while (inp); return STRBUF(result); }
static void zvm_mdc_report(char *hostname, char *clientclass, enum ostype_t os, void *hinfo, char *fromline, char *timestr, char *cpuutilstr) { char *p; int mdcreads, mdcwrites, mdchitpct; char mdcresult[100]; char msgline[256]; strbuffer_t *msg; if (!cpuutilstr) return; msg = newstrbuffer(0); /* * Looking for MDC info in 'IND' command response * MDC READS-000001/SEC WRITES-000001/SEC HIT RATIO-098% */ *mdcresult = '\0'; /* Skip past three newlines in message to the PAGING text */ p=strstr(cpuutilstr,"READS-"); if (p) { p += 6; sscanf(p, "%d/SEC", &mdcreads); p=strstr(cpuutilstr,"WRITES-") + 7; sscanf(p, "%d/SEC", &mdcwrites); p=strstr(cpuutilstr,"RATIO-") + 6; sscanf(p, "%d", &mdchitpct); sprintf(msgline, "data %s.mdc\n%s\n%d:%d:%d\n", commafy(hostname), osname(os), mdcreads, mdcwrites, mdchitpct); addtobuffer(msg, msgline); sendmessage(STRBUF(msg), NULL, BBTALK_TIMEOUT, NULL); } freestrbuffer(msg); }
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 meta_flush(void) { if (!xymonmetaqueued) { dbgprintf("Flush, but xymonmeta is empty\n"); return; } sendmessage(STRBUF(metamsg), NULL, XYMON_TIMEOUT, NULL); meta_start(); /* Get ready for the next */ }
int main(int argc, char *argv[]) { char *fn, *p; char cmd[1024]; FILE *fd; strbuffer_t *inbuf = newstrbuffer(0); void *listhead = NULL; int done, linenum; fn = strdup(argv[1]); strcpy(cmd, "!"); done = 0; while (!done) { if (*cmd == '!') { fd = stackfopen(fn, "r", &listhead); linenum = 1; if (!fd) { errprintf("Cannot open file %s\n", fn); continue; } while (stackfgets(inbuf, NULL)) { linenum++; printf("%s", STRBUF(inbuf)); } stackfclose(fd); } else if (*cmd == '?') { filelist_t *walk = (filelist_t *)listhead; while (walk) { printf("%s %lu\n", walk->filename, (unsigned long)walk->fsize); walk = walk->next; } if (stackfmodified(listhead)) printf("File(s) have been modified\n"); else printf("No changes\n"); } else if (*cmd == '.') { done = 1; continue; } else { xfree(fn); fn = strdup(cmd); stackfclist(&listhead); strcpy(cmd, "!"); continue; } printf("\nCmd: "); fflush(stdout); fgets(cmd, sizeof(cmd), stdin); p = strchr(cmd, '\n'); if (p) *p = '\0'; } xfree(fn); stackfclist(&listhead); return 0; }
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); } }
int main(int argc, char *argv[]) { FILE *bbhosts; char *fn = NULL; strbuffer_t *inbuf; int argi; char *include2 = NULL; for (argi=1; (argi < argc); argi++) { if (strcmp(argv[argi], "--version") == 0) { printf("bbhostshow version %s\n", VERSION); exit(0); } else if (strcmp(argv[argi], "--help") == 0) { printf("Usage:\n%s [filename]\n", argv[0]); exit(0); } else if (strcmp(argv[argi], "--bbnet") == 0) { include2 = "netinclude"; } else if (strcmp(argv[argi], "--bbdisp") == 0) { include2 = "dispinclude"; } else if (*argv[argi] != '-') { fn = strdup(argv[argi]); } } if (!fn || (strlen(fn) == 0)) { fn = getenv("BBHOSTS"); if (!fn) { errprintf("Environment variable BBHOSTS is not set - aborting\n"); exit(2); } } bbhosts = stackfopen(fn, "r", NULL); if (bbhosts == NULL) { printf("Cannot open the BBHOSTS file '%s'\n", fn); exit(1); } inbuf = newstrbuffer(0); while (stackfgets(inbuf, include2)) { printf("%s", STRBUF(inbuf)); } stackfclose(bbhosts); freestrbuffer(inbuf); return 0; }
void test_is_done(myconn_t *rec) { rec->testendtime = getcurrenttime(NULL); list_item_move(donetests, rec->listitem, rec->testspec); free_net_dialog(rec->dialog, rec->dialogtoken); if (!rec->ignoreresult && !rec->noredirect && (rec->talkprotocol == TALK_PROTO_HTTP) && (rec->httpstatus >= 300) && (rec->httpstatus <= 399) && (rec->redircount < MAXREDIRECTS)) { /* HTTP redirect */ char *lochdr; lochdr = strstr(STRBUF(rec->httpheaders), "\nLocation:"); rec->ignoreresult = 1; if (lochdr) { char *locend, savchar; char **dialog; int dtoken, advtest = 0; net_test_options_t options; myconn_netparams_t netparams; myconn_t *newtest; lochdr += strlen("\nLocation:"); lochdr += strspn(lochdr, " \t"); locend = lochdr + strcspn(lochdr, "\r\n"); savchar = *locend; *locend = '\0'; /* Copy options from the original test */ memset(&options, 0, sizeof(options)); options.testtype = NET_TEST_HTTP; options.timeout = rec->timeout; options.interval = rec->interval; options.testid = rec->testid; options.sourceip = (rec->netparams.sourceip ? strdup(rec->netparams.sourceip) : NULL); memset(&netparams, 0, sizeof(netparams)); dialog = net_dialog(rec->testspec, &netparams, &options, rec->hostinfo, &dtoken, lochdr); newtest = add_net_test(rec->testspec, dialog, dtoken, &options, &netparams, rec->hostinfo); *locend = savchar; /* * Flag the original result record so it is not transmitted as part of the result data. * Bump redirect counter so we wont end up looping. */ newtest->teststarttime = rec->teststarttime; newtest->redircount = rec->redircount + 1; } } }
void do_extensions(FILE *output, char *extenv, char *family) { /* * Extension scripts. These are ad-hoc, and implemented as a * simple pipe. So we do a fork here ... */ char *exts, *p; FILE *inpipe; char extfn[PATH_MAX]; strbuffer_t *inbuf; p = xgetenv(extenv); if (p == NULL) { /* No extension */ return; } MEMDEFINE(extfn); exts = strdup(p); p = strtok(exts, "\t "); inbuf = newstrbuffer(0); while (p) { /* Dont redo the eventlog or acklog things */ if ((strcmp(p, "eventlog.sh") != 0) && (strcmp(p, "acklog.sh") != 0)) { sprintf(extfn, "%s/ext/%s/%s", xgetenv("XYMONHOME"), family, p); inpipe = popen(extfn, "r"); if (inpipe) { initfgets(inpipe); while (unlimfgets(inbuf, inpipe)) fputs(STRBUF(inbuf), output); pclose(inpipe); freestrbuffer(inbuf); } } p = strtok(NULL, "\t "); } xfree(exts); MEMUNDEFINE(extfn); MEMUNDEFINE(buf); }
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; } }
char *getsendreturnstr(sendreturn_t *s, int takeover) { char *result = NULL; if (!s) return NULL; if (!s->respstr) return NULL; result = STRBUF(s->respstr); if (takeover) { /* * We cannot leave respstr as NULL, because later calls * to sendmessage() might re-use this sendreturn_t struct * and expect to get the data back. So allocate a new * responsebuffer for future use - if it isn't used, it * will be freed by freesendreturnbuf(). */ s->respstr = newstrbuffer(0); } return result; }
static char *preprocess(char *buf) { /* Expands config-file macros */ static strbuffer_t *result = NULL; char *inp; if (result == NULL) result = newstrbuffer(8192); clearstrbuffer(result); inp = buf; while (inp) { char *p; p = strchr(inp, '$'); if (p == NULL) { addtobuffer(result, inp); inp = NULL; } else { token_t *twalk; char savech; int n; *p = '\0'; addtobuffer(result, inp); p = (p+1); n = strcspn(p, "\t $.,|%!()[]{}+?/&@:;*"); savech = *(p+n); *(p+n) = '\0'; for (twalk = tokhead; (twalk && strcmp(p, twalk->name)); twalk = twalk->next) ; *(p+n) = savech; if (twalk) addtobuffer(result, twalk->value); inp = p+n; } } return STRBUF(result); }
void load_columndocs(void) { char fn[PATH_MAX]; FILE *fd; strbuffer_t *inbuf; sprintf(fn, "%s/etc/columndoc.csv", xgetenv("BBHOME")); fd = fopen(fn, "r"); if (!fd) return; inbuf = newstrbuffer(0); initfgets(fd); /* Skip the header line */ if (!unlimfgets(inbuf, fd)) { fclose(fd); freestrbuffer(inbuf); return; } while (unlimfgets(inbuf, fd)) { char *s1 = NULL, *s2 = NULL; s1 = strtok(STRBUF(inbuf), coldelim); if (s1) s2 = strtok(NULL, coldelim); if (s1 && s2) { coltext_t *newitem = (coltext_t *)calloc(1, sizeof(coltext_t)); newitem->colname = strdup(s1); newitem->coldescr = strdup(s2); newitem->next = chead; chead = newitem; ccount++; } } fclose(fd); freestrbuffer(inbuf); }
void sendresult(void) { struct req_t *rwalk; struct oid_t *owalk; char msgline[1024]; char *currdev, *currhost; mibdef_t *mib; strbuffer_t *clientmsg = newstrbuffer(0); int havemsg = 0; int itemcount = 0; currhost = ""; for (rwalk = reqhead; (rwalk); rwalk = rwalk->next) { if (strcmp(rwalk->hostname, currhost) != 0) { /* Flush buffer */ if (havemsg) { sprintf(msgline, "\n.<!-- linecount=%d -->\n", itemcount); addtobuffer(clientmsg, msgline); sendmessage(STRBUF(clientmsg), NULL, XYMON_TIMEOUT, NULL); } clearstrbuffer(clientmsg); havemsg = 0; itemcount = 0; sprintf(msgline, "client/snmpcollect %s.snmpcollect snmp\n\n", rwalk->hostname); addtobuffer(clientmsg, msgline); } currdev = ""; for (mib = first_mib(); (mib); mib = next_mib()) { clearstrbuffer(mib->resultbuf); mib->haveresult = 0; sprintf(msgline, "\n[%s]\nInterval=%d\nActiveIP=%s\n\n", mib->mibname, atoi(xgetenv("TASKSLEEP")), rwalk->hostip[rwalk->hostipidx]); addtobuffer(mib->resultbuf, msgline); } for (owalk = rwalk->oidhead; (owalk); owalk = owalk->next) { if (strcmp(currdev, owalk->devname)) { currdev = owalk->devname; /* OK, because ->devname is permanent */ if (*owalk->devname && (*owalk->devname != '-') ) { addtobuffer(owalk->mib->resultbuf, "\n<"); addtobuffer(owalk->mib->resultbuf, owalk->devname); addtobuffer(owalk->mib->resultbuf, ">\n"); itemcount++; } } addtobuffer(owalk->mib->resultbuf, "\t"); addtobuffer(owalk->mib->resultbuf, owalk->oiddef->dsname); addtobuffer(owalk->mib->resultbuf, " = "); if (owalk->result) { int ival; unsigned int uval; switch (owalk->oiddef->conversion) { case OID_CONVERT_U32: ival = atoi(owalk->result); memcpy(&uval, &ival, sizeof(uval)); sprintf(msgline, "%u", uval); addtobuffer(owalk->mib->resultbuf, msgline); break; default: addtobuffer(owalk->mib->resultbuf, owalk->result); break; } } else addtobuffer(owalk->mib->resultbuf, "NODATA"); addtobuffer(owalk->mib->resultbuf, "\n"); owalk->mib->haveresult = 1; } for (mib = first_mib(); (mib); mib = next_mib()) { if (mib->haveresult) { addtostrbuffer(clientmsg, mib->resultbuf); havemsg = 1; } } } if (havemsg) { sendmessage(STRBUF(clientmsg), NULL, XYMON_TIMEOUT, NULL); } freestrbuffer(clientmsg); }
void readconfig(char *cfgfn, int verbose) { static void *cfgfiles = NULL; FILE *cfgfd; strbuffer_t *inbuf; struct req_t *reqitem = NULL; int tasksleep = atoi(xgetenv("TASKSLEEP")); mibdef_t *mib; /* Check if config was modified */ if (cfgfiles) { if (!stackfmodified(cfgfiles)) { dbgprintf("No files changed, skipping reload\n"); return; } else { stackfclist(&cfgfiles); cfgfiles = NULL; } } cfgfd = stackfopen(cfgfn, "r", &cfgfiles); if (cfgfd == NULL) { errprintf("Cannot open configuration files %s\n", cfgfn); return; } inbuf = newstrbuffer(0); while (stackfgets(inbuf, NULL)) { char *bot, *p, *mibidx; char savech; sanitize_input(inbuf, 0, 0); bot = STRBUF(inbuf) + strspn(STRBUF(inbuf), " \t"); if ((*bot == '\0') || (*bot == '#')) continue; if (*bot == '[') { char *intvl = strchr(bot, '/'); /* * See if we're running a non-standard interval. * If yes, then process only the records that match * this TASKSLEEP setting. */ if (tasksleep != 300) { /* Non-default interval. Skip the host if it HASN'T got an interval setting */ if (!intvl) continue; /* Also skip the hosts that have an interval different from the current */ *intvl = '\0'; /* Clip the interval from the hostname */ if (atoi(intvl+1) != tasksleep) continue; } else { /* Default interval. Skip the host if it HAS an interval setting */ if (intvl) continue; } reqitem = (req_t *)calloc(1, sizeof(req_t)); p = strchr(bot, ']'); if (p) *p = '\0'; reqitem->hostname = strdup(bot + 1); if (p) *p = ']'; reqitem->hostip[0] = reqitem->hostname; reqitem->version = SNMP_VERSION_1; reqitem->authmethod = SNMP_V3AUTH_MD5; reqitem->next = reqhead; reqhead = reqitem; continue; } /* If we have nowhere to put the data, then skip further processing */ if (!reqitem) continue; if (strncmp(bot, "ip=", 3) == 0) { char *nextip = strtok(strdup(bot+3), ","); int i = 0; do { reqitem->hostip[i++] = nextip; nextip = strtok(NULL, ","); } while (nextip); continue; } if (strncmp(bot, "version=", 8) == 0) { switch (*(bot+8)) { case '1': reqitem->version = SNMP_VERSION_1; break; case '2': reqitem->version = SNMP_VERSION_2c; break; case '3': reqitem->version = SNMP_VERSION_3; break; } continue; } if (strncmp(bot, "community=", 10) == 0) { reqitem->community = strdup(bot+10); continue; } if (strncmp(bot, "username="******"passphrase=", 10) == 0) { reqitem->passphrase = strdup(bot+10); continue; } if (strncmp(bot, "authmethod=", 10) == 0) { if (strcasecmp(bot+10, "md5") == 0) reqitem->authmethod = SNMP_V3AUTH_MD5; else if (strcasecmp(bot+10, "sha1") == 0) reqitem->authmethod = SNMP_V3AUTH_SHA1; else errprintf("Unknown SNMPv3 authentication method '%s'\n", bot+10); continue; } /* Custom mibs */ p = bot + strcspn(bot, "= \t\r\n"); savech = *p; *p = '\0'; mib = find_mib(bot); *p = savech; p += strspn(p, "= \t"); mibidx = p; if (mib) { int i; mibidx_t *iwalk = NULL; char *oid, *oidbuf; char *devname; oidset_t *swalk; setupmib(mib, verbose); if (mib->loadstatus != MIB_STATUS_LOADED) continue; /* Cannot use this MIB */ /* See if this is an entry where we must determine the index ourselves */ if (*mibidx) { for (iwalk = mib->idxlist; (iwalk && (*mibidx != iwalk->marker)); iwalk = iwalk->next) ; } if ((*mibidx == '*') && !iwalk) { errprintf("Cannot do wildcard matching without an index (host %s, mib %s)\n", reqitem->hostname, mib->mibname); continue; } if (!iwalk) { /* No key lookup */ swalk = mib->oidlisthead; while (swalk) { reqitem->setnumber++; for (i=0; (i <= swalk->oidcount); i++) { if (*mibidx) { oid = oidbuf = (char *)malloc(strlen(swalk->oids[i].oid) + strlen(mibidx) + 2); sprintf(oidbuf, "%s.%s", swalk->oids[i].oid, mibidx); devname = mibidx; } else { oid = swalk->oids[i].oid; oidbuf = NULL; devname = "-"; } make_oitem(mib, devname, &swalk->oids[i], oid, reqitem); if (oidbuf) xfree(oidbuf); } swalk = swalk->next; } reqitem->next_oid = reqitem->oidhead; } else { /* Add a key-record so we can try to locate the index */ keyrecord_t *newitem = (keyrecord_t *)calloc(1, sizeof(keyrecord_t)); char endmarks[6]; mibidx++; /* Skip the key-marker */ sprintf(endmarks, "%s%c", ")]}>", iwalk->marker); p = mibidx + strcspn(mibidx, endmarks); *p = '\0'; newitem->key = strdup(mibidx); newitem->indexmethod = iwalk; newitem->mib = mib; newitem->next = reqitem->keyrecords; reqitem->currentkey = reqitem->keyrecords = newitem; } continue; } else { errprintf("Unknown MIB (not in snmpmibs.cfg): '%s'\n", bot); } } stackfclose(cfgfd); freestrbuffer(inbuf); }
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; } } } }
int main(int argc, char *argv[]) { void *hwalk; char *hostsfn = NULL; char *netstring = NULL; char *include2 = NULL; int extras = 1; int testuntagged = 0; int nodownhosts = 0; int onlypreferredentry = 0; char *p; char **lookv; int argi, lookc; strbuffer_t *wantedtags; if ((argc <= 1) || (strcmp(argv[1], "--help") == 0)) { printf("Usage:\n%s test1 [test1] [test2] ... \n", argv[0]); exit(1); } lookv = (char **)malloc(argc*sizeof(char *)); lookc = 0; hostsfn = xgetenv("HOSTSCFG"); conncolumn = xgetenv("PINGCOLUMN"); for (argi=1; (argi < argc); argi++) { if (strcmp(argv[argi], "--noextras") == 0) { extras = 0; } else if (strcmp(argv[argi], "--test-untagged") == 0) { testuntagged = 1; } else if (argnmatch(argv[argi], "--no-down")) { char *p; nodownhosts = 1; p = strchr(argv[argi], '='); if (p) testcolumn = strdup(p+1); } else if (strcmp(argv[argi], "--version") == 0) { printf("xymongrep version %s\n", VERSION); exit(0); } else if ((strcmp(argv[argi], "--net") == 0) || (strcmp(argv[argi], "--bbnet") == 0)) { include2 = "netinclude"; onlypreferredentry = 0; } else if ((strcmp(argv[argi], "--web") == 0) || (strcmp(argv[argi], "--bbdisp") == 0)) { include2 = "dispinclude"; onlypreferredentry = 1; } else if (argnmatch(argv[argi], "--hosts=")) { hostsfn = strchr(argv[argi], '=') + 1; } else { lookv[lookc] = strdup(argv[argi]); lookc++; } } lookv[lookc] = NULL; if ((hostsfn == NULL) || (strlen(hostsfn) == 0)) { errprintf("Environment variable HOSTSCFG is not set - aborting\n"); exit(2); } load_hostnames(hostsfn, include2, get_fqdn()); if (first_host() == NULL) { errprintf("Cannot load %s, or file is empty\n", hostsfn); exit(3); } /* If we must avoid downed or disabled hosts, let's find out what those are */ if (nodownhosts) load_hoststatus(); /* Each network test tagged with NET:locationname */ p = xgetenv("XYMONNETWORK"); if ((p == NULL) || (strlen(p) == 0)) p = xgetenv("BBLOCATION"); if (p && strlen(p)) netstring = strdup(p); hwalk = first_host(); wantedtags = newstrbuffer(0); while (hwalk) { char hostip[IP_ADDR_STRLEN]; char *curnet = xmh_item(hwalk, XMH_NET); char *curname = xmh_item(hwalk, XMH_HOSTNAME); /* * Only look at the hosts whose NET: definition matches the wanted one. * Must also check if the host is currently down (not responding to ping). * And if the host is OK with knownhost(), because it may be time-limited. */ if (netok(netstring, curnet, testuntagged) && downok(curname, nodownhosts) && knownhost(curname, hostip, GH_IGNORE)) { char *item; clearstrbuffer(wantedtags); for (item = xmh_item_walk(hwalk); (item); item = xmh_item_walk(NULL)) { int i; char *realitem = item + strspn(item, "!~?"); for (i=0; lookv[i]; i++) { char *outitem = NULL; if (lookv[i][strlen(lookv[i])-1] == '*') { if (strncasecmp(realitem, lookv[i], strlen(lookv[i])-1) == 0) { outitem = (extras ? item : realitem); } } else if (strcasecmp(realitem, lookv[i]) == 0) { outitem = (extras ? item : realitem); } if (outitem) { int needquotes = ((strchr(outitem, ' ') != NULL) || (strchr(outitem, '\t') != NULL)); addtobuffer(wantedtags, " "); if (needquotes) addtobuffer(wantedtags, "\""); addtobuffer(wantedtags, outitem); if (needquotes) addtobuffer(wantedtags, "\""); } } } if (STRBUF(wantedtags) && (*STRBUF(wantedtags) != '\0') && extras) { if (xmh_item(hwalk, XMH_FLAG_DIALUP)) addtobuffer(wantedtags, " dialup"); if (xmh_item(hwalk, XMH_FLAG_TESTIP)) addtobuffer(wantedtags, " testip"); } if (STRBUF(wantedtags) && *STRBUF(wantedtags)) { printf("%s %s #%s\n", xmh_item(hwalk, XMH_IP), xmh_item(hwalk, XMH_HOSTNAME), STRBUF(wantedtags)); } } do { hwalk = next_host(hwalk, 1); } while (hwalk && onlypreferredentry && (strcmp(curname, xmh_item(hwalk, XMH_HOSTNAME)) == 0)); } return 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); }
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); }
char *hostscfg_content(void) { return strdup(STRBUF(contentbuffer)); }
char *stackfgets(strbuffer_t *buffer, char *extraincl) { char *result; result = unlimfgets(buffer, fdhead->fd); if (result) { char *bufpastwhitespace = STRBUF(buffer) + strspn(STRBUF(buffer), " \t"); if ( (strncmp(bufpastwhitespace, "include ", 8) == 0) || (extraincl && (strncmp(bufpastwhitespace, extraincl, strlen(extraincl)) == 0)) ) { char *newfn, *eol, eolchar; eol = bufpastwhitespace + strcspn(bufpastwhitespace, "\r\n"); if (eol) { eolchar = *eol; *eol = '\0'; } newfn = bufpastwhitespace + strcspn(bufpastwhitespace, " \t"); newfn += strspn(newfn, " \t"); if (*newfn && (stackfopen(newfn, "r", (void **)fdhead->listhead) != NULL)) return stackfgets(buffer, extraincl); else { errprintf("WARNING: Cannot open include file '%s', line was:%s\n", newfn, STRBUF(buffer)); if (eol) *eol = eolchar; return result; } } else if (strncmp(bufpastwhitespace, "directory ", 10) == 0) { char *dirfn, *eol, eolchar; eol = bufpastwhitespace + strcspn(bufpastwhitespace, "\r\n"); if (eol) { eolchar = *eol; *eol = '\0'; } dirfn = bufpastwhitespace + 9; dirfn += strspn(dirfn, " \t"); if (*dirfn) addtofnlist(dirfn, (void **)fdhead->listhead); if (fnlist && (stackfopen(fnlist->name, "r", (void **)fdhead->listhead) != NULL)) { htnames_t *tmp = fnlist; fnlist = fnlist->next; xfree(tmp->name); xfree(tmp); return stackfgets(buffer, extraincl); } else if (fnlist) { htnames_t *tmp = fnlist; errprintf("WARNING: Cannot open include file '%s', line was:%s\n", fnlist->name, buffer); fnlist = fnlist->next; xfree(tmp->name); xfree(tmp); if (eol) *eol = eolchar; return result; } else { /* Empty directory include - return a blank line */ *result = '\0'; return result; } } } else if (result == NULL) { /* end-of-file on read */ stackfclose(NULL); if (fnlist) { if (stackfopen(fnlist->name, "r", (void **)fdhead->listhead) != NULL) { htnames_t *tmp = fnlist; fnlist = fnlist->next; xfree(tmp->name); xfree(tmp); return stackfgets(buffer, extraincl); } else { htnames_t *tmp = fnlist; errprintf("WARNING: Cannot open include file '%s', line was:%s\n", fnlist->name, buffer); fnlist = fnlist->next; xfree(tmp->name); xfree(tmp); return result; } } else if (fdhead != NULL) return stackfgets(buffer, extraincl); else return NULL; } return result; }
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 : " ")); 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, " "); } 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); }
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; }
char *init_tcp_services(void) { static char *xymonnetsvcs = NULL; static time_t lastupdate = 0; char filename[PATH_MAX]; struct stat st; FILE *fd = NULL; strbuffer_t *inbuf; svclist_t *head, *tail, *first, *walk; char *searchstring; int svcnamebytes = 0; int svccount = 0; int i; MEMDEFINE(filename); filename[0] = '\0'; if (xgetenv("XYMONHOME")) { sprintf(filename, "%s/etc/", xgetenv("XYMONHOME")); } strcat(filename, "protocols.cfg"); if ((stat(filename, &st) == 0) && xymonnetsvcs) { /* See if we have already run and the file is unchanged - if so just pickup the result */ if (st.st_mtime == lastupdate) return xymonnetsvcs; /* File has changed - reload configuration. But clean up first so we dont leak memory. */ if (svcinfo != default_svcinfo) { for (i=0; (svcinfo[i].svcname); i++) { if (svcinfo[i].svcname) xfree(svcinfo[i].svcname); if (svcinfo[i].sendtxt) xfree(svcinfo[i].sendtxt); if (svcinfo[i].exptext) xfree(svcinfo[i].exptext); } xfree(svcinfo); svcinfo = default_svcinfo; } xfree(xymonnetsvcs); xymonnetsvcs = NULL; } if (xgetenv("XYMONNETSVCS") == NULL) { putenv("XYMONNETSVCS=smtp telnet ftp pop pop3 pop-3 ssh imap ssh1 ssh2 imap2 imap3 imap4 pop2 pop-2 nntp"); } fd = fopen(filename, "r"); if (fd == NULL) { errprintf("Cannot open TCP service-definitions file %s - using defaults\n", filename); xymonnetsvcs = strdup(xgetenv("XYMONNETSVCS")); MEMUNDEFINE(filename); return xymonnetsvcs; } lastupdate = st.st_mtime; head = tail = first = NULL; inbuf = newstrbuffer(0); initfgets(fd); while (unlimfgets(inbuf, fd)) { char *l, *eol; sanitize_input(inbuf, 1, 0); l = STRBUF(inbuf); if (*l == '[') { char *svcname; eol = strchr(l, ']'); if (eol) *eol = '\0'; l = skipwhitespace(l+1); svcname = strtok(l, "|"); first = NULL; while (svcname) { svclist_t *newitem; svccount++; svcnamebytes += (strlen(svcname) + 1); newitem = (svclist_t *) malloc(sizeof(svclist_t)); newitem->rec = (svcinfo_t *)calloc(1, sizeof(svcinfo_t)); newitem->rec->svcname = strdup(svcname); newitem->next = NULL; if (first == NULL) first = newitem; if (head == NULL) { head = tail = newitem; } else { tail->next = newitem; tail = newitem; } svcname = strtok(NULL, "|"); } } else if (strncmp(l, "send ", 5) == 0) { if (first) { getescapestring(skipwhitespace(l+4), &first->rec->sendtxt, &first->rec->sendlen); for (walk = first->next; (walk); walk = walk->next) { walk->rec->sendtxt = strdup(first->rec->sendtxt); walk->rec->sendlen = first->rec->sendlen; } } } else if (strncmp(l, "expect ", 7) == 0) { if (first) { getescapestring(skipwhitespace(l+6), &first->rec->exptext, &first->rec->explen); for (walk = first->next; (walk); walk = walk->next) { walk->rec->exptext = strdup(first->rec->exptext); walk->rec->explen = first->rec->explen; walk->rec->expofs = 0; /* HACK - not used right now */ } } } else if (strncmp(l, "options ", 8) == 0) { if (first) { char *opt; first->rec->flags = 0; l = skipwhitespace(l+7); opt = strtok(l, ","); while (opt) { if (strcmp(opt, "ssl") == 0) first->rec->flags |= TCP_SSL; else if (strcmp(opt, "banner") == 0) first->rec->flags |= TCP_GET_BANNER; else if (strcmp(opt, "telnet") == 0) first->rec->flags |= TCP_TELNET; else errprintf("Unknown option: %s\n", opt); opt = strtok(NULL, ","); } for (walk = first->next; (walk); walk = walk->next) { walk->rec->flags = first->rec->flags; } } } else if (strncmp(l, "port ", 5) == 0) { if (first) { first->rec->port = atoi(skipwhitespace(l+4)); for (walk = first->next; (walk); walk = walk->next) { walk->rec->port = first->rec->port; } } } } if (fd) fclose(fd); freestrbuffer(inbuf); /* Copy from the svclist to svcinfo table */ svcinfo = (svcinfo_t *) malloc((svccount+1) * sizeof(svcinfo_t)); for (walk=head, i=0; (walk && (i < svccount)); walk = walk->next, i++) { svcinfo[i].svcname = walk->rec->svcname; svcinfo[i].sendtxt = walk->rec->sendtxt; svcinfo[i].sendlen = walk->rec->sendlen; svcinfo[i].exptext = walk->rec->exptext; svcinfo[i].explen = walk->rec->explen; svcinfo[i].expofs = walk->rec->expofs; svcinfo[i].flags = walk->rec->flags; svcinfo[i].port = walk->rec->port; } memset(&svcinfo[svccount], 0, sizeof(svcinfo_t)); /* This should not happen */ if (walk) { errprintf("Whoa - didnt copy all services! svccount=%d, next service '%s'\n", svccount, walk->rec->svcname); } /* Free the temp. svclist list */ while (head) { /* * Note: Dont free the strings inside the records, * as they are now owned by the svcinfo records. */ walk = head; head = head->next; xfree(walk); } searchstring = strdup(xgetenv("XYMONNETSVCS")); xymonnetsvcs = (char *) malloc(strlen(xgetenv("XYMONNETSVCS")) + svcnamebytes + 1); strcpy(xymonnetsvcs, xgetenv("XYMONNETSVCS")); for (i=0; (svcinfo[i].svcname); i++) { char *p; strcpy(searchstring, xgetenv("XYMONNETSVCS")); p = strtok(searchstring, " "); while (p && (strcmp(p, svcinfo[i].svcname) != 0)) p = strtok(NULL, " "); if (p == NULL) { strcat(xymonnetsvcs, " "); strcat(xymonnetsvcs, svcinfo[i].svcname); } } xfree(searchstring); if (debug) { dump_tcp_services(); dbgprintf("XYMONNETSVCS set to : %s\n", xymonnetsvcs); } MEMUNDEFINE(filename); return xymonnetsvcs; }