/*----------------------------------------------------------------------------*/ /* Xymon hosts.cfg file grep'er */ /* */ /* This tool will pick out the hosts from a hosts.cfg file that has one of */ /* the tags given on the command line. This allows an extension script to */ /* deal with only the relevant parts of the hosts.cfg file, instead of */ /* having to parse the entire file. */ /* */ /* Copyright (C) 2003-2011 Henrik Storner */ /* */ /* This program is released under the GNU General Public License (GPL), */ /* version 2. See the file "COPYING" for details. */ /* */ /*----------------------------------------------------------------------------*/ static char rcsid[] = "$Id: xymongrep.c 7706 2015-10-19 21:54:16Z jccleaver $"; #include #include #include #include #include "version.h" #include "libxymon.h" static char *connstatus = NULL; static char *teststatus = NULL; static char *conncolumn = "conn"; static char *testcolumn = NULL; static void load_hoststatus() { int res; char msg[1024]; sendreturn_t *sres; sprintf(msg, "xymondboard fields=hostname,testname,color test=%s", conncolumn); sres = newsendreturnbuf(1, NULL); res = sendmessage(msg, NULL, XYMON_TIMEOUT, sres); if (res == XYMONSEND_OK) connstatus = getsendreturnstr(sres, 1); if ((res == XYMONSEND_OK) && testcolumn) { sprintf(msg, "xymondboard fields=hostname,testname,color test=%s", testcolumn); res = sendmessage(msg, NULL, XYMON_TIMEOUT, sres); if (res == XYMONSEND_OK) teststatus = getsendreturnstr(sres, 1); } if (res != XYMONSEND_OK) { errprintf("Cannot fetch Xymon status, ignoring --no-down\n"); connstatus = NULL; teststatus = NULL; } freesendreturnbuf(sres); } static int netok(char *netstring, char *curnet, int testuntagged) { return ( (netstring == NULL) || (curnet && netstring && (strcmp(curnet, netstring) == 0)) || (testuntagged && (curnet == NULL)) ); } static int downok(char *hostname, int nodownhosts) { char *mark, *colorstr; int color; if (!nodownhosts) return 1; /* Check if the host is down (i.e. "conn" test is non-green) */ if (!connstatus) return 1; mark = (char *)malloc(strlen(hostname) + strlen(conncolumn) + 4); sprintf(mark, "\n%s|%s|", hostname, conncolumn); colorstr = strstr(connstatus, mark); if (colorstr) { colorstr += strlen(mark); /* Skip to the color data */ } else if (strncmp(connstatus, mark+1, strlen(mark+1)) == 0) { colorstr = connstatus + strlen(mark+1); /* First entry we get */ } xfree(mark); color = (colorstr ? parse_color(colorstr) : COL_GREEN); if ((color == COL_RED) || (color == COL_BLUE)) return 0; /* Check if the test is currently disabled */ if (!teststatus) return 1; mark = (char *)malloc(strlen(hostname) + strlen(testcolumn) + 4); sprintf(mark, "\n%s|%s|", hostname, testcolumn); colorstr = strstr(teststatus, mark); if (colorstr) { colorstr += strlen(mark); /* Skip to the color data */ } else if (strncmp(teststatus, mark+1, strlen(mark+1)) == 0) { colorstr = teststatus + strlen(mark+1); /* First entry we get */ } xfree(mark); color = (colorstr ? parse_color(colorstr) : COL_GREEN); if ((color == COL_RED) || (color == COL_BLUE)) return 0; return 1; } 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 loadhostsfromxymond = 0; int onlypreferredentry = 0; char *p; char **lookv; int argi, lookc; strbuffer_t *wantedtags; lookv = (char **)malloc(argc*sizeof(char *)); lookc = 0; conncolumn = xgetenv("PINGCOLUMN"); for (argi=1; (argi < argc); argi++) { if (strcmp(argv[argi], "--debug") == 0) { char *delim = strchr(argv[argi], '='); debug = 1; if (delim) set_debugfile(delim+1, 0); } else if (strcmp(argv[argi], "--help") == 0) { printf("Usage:\n%s [options] test1 [test2] [test3] ... \n", argv[0]); exit(1); } else 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 if (strcmp(argv[argi], "--loadhostsfromxymond") == 0) { loadhostsfromxymond = 1; } else if ((*(argv[argi]) == '-') && (strlen(argv[argi]) > 1)) { fprintf(stderr, "Unknown option %s\n", argv[argi]); } else { lookv[lookc] = strdup(argv[argi]); lookc++; } } lookv[lookc] = NULL; if ((hostsfn == NULL) || (strlen(hostsfn) == 0)) { hostsfn = strdup(xgetenv("HOSTSCFG")); if (!loadhostsfromxymond) { /* The default in load_hostnames is to try xymond first when */ /* hostsfn = xgetenv("HOSTSCFG"), however we don't want that here */ /* unless we're told to explicitly. Thus, copy xymond logic here. */ hostsfn = (char *)realloc(hostsfn, strlen(hostsfn) + 2); memmove(hostsfn+1, hostsfn, strlen(hostsfn)+1); *hostsfn = '!'; } } dbgprintf("Loading host configuration from %s%s\n", (loadhostsfromxymond ? "xymond, failing back to " : ""), hostsfn); 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; }