static RbtHandle findrec(char *key) { RbtHandle handle; handle = rbtFind(rbconf, key); if (handle == rbtEnd(rbconf)) { /* Check if there's a clone pointer record */ char *clonekey, *p; clonekey = strdup(key); p = strchr(clonekey, '|'); if (p && *(p+1)) { *p = '='; *(p+1) = '\0'; } handle = rbtFind(rbconf, clonekey); xfree(clonekey); if (handle != rbtEnd(rbconf)) { void *k1, *k2; char *pointsto; char *service; /* Get the origin record for this cloned record, using the same service name */ rbtKeyValue(rbconf, handle, &k1, &k2); pointsto = (char *)k2; service = strchr(key, '|'); if (service) service++; clonekey = (char *)malloc(strlen(pointsto) + strlen(service) + 2); sprintf(clonekey, "%s|%s", pointsto, service); handle = rbtFind(rbconf, clonekey); xfree(clonekey); } } return handle; }
char *knownhost(char *hostname, char *hostip, int ghosthandling) { /* * ghosthandling = 0 : Default BB method (case-sensitive, no logging, keep ghosts) * ghosthandling = 1 : Case-insensitive, no logging, drop ghosts * ghosthandling = 2 : Case-insensitive, log ghosts, drop ghosts */ RbtIterator hosthandle; namelist_t *walk = NULL; static char *result = NULL; void *k1, *k2; time_t now = getcurrenttime(NULL); if (result) xfree(result); result = NULL; /* Find the host in the normal hostname list */ hosthandle = rbtFind(rbhosts, hostname); if (hosthandle != rbtEnd(rbhosts)) { rbtKeyValue(rbhosts, hosthandle, &k1, &k2); walk = (namelist_t *)k2; } else { /* Not found - lookup in the client alias list */ hosthandle = rbtFind(rbclients, hostname); if (hosthandle != rbtEnd(rbclients)) { rbtKeyValue(rbclients, hosthandle, &k1, &k2); walk = (namelist_t *)k2; } } if (walk) { /* * Force our version of the hostname. Done here so CLIENT works always. */ strcpy(hostip, walk->ip); result = strdup(walk->bbhostname); } else { *hostip = '\0'; result = strdup(hostname); } /* If default method, just say yes */ if (ghosthandling == 0) return result; /* Allow all summaries */ if (strcmp(hostname, "summary") == 0) return result; if (walk && ( ((walk->notbefore > now) || (walk->notafter < now)) )) walk = NULL; return (walk ? result : NULL); }
void print_colheaders(FILE *output, RbtHandle rbcolumns) { int colcount; RbtIterator colhandle; colcount = 1; /* Remember the hostname column */ /* Group column headings */ fprintf(output, "<TR>"); fprintf(output, "<TD ROWSPAN=2> </TD>\n"); /* For the prio column - in both row headers+dash rows */ fprintf(output, "<TD ROWSPAN=2> </TD>\n"); /* For the host column - in both row headers+dash rows */ for (colhandle = rbtBegin(rbcolumns); (colhandle != rbtEnd(rbcolumns)); colhandle = rbtNext(rbcolumns, colhandle)) { void *k1, *k2; char *colname; rbtKeyValue(rbcolumns, colhandle, &k1, &k2); colname = (char *)k1; colcount++; fprintf(output, " <TD ALIGN=CENTER VALIGN=BOTTOM WIDTH=45>\n"); fprintf(output, " <A HREF=\"%s\"><FONT %s><B>%s</B></FONT></A> </TD>\n", columnlink(colname), xgetenv("XYMONPAGECOLFONT"), colname); } fprintf(output, "</TR>\n"); fprintf(output, "<TR><TD COLSPAN=%d><HR WIDTH=\"100%%\"></TD></TR>\n\n", colcount); }
void print_oneprio(FILE *output, RbtHandle rbstate, RbtHandle rbcolumns, int prio) { RbtIterator hhandle; int firsthost = 1; char *curhost = ""; /* Then output each host and their column status */ for (hhandle = rbtBegin(rbstate); (hhandle != rbtEnd(rbstate)); hhandle = rbtNext(rbstate, hhandle)) { void *k1, *k2; hstatus_t *itm; rbtKeyValue(rbstate, hhandle, &k1, &k2); itm = (hstatus_t *)k2; if (itm->config->priority != prio) continue; if (strcmp(curhost, itm->hostname) == 0) continue; /* New host */ curhost = itm->hostname; print_hoststatus(output, itm, rbcolumns, prio, firsthost); firsthost = 0; } /* If we did output any hosts, make some room for the next priority */ if (!firsthost) fprintf(output, "<TR><TD> </TD></TR>\n"); }
static void locator_updatecache(enum locator_servicetype_t svc, char *key, char *resp) { RbtIterator handle; cacheitm_t *newitm; if (!havecache[svc]) return; handle = rbtFind(locatorcache[svc], key); if (handle == rbtEnd(locatorcache[svc])) { newitm = (cacheitm_t *)calloc(1, sizeof(cacheitm_t)); newitm->key = strdup(key); newitm->resp = strdup(resp); if (rbtInsert(locatorcache[svc], newitm->key, newitm) != RBT_STATUS_OK) { xfree(newitm->key); xfree(newitm->resp); xfree(newitm); } } else { newitm = (cacheitm_t *)gettreeitem(locatorcache[svc], handle); if (newitm->resp) xfree(newitm->resp); newitm->resp = strdup(resp); newitm->tstamp = getcurrenttime(NULL); } }
static link_t *find_link(char *key) { link_t *l = NULL; RbtIterator handle; handle = rbtFind(linkstree, key); if (handle != rbtEnd(linkstree)) l = (link_t *)gettreeitem(linkstree, handle); return l; }
int delete_nkconfig(char *dropkey, int evenifcloned) { RbtHandle handle; void *k1, *k2; handle = rbtFind(rbconf, dropkey); if (handle == rbtEnd(rbconf)) return 0; if (!evenifcloned) { /* Check if this record has any clones attached to it */ char *hostname, *p; hostname = strdup(dropkey); p = strchr(hostname, '|'); if (p) *p = '\0'; handle = rbtBegin(rbconf); while (handle != rbtEnd(rbconf)) { void *k1, *k2; char *key, *ptr; rbtKeyValue(rbconf, handle, &k1, &k2); key = (char *)k1; ptr = (char *)k2; if ((*(key + strlen(key) - 1) == '=') && (strcmp(hostname, ptr) == 0)) { xfree(hostname); return 1; } handle = rbtNext(rbconf, handle); } xfree(hostname); } handle = rbtFind(rbconf, dropkey); if (handle != rbtEnd(rbconf)) { rbtKeyValue(rbconf, handle, &k1, &k2); rbtErase(rbconf, handle); flushrec(k1, k2); } return 0; }
void addclone_nkconfig(char *origin, char *newclone) { char *newkey; RbtHandle handle; newkey = (char *)malloc(strlen(newclone) + 2); sprintf(newkey, "%s=", newclone); handle = rbtFind(rbconf, newkey); if (handle != rbtEnd(rbconf)) dropclone_nkconfig(newclone); rbtInsert(rbconf, newkey, strdup(origin)); }
void locator_flushcache(enum locator_servicetype_t svc, char *key) { RbtIterator handle; if (!havecache[svc]) return; if (key) { handle = rbtFind(locatorcache[svc], key); if (handle != rbtEnd(locatorcache[svc])) { cacheitm_t *itm = (cacheitm_t *)gettreeitem(locatorcache[svc], handle); itm->tstamp = 0; } } else { for (handle = rbtBegin(locatorcache[svc]); (handle != rbtEnd(locatorcache[svc])); handle = rbtNext(locatorcache[svc], handle)) { cacheitm_t *itm = (cacheitm_t *)gettreeitem(locatorcache[svc], handle); itm->tstamp = 0; } } }
static char *locator_querycache(enum locator_servicetype_t svc, char *key) { RbtIterator handle; cacheitm_t *itm; if (!havecache[svc]) return NULL; handle = rbtFind(locatorcache[svc], key); if (handle == rbtEnd(locatorcache[svc])) return NULL; itm = (cacheitm_t *)gettreeitem(locatorcache[svc], handle); return (itm->tstamp + cachetimeout[svc]) > getcurrenttime(NULL) ? itm->resp : NULL; }
void generate_critpage(FILE *output, char *hfprefix) { RbtIterator hhandle; int color = COL_GREEN; int maxprio = 0; /* Determine background color and max. priority */ for (hhandle = rbtBegin(rbstate); (hhandle != rbtEnd(rbstate)); hhandle = rbtNext(rbstate, hhandle)) { void *k1, *k2; hstatus_t *itm; rbtKeyValue(rbstate, hhandle, &k1, &k2); itm = (hstatus_t *)k2; if (itm->color > color) color = itm->color; if (itm->config->priority > maxprio) maxprio = itm->config->priority; } headfoot(output, hfprefix, "", "header", color); fprintf(output, "<center>\n"); if (color != COL_GREEN) { RbtHandle rbcolumns; int prio; rbcolumns = columnlist(rbstate); fprintf(output, "<TABLE BORDER=0 CELLPADDING=4 SUMMARY=\"Critical status display\">\n"); print_colheaders(output, rbcolumns); for (prio = 1; (prio <= maxprio); prio++) { print_oneprio(output, rbstate, rbcolumns, prio); } fprintf(output, "</TABLE>\n"); rbtDelete(rbcolumns); } else { /* "All Monitored Systems OK */ fprintf(output, "%s", xgetenv("XYMONALLOKTEXT")); } fprintf(output, "</center>\n"); headfoot(output, hfprefix, "", "footer", color); }
void dropclone_nkconfig(char *drop) { RbtHandle handle; char *key; void *k1, *k2; char *dropkey, *dropsrc; key = (char *)malloc(strlen(drop) + 2); sprintf(key, "%s=", drop); handle = rbtFind(rbconf, key); if (handle == rbtEnd(rbconf)) return; rbtKeyValue(rbconf, handle, &k1, &k2); dropkey = k1; dropsrc = k2; rbtErase(rbconf, handle); xfree(dropkey); xfree(dropsrc); xfree(key); }
RbtHandle columnlist(RbtHandle statetree) { RbtHandle rbcolumns; RbtIterator hhandle; rbcolumns = rbtNew(name_compare); for (hhandle = rbtBegin(statetree); (hhandle != rbtEnd(statetree)); hhandle = rbtNext(statetree, hhandle)) { void *k1, *k2; hstatus_t *itm; RbtStatus status; rbtKeyValue(statetree, hhandle, &k1, &k2); itm = (hstatus_t *)k2; status = rbtInsert(rbcolumns, itm->testname, NULL); } return rbcolumns; }
void *hostinfo(char *hostname) { RbtIterator hosthandle; namelist_t *result = NULL; time_t now = getcurrenttime(NULL); if (!configloaded) load_hostnames(xgetenv("BBHOSTS"), NULL, get_fqdn()); hosthandle = rbtFind(rbhosts, hostname); if (hosthandle != rbtEnd(rbhosts)) { void *k1, *k2; rbtKeyValue(rbhosts, hosthandle, &k1, &k2); result = (namelist_t *)k2; if ((result->notbefore > now) || (result->notafter < now)) return NULL; } return result; }
int load_hostnames(char *bbhostsfn, char *extrainclude, int fqdn) { /* Return value: 0 for load OK, 1 for "No files changed since last load", -1 for error (file not found) */ static void *bbhfiles = NULL; FILE *bbhosts; int ip1, ip2, ip3, ip4, groupid, pageidx; char hostname[4096]; strbuffer_t *inbuf; pagelist_t *curtoppage, *curpage, *pgtail; namelist_t *nametail = NULL; RbtHandle htree; /* First check if there were no modifications at all */ if (bbhfiles) { if (!stackfmodified(bbhfiles)){ dbgprintf("No files modified, skipping reload of %s\n", bbhostsfn); return 1; } else { stackfclist(&bbhfiles); bbhfiles = NULL; } } MEMDEFINE(hostname); MEMDEFINE(l); configloaded = 1; initialize_hostlist(); curpage = curtoppage = pgtail = pghead; pageidx = groupid = 0; bbhosts = stackfopen(bbhostsfn, "r", &bbhfiles); if (bbhosts == NULL) return -1; inbuf = newstrbuffer(0); htree = rbtNew(name_compare); while (stackfgets(inbuf, extrainclude)) { sanitize_input(inbuf, 0, 0); if (strncmp(STRBUF(inbuf), "page", 4) == 0) { pagelist_t *newp; char *name, *title; pageidx = groupid = 0; if (get_page_name_title(STRBUF(inbuf), "page", &name, &title) == 0) { newp = (pagelist_t *)malloc(sizeof(pagelist_t)); newp->pagepath = strdup(name); newp->pagetitle = (title ? strdup(title) : NULL); newp->next = NULL; pgtail->next = newp; pgtail = newp; curpage = curtoppage = newp; } } else if (strncmp(STRBUF(inbuf), "subpage", 7) == 0) { pagelist_t *newp; char *name, *title; pageidx = groupid = 0; if (get_page_name_title(STRBUF(inbuf), "subpage", &name, &title) == 0) { newp = (pagelist_t *)malloc(sizeof(pagelist_t)); newp->pagepath = malloc(strlen(curtoppage->pagepath) + strlen(name) + 2); sprintf(newp->pagepath, "%s/%s", curtoppage->pagepath, name); newp->pagetitle = malloc(strlen(curtoppage->pagetitle) + strlen(title) + 2); sprintf(newp->pagetitle, "%s/%s", curtoppage->pagetitle, title); newp->next = NULL; pgtail->next = newp; pgtail = newp; curpage = newp; } } else if (strncmp(STRBUF(inbuf), "subparent", 9) == 0) { pagelist_t *newp, *parent; char *pname, *name, *title; pageidx = groupid = 0; parent = NULL; if (get_page_name_title(STRBUF(inbuf), "subparent", &pname, &title) == 0) { for (parent = pghead; (parent && !pagematch(parent, pname)); parent = parent->next); } if (parent && (get_page_name_title(title, "", &name, &title) == 0)) { newp = (pagelist_t *)malloc(sizeof(pagelist_t)); newp->pagepath = malloc(strlen(parent->pagepath) + strlen(name) + 2); sprintf(newp->pagepath, "%s/%s", parent->pagepath, name); newp->pagetitle = malloc(strlen(parent->pagetitle) + strlen(title) + 2); sprintf(newp->pagetitle, "%s/%s", parent->pagetitle, title); newp->next = NULL; pgtail->next = newp; pgtail = newp; curpage = newp; } } else if (strncmp(STRBUF(inbuf), "group", 5) == 0) { groupid++; } else if (sscanf(STRBUF(inbuf), "%d.%d.%d.%d %s", &ip1, &ip2, &ip3, &ip4, hostname) == 5) { char *startoftags, *tag, *delim; int elemidx, elemsize; char clientname[4096]; char downtime[4096]; char groupidstr[10]; RbtIterator handle; namelist_t *newitem = calloc(1, sizeof(namelist_t)); namelist_t *iwalk, *iprev; MEMDEFINE(clientname); MEMDEFINE(downtime); /* Hostname beginning with '@' are "no-display" hosts. But we still want them. */ if (*hostname == '@') memmove(hostname, hostname+1, strlen(hostname)); if (!fqdn) { /* Strip any domain from the hostname */ char *p = strchr(hostname, '.'); if (p) *p = '\0'; } sprintf(newitem->ip, "%d.%d.%d.%d", ip1, ip2, ip3, ip4); sprintf(groupidstr, "%d", groupid); newitem->groupid = strdup(groupidstr); newitem->pageindex = pageidx++; newitem->bbhostname = strdup(hostname); if (ip1 || ip2 || ip3 || ip4) newitem->preference = 1; else newitem->preference = 0; newitem->logname = strdup(newitem->bbhostname); { char *p = newitem->logname; while ((p = strchr(p, '.')) != NULL) { *p = '_'; } } newitem->page = curpage; newitem->defaulthost = defaulthost; clientname[0] = downtime[0] = '\0'; startoftags = strchr(STRBUF(inbuf), '#'); if (startoftags == NULL) startoftags = ""; else startoftags++; startoftags += strspn(startoftags, " \t\r\n"); newitem->allelems = strdup(startoftags); elemsize = 5; newitem->elems = (char **)malloc((elemsize+1)*sizeof(char *)); tag = newitem->allelems; elemidx = 0; while (tag && *tag) { if (elemidx == elemsize) { elemsize += 5; newitem->elems = (char **)realloc(newitem->elems, (elemsize+1)*sizeof(char *)); } newitem->elems[elemidx] = tag; /* Skip until we hit a whitespace or a quote */ tag += strcspn(tag, " \t\r\n\""); if (*tag == '"') { delim = tag; /* Hit a quote - skip until the next matching quote */ tag = strchr(tag+1, '"'); if (tag != NULL) { /* Found end-quote, NULL the item here and move on */ *tag = '\0'; tag++; } /* Now move quoted data one byte down (including the NUL) to kill quotechar */ memmove(delim, delim+1, strlen(delim)); } else if (*tag) { /* Normal end of item, NULL it and move on */ *tag = '\0'; tag++; } else { /* End of line - no more to do. */ tag = NULL; } /* * If we find a "noconn", drop preference value to 0. * If we find a "prefer", up reference value to 2. */ if ((newitem->preference == 1) && (strcmp(newitem->elems[elemidx], "noconn") == 0)) newitem->preference = 0; else if (strcmp(newitem->elems[elemidx], "prefer") == 0) newitem->preference = 2; /* Skip whitespace until start of next tag */ if (tag) tag += strspn(tag, " \t\r\n"); elemidx++; } newitem->elems[elemidx] = NULL; /* See if this host is defined before */ handle = rbtFind(htree, newitem->bbhostname); if (strcasecmp(newitem->bbhostname, ".default.") == 0) { /* The pseudo DEFAULT host */ newitem->next = NULL; defaulthost = newitem; } else if (handle == rbtEnd(htree)) { /* New item, so add to end of list */ newitem->next = NULL; if (namehead == NULL) namehead = nametail = newitem; else { nametail->next = newitem; nametail = newitem; } rbtInsert(htree, newitem->bbhostname, newitem); } else { /* Find the existing record - compare the record pointer instead of the name */ namelist_t *existingrec = (namelist_t *)gettreeitem(htree, handle); for (iwalk = namehead, iprev = NULL; ((iwalk != existingrec) && iwalk); iprev = iwalk, iwalk = iwalk->next) ; if (newitem->preference <= iwalk->preference) { /* Add after the existing (more preferred) entry */ newitem->next = iwalk->next; iwalk->next = newitem; } else { /* New item has higher preference, so add before the iwalk item (i.e. after iprev) */ if (iprev == NULL) { newitem->next = namehead; namehead = newitem; } else { newitem->next = iprev->next; iprev->next = newitem; } } } newitem->clientname = bbh_find_item(newitem, BBH_CLIENTALIAS); if (newitem->clientname == NULL) newitem->clientname = newitem->bbhostname; newitem->downtime = bbh_find_item(newitem, BBH_DOWNTIME); MEMUNDEFINE(clientname); MEMUNDEFINE(downtime); } } stackfclose(bbhosts); freestrbuffer(inbuf); rbtDelete(htree); MEMUNDEFINE(hostname); MEMUNDEFINE(l); build_hosttree(); return 0; }
int addmessage(char *inbuf) { RbtIterator phandle; xymon_peer_t *peer; int bcastmsg = 0; int inlen = strlen(inbuf); if (locatorbased) { char *hostname, *hostend, *peerlocation; /* xymond sends us messages with the KEY in the first field, between a '/' and a '|' */ hostname = inbuf + strcspn(inbuf, "/|\r\n"); if (*hostname != '/') { errprintf("No key field in message, dropping it\n"); return -1; /* Malformed input */ } hostname++; bcastmsg = (*hostname == '*'); if (!bcastmsg) { /* Lookup which server handles this host */ hostend = hostname + strcspn(hostname, "|\r\n"); if (*hostend != '|') { errprintf("No delimiter found in input, dropping it\n"); return -1; /* Malformed input */ } *hostend = '\0'; peerlocation = locator_query(hostname, locatorservice, NULL); /* * If we get no response, or an empty response, * then there is no server capable of handling this * request. */ if (!peerlocation || (*peerlocation == '\0')) { errprintf("No response from locator for %s/%s, dropping it\n", servicetype_names[locatorservice], hostname); return -1; } *hostend = '|'; phandle = rbtFind(peers, peerlocation); if (phandle == rbtEnd(peers)) { /* New peer - register it */ addnetpeer(peerlocation); phandle = rbtFind(peers, peerlocation); } } } else { phandle = rbtFind(peers, ""); } if (bcastmsg) { for (phandle = rbtBegin(peers); (phandle != rbtEnd(peers)); phandle = rbtNext(peers, phandle)) { peer = (xymon_peer_t *)gettreeitem(peers, phandle); addmessage_onepeer(peer, inbuf, inlen); } } else { if (phandle == rbtEnd(peers)) { errprintf("No peer found to handle message, dropping it\n"); return -1; } peer = (xymon_peer_t *)gettreeitem(peers, phandle); addmessage_onepeer(peer, inbuf, inlen); } return 0; }
int main(int argc, char *argv[]) { int argi; struct sigaction sa; namelist_t *hostwalk; time_t nexttimeout; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--server=")) { char *p = strchr(argv[argi], '='); serverip = strdup(p+1); } else if (argnmatch(argv[argi], "--interval=")) { char *p = strchr(argv[argi], '='); pollinterval = atoi(p+1); } else if (argnmatch(argv[argi], "--log-interval=")) { char *p = strchr(argv[argi], '='); errorloginterval = atoi(p+1); } else if (argnmatch(argv[argi], "--id=")) { char *p = strchr(argv[argi], '='); serverid = atoi(p+1); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } } setup_signalhandler("hobbitfetch"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigmisc_handler; sigaction(SIGHUP, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGUSR1, &sa, NULL); /* SIGUSR1 triggers logging of active requests */ clients = rbtNew(name_compare); nexttimeout = time(NULL) + 60; { /* Seed the random number generator */ struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); srandom(tv.tv_usec); } do { RbtIterator handle; conn_t *connwalk, *cprev; fd_set fdread, fdwrite; int n, maxfd; struct timeval tmo; time_t now; now = time(NULL); if (now > reloadtime) { /* Time to reload the bb-hosts file */ reloadtime = now + 600; load_hostnames(xgetenv("BBHOSTS"), NULL, get_fqdn()); for (hostwalk = first_host(); (hostwalk); hostwalk = hostwalk->next) { char *hname; clients_t *newclient; if (!bbh_item(hostwalk, BBH_FLAG_PULLDATA)) continue; hname = bbh_item(hostwalk, BBH_HOSTNAME); handle = rbtFind(clients, hname); if (handle == rbtEnd(clients)) { newclient = (clients_t *)calloc(1, sizeof(clients_t)); newclient->hostname = strdup(hname); rbtInsert(clients, newclient->hostname, newclient); whentoqueue = now; } } } now = time(NULL); if (now > nexttimeout) { /* Check for connections that have timed out */ nexttimeout = now + 60; for (connwalk = chead; (connwalk); connwalk = connwalk->next) { if ((connwalk->tstamp + 60) < now) { if (debug || (connwalk->client->nexterrortxt < now)) { errprintf("Timeout while talking to %s (req %lu): Aborting session\n", addrstring(&connwalk->caddr), connwalk->seq); connwalk->client->nexterrortxt = now + errorloginterval; } flag_cleanup(connwalk); } } } if (needcleanup) { /* Remove any finished requests */ needcleanup = 0; connwalk = chead; cprev = NULL; dbgprintf("Doing cleanup\n"); while (connwalk) { conn_t *zombie; if ((connwalk->action == C_READING) || (connwalk->action == C_WRITING)) { /* Active connection - skip to the next conn_t record */ cprev = connwalk; connwalk = connwalk->next; continue; } if (connwalk->action == C_CLEANUP) { if (connwalk->ctype == C_CLIENT) { /* * Finished getting data from a client, * flag idle and set next poll time. */ connwalk->client->busy = 0; set_polltime(connwalk->client); } else if (connwalk->ctype == C_SERVER) { /* Nothing needed for server cleanups */ } } /* Unlink the request from the list of active connections */ zombie = connwalk; if (cprev == NULL) { chead = zombie->next; connwalk = chead; cprev = NULL; } else { cprev->next = zombie->next; connwalk = zombie->next; } /* Purge the zombie */ dbgprintf("Request completed: req %lu, peer %s, action was %d, type was %d\n", zombie->seq, addrstring(&zombie->caddr), zombie->action, zombie->ctype); close(zombie->sockfd); freestrbuffer(zombie->msgbuf); xfree(zombie); } /* Set the tail pointer correctly */ ctail = chead; if (ctail) { while (ctail->next) ctail = ctail->next; } } if (dumpsessions) { /* Set by SIGUSR1 - dump the list of active requests */ dumpsessions = 0; for (connwalk = chead; (connwalk); connwalk = connwalk->next) { char *ctypestr, *actionstr; char timestr[30]; switch (connwalk->ctype) { case C_CLIENT: ctypestr = "client"; break; case C_SERVER: ctypestr = "server"; break; } switch (connwalk->action) { case C_READING: actionstr = "reading"; break; case C_WRITING: actionstr = "writing"; break; case C_CLEANUP: actionstr = "cleanup"; break; } strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&connwalk->tstamp)); errprintf("Request %lu: state %s/%s, peer %s, started %s (%lu secs ago)\n", connwalk->seq, ctypestr, actionstr, addrstring(&connwalk->caddr), timestr, (now - connwalk->tstamp)); } } now = time(NULL); if (now >= whentoqueue) { /* Scan host-tree for clients we need to contact */ for (handle = rbtBegin(clients); (handle != rbtEnd(clients)); handle = rbtNext(clients, handle)) { clients_t *clientwalk; char msgline[100]; strbuffer_t *request; char *pullstr, *ip; int port; clientwalk = (clients_t *)gettreeitem(clients, handle); if (clientwalk->busy) continue; if (clientwalk->nextpoll > now) continue; /* Deleted hosts stay in our tree - but should disappear from the known hosts */ hostwalk = hostinfo(clientwalk->hostname); if (!hostwalk) continue; pullstr = bbh_item(hostwalk, BBH_FLAG_PULLDATA); if (!pullstr) continue; ip = strchr(pullstr, '='); port = atoi(xgetenv("BBPORT")); if (!ip) { ip = strdup(bbh_item(hostwalk, BBH_IP)); } else { /* There is an explicit IP setting in the pulldata tag */ char *p; ip++; /* Skip the '=' */ ip = strdup(ip); p = strchr(ip, ':'); if (p) { *p = '\0'; port = atoi(p+1); } if (*ip == '\0') { /* No IP given, just a port number */ xfree(ip); ip = strdup(bbh_item(hostwalk, BBH_IP)); } } if (strcmp(ip, "0.0.0.0") == 0) { struct hostent *hent; xfree(ip); ip = NULL; hent = gethostbyname(clientwalk->hostname); if (hent) { struct in_addr addr; memcpy(&addr, *(hent->h_addr_list), sizeof(addr)); ip = strdup(inet_ntoa(addr)); } } if (!ip) continue; /* * Build the "pullclient" request, which includes the latest * clientdata config we got from the server. Keep the clientdata * here - we send "pullclient" requests more often that we actually * contact the server, but we should provide the config data always. */ request = newstrbuffer(0); sprintf(msgline, "pullclient %d\n", serverid); addtobuffer(request, msgline); if (clientwalk->clientdata) addtobuffer(request, clientwalk->clientdata); /* Put the request on the connection queue */ addrequest(C_CLIENT, ip, port, request, clientwalk); clientwalk->busy = 1; xfree(ip); } } /* Handle request queue */ FD_ZERO(&fdread); FD_ZERO(&fdwrite); maxfd = -1; for (connwalk = chead; (connwalk); connwalk = connwalk->next) { switch (connwalk->action) { case C_READING: FD_SET(connwalk->sockfd, &fdread); if (connwalk->sockfd > maxfd) maxfd = connwalk->sockfd; break; case C_WRITING: FD_SET(connwalk->sockfd, &fdwrite); if (connwalk->sockfd > maxfd) maxfd = connwalk->sockfd; break; case C_CLEANUP: break; } } /* Do select with a 1 second timeout */ tmo.tv_sec = 1; tmo.tv_usec = 0; n = select(maxfd+1, &fdread, &fdwrite, NULL, &tmo); if (n == -1) { if (errno == EINTR) continue; /* Interrupted, e.g. a SIGHUP */ /* This is a "cannot-happen" failure. Bail out */ errprintf("select failure: %s\n", strerror(errno)); return 0; } if (n == 0) continue; /* Timeout */ for (connwalk = chead; (connwalk); connwalk = connwalk->next) { switch (connwalk->action) { case C_READING: if (FD_ISSET(connwalk->sockfd, &fdread)) grabdata(connwalk); break; case C_WRITING: if (FD_ISSET(connwalk->sockfd, &fdwrite)) senddata(connwalk); break; case C_CLEANUP: break; } } } while (running); return 0; }
nkconf_t *get_nkconfig(char *key, int flags, char **resultkey) { static RbtHandle handle; static char *realkey = NULL; void *k1, *k2; nkconf_t *result = NULL; int isclone; if (resultkey) *resultkey = NULL; switch (flags) { case NKCONF_TIMEFILTER: handle = findrec(key); /* We may have hit a cloned record, so use the real key for further searches */ if (handle != rbtEnd(rbconf)) { rbtKeyValue(rbconf, handle, &k1, &k2); realkey = k1; } while (handle != rbtEnd(rbconf)) { rbtKeyValue(rbconf, handle, &k1, &k2); result = (nkconf_t *)k2; if (timecheck(result->starttime, result->endtime, result->nktime)) return result; /* Go to the next */ handle = rbtNext(rbconf, handle); if (handle != rbtEnd(rbconf)) { rbtKeyValue(rbconf, handle, &k1, &k2); if (strncmp(realkey, ((nkconf_t *)k2)->key, strlen(realkey)) != 0) handle=rbtEnd(rbconf); } } realkey = NULL; break; case NKCONF_FIRSTMATCH: handle = findrec(key); realkey = NULL; if (handle != rbtEnd(rbconf)) { rbtKeyValue(rbconf, handle, &k1, &k2); realkey = (char *)k1; } break; case NKCONF_FIRST: realkey = NULL; handle = rbtBegin(rbconf); if (handle == rbtEnd(rbconf)) return NULL; do { rbtKeyValue(rbconf, handle, &k1, &k2); realkey = (char *)k1; isclone = (*(realkey + strlen(realkey) - 1) == '='); if (isclone) handle = rbtNext(rbconf, handle); } while (isclone && (handle != rbtEnd(rbconf))); break; case NKCONF_NEXT: if (!realkey || (handle == rbtEnd(rbconf))) return NULL; isclone = 1; while (isclone && (handle != rbtEnd(rbconf))) { handle = rbtNext(rbconf, handle); if (handle) { rbtKeyValue(rbconf, handle, &k1, &k2); realkey = (char *)k1; isclone = (*(realkey + strlen(realkey) - 1) == '='); } } break; case NKCONF_RAW_FIRST: handle = rbtBegin(rbconf); realkey = NULL; break; case NKCONF_RAW_NEXT: handle = rbtNext(rbconf, handle); realkey = NULL; break; case NKCONF_FIRSTHOSTMATCH: do { int found = 0; char *delim; realkey = NULL; handle = rbtBegin(rbconf); while (!found && (handle != rbtEnd(rbconf))) { rbtKeyValue(rbconf, handle, &k1, &k2); realkey = (char *)k1; delim = realkey + strlen(key); /* OK even if past end of realkey */ found = ((strncmp(realkey, key, strlen(key)) == 0) && ((*delim == '|') || (*delim == '='))); if (!found) { handle = rbtNext(rbconf, handle); realkey = NULL; } } if ((handle != rbtEnd(rbconf)) && (*(realkey + strlen(realkey) - 1) == '=')) { key = (char *)k2; isclone = 1; } else isclone = 0; } while (isclone && (handle != rbtEnd(rbconf))); break; } if (handle == rbtEnd(rbconf)) { realkey = NULL; return NULL; } rbtKeyValue(rbconf, handle, &k1, &k2); if (resultkey) *resultkey = (char *)k1; result = (nkconf_t *)k2; return result; }
int do_la_rrd(char *hostname, char *testname, char *msg, time_t tstamp) { static char *la_params[] = { "rrdcreate", rrdfn, "DS:la:GAUGE:600:0:U", rra1, rra2, rra3, rra4, NULL }; static char *la_tpl = NULL; static pcre *as400_exp = NULL; static pcre *zVM_exp = NULL; static time_t starttime = 0; char *p, *eoln = NULL; int gotusers=0, gotprocs=0, gotload=0, gotclock=0; int users=0, procs=0, load=0, clockdiff=0; time_t now = time(NULL); if (la_tpl == NULL) la_tpl = setup_template(la_params); if (starttime == 0) starttime = now; if (strstr(msg, "bb-xsnmp") || strstr(msg, "netapp.pl")) { /* * bb-xsnmp.pl script output. * * green Tue Apr 5 12:57:37 2005 up: 254.58 days, CPU Usage= 9% * * &green CPU Time in Busy Mode: 9% * &green CPU Time in Idle Mode: 91% * * &yellow CPU Usage Threshold: 90% * &red CPU Usage Threshold: 95% * * <!-- Enterprise: netapp , Version: 6.42 --> * bb-xsnmp.pl Version: 1.78 */ p = strstr(msg, "CPU Usage="); if (p) { p += strlen("CPU Usage="); gotload = 1; load = atoi(p); } goto done_parsing; } else if (strstr(msg, "z/VM") || strstr(msg, "VSE/ESA") || strstr(msg, "z/VSE")) { /* z/VM cpu message. Looks like this, from Rich Smrcina: * green 5 Apr 2005 20:07:34 CPU Utilization 7% z/VM Version 4 Release 4.0, service level 0402 (32-bit) AVGPROC-007% 01 * VSE/ESA or z/VSE cpu message. Looks like this, from Rich Smrcina: * VSE/ESA 2.7.2 cr IPLed on ... * or * z/VSE 3.1.1 cr IPLed on ... */ int ovector[30]; char w[100]; int res; if (zVM_exp == NULL) { const char *errmsg = NULL; int errofs = 0; zVM_exp = pcre_compile(".* CPU Utilization *([0-9]+)%", PCRE_CASELESS, &errmsg, &errofs, NULL); } res = pcre_exec(zVM_exp, NULL, msg, strlen(msg), 0, 0, ovector, (sizeof(ovector)/sizeof(int))); if (res >= 0) { /* We have a match - pick up the data. */ *w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 1, w, sizeof(w)); if (strlen(w)) { load = atoi(w); gotload = 1; } } goto done_parsing; } eoln = strchr(msg, '\n'); if (eoln) *eoln = '\0'; p = strstr(msg, "up: "); if (!p) p = strstr(msg, "Uptime:"); /* Netapp filerstats2bb script */ if (!p) p = strstr(msg, "uptime:"); if (p) { /* First line of cpu report, contains "up: 159 days, 1 users, 169 procs, load=21" */ p = strchr(p, ','); if (p) { gotusers = (sscanf(p, ", %d users", &users) == 1); p = strchr(p+1, ','); } if (p) { gotprocs = (sscanf(p, ", %d procs", &procs) == 1); p = strchr(p+1, ','); } /* * Load can be either * - "load=xx%" (Windows) * - "load=xx.xx" (Unix, DISPREALLOADAVG=TRUE) * - "load=xx" (Unix, DISPREALLOADAVG=FALSE) * * We want the load in percent (Windows), or LA*100 (Unix). */ p = strstr(msg, "load="); if (p) { p += 5; if (strchr(p, '%')) { gotload = 1; load = atoi(p); } else if (strchr(p, '.')) { gotload = 1; load = 100*atoi(p); /* Find the decimal part, and cut off at 2 decimals */ p = strchr(p, '.'); if (strlen(p) > 3) *(p+3) = '\0'; load += atoi(p+1); } else { gotload = 1; load = atoi(p); } } } else { /* * No "uptime" in message - could be from an AS/400. They look like this: * green March 21, 2005 12:33:24 PM EST deltacdc 108 users 45525 jobs(126 batch,0 waiting for message), load=26% */ int ovector[30]; char w[100]; int res; if (as400_exp == NULL) { const char *errmsg = NULL; int errofs = 0; as400_exp = pcre_compile(".* ([0-9]+) users ([0-9]+) jobs.* load=([0-9]+)\\%", PCRE_CASELESS, &errmsg, &errofs, NULL); } res = pcre_exec(as400_exp, NULL, msg, strlen(msg), 0, 0, ovector, (sizeof(ovector)/sizeof(int))); if (res >= 0) { /* We have a match - pick up the AS/400 data. */ *w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 1, w, sizeof(w)); if (strlen(w)) { users = atoi(w); gotusers = 1; } *w = '\0'; if (res > 0) pcre_copy_substring(msg, ovector, res, 3, w, sizeof(w)); if (strlen(w)) { load = atoi(w); gotload = 1; } } } done_parsing: if (eoln) *eoln = '\n'; p = strstr(msg, "System clock is "); if (p) { if (sscanf(p, "System clock is %d seconds off", &clockdiff) == 1) gotclock = 1; } if (!gotload) { /* See if it's a report from the ciscocpu.pl script. */ p = strstr(msg, "<br>CPU 5 min average:"); if (p) { /* It reports in % cpu utilization */ p = strchr(p, ':'); load = atoi(p+1); gotload = 1; } } if (gotload) { sprintf(rrdfn, "la.rrd"); sprintf(rrdvalues, "%d:%d", (int)tstamp, load); create_and_update_rrd(hostname, rrdfn, la_params, la_tpl); } if (gotprocs) { sprintf(rrdfn, "procs.rrd"); sprintf(rrdvalues, "%d:%d", (int)tstamp, procs); create_and_update_rrd(hostname, rrdfn, la_params, la_tpl); } if (gotusers) { sprintf(rrdfn, "users.rrd"); sprintf(rrdvalues, "%d:%d", (int)tstamp, users); create_and_update_rrd(hostname, rrdfn, la_params, la_tpl); } if (gotclock) { sprintf(rrdfn, "clock.rrd"); sprintf(rrdvalues, "%d:%d", (int)tstamp, clockdiff); create_and_update_rrd(hostname, rrdfn, la_params, la_tpl); } /* * If we have run for less than 6 minutes, drop the memory updates here. * We want to be sure not to use memory statistics from the CPU report * if there is a memory add-on sending a separate memory statistics */ if ((now - starttime) < 360) return 0; if (!memhosts_init || (rbtFind(memhosts, hostname) == rbtEnd(memhosts))) { /* Pick up memory statistics */ int found, overflow, realuse, swapuse; long long phystotal, physavail, pagetotal, pageavail; found = overflow = realuse = swapuse = 0; phystotal = physavail = pagetotal = pageavail = 0; p = strstr(msg, "Total Physical memory:"); if (p) { phystotal = str2ll(strchr(p, ':') + 1, NULL); if (phystotal != LONG_MAX) found++; else overflow++; } if (found == 1) { p = strstr(msg, "Available Physical memory:"); if (p) { physavail = str2ll(strchr(p, ':') + 1, NULL); if (physavail != LONG_MAX) found++; else overflow++; } } if (found == 2) { p = strstr(msg, "Total PageFile size:"); if (p) { pagetotal = str2ll(strchr(p, ':') + 1, NULL); if (pagetotal != LONG_MAX) found++; else overflow++; } } if (found == 3) { p = strstr(msg, "Available PageFile size:"); if (p) { pageavail = str2ll(strchr(p, ':') + 1, NULL); if (pageavail != LONG_MAX) found++; else overflow++; } } if (found == 4) { phystotal = phystotal / 100; pagetotal = pagetotal / 100; realuse = 100 - (physavail / phystotal); swapuse = 100 - (pageavail / pagetotal); do_memory_rrd_update(tstamp, hostname, realuse, swapuse, -1); } else if (overflow) { errprintf("Host %s cpu report overflows in memory usage calculation\n", hostname); } } return 0; }
int update_nkconfig(nkconf_t *rec) { char *bakfn; FILE *bakfd; unsigned char buf[8192]; int n; struct stat st; struct utimbuf ut; RbtHandle handle; FILE *fd; int result = 0; /* First, copy the old file */ bakfn = (char *)malloc(strlen(configfn) + 5); sprintf(bakfn, "%s.bak", configfn); if (stat(configfn, &st) == 0) { ut.actime = st.st_atime; ut.modtime = st.st_mtime; } else ut.actime = ut.modtime = getcurrenttime(NULL); fd = fopen(configfn, "r"); if (fd) { bakfd = fopen(bakfn, "w"); if (bakfd) { while ((n = fread(buf, 1, sizeof(buf), fd)) > 0) fwrite(buf, 1, n, bakfd); fclose(bakfd); utime(bakfn, &ut); } fclose(fd); } xfree(bakfn); fd = fopen(configfn, "w"); if (fd == NULL) { errprintf("Cannot open output file %s\n", configfn); return 1; } if (rec) { handle = rbtFind(rbconf, rec->key); if (handle == rbtEnd(rbconf)) rbtInsert(rbconf, rec->key, rec); } handle = rbtBegin(rbconf); while (handle != rbtEnd(rbconf)) { void *k1, *k2; char *onekey; rbtKeyValue(rbconf, handle, &k1, &k2); onekey = (char *)k1; if (*(onekey + strlen(onekey) - 1) == '=') { char *pointsto = (char *)k2; char *hostname; hostname = strdup(onekey); *(hostname + strlen(hostname) - 1) = '\0'; fprintf(fd, "%s|=%s\n", hostname, pointsto); } else { nkconf_t *onerec = (nkconf_t *)k2; char startstr[20], endstr[20]; *startstr = *endstr = '\0'; if (onerec->starttime > 0) sprintf(startstr, "%d", (int)onerec->starttime); if (onerec->endtime > 0) sprintf(endstr, "%d", (int)onerec->endtime); fprintf(fd, "%s|%s|%s|%s|%d|%s|%s|%s\n", onekey, startstr, endstr, (onerec->nktime ? onerec->nktime : ""), onerec->priority, (onerec->ttgroup ? onerec->ttgroup : ""), (onerec->ttextra ? onerec->ttextra : ""), (onerec->updinfo ? onerec->updinfo : "")); } handle = rbtNext(rbconf, handle); } fclose(fd); return result; }
int main(int argc, char *argv[]) { int daemonize = 0; char *pidfile = NULL; char *envarea = NULL; int cnid = -1; pcre *msgfilter = NULL; pcre *stdfilter = NULL; int argi; struct sigaction sa; RbtIterator handle; /* Dont save the error buffer */ save_errbuf = 0; /* Create the peer container */ peers = rbtNew(name_compare); for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--debug")) { debug = 1; } else if (argnmatch(argv[argi], "--channel=")) { char *cn = strchr(argv[argi], '=') + 1; for (cnid = C_STATUS; (channelnames[cnid] && strcmp(channelnames[cnid], cn)); cnid++) ; if (channelnames[cnid] == NULL) cnid = -1; } else if (argnmatch(argv[argi], "--daemon")) { daemonize = 1; } else if (argnmatch(argv[argi], "--no-daemon")) { daemonize = 0; } else if (argnmatch(argv[argi], "--pidfile=")) { char *p = strchr(argv[argi], '='); pidfile = strdup(p+1); } else if (argnmatch(argv[argi], "--log=")) { char *p = strchr(argv[argi], '='); logfn = strdup(p+1); } else if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (argnmatch(argv[argi], "--locator=")) { char *p = strchr(argv[argi], '='); locator_init(p+1); locatorbased = 1; } else if (argnmatch(argv[argi], "--service=")) { char *p = strchr(argv[argi], '='); locatorservice = get_servicetype(p+1); } else if (argnmatch(argv[argi], "--filter=")) { char *p = strchr(argv[argi], '='); msgfilter = compileregex(p+1); if (!msgfilter) { errprintf("Invalid filter (bad expression): %s\n", p+1); } else { stdfilter = compileregex("^@@(logrotate|shutdown|drophost|droptest|renamehost|renametest)"); } } else { char *childcmd; char **childargs; int i = 0; childcmd = argv[argi]; childargs = (char **) calloc((1 + argc - argi), sizeof(char *)); while (argi < argc) { childargs[i++] = argv[argi++]; } addlocalpeer(childcmd, childargs); } } /* Sanity checks */ if (cnid == -1) { errprintf("No channel/unknown channel specified\n"); return 1; } if (locatorbased && (locatorservice == ST_MAX)) { errprintf("Must specify --service when using locator\n"); return 1; } if (!locatorbased && (rbtBegin(peers) == rbtEnd(peers))) { errprintf("Must specify command for local worker\n"); return 1; } /* Do cache responses to avoid doing too many lookups */ if (locatorbased) locator_prepcache(locatorservice, 0); /* Go daemon */ if (daemonize) { /* Become a daemon */ pid_t daemonpid = fork(); if (daemonpid < 0) { /* Fork failed */ errprintf("Could not fork child\n"); exit(1); } else if (daemonpid > 0) { /* Parent creates PID file and exits */ FILE *fd = NULL; if (pidfile) fd = fopen(pidfile, "w"); if (fd) { fprintf(fd, "%d\n", (int)daemonpid); fclose(fd); } exit(0); } /* Child (daemon) continues here */ setsid(); } /* Catch signals */ setup_signalhandler("xymond_channel"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGCHLD, &sa, NULL); signal(SIGALRM, SIG_IGN); /* Switch stdout/stderr to the logfile, if one was specified */ freopen("/dev/null", "r", stdin); /* xymond_channel's stdin is not used */ if (logfn) { freopen(logfn, "a", stdout); freopen(logfn, "a", stderr); } /* Attach to the channel */ channel = setup_channel(cnid, CHAN_CLIENT); if (channel == NULL) { errprintf("Channel not available\n"); running = 0; } while (running) { /* * Wait for GOCLIENT to go up. * * Note that we use IPC_NOWAIT if there are messages in the * queue, because then we just want to pick up a message if * there is one, and if not we want to continue pushing the * queued data to the worker. */ struct sembuf s; int n; s.sem_num = GOCLIENT; s.sem_op = -1; s.sem_flg = ((pendingcount > 0) ? IPC_NOWAIT : 0); n = semop(channel->semid, &s, 1); if (n == 0) { /* * GOCLIENT went high, and so we got alerted about a new * message arriving. Copy the message to our own buffer queue. */ char *inbuf = NULL; if (!msgfilter || matchregex(channel->channelbuf, msgfilter) || matchregex(channel->channelbuf, stdfilter)) { inbuf = strdup(channel->channelbuf); } /* * Now we have safely stored the new message in our buffer. * Wait until any other clients on the same channel have picked up * this message (GOCLIENT reaches 0). * * We wrap this into an alarm handler, because it can occasionally * fail, causing the whole system to lock up. We dont want that.... * We'll set the alarm to trigger after 1 second. Experience shows * that we'll either succeed in a few milliseconds, or fail completely * and wait the full alarm-timer duration. */ gotalarm = 0; signal(SIGALRM, sig_handler); alarm(2); do { s.sem_num = GOCLIENT; s.sem_op = 0; s.sem_flg = 0; n = semop(channel->semid, &s, 1); } while ((n == -1) && (errno == EAGAIN) && running && (!gotalarm)); signal(SIGALRM, SIG_IGN); if (gotalarm) { errprintf("Gave up waiting for GOCLIENT to go low.\n"); } /* * Let master know we got it by downing BOARDBUSY. * This should not block, since BOARDBUSY is upped * by the master just before he ups GOCLIENT. */ do { s.sem_num = BOARDBUSY; s.sem_op = -1; s.sem_flg = IPC_NOWAIT; n = semop(channel->semid, &s, 1); } while ((n == -1) && (errno == EINTR)); if (n == -1) { errprintf("Tried to down BOARDBUSY: %s\n", strerror(errno)); } if (inbuf) { /* * See if they want us to rotate logs. We pass this on to * the worker module as well, but must handle our own logfile. */ if (strncmp(inbuf, "@@logrotate", 11) == 0) { freopen(logfn, "a", stdout); freopen(logfn, "a", stderr); } /* * Put the new message on our outbound queue. */ if (addmessage(inbuf) != 0) { /* Failed to queue message, free the buffer */ xfree(inbuf); } } } else { if (errno != EAGAIN) { dbgprintf("Semaphore wait aborted: %s\n", strerror(errno)); continue; } } /* * We've picked up messages from the master. Now we * must push them to the worker process. Since there * is no way to hang off both a semaphore and select(), * we'll just push as much data as possible into the * pipe. If we get to a point where we would block, * then wait a teeny bit of time and restart the * whole loop with checking for new messages from the * master etc. * * In theory, this could become an almost busy-wait loop. * In practice, however, the queue will be empty most * of the time because we'll just shove the data to the * worker child. */ for (handle = rbtBegin(peers); (handle != rbtEnd(peers)); handle = rbtNext(peers, handle)) { int canwrite = 1, hasfailed = 0; xymon_peer_t *pwalk; time_t msgtimeout = gettimer() - MSGTIMEOUT; int flushcount = 0; pwalk = (xymon_peer_t *) gettreeitem(peers, handle); if (pwalk->msghead == NULL) continue; /* Ignore peers with nothing queued */ switch (pwalk->peerstatus) { case P_UP: canwrite = 1; break; case P_DOWN: openconnection(pwalk); canwrite = (pwalk->peerstatus == P_UP); break; case P_FAILED: canwrite = 0; break; } /* See if we have stale messages queued */ while (pwalk->msghead && (pwalk->msghead->tstamp < msgtimeout)) { flushmessage(pwalk); flushcount++; } if (flushcount) { errprintf("Flushed %d stale messages for %s:%d\n", flushcount, inet_ntoa(pwalk->peeraddr.sin_addr), ntohs(pwalk->peeraddr.sin_port)); } while (pwalk->msghead && canwrite) { fd_set fdwrite; struct timeval tmo; /* Check that this peer is ready for writing. */ FD_ZERO(&fdwrite); FD_SET(pwalk->peersocket, &fdwrite); tmo.tv_sec = 0; tmo.tv_usec = 2000; n = select(pwalk->peersocket+1, NULL, &fdwrite, NULL, &tmo); if (n == -1) { errprintf("select() failed: %s\n", strerror(errno)); canwrite = 0; hasfailed = 1; continue; } else if ((n == 0) || (!FD_ISSET(pwalk->peersocket, &fdwrite))) { canwrite = 0; continue; } n = write(pwalk->peersocket, pwalk->msghead->bufp, pwalk->msghead->buflen); if (n >= 0) { pwalk->msghead->bufp += n; pwalk->msghead->buflen -= n; if (pwalk->msghead->buflen == 0) flushmessage(pwalk); } else if (errno == EAGAIN) { /* * Write would block ... stop for now. */ canwrite = 0; } else { hasfailed = 1; } if (hasfailed) { /* Write failed, or message grew stale */ errprintf("Peer at %s:%d failed: %s\n", inet_ntoa(pwalk->peeraddr.sin_addr), ntohs(pwalk->peeraddr.sin_port), strerror(errno)); canwrite = 0; shutdownconnection(pwalk); if (pwalk->peertype == P_NET) locator_serverdown(pwalk->peername, locatorservice); pwalk->peerstatus = P_FAILED; } } } } /* Detach from channels */ close_channel(channel, CHAN_CLIENT); /* Close peer connections */ for (handle = rbtBegin(peers); (handle != rbtEnd(peers)); handle = rbtNext(peers, handle)) { xymon_peer_t *pwalk = (xymon_peer_t *) gettreeitem(peers, handle); shutdownconnection(pwalk); } /* Remove the PID file */ if (pidfile) unlink(pidfile); return 0; }
void print_hoststatus(FILE *output, hstatus_t *itm, RbtHandle columns, int prio, int firsthost) { void *hinfo; char *dispname, *ip, *key; time_t now; RbtIterator colhandle; now = getcurrenttime(NULL); hinfo = hostinfo(itm->hostname); dispname = xmh_item(hinfo, XMH_DISPLAYNAME); ip = xmh_item(hinfo, XMH_IP); fprintf(output, "<TR>\n"); /* Print the priority */ fprintf(output, "<TD ALIGN=LEFT VALIGN=TOP WIDTH=25%% NOWRAP>"); if (firsthost) fprintf(output, "<FONT %s>PRIO %d</FONT>", xgetenv("XYMONPAGEROWFONT"), prio); else fprintf(output, " "); fprintf(output, "</TD>\n"); /* Print the hostname with a link to the critical systems info page */ fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", hostnamehtml(itm->hostname, NULL, usetooltips)); key = (char *)malloc(strlen(itm->hostname) + 1024); for (colhandle = rbtBegin(columns); (colhandle != rbtEnd(columns)); colhandle = rbtNext(columns, colhandle)) { void *k1, *k2; char *colname; RbtIterator sthandle; fprintf(output, "<TD ALIGN=CENTER>"); rbtKeyValue(columns, colhandle, &k1, &k2); colname = (char *)k1; sprintf(key, "%s|%s", itm->hostname, colname); sthandle = rbtFind(rbstate, key); if (sthandle == rbtEnd(rbstate)) { fprintf(output, "-"); } else { hstatus_t *column; char *htmlalttag; char *htmlackstr; rbtKeyValue(rbstate, sthandle, &k1, &k2); column = (hstatus_t *)k2; if (column->config->priority != prio) fprintf(output, "-"); else { time_t age = now - column->lastchange; char *htmlgroupstr; char *htmlextrastr; htmlalttag = alttag(colname, column->color, 0, 1, agestring(age)); htmlackstr = (column->ackmsg ? column->ackmsg : ""); htmlgroupstr = strdup(urlencode(column->config->ttgroup ? column->config->ttgroup : "")); htmlextrastr = strdup(urlencode(column->config->ttextra ? column->config->ttextra : "")); fprintf(output, "<A HREF=\"%s&NKPRIO=%d&NKTTGROUP=%s&NKTTEXTRA=%s\">", hostsvcurl(itm->hostname, colname, 1), prio, htmlgroupstr, htmlextrastr); fprintf(output, "<IMG SRC=\"%s/%s\" ALT=\"%s\" TITLE=\"%s %s\" HEIGHT=\"%s\" WIDTH=\"%s\" BORDER=0></A>", xgetenv("XYMONSKIN"), dotgiffilename(column->color, (column->acktime > 0), (age > oldlimit)), colorname(column->color), htmlalttag, htmlackstr, xgetenv("DOTHEIGHT"), xgetenv("DOTWIDTH")); xfree(htmlgroupstr); xfree(htmlextrastr); } } fprintf(output, "</TD>\n"); } xfree(key); fprintf(output, "</TR>\n"); }
int load_nkconfig(char *fn) { static void *configfiles = NULL; static int firsttime = 1; FILE *fd; strbuffer_t *inbuf; /* Setup the default configuration filename */ if (!fn) { if (!defaultfn) { char *bbhome = xgetenv("BBHOME"); defaultfn = (char *)malloc(strlen(bbhome) + strlen(DEFAULTCONFIG) + 2); sprintf(defaultfn, "%s/%s", bbhome, DEFAULTCONFIG); } fn = defaultfn; } if (configfn) xfree(configfn); configfn = strdup(fn); /* First check if there were no modifications at all */ if (configfiles) { if (!stackfmodified(configfiles)){ dbgprintf("No files modified, skipping reload of %s\n", fn); return 0; } else { stackfclist(&configfiles); configfiles = NULL; } } if (!firsttime) { /* Clean up existing datatree */ RbtHandle handle; void *k1, *k2; for (handle = rbtBegin(rbconf); (handle != rbtEnd(rbconf)); handle = rbtNext(rbconf, handle)) { rbtKeyValue(rbconf, handle, &k1, &k2); flushrec(k1, k2); } rbtDelete(rbconf); } firsttime = 0; rbconf = rbtNew(name_compare); fd = stackfopen(fn, "r", &configfiles); if (fd == NULL) return 1; inbuf = newstrbuffer(0); while (stackfgets(inbuf, NULL)) { /* Full record : Host service START END TIMESPEC TTPrio TTGroup TTExtra */ /* Clone record: Host =HOST */ char *ehost, *eservice, *estart, *eend, *etime, *ttgroup, *ttextra, *updinfo; int ttprio = 0; nkconf_t *newitem; RbtStatus status; int idx = 0; ehost = gettok(STRBUF(inbuf), "|\n"); if (!ehost) continue; eservice = gettok(NULL, "|\n"); if (!eservice) continue; if (*eservice == '=') { char *key = (char *)malloc(strlen(ehost) + 2); char *pointsto = strdup(eservice+1); sprintf(key, "%s=", ehost); status = rbtInsert(rbconf, key, pointsto); } else { estart = gettok(NULL, "|\n"); if (!estart) continue; eend = gettok(NULL, "|\n"); if (!eend) continue; etime = gettok(NULL, "|\n"); if (!etime) continue; ttprio = atoi(gettok(NULL, "|\n")); if (ttprio == 0) continue; ttgroup = gettok(NULL, "|\n"); ttextra = gettok(NULL, "|\n"); updinfo = gettok(NULL, "|\n"); newitem = (nkconf_t *)malloc(sizeof(nkconf_t)); newitem->key = (char *)malloc(strlen(ehost) + strlen(eservice) + 15); sprintf(newitem->key, "%s|%s", ehost, eservice); newitem->starttime= ((estart && *estart) ? atoi(estart) : 0); newitem->endtime = ((eend && *eend) ? atoi(eend) : 0); newitem->nktime = ((etime && *etime) ? strdup(etime) : NULL); newitem->priority = ttprio; newitem->ttgroup = strdup(ttgroup); newitem->ttextra = strdup(ttextra); newitem->updinfo = strdup(updinfo); status = rbtInsert(rbconf, newitem->key, newitem); while (status == RBT_STATUS_DUPLICATE_KEY) { idx++; sprintf(newitem->key, "%s|%s|%d", ehost, eservice, idx); status = rbtInsert(rbconf, newitem->key, newitem); } } } stackfclose(fd); freestrbuffer(inbuf); if (debug) { RbtHandle handle; handle = rbtBegin(rbconf); while (handle != rbtEnd(rbconf)) { void *k1, *k2; rbtKeyValue(rbconf, handle, &k1, &k2); printf("%s\n", (char *)k1); handle = rbtNext(rbconf, handle); } } return 0; }