1 /*----------------------------------------------------------------------------*/
2 /* Xymon hosts.cfg file grep'er */
3 /* */
4 /* This tool will pick out the hosts from a hosts.cfg file that has one of */
5 /* the tags given on the command line. This allows an extension script to */
6 /* deal with only the relevant parts of the hosts.cfg file, instead of */
7 /* having to parse the entire file. */
8 /* */
9 /* Copyright (C) 2003-2011 Henrik Storner <henrik@hswn.dk> */
10 /* */
11 /* This program is released under the GNU General Public License (GPL), */
12 /* version 2. See the file "COPYING" for details. */
13 /* */
14 /*----------------------------------------------------------------------------*/
15
16 static char rcsid[] = "$Id: xymongrep.c 7706 2015-10-19 21:54:16Z jccleaver $";
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22
23 #include "version.h"
24 #include "libxymon.h"
25
26 static char *connstatus = NULL;
27 static char *teststatus = NULL;
28 static char *conncolumn = "conn";
29 static char *testcolumn = NULL;
30
31
load_hoststatus()32 static void load_hoststatus()
33 {
34 int res;
35 char msg[1024];
36 sendreturn_t *sres;
37
38 sprintf(msg, "xymondboard fields=hostname,testname,color test=%s", conncolumn);
39 sres = newsendreturnbuf(1, NULL);
40 res = sendmessage(msg, NULL, XYMON_TIMEOUT, sres);
41 if (res == XYMONSEND_OK) connstatus = getsendreturnstr(sres, 1);
42
43 if ((res == XYMONSEND_OK) && testcolumn) {
44 sprintf(msg, "xymondboard fields=hostname,testname,color test=%s", testcolumn);
45 res = sendmessage(msg, NULL, XYMON_TIMEOUT, sres);
46 if (res == XYMONSEND_OK) teststatus = getsendreturnstr(sres, 1);
47 }
48
49 if (res != XYMONSEND_OK) {
50 errprintf("Cannot fetch Xymon status, ignoring --no-down\n");
51 connstatus = NULL;
52 teststatus = NULL;
53 }
54
55 freesendreturnbuf(sres);
56 }
57
58
netok(char * netstring,char * curnet,int testuntagged)59 static int netok(char *netstring, char *curnet, int testuntagged)
60 {
61 return ( (netstring == NULL) ||
62 (curnet && netstring && (strcmp(curnet, netstring) == 0)) ||
63 (testuntagged && (curnet == NULL)) );
64 }
65
downok(char * hostname,int nodownhosts)66 static int downok(char *hostname, int nodownhosts)
67 {
68 char *mark, *colorstr;
69 int color;
70
71 if (!nodownhosts) return 1;
72
73 /* Check if the host is down (i.e. "conn" test is non-green) */
74 if (!connstatus) return 1;
75 mark = (char *)malloc(strlen(hostname) + strlen(conncolumn) + 4);
76 sprintf(mark, "\n%s|%s|", hostname, conncolumn);
77 colorstr = strstr(connstatus, mark);
78 if (colorstr) {
79 colorstr += strlen(mark); /* Skip to the color data */
80 }
81 else if (strncmp(connstatus, mark+1, strlen(mark+1)) == 0) {
82 colorstr = connstatus + strlen(mark+1); /* First entry we get */
83 }
84 xfree(mark);
85 color = (colorstr ? parse_color(colorstr) : COL_GREEN);
86 if ((color == COL_RED) || (color == COL_BLUE)) return 0;
87
88 /* Check if the test is currently disabled */
89 if (!teststatus) return 1;
90 mark = (char *)malloc(strlen(hostname) + strlen(testcolumn) + 4);
91 sprintf(mark, "\n%s|%s|", hostname, testcolumn);
92 colorstr = strstr(teststatus, mark);
93 if (colorstr) {
94 colorstr += strlen(mark); /* Skip to the color data */
95 }
96 else if (strncmp(teststatus, mark+1, strlen(mark+1)) == 0) {
97 colorstr = teststatus + strlen(mark+1); /* First entry we get */
98 }
99 xfree(mark);
100 color = (colorstr ? parse_color(colorstr) : COL_GREEN);
101 if ((color == COL_RED) || (color == COL_BLUE)) return 0;
102
103 return 1;
104 }
105
main(int argc,char * argv[])106 int main(int argc, char *argv[])
107 {
108 void *hwalk;
109 char *hostsfn = NULL;
110 char *netstring = NULL;
111 char *include2 = NULL;
112 int extras = 1;
113 int testuntagged = 0;
114 int nodownhosts = 0;
115 int loadhostsfromxymond = 0;
116 int onlypreferredentry = 0;
117 char *p;
118 char **lookv;
119 int argi, lookc;
120 strbuffer_t *wantedtags;
121
122 lookv = (char **)malloc(argc*sizeof(char *));
123 lookc = 0;
124
125 conncolumn = xgetenv("PINGCOLUMN");
126
127 for (argi=1; (argi < argc); argi++) {
128 if (strcmp(argv[argi], "--debug") == 0) {
129 char *delim = strchr(argv[argi], '=');
130 debug = 1;
131 if (delim) set_debugfile(delim+1, 0);
132 }
133 else if (strcmp(argv[argi], "--help") == 0) {
134 printf("Usage:\n%s [options] test1 [test2] [test3] ... \n", argv[0]);
135 exit(1);
136 }
137 else if (strcmp(argv[argi], "--noextras") == 0) {
138 extras = 0;
139 }
140 else if (strcmp(argv[argi], "--test-untagged") == 0) {
141 testuntagged = 1;
142 }
143 else if (argnmatch(argv[argi], "--no-down")) {
144 char *p;
145 nodownhosts = 1;
146 p = strchr(argv[argi], '=');
147 if (p) testcolumn = strdup(p+1);
148 }
149 else if (strcmp(argv[argi], "--version") == 0) {
150 printf("xymongrep version %s\n", VERSION);
151 exit(0);
152 }
153 else if ((strcmp(argv[argi], "--net") == 0) || (strcmp(argv[argi], "--bbnet") == 0)) {
154 include2 = "netinclude";
155 onlypreferredentry = 0;
156 }
157 else if ((strcmp(argv[argi], "--web") == 0) || (strcmp(argv[argi], "--bbdisp") == 0)) {
158 include2 = "dispinclude";
159 onlypreferredentry = 1;
160 }
161 else if (argnmatch(argv[argi], "--hosts=")) {
162 hostsfn = strchr(argv[argi], '=') + 1;
163 }
164 else if (strcmp(argv[argi], "--loadhostsfromxymond") == 0) {
165 loadhostsfromxymond = 1;
166 }
167 else if ((*(argv[argi]) == '-') && (strlen(argv[argi]) > 1)) {
168 fprintf(stderr, "Unknown option %s\n", argv[argi]);
169 }
170 else {
171 lookv[lookc] = strdup(argv[argi]);
172 lookc++;
173 }
174 }
175 lookv[lookc] = NULL;
176
177 if ((hostsfn == NULL) || (strlen(hostsfn) == 0)) {
178 hostsfn = strdup(xgetenv("HOSTSCFG"));
179 if (!loadhostsfromxymond) {
180 /* The default in load_hostnames is to try xymond first when */
181 /* hostsfn = xgetenv("HOSTSCFG"), however we don't want that here */
182 /* unless we're told to explicitly. Thus, copy xymond logic here. */
183 hostsfn = (char *)realloc(hostsfn, strlen(hostsfn) + 2);
184 memmove(hostsfn+1, hostsfn, strlen(hostsfn)+1);
185 *hostsfn = '!';
186 }
187 }
188 dbgprintf("Loading host configuration from %s%s\n", (loadhostsfromxymond ? "xymond, failing back to " : ""), hostsfn);
189
190 load_hostnames(hostsfn, include2, get_fqdn());
191 if (first_host() == NULL) {
192 errprintf("Cannot load %s, or file is empty\n", hostsfn);
193 exit(3);
194 }
195
196 /* If we must avoid downed or disabled hosts, let's find out what those are */
197 if (nodownhosts) load_hoststatus();
198
199 /* Each network test tagged with NET:locationname */
200 p = xgetenv("XYMONNETWORK");
201 if ((p == NULL) || (strlen(p) == 0)) p = xgetenv("BBLOCATION");
202 if (p && strlen(p)) netstring = strdup(p);
203
204 hwalk = first_host();
205 wantedtags = newstrbuffer(0);
206 while (hwalk) {
207 char hostip[IP_ADDR_STRLEN];
208 char *curnet = xmh_item(hwalk, XMH_NET);
209 char *curname = xmh_item(hwalk, XMH_HOSTNAME);
210
211 /*
212 * Only look at the hosts whose NET: definition matches the wanted one.
213 * Must also check if the host is currently down (not responding to ping).
214 * And if the host is OK with knownhost(), because it may be time-limited.
215 */
216 if (netok(netstring, curnet, testuntagged) && downok(curname, nodownhosts) && knownhost(curname, hostip, GH_IGNORE)) {
217 char *item;
218
219 clearstrbuffer(wantedtags);
220 for (item = xmh_item_walk(hwalk); (item); item = xmh_item_walk(NULL)) {
221 int i;
222 char *realitem = item + strspn(item, "!~?");
223
224 for (i=0; lookv[i]; i++) {
225 char *outitem = NULL;
226
227 if (lookv[i][strlen(lookv[i])-1] == '*') {
228 if (strncasecmp(realitem, lookv[i], strlen(lookv[i])-1) == 0) {
229 outitem = (extras ? item : realitem);
230 }
231 }
232 else if (strcasecmp(realitem, lookv[i]) == 0) {
233 outitem = (extras ? item : realitem);
234 }
235
236 if (outitem) {
237 int needquotes = ((strchr(outitem, ' ') != NULL) || (strchr(outitem, '\t') != NULL));
238 addtobuffer(wantedtags, " ");
239 if (needquotes) addtobuffer(wantedtags, "\"");
240 addtobuffer(wantedtags, outitem);
241 if (needquotes) addtobuffer(wantedtags, "\"");
242 }
243 }
244 }
245
246 if (STRBUF(wantedtags) && (*STRBUF(wantedtags) != '\0') && extras) {
247 if (xmh_item(hwalk, XMH_FLAG_DIALUP)) addtobuffer(wantedtags, " dialup");
248 if (xmh_item(hwalk, XMH_FLAG_TESTIP)) addtobuffer(wantedtags, " testip");
249 }
250
251 if (STRBUF(wantedtags) && *STRBUF(wantedtags)) {
252 printf("%s %s #%s\n", xmh_item(hwalk, XMH_IP), xmh_item(hwalk, XMH_HOSTNAME), STRBUF(wantedtags));
253 }
254 }
255
256 do { hwalk = next_host(hwalk, 1); } while (hwalk && onlypreferredentry && (strcmp(curname, xmh_item(hwalk, XMH_HOSTNAME)) == 0));
257 }
258
259 return 0;
260 }
261
262