int net_worker_option(char *arg) { int res = 1; if (argnmatch(arg, "--locator=")) { char *p = strchr(arg, '='); locatorlocation = strdup(p+1); } else if (argnmatch(arg, "--locatorid=")) { char *p = strchr(arg, '='); locatorid = strdup(p+1); } else if (argnmatch(arg, "--locatorweight=")) { char *p = strchr(arg, '='); locatorweight = atoi(p+1); } else if (argnmatch(arg, "--locatorextra=")) { char *p = strchr(arg, '='); locatorextra = strdup(p+1); } else if (argnmatch(arg, "--listen=")) { char *p = strchr(arg, '='); listenipport = strdup(p+1); } else { res = 0; } return res; }
int main(int argc, char *argv[]) { int argi; char *envarea = NULL; char *critconfig = NULL; char *hffile = "critical"; for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (strcmp(argv[argi], "--tooltips") == 0) { usetooltips = 1; } else if (argnmatch(argv[argi], "--acklevel=")) { char *p = strchr(argv[argi], '='); critacklevel = atoi(p+1); } else if (argnmatch(argv[argi], "--config=")) { char *p = strchr(argv[argi], '='); critconfig = strdup(p+1); } else if (argnmatch(argv[argi], "--hffile=")) { char *p = strchr(argv[argi], '='); hffile = strdup(p+1); } } redirect_cgilog("criticalview"); setdocurl(hostsvcurl("%s", xgetenv("INFOCOLUMN"), 1)); parse_query(); load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn()); load_critconfig(critconfig); load_all_links(); fprintf(stdout, "Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); if (loadstatus(maxprio, maxage, mincolor, wantacked) == 0) { use_recentgifs = 1; generate_critpage(stdout, hffile); } else { fprintf(stdout, "Cannot load Xymon status\n"); } return 0; }
int main(int argc, char *argv[]) { int argi; char *envarea = NULL; for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } } redirect_cgilog("hobbit-notifylog"); load_hostnames(xgetenv("BBHOSTS"), NULL, get_fqdn()); fprintf(stdout, "Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); cgidata = cgi_request(); if (cgidata == NULL) { /* Present the query form */ sethostenv("", "", "", colorname(COL_BLUE), NULL); showform(stdout, "notify", "notify_form", COL_BLUE, getcurrenttime(NULL), NULL, NULL); return 0; } parse_query(); /* Now generate the webpage */ headfoot(stdout, "notify", "", "header", COL_GREEN); fprintf(stdout, "<center>\n"); do_notifylog(stdout, maxcount, maxminutes, fromtime, totime, pageregex, expageregex, hostregex, exhostregex, testregex, extestregex, rcptregex, exrcptregex); fprintf(stdout, "</center>\n"); headfoot(stdout, "notify", "", "footer", COL_GREEN); return 0; }
int standardoption(char *opt) { if (!opt) return 0; if (strcmp(opt, "--debug") == 0) { debug = 1; } else if (strcmp(opt, "--no-update") == 0) { dontsendmessages = 1; } else if (strcmp(opt, "--no-update-brief") == 0) { dontsendmessages = 2; } else if (argnmatch(opt, "--env=")) { char *p = strchr(opt, '='); loadenv(p+1, envarea); } else if (argnmatch(opt, "--area=")) { char *p = strchr(opt, '='); envarea = strdup(p+1); } else if (argnmatch(opt, "--hosts=")) { char *p = strchr(opt, '='); hostsfn = strdup(p+1); } else if (argnmatch(opt, "--log=") || argnmatch(opt, "--logfile=")) { char *p = strchr(opt, '='); logfn = strdup(p+1); } else if (argnmatch(opt, "--pidfile=") || argnmatch(opt, "--pid=")) { char *p = strchr(opt, '='); pidfn = strdup(p+1); } else if ((strcmp(opt, "--version") == 0) || (strcmp(opt, "--help") == 0) || (strcmp(opt, "-?") == 0)) { fprintf(stderr, "%s %s\n", programname, VERSION); showhelp = 1; } else { return 0; } return 1; }
int main(int argc, char *argv[]) { int argi; char *envarea = NULL; char **critconfig = NULL; int cccount = 0; char *hffile = "critical"; critconfig = (char **)calloc(1, sizeof(char *)); for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (strcmp(argv[argi], "--tooltips") == 0) { usetooltips = 1; } else if (argnmatch(argv[argi], "--acklevel=")) { char *p = strchr(argv[argi], '='); critacklevel = atoi(p+1); } else if (argnmatch(argv[argi], "--config=")) { char *p = strchr(argv[argi], '='); critconfig[cccount] = strdup(p+1); cccount++; critconfig = (char **)realloc(critconfig, (1 + cccount)*sizeof(char *)); critconfig[cccount] = NULL; } else if (argnmatch(argv[argi], "--hffile=")) { char *p = strchr(argv[argi], '='); hffile = strdup(p+1); } } if (!critconfig[0]) { critconfig = (char **)realloc(critconfig, 2*sizeof(char *)); critconfig[0] = (char *)malloc(strlen(xgetenv("XYMONHOME")) + strlen(DEFAULT_CRITCONFIGFN) + 2); sprintf(critconfig[0], "%s/%s", xgetenv("XYMONHOME"), DEFAULT_CRITCONFIGFN); critconfig[1] = NULL; } redirect_cgilog("criticalview"); setdocurl(hostsvcurl("%s", xgetenv("INFOCOLUMN"), 1)); parse_query(); load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn()); load_all_links(); fprintf(stdout, "Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); use_recentgifs = 1; if (getboard(mincolor) == 0) { int i; char *oneconfig, *onename; int *partcolor = NULL, *partprio = NULL; xtreePos_t hhandle; for (i=0; (critconfig[i]); i++) { oneconfig = strchr(critconfig[i], ':'); load_critconfig(oneconfig ? oneconfig+1 : critconfig[i]); loadstatus(maxprio, maxage, mincolor, wantacked); /* Determine background color and max. priority */ if (i == 0) { partcolor = (int *)malloc(sizeof(int)); partprio = (int *)malloc(sizeof(int)); } else { partcolor = (int *)realloc(partcolor, (i+1)*sizeof(int)); partprio = (int *)realloc(partprio, (i+1)*sizeof(int)); } partcolor[i] = COL_GREEN; partprio[i] = 0; for (hhandle = xtreeFirst(rbstate[i]); (hhandle != xtreeEnd(rbstate[i])); hhandle = xtreeNext(rbstate[i], hhandle)) { hstatus_t *itm; itm = (hstatus_t *)xtreeData(rbstate[i], hhandle); if (itm->color > partcolor[i]) partcolor[i] = itm->color; if (itm->config->priority > partprio[i]) partprio[i] = itm->config->priority; } if (partcolor[i] > pagecolor) pagecolor = partcolor[i]; } for (i=0; (critconfig[i]); i++) { oneconfig = strchr(critconfig[i], ':'); if (oneconfig) { *oneconfig = '\0'; oneconfig++; onename = (char *)malloc(strlen("DIVIDERTEXT=") + strlen(critconfig[i]) + 1); sprintf(onename, "DIVIDERTEXT=%s", critconfig[i]); putenv(onename); } else { oneconfig = critconfig[i]; putenv("DIVIDERTEXT="); } generate_critpage(rbstate[i], hostsonpage[i], stdout, (i == 0) ? (critconfig[1] ? "critmulti" : hffile) : "divider", (critconfig[i+1] == NULL) ? hffile : "divider", partcolor[i], partprio[i]); } } else { fprintf(stdout, "Cannot load Xymon status\n"); } return 0; }
int main(int argc, char *argv[]) { int argi; char *envarea = NULL; for (argi = 1; (argi < argc); argi++) { if (strcmp(argv[argi], "--historical") == 0) { source = SRC_HISTLOGS; } else if (strcmp(argv[argi], "--hobbitd") == 0) { source = SRC_HOBBITD; } else if (strncmp(argv[argi], "--history=", 10) == 0) { char *val = strchr(argv[argi], '=')+1; if (strcmp(val, "none") == 0) histlocation = HIST_NONE; else if (strcmp(val, "top") == 0) histlocation = HIST_TOP; else if (strcmp(val, "bottom") == 0) histlocation = HIST_BOTTOM; } 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 (strcmp(argv[argi], "--no-svcid") == 0) { wantserviceid = 0; } else if (argnmatch(argv[argi], "--templates=")) { char *p = strchr(argv[argi], '='); sethostenv_template(p+1); } else if (argnmatch(argv[argi], "--multigraphs=")) { char *p = strchr(argv[argi], '='); multigraphs = (char *)malloc(strlen(p+1) + 3); sprintf(multigraphs, ",%s,", p+1); } else if (strcmp(argv[argi], "--no-disable") == 0) { showenadis = 0; } else if (strcmp(argv[argi], "--no-jsvalidation") == 0) { usejsvalidation = 0; } else if (strcmp(argv[argi], "--old-nk-config") == 0) { newnkconfig = 0; } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } } redirect_cgilog("hobbitsvc"); *errortxt = '\0'; hostname = service = tstamp = NULL; if (do_request() != 0) { fprintf(stdout, "%s", errortxt); return 1; } return 0; }
int main(int argc, char *argv[]) { char *pagedir; bbgen_page_t *p; dispsummary_t *s; int i; char *pageset = NULL; char *nssidebarfilename = NULL; char *egocolumn = NULL; char *csvfile = NULL; char csvdelim = ','; int embedded = 0; int hobbitddump = 0; char *envarea = NULL; int do_normal_pages = 1; /* Setup standard header+footer (might be modified by option pageset) */ select_headers_and_footers("bb"); bb_color = bb2_color = bbnk_color = -1; pagedir = NULL; init_timestamp(); fqdn = get_fqdn(); /* Setup values from env. vars that may be overridden via commandline options */ if (xgetenv("MKBB2COLREPEAT")) { int i = atoi(xgetenv("MKBB2COLREPEAT")); if (i > 0) maxrowsbeforeheading = i; } for (i = 1; (i < argc); i++) { if ( (strcmp(argv[i], "--hobbitd") == 0) || (argnmatch(argv[i], "--purplelifetime=")) || (strcmp(argv[i], "--nopurple") == 0) ) { /* Deprecated */ } else if (argnmatch(argv[i], "--env=")) { char *lp = strchr(argv[i], '='); loadenv(lp+1, envarea); } else if (argnmatch(argv[i], "--area=")) { char *lp = strchr(argv[i], '='); envarea = strdup(lp+1); } else if (argnmatch(argv[i], "--hobbitddump")) { hobbitddump = 1; } else if (argnmatch(argv[i], "--ignorecolumns=")) { char *lp = strchr(argv[i], '='); ignorecolumns = (char *) malloc(strlen(lp)+2); sprintf(ignorecolumns, ",%s,", (lp+1)); } else if (argnmatch(argv[i], "--nk-reds-only")) { nkonlyreds = 1; } else if (argnmatch(argv[i], "--bb2-ignorecolumns=")) { char *lp = strchr(argv[i], '='); bb2ignorecolumns = (char *) malloc(strlen(lp)+2); sprintf(bb2ignorecolumns, ",%s,", (lp+1)); } else if (argnmatch(argv[i], "--bb2-colors=")) { char *lp = strchr(argv[i], '=') + 1; bb2colors = colorset(lp, (1 << COL_GREEN)); } else if (argnmatch(argv[i], "--bb2-ignorepurples")) { bb2colors = (bb2colors & ~(1 << COL_PURPLE)); } else if (argnmatch(argv[i], "--bb2-ignoredialups")) { bb2nodialups = 1; } else if (argnmatch(argv[i], "--includecolumns=")) { char *lp = strchr(argv[i], '='); includecolumns = (char *) malloc(strlen(lp)+2); sprintf(includecolumns, ",%s,", (lp+1)); } else if (argnmatch(argv[i], "--eventignore=")) { char *lp = strchr(argv[i], '='); eventignorecolumns = (char *) malloc(strlen(lp)+2); sprintf(eventignorecolumns, ",%s,", (lp+1)); } else if (argnmatch(argv[i], "--doccgi=")) { char *lp = strchr(argv[i], '='); char *url = (char *)malloc(strlen(xgetenv("CGIBINURL"))+strlen(lp+1)+2); sprintf(url, "%s/%s", xgetenv("CGIBINURL"), lp+1); setdocurl(url); xfree(url); } else if (argnmatch(argv[i], "--docurl=")) { char *lp = strchr(argv[i], '='); setdocurl(lp+1); } else if (argnmatch(argv[i], "--no-doc-window")) { /* This is a no-op now */ } else if (argnmatch(argv[i], "--doc-window")) { setdocurl("TARGET=\"_blank\""); } else if (argnmatch(argv[i], "--htmlextension=")) { char *lp = strchr(argv[i], '='); htmlextension = strdup(lp+1); } else if (argnmatch(argv[i], "--htaccess")) { char *lp = strchr(argv[i], '='); if (lp) htaccess = strdup(lp+1); else htaccess = ".htaccess"; } else if ((strcmp(argv[i], "--wml") == 0) || argnmatch(argv[i], "--wml=")) { char *lp = strchr(argv[i], '='); if (lp) { wapcolumns = (char *) malloc(strlen(lp)+2); sprintf(wapcolumns, ",%s,", (lp+1)); } enable_wmlgen = 1; } else if (argnmatch(argv[i], "--nstab=")) { char *lp = strchr(argv[i], '='); if (strlen(lp+1) > 0) { nssidebarfilename = strdup(lp+1); } else errprintf("--nstab requires a filename\n"); } else if (argnmatch(argv[i], "--nslimit=")) { char *lp = strchr(argv[i], '='); nssidebarcolorlimit = parse_color(lp+1); } else if (argnmatch(argv[i], "--rssversion=")) { char *lp = strchr(argv[i], '='); rssversion = strdup(lp+1); } else if (argnmatch(argv[i], "--rsslimit=")) { char *lp = strchr(argv[i], '='); rsscolorlimit = parse_color(lp+1); } else if (argnmatch(argv[i], "--rss")) { wantrss = 1; } else if (argnmatch(argv[i], "--rssextension=")) { char *lp = strchr(argv[i], '='); rssextension = strdup(lp+1); } else if (argnmatch(argv[i], "--reportopts=")) { char style[MAX_LINE_LEN]; unsigned int rstart, rend; int count = sscanf(argv[i], "--reportopts=%u:%u:%d:%s", &rstart, &rend, &dynamicreport, style); reportstart = rstart; reportend = rend; if (count < 2) { errprintf("Invalid --reportopts option: Must have start- and end-times\n"); return 1; } if (count < 3) dynamicreport = 1; if (count == 4) { if (strcmp(style, stylenames[STYLE_CRIT]) == 0) reportstyle = STYLE_CRIT; else if (strcmp(style, stylenames[STYLE_NONGR]) == 0) reportstyle = STYLE_NONGR; else reportstyle = STYLE_OTHER; } if (reportstart < 788918400) reportstart = 788918400; if (reportend > time(NULL)) reportend = time(NULL); if (xgetenv("BBREPWARN")) reportwarnlevel = atof(xgetenv("BBREPWARN")); if (xgetenv("BBREPGREEN")) reportgreenlevel = atof(xgetenv("BBREPGREEN")); if ((reportwarnlevel < 0.0) || (reportwarnlevel > 100.0)) reportwarnlevel = 97.0; if ((reportgreenlevel < 0.0) || (reportgreenlevel > 100.0)) reportgreenlevel = 99.995; select_headers_and_footers("bbrep"); sethostenv_report(reportstart, reportend, reportwarnlevel, reportgreenlevel); } else if (argnmatch(argv[i], "--csv=")) { char *lp = strchr(argv[i], '='); csvfile = strdup(lp+1); } else if (argnmatch(argv[i], "--csvdelim=")) { char *lp = strchr(argv[i], '='); csvdelim = *(lp+1); } else if (argnmatch(argv[i], "--snapshot=")) { char *lp = strchr(argv[i], '='); snapshot = atol(lp+1); select_headers_and_footers("bbsnap"); sethostenv_snapshot(snapshot); } else if (strcmp(argv[i], "--pages-first") == 0) { hostsbeforepages = 0; } else if (strcmp(argv[i], "--pages-last") == 0) { hostsbeforepages = 1; } else if (argnmatch(argv[i], "--subpagecolumns=")) { char *lp = strchr(argv[i], '='); subpagecolumns = atoi(lp+1); if (subpagecolumns < 1) subpagecolumns=1; } else if (argnmatch(argv[i], "--maxrows=")) { char *lp = strchr(argv[i], '='); maxrowsbeforeheading = atoi(lp+1); if (maxrowsbeforeheading < 0) maxrowsbeforeheading=0; } else if (strcmp(argv[i], "--recentgifs") == 0) { use_recentgifs = 1; } else if (argnmatch(argv[i], "--recentgifs=")) { char *lp = strchr(argv[i], '='); use_recentgifs = 1; recentgif_limit = 60*durationvalue(lp+1); } else if (strcmp(argv[i], "--sort-group-only-items") == 0) { sort_grouponly_items = 1; } else if (argnmatch(argv[i], "--page-title=")) { char *lp = strchr(argv[i], '='); defaultpagetitle = strdup(lp+1); } else if (argnmatch(argv[i], "--dialupskin=")) { char *lp = strchr(argv[i], '='); dialupskin = strdup(lp+1); } else if (argnmatch(argv[i], "--reverseskin=")) { char *lp = strchr(argv[i], '='); reverseskin = strdup(lp+1); } else if (strcmp(argv[i], "--pagetitle-links") == 0) { pagetitlelinks = 1; } else if (strcmp(argv[i], "--pagetext-headings") == 0) { pagetextheadings = 1; } else if (strcmp(argv[i], "--underline-headings") == 0) { underlineheadings = 1; } else if (strcmp(argv[i], "--no-underline-headings") == 0) { underlineheadings = 0; } else if (strcmp(argv[i], "--no-eventlog") == 0) { bb2eventlog = 0; } else if (argnmatch(argv[i], "--max-eventcount=")) { char *lp = strchr(argv[i], '='); bb2eventlogmaxcount = atoi(lp+1); } else if (argnmatch(argv[i], "--max-eventtime=")) { char *lp = strchr(argv[i], '='); bb2eventlogmaxtime = atoi(lp+1); } else if (argnmatch(argv[i], "--max-ackcount=")) { char *lp = strchr(argv[i], '='); bb2acklogmaxcount = atoi(lp+1); } else if (argnmatch(argv[i], "--max-acktime=")) { char *lp = strchr(argv[i], '='); bb2acklogmaxtime = atoi(lp+1); } else if (strcmp(argv[i], "--no-acklog") == 0) { bb2acklog = 0; } else if (strcmp(argv[i], "--no-pages") == 0) { do_normal_pages = 0; } else if (argnmatch(argv[i], "--noprop=")) { char *lp = strchr(argv[i], '='); nopropyellowdefault = (char *) malloc(strlen(lp)+2); sprintf(nopropyellowdefault, ",%s,", (lp+1)); errprintf("--noprop is deprecated - use --nopropyellow instead\n"); } else if (argnmatch(argv[i], "--nopropyellow=")) { char *lp = strchr(argv[i], '='); nopropyellowdefault = (char *) malloc(strlen(lp)+2); sprintf(nopropyellowdefault, ",%s,", (lp+1)); } else if (argnmatch(argv[i], "--nopropred=")) { char *lp = strchr(argv[i], '='); nopropreddefault = (char *) malloc(strlen(lp)+2); sprintf(nopropreddefault, ",%s,", (lp+1)); } else if (argnmatch(argv[i], "--noproppurple=")) { char *lp = strchr(argv[i], '='); noproppurpledefault = (char *) malloc(strlen(lp)+2); sprintf(noproppurpledefault, ",%s,", (lp+1)); } else if (argnmatch(argv[i], "--nopropack=")) { char *lp = strchr(argv[i], '='); nopropackdefault = (char *) malloc(strlen(lp)+2); sprintf(nopropackdefault, ",%s,", (lp+1)); } else if (strcmp(argv[i], "--bbpageONLY") == 0) { /* Deprecated */ errprintf("--bbpageONLY is deprecated - use --pageset=NAME to generate pagesets\n"); } else if (strcmp(argv[i], "--embedded") == 0) { embedded = 1; } else if (argnmatch(argv[i], "--pageset=")) { char *lp = strchr(argv[i], '='); pageset = strdup(lp+1); } else if (argnmatch(argv[i], "--template=")) { char *lp = strchr(argv[i], '='); lp++; select_headers_and_footers(lp); } else if (argnmatch(argv[i], "--purplelog=")) { char *lp = strchr(argv[i], '='); if (*(lp+1) == '/') purplelogfn = strdup(lp+1); else { purplelogfn = (char *) malloc(strlen(xgetenv("BBHOME"))+1+strlen(lp+1)+1); sprintf(purplelogfn, "%s/%s", xgetenv("BBHOME"), (lp+1)); } } else if (argnmatch(argv[i], "--report=") || (strcmp(argv[i], "--report") == 0)) { char *lp = strchr(argv[i], '='); if (lp) { egocolumn = strdup(lp+1); } else egocolumn = "bbgen"; timing = 1; } else if (argnmatch(argv[i], "--nklog=") || (strcmp(argv[i], "--nklog") == 0)) { char *lp = strchr(argv[i], '='); if (lp) { lognkstatus = strdup(lp+1); } else lognkstatus = "nk"; } else if (strcmp(argv[i], "--timing") == 0) { timing = 1; } else if (strcmp(argv[i], "--debug") == 0) { debug = 1; } else if (strcmp(argv[i], "--no-update") == 0) { dontsendmessages = 1; } else if (strcmp(argv[i], "--version") == 0) { printf("bbgen version %s\n", VERSION); printf("\n"); exit(0); } else if ((strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-?") == 0)) { printf("bbgen for Hobbit version %s\n\n", VERSION); printf("Usage: %s [options] [WebpageDirectory]\n", argv[0]); printf("Options:\n"); printf(" --ignorecolumns=test[,test] : Completely ignore these columns\n"); printf(" --nk-reds-only : Only show red statuses on the NK page\n"); printf(" --bb2-ignorecolumns=test[,test]: Ignore these columns for the BB2 page\n"); printf(" --bb2-ignorepurples : Ignore all-purple hosts on BB2 page\n"); printf(" --includecolumns=test[,test]: Always include these columns on BB2 page\n"); printf(" --max-eventcount=N : Max number of events to include in eventlog\n"); printf(" --max-eventtime=N : Show events that occurred within the last N minutes\n"); printf(" --eventignore=test[,test] : Columns to ignore in bb2 event-log display\n"); printf(" --no-eventlog : Do not generate the bb2 eventlog display\n"); printf(" --no-acklog : Do not generate the bb2 ack-log display\n"); printf(" --no-pages : Generate only the bb2 and bbnk pages\n"); printf(" --docurl=documentation-URL : Hostnames link to a general (dynamic) web page for docs\n"); printf(" --no-doc-window : Open doc-links in same window\n"); printf(" --htmlextension=.EXT : Sets filename extension for generated file (default: .html\n"); printf(" --report[=COLUMNNAME] : Send a status report about the running of bbgen\n"); printf(" --reportopts=ST:END:DYN:STL : Run in Hobbit Reporting mode\n"); printf(" --csv=FILENAME : For Hobbit Reporting, output CSV file\n"); printf(" --csvdelim=CHARACTER : Delimiter in CSV file output (default: comma)\n"); printf(" --snapshot=TIME : Snapshot mode\n"); printf("\nPage layout options:\n"); printf(" --pages-first : Put page- and subpage-links before hosts (default)\n"); printf(" --pages-last : Put page- and subpage-links after hosts\n"); printf(" --subpagecolumns=N : Number of columns for links to pages and subpages\n"); printf(" --maxrows=N : Repeat column headings for every N hosts shown\n"); printf(" --recentgifs : Use xxx-recent.gif icons for newly changed tests\n"); printf(" --sort-group-only-items : Display group-only items in alphabetical order\n"); printf(" --page-title=TITLE : Set a default page title for all pages\n"); printf(" --dialupskin=URL : Use a different icon skin for dialup tests\n"); printf(" --reverseskin=URL : Use a different icon skin for reverse tests\n"); printf(" --pagetitle-links : Make page- and subpage-titles act as links\n"); printf(" --pagetext-headings : Use page texts as headings\n"); printf(" --no-underline-headings : Do not underline the page headings\n"); printf("\nStatus propagation control options:\n"); printf(" --noprop=test[,test] : Disable upwards status propagation when YELLOW\n"); printf(" --nopropred=test[,test] : Disable upwards status propagation when RED or YELLOW\n"); printf(" --noproppurple=test[,test] : Disable upwards status propagation when PURPLE\n"); printf("\nAlternate pageset generation support:\n"); printf(" --pageset=SETNAME : Generate non-standard pageset with tag SETNAME\n"); printf(" --template=TEMPLATE : template for header and footer files\n"); printf("\nAlternate output formats:\n"); printf(" --wml[=test1,test2,...] : Generate a small (bb2-style) WML page\n"); printf(" --nstab=FILENAME : Generate a Netscape Sidebar feed\n"); printf(" --nslimit=COLOR : Minimum color to include on Netscape sidebar\n"); printf(" --rss : Generate a RSS/RDF feed of alerts\n"); printf(" --rssextension=.EXT : Sets filename extension for RSS files (default: .rss\n"); printf(" --rssversion={0.91|0.92|1.0|2.0} : Specify RSS/RDF version (default: 0.91)\n"); printf(" --rsslimit=COLOR : Minimum color to include on RSS feed\n"); printf("\nDebugging/troubleshooting options:\n"); printf(" --timing : Collect timing information\n"); printf(" --debug : Debugging information\n"); printf(" --version : Show version information\n"); printf(" --purplelog=FILENAME : Create a log of purple hosts and tests\n"); exit(0); } else if (argnmatch(argv[i], "-")) { errprintf("Unknown option : %s\n", argv[i]); } else { /* Last argument is pagedir */ pagedir = strdup(argv[i]); } } /* In case they changed the name of our column ... */ if (egocolumn) setup_signalhandler(egocolumn); if (debug) { int i; printf("Command: bbgen"); for (i=1; (i<argc); i++) printf(" '%s'", argv[i]); printf("\n"); printf("Environment BBHOSTS='%s'\n", textornull(xgetenv("BBHOSTS"))); printf("\n"); } add_timestamp("Startup"); /* Check that all needed environment vars are defined */ envcheck(reqenv); /* Catch a SEGV fault */ setup_signalhandler("bbgen"); /* Set umask to 0022 so that the generated HTML pages have world-read access */ umask(0022); if (pagedir == NULL) { if (xgetenv("BBWWW")) { pagedir = strdup(xgetenv("BBWWW")); } else { pagedir = (char *) malloc(strlen(xgetenv("BBHOME"))+5); sprintf(pagedir, "%s/www", xgetenv("BBHOME")); } } if (xgetenv("BBHTACCESS")) bbhtaccess = strdup(xgetenv("BBHTACCESS")); if (xgetenv("BBPAGEHTACCESS")) bbpagehtaccess = strdup(xgetenv("BBPAGEHTACCESS")); if (xgetenv("BBSUBPAGEHTACCESS")) bbsubpagehtaccess = strdup(xgetenv("BBSUBPAGEHTACCESS")); /* * When doing alternate pagesets, disable some stuff: * No WML or RSS pages. */ if (pageset || embedded || snapshot) enable_wmlgen = wantrss = 0; if (embedded) { egocolumn = htaccess = NULL; /* * Need to have default SIGPIPE handling when doing embedded stuff. * We are probably run from a CGI script or something similar. */ signal(SIGPIPE, SIG_DFL); } /* Load all data from the various files */ load_all_links(); add_timestamp("Load links done"); pagehead = load_bbhosts(pageset); add_timestamp("Load bbhosts done"); if (!embedded) { /* Remove old acknowledgements */ delete_old_acks(); add_timestamp("ACK removal done"); } statehead = load_state(&dispsums); if (embedded || snapshot) dispsums = NULL; add_timestamp("Load STATE done"); if (hobbitddump) { dump_hobbitdchk(); return 0; } /* Calculate colors of hosts and pages */ calc_hostcolors(bb2ignorecolumns); calc_pagecolors(pagehead); /* Topmost page (background color for bb.html) */ for (p=pagehead; (p); p = p->next) { if (p->color > pagehead->color) pagehead->color = p->color; } bb_color = pagehead->color; if (xgetenv("SUMMARY_SET_BKG") && (strcmp(xgetenv("SUMMARY_SET_BKG"), "TRUE") == 0)) { /* * Displayed summaries affect the BB page only, * but should not go into the color we report to * others. */ for (s=dispsums; (s); s = s->next) { if (s->color > pagehead->color) pagehead->color = s->color; } } add_timestamp("Color calculation done"); if (debug) dumpall(pagehead); /* Generate pages */ if (chdir(pagedir) != 0) { errprintf("Cannot change to webpage directory %s\n", pagedir); exit(1); } if (embedded) { /* Just generate that one page */ do_one_page(pagehead, NULL, 1); return 0; } /* The main page - bb.html and pages/subpages thereunder */ add_timestamp("Hobbit pagegen start"); if (reportstart && csvfile) { csv_availability(csvfile, csvdelim); } else if (do_normal_pages) { do_page_with_subs(pagehead, dispsums); } add_timestamp("Hobbit pagegen done"); if (reportstart) { /* Reports end here */ return 0; } /* The full summary page - bb2.html */ bb2_color = do_bb2_page(nssidebarfilename, PAGE_BB2); add_timestamp("BB2 generation done"); /* Reduced summary (alerts) page - bbnk.html */ bbnk_color = do_bb2_page(NULL, PAGE_NK); add_timestamp("BBNK generation done"); if (snapshot) { /* Snapshots end here */ return 0; } /* Send summary notices - only once, so not on pagesets */ if (pageset == NULL) { send_summaries(sumhead); add_timestamp("Summary transmission done"); } /* Generate WML cards */ if (enable_wmlgen) { do_wml_cards(pagedir); add_timestamp("WML generation done"); } /* Need to do this before sending in our report */ add_timestamp("Run completed"); /* Tell about us */ if (egocolumn) { char msgline[4096]; char *timestamps; long bbsleep = (xgetenv("BBSLEEP") ? atol(xgetenv("BBSLEEP")) : 300); int color; /* Go yellow if it runs for too long */ if (total_runtime() > bbsleep) { errprintf("WARNING: Runtime %ld longer than BBSLEEP (%ld)\n", total_runtime(), bbsleep); } color = (errbuf ? COL_YELLOW : COL_GREEN); combo_start(); init_status(color); sprintf(msgline, "status %s.%s %s %s\n\n", xgetenv("MACHINE"), egocolumn, colorname(color), timestamp); addtostatus(msgline); sprintf(msgline, "bbgen for Hobbit version %s\n", VERSION); addtostatus(msgline); sprintf(msgline, "\nStatistics:\n Hosts : %5d\n Status messages : %5d\n Purple messages : %5d\n Pages : %5d\n", hostcount, statuscount, purplecount, pagecount); addtostatus(msgline); if (errbuf) { addtostatus("\n\nError output:\n"); addtostatus(errbuf); } show_timestamps(×tamps); addtostatus(timestamps); finish_status(); combo_end(); } else show_timestamps(NULL); return 0; }
int main(int argc, char *argv[]) { char histlogfn[PATH_MAX]; FILE *fd; char textrepfullfn[PATH_MAX], textrepfn[1024], textrepurl[PATH_MAX]; FILE *textrep; reportinfo_t repinfo; int argi; char *envarea = NULL; void *hinfo; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } } redirect_cgilog("reportlog"); cgidata = cgi_request(); parse_query(); load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn()); if ((hinfo = hostinfo(hostname)) == NULL) { errormsg("No such host"); return 1; } ip = xmh_item(hinfo, XMH_IP); displayname = xmh_item(hinfo, XMH_DISPLAYNAME); if (!displayname) displayname = hostname; sprintf(histlogfn, "%s/%s.%s", xgetenv("XYMONHISTDIR"), commafy(hostname), service); fd = fopen(histlogfn, "r"); if (fd == NULL) { errormsg("Cannot open history file"); } color = parse_historyfile(fd, &repinfo, hostname, service, st, end, 0, reportwarnlevel, reportgreenlevel, reportwarnstops, reporttime); fclose(fd); sprintf(textrepfn, "avail-%s-%s-%u-%u.txt", hostname, service, (unsigned int)getcurrenttime(NULL), (int)getpid()); sprintf(textrepfullfn, "%s/%s", xgetenv("XYMONREPDIR"), textrepfn); sprintf(textrepurl, "%s/%s", xgetenv("XYMONREPURL"), textrepfn); textrep = fopen(textrepfullfn, "w"); /* Now generate the webpage */ printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); generate_replog(stdout, textrep, textrepurl, hostname, service, color, style, ip, displayname, st, end, reportwarnlevel, reportgreenlevel, reportwarnstops, &repinfo); if (textrep) fclose(textrep); return 0; }
int main(int argc, char *argv[]) { void *hwalk; int argi; strbuffer_t *statusmsg, *jrockout, *qout; for (argi = 1; (argi < argc); argi++) { if ((strcmp(argv[argi], "--help") == 0)) { printf("beastat version %s\n\n", VERSION); printf("Usage:\n%s [--debug] [--no-update] [--port=SNMPPORT] [--community=SNMPCOMMUNITY]\n", argv[0]); exit(0); } else if ((strcmp(argv[argi], "--version") == 0)) { printf("beastat version %s\n", VERSION); exit(0); } else if ((strcmp(argv[argi], "--debug") == 0)) { debug = 1; } else if ((strcmp(argv[argi], "--no-update") == 0)) { dontsendmessages = 1; } else if (argnmatch(argv[argi], "--timeout=")) { char *p = strchr(argv[argi], '='); extcmdtimeout = atoi(p+1); } else if (argnmatch(argv[argi], "--port=")) { char *p = strchr(argv[argi], '='); default_port = atoi(p+1); } else if (argnmatch(argv[argi], "--community=")) { char *p = strchr(argv[argi], '='); default_community = strdup(p+1); } } load_hostnames(xgetenv("BBHOSTS"), "netinclude", get_fqdn()); if (first_host() == NULL) { errprintf("Cannot load bb-hosts\n"); return 1; } if (xgetenv("BBLOCATION")) location = strdup(xgetenv("BBLOCATION")); init_timestamp(); combo_start(); statusmsg = newstrbuffer(0); jrockout = newstrbuffer(0); qout = newstrbuffer(0); for (hwalk = first_host(); (hwalk); hwalk = next_host(hwalk, 0)) { char *tspec = bbh_custom_item(hwalk, "bea="); char *snmpcommunity = default_community; char *beadomain = ""; int snmpport = default_port; char *p; char pipecmd[4096]; int jrockres, qres; clearstrbuffer(statusmsg); clearstrbuffer(jrockout); clearstrbuffer(qout); /* Check if we have a "bea" test for this host, and it is a host we want to test */ if (!tspec || !wanted_host(hwalk, location)) continue; /* Parse the testspec: bea=[SNMPCOMMUNITY@]BEADOMAIN[:SNMPPORT] */ tspec = strdup(tspec+strlen("bea=")); p = strchr(tspec, ':'); if (p) { *p = '\0'; snmpport = atoi(p+1); } p = strchr(tspec, '@'); if (p) { *p = '\0'; snmpcommunity = strdup(tspec); beadomain = strdup(p+1); } else { beadomain = strdup(tspec); } /* Prepare for the host status */ statuscolor = COL_GREEN; /* Setup the snmpwalk pipe-command for jrockit stats */ sprintf(pipecmd, "snmpwalk -m BEA-WEBLOGIC-MIB -c %s@%s -v 1 %s:%d enterprises.140.625.302.1", snmpcommunity, beadomain, bbh_item(hwalk, BBH_IP), snmpport); jrockres = run_command(pipecmd, NULL, jrockout, 0, extcmdtimeout); if (jrockres == 0) { find_idxes(STRBUF(jrockout), "BEA-WEBLOGIC-MIB::jrockitRuntimeIndex."); send_data(hwalk, beadomain, STRBUF(jrockout), jrockitems); } else { if (statuscolor < COL_YELLOW) statuscolor = COL_YELLOW; sprintf(msgline, "Could not retrieve BEA jRockit statistics from %s:%d domain %s (code %d)\n", bbh_item(hwalk, BBH_IP), snmpport, beadomain, jrockres); addtobuffer(statusmsg, msgline); } /* Setup the snmpwalk pipe-command for executeQueur stats */ sprintf(pipecmd, "snmpwalk -m BEA-WEBLOGIC-MIB -c %s@%s -v 1 %s:%d enterprises.140.625.180.1", snmpcommunity, beadomain, bbh_item(hwalk, BBH_IP), snmpport); qres = run_command(pipecmd, NULL, qout, 0, extcmdtimeout); if (qres == 0) { find_idxes(STRBUF(qout), "BEA-WEBLOGIC-MIB::executeQueueRuntimeIndex."); send_data(hwalk, beadomain, STRBUF(qout), qitems); } else { if (statuscolor < COL_YELLOW) statuscolor = COL_YELLOW; sprintf(msgline, "Could not retrieve BEA executeQueue statistics from %s:%d domain %s (code %d)\n", bbh_item(hwalk, BBH_IP), snmpport, beadomain, qres); addtobuffer(statusmsg, msgline); } /* FUTURE: Have the statuscolor/statusmsg be updated to check against thresholds */ /* Right now, the "bea" status is always green */ init_status(statuscolor); sprintf(msgline, "status %s.%s %s %s\n\n", commafy(bbh_item(hwalk, BBH_HOSTNAME)), "bea", colorname(statuscolor), timestamp); addtostatus(msgline); if (STRBUFLEN(statusmsg) == 0) addtobuffer(statusmsg, "All BEA monitors OK\n"); addtostrstatus(statusmsg); finish_status(); } combo_end(); freestrbuffer(statusmsg); freestrbuffer(jrockout); freestrbuffer(qout); return 0; }
int main(int argc, char *argv[]) { int argi, hosti, testi; char *pagepattern = NULL, *hostpattern = NULL; char *envarea = NULL, *cookie = NULL, *nexthost; char *hobbitcmd, *procscmd, *svcscmd; int alertcolors, alertinterval; char configfn[PATH_MAX]; char *respbuf = NULL, *procsbuf = NULL, *svcsbuf = NULL; hostlist_t *hwalk; htnames_t *twalk; hostlist_t **allhosts = NULL; htnames_t **alltests = NULL; int hostcount = 0, maxtests = 0; time_t now = getcurrenttime(NULL); sendreturn_t *sres; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (argnmatch(argv[argi], "--delimiter=")) { char *p = strchr(argv[argi], '='); coldelim = strdup(p+1); } else if (strcmp(argv[argi], "--critical") == 0) { nkonly = 1; } else if (strcmp(argv[argi], "--old-nk-config") == 0) { newnkconfig = 0; } } redirect_cgilog("hobbit-confreport"); load_hostnames(xgetenv("BBHOSTS"), NULL, get_fqdn()); load_nkconfig(NULL); /* Setup the filter we use for the report */ cookie = get_cookie("pagepath"); if (cookie && *cookie) pagepattern = strdup(cookie); cookie = get_cookie("host"); if (cookie && *cookie) hostpattern = strdup(cookie); /* Fetch the list of host+test statuses we currently know about */ if (pagepattern) { hobbitcmd = (char *)malloc(2*strlen(pagepattern) + 1024); procscmd = (char *)malloc(2*strlen(pagepattern) + 1024); svcscmd = (char *)malloc(2*strlen(pagepattern) + 1024); sprintf(hobbitcmd, "hobbitdboard page=^%s$|^%s/.+ fields=hostname,testname", pagepattern, pagepattern); sprintf(procscmd, "hobbitdboard page=^%s$|^%s/.+ test=procs fields=hostname,msg", pagepattern, pagepattern); sprintf(svcscmd, "hobbitdboard page=^%s$|^%s/.+ test=svcs fields=hostname,msg", pagepattern, pagepattern); } else if (hostpattern) { hobbitcmd = (char *)malloc(strlen(hostpattern) + 1024); procscmd = (char *)malloc(strlen(hostpattern) + 1024); svcscmd = (char *)malloc(strlen(hostpattern) + 1024); sprintf(hobbitcmd, "hobbitdboard host=^%s$ fields=hostname,testname", hostpattern); sprintf(procscmd, "hobbitdboard host=^%s$ test=procs fields=hostname,msg", hostpattern); sprintf(svcscmd, "hobbitdboard host=^%s$ test=svcs fields=hostname,msg", hostpattern); } else { hobbitcmd = (char *)malloc(1024); procscmd = (char *)malloc(1024); svcscmd = (char *)malloc(1024); sprintf(hobbitcmd, "hobbitdboard fields=hostname,testname"); sprintf(procscmd, "hobbitdboard test=procs fields=hostname,msg"); sprintf(svcscmd, "hobbitdboard test=svcs fields=hostname,msg"); } sres = newsendreturnbuf(1, NULL); if (sendmessage(hobbitcmd, NULL, BBTALK_TIMEOUT, sres) != BB_OK) { errormsg("Cannot contact the Hobbit server\n"); return 1; } respbuf = getsendreturnstr(sres, 1); if (sendmessage(procscmd, NULL, BBTALK_TIMEOUT, sres) != BB_OK) { errormsg("Cannot contact the Hobbit server\n"); return 1; } procsbuf = getsendreturnstr(sres, 1); if (sendmessage(svcscmd, NULL, BBTALK_TIMEOUT, sres) != BB_OK) { errormsg("Cannot contact the Hobbit server\n"); return 1; } svcsbuf = getsendreturnstr(sres, 1); freesendreturnbuf(sres); if (!respbuf) { errormsg("Unable to find host information\n"); return 1; } /* Parse it into a usable list */ nexthost = respbuf; do { char *hname, *tname, *eoln; int wanted = 1; eoln = strchr(nexthost, '\n'); if (eoln) *eoln = '\0'; hname = nexthost; tname = strchr(nexthost, '|'); if (tname) { *tname = '\0'; tname++; } if (nkonly) { void *hinfo = hostinfo(hname); char *nkalerts = bbh_item(hinfo, BBH_NK); if (newnkconfig) { if (strcmp(nkval(hname, tname, nkalerts), "No") == 0 ) wanted = 0; } else { if (!nkalerts) wanted = 0; } } if (wanted && hname && tname && strcmp(hname, "summary") && strcmp(tname, xgetenv("INFOCOLUMN")) && strcmp(tname, xgetenv("TRENDSCOLUMN"))) { htnames_t *newitem = (htnames_t *)malloc(sizeof(htnames_t)); for (hwalk = hosthead; (hwalk && strcmp(hwalk->hostname, hname)); hwalk = hwalk->next); if (!hwalk) { hwalk = (hostlist_t *)calloc(1, sizeof(hostlist_t)); hwalk->hostname = strdup(hname); hwalk->procs = get_proclist(hname, procsbuf); hwalk->svcs = get_proclist(hname, svcsbuf); hwalk->next = hosthead; hosthead = hwalk; hostcount++; } newitem->name = strdup(tname); newitem->next = hwalk->tests; hwalk->tests = newitem; hwalk->testcount++; } if (eoln) { nexthost = eoln+1; if (*nexthost == '\0') nexthost = NULL; } } while (nexthost); allhosts = (hostlist_t **) malloc(hostcount * sizeof(hostlist_t *)); for (hwalk = hosthead, hosti=0; (hwalk); hwalk = hwalk->next, hosti++) { allhosts[hosti] = hwalk; if (hwalk->testcount > maxtests) maxtests = hwalk->testcount; } alltests = (htnames_t **) malloc(maxtests * sizeof(htnames_t *)); qsort(&allhosts[0], hostcount, sizeof(hostlist_t **), host_compare); /* Get the static info */ load_all_links(); init_tcp_services(); pingcolumn = xgetenv("PINGCOLUMN"); pingplus = (char *)malloc(strlen(pingcolumn) + 2); sprintf(pingplus, "%s=", pingcolumn); /* Load alert config */ alertcolors = colorset(xgetenv("ALERTCOLORS"), ((1 << COL_GREEN) | (1 << COL_BLUE))); alertinterval = 60*atoi(xgetenv("ALERTREPEAT")); sprintf(configfn, "%s/etc/hobbit-alerts.cfg", xgetenv("BBHOME")); load_alertconfig(configfn, alertcolors, alertinterval); load_columndocs(); printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); sethostenv("", "", "", colorname(COL_BLUE), NULL); headfoot(stdout, "confreport", "", "header", COL_BLUE); fprintf(stdout, "<table width=\"100%%\" border=0>\n"); fprintf(stdout, "<tr><th align=center colspan=2><font size=\"+2\">Hobbit configuration Report</font></th></tr>\n"); fprintf(stdout, "<tr><th valign=top align=left>Date</th><td>%s</td></tr>\n", ctime(&now)); fprintf(stdout, "<tr><th valign=top align=left>%d hosts included</th><td>\n", hostcount); for (hosti=0; (hosti < hostcount); hosti++) { fprintf(stdout, "%s ", allhosts[hosti]->hostname); } fprintf(stdout, "</td></tr>\n"); if (nkonly) { fprintf(stdout, "<tr><th valign=top align=left>Filter</th><td>Only data for the "Critical Systems" view reported</td></tr>\n"); } fprintf(stdout, "</table>\n"); headfoot(stdout, "confreport", "", "front", COL_BLUE); for (hosti=0; (hosti < hostcount); hosti++) { for (twalk = allhosts[hosti]->tests, testi = 0; (twalk); twalk = twalk->next, testi++) { alltests[testi] = twalk; } qsort(&alltests[0], allhosts[hosti]->testcount, sizeof(htnames_t **), test_compare); print_host(allhosts[hosti], alltests, allhosts[hosti]->testcount); } headfoot(stdout, "confreport", "", "back", COL_BLUE); print_columndocs(); headfoot(stdout, "confreport", "", "footer", COL_BLUE); return 0; }
int main(int argc, char *argv[]) { int daemonize = 1; int listenq = 10; char *pidfile = "msgcache.pid"; int lsocket; struct sockaddr_in laddr; struct sigaction sa; int opt; /* Dont save the output from errprintf() */ save_errbuf = 0; memset(&laddr, 0, sizeof(laddr)); inet_aton("0.0.0.0", (struct in_addr *) &laddr.sin_addr.s_addr); laddr.sin_port = htons(1984); laddr.sin_family = AF_INET; for (opt=1; (opt < argc); opt++) { if (argnmatch(argv[opt], "--listen=")) { char *locaddr, *p; int locport; locaddr = strchr(argv[opt], '=')+1; p = strchr(locaddr, ':'); if (p) { locport = atoi(p+1); *p = '\0'; } else locport = 1984; memset(&laddr, 0, sizeof(laddr)); laddr.sin_port = htons(locport); laddr.sin_family = AF_INET; if (inet_aton(locaddr, (struct in_addr *) &laddr.sin_addr.s_addr) == 0) { errprintf("Invalid listen address %s\n", locaddr); return 1; } } else if (argnmatch(argv[opt], "--server=")) { /* Who is allowed to fetch cached messages */ char *p = strchr(argv[opt], '='); serverlist = getsenderlist(p+1); } else if (argnmatch(argv[opt], "--max-age=")) { char *p = strchr(argv[opt], '='); maxage = atoi(p+1); } else if (argnmatch(argv[opt], "--lqueue=")) { char *p = strchr(argv[opt], '='); listenq = atoi(p+1); } else if (strcmp(argv[opt], "--daemon") == 0) { daemonize = 1; } else if (strcmp(argv[opt], "--no-daemon") == 0) { daemonize = 0; } else if (argnmatch(argv[opt], "--pidfile=")) { char *p = strchr(argv[opt], '='); pidfile = strdup(p+1); } else if (argnmatch(argv[opt], "--logfile=")) { char *p = strchr(argv[opt], '='); logfile = strdup(p+1); } else if (strcmp(argv[opt], "--debug") == 0) { debug = 1; } else if (strcmp(argv[opt], "--version") == 0) { printf("xymonproxy version %s\n", VERSION); return 0; } } /* Set up a socket to listen for new connections */ lsocket = socket(AF_INET, SOCK_STREAM, 0); if (lsocket == -1) { errprintf("Cannot create listen socket (%s)\n", strerror(errno)); return 1; } opt = 1; setsockopt(lsocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(lsocket, F_SETFL, O_NONBLOCK); if (bind(lsocket, (struct sockaddr *)&laddr, sizeof(laddr)) == -1) { errprintf("Cannot bind to listen socket (%s)\n", strerror(errno)); return 1; } if (listen(lsocket, listenq) == -1) { errprintf("Cannot listen (%s)\n", strerror(errno)); return 1; } /* Redirect logging to the logfile, if requested */ if (logfile) { reopen_file(logfile, "a", stdout); reopen_file(logfile, "a", stderr); } errprintf("Xymon msgcache version %s starting\n", VERSION); errprintf("Listening on %s:%d\n", inet_ntoa(laddr.sin_addr), ntohs(laddr.sin_port)); if (daemonize) { pid_t childpid; reopen_file("/dev/null", "r", stdin); /* Become a daemon */ childpid = fork(); if (childpid < 0) { /* Fork failed */ errprintf("Could not fork\n"); exit(1); } else if (childpid > 0) { /* Parent - save PID and exit */ FILE *fd = fopen(pidfile, "w"); if (fd) { fprintf(fd, "%d\n", (int)childpid); fclose(fd); } exit(0); } /* Child (daemon) continues here */ setsid(); } setup_signalhandler("msgcache"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigmisc_handler; sigaction(SIGHUP, &sa, NULL); sigaction(SIGTERM, &sa, NULL); do { fd_set fdread, fdwrite; int maxfd; int n; conn_t *cwalk, *cprev; msgqueue_t *qwalk, *qprev; time_t mintstamp; /* Remove any finished connections */ cwalk = chead; cprev = NULL; while (cwalk) { conn_t *zombie; if (cwalk->action != C_DONE) { cprev = cwalk; cwalk = cwalk->next; continue; } /* Close the socket */ close(cwalk->sockfd); zombie = cwalk; if (cprev == NULL) { chead = zombie->next; cwalk = chead; cprev = NULL; } else { cprev->next = zombie->next; cwalk = zombie->next; } freestrbuffer(zombie->msgbuf); xfree(zombie); } ctail = chead; if (ctail) { while (ctail->next) ctail = ctail->next; } /* Remove expired messages */ qwalk = qhead; qprev = NULL; mintstamp = getcurrenttime(NULL) - maxage; while (qwalk) { msgqueue_t *zombie; if (qwalk->tstamp > mintstamp) { /* Hasn't expired yet */ qprev = qwalk; qwalk = qwalk->next; continue; } zombie = qwalk; if (qprev == NULL) { qhead = zombie->next; qwalk = qhead; qprev = NULL; } else { qprev->next = zombie->next; qwalk = zombie->next; } freestrbuffer(zombie->msgbuf); xfree(zombie); } qtail = qhead; if (qtail) { while (qtail->next) qtail = qtail->next; } /* Now we're ready to handle some data */ FD_ZERO(&fdread); FD_ZERO(&fdwrite); /* Add the listen socket */ FD_SET(lsocket, &fdread); maxfd = lsocket; for (cwalk = chead; (cwalk); cwalk = cwalk->next) { switch (cwalk->action) { case C_READING: FD_SET(cwalk->sockfd, &fdread); if (cwalk->sockfd > maxfd) maxfd = cwalk->sockfd; break; case C_WRITING: FD_SET(cwalk->sockfd, &fdwrite); if (cwalk->sockfd > maxfd) maxfd = cwalk->sockfd; break; case C_DONE: break; } } n = select(maxfd+1, &fdread, &fdwrite, NULL, NULL); if (n < 0) { if (errno == EINTR) continue; errprintf("select failed: %s\n", strerror(errno)); return 0; } if (n == 0) continue; /* Timeout */ for (cwalk = chead; (cwalk); cwalk = cwalk->next) { switch (cwalk->action) { case C_READING: if (FD_ISSET(cwalk->sockfd, &fdread)) grabdata(cwalk); break; case C_WRITING: if (FD_ISSET(cwalk->sockfd, &fdwrite)) senddata(cwalk); break; case C_DONE: break; } } if (FD_ISSET(lsocket, &fdread)) { /* New incoming connection */ conn_t *newconn; int caddrsize; dbgprintf("New connection\n"); newconn = calloc(1, sizeof(conn_t)); caddrsize = sizeof(newconn->caddr); newconn->sockfd = accept(lsocket, (struct sockaddr *)&newconn->caddr, &caddrsize); if (newconn->sockfd == -1) { /* accept() failure. Yes, it does happen! */ dbgprintf("accept failure, ignoring connection (%s)\n", strerror(errno)); xfree(newconn); newconn = NULL; } else { fcntl(newconn->sockfd, F_SETFL, O_NONBLOCK); newconn->action = C_READING; newconn->msgbuf = newstrbuffer(0); newconn->tstamp = getcurrenttime(NULL); } if (newconn) { if (ctail) { ctail->next = newconn; ctail = newconn; } else chead = ctail = newconn; } } } while (keeprunning); if (pidfile) unlink(pidfile); return 0; }
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; }
int main(int argc, char *argv[]) { char dirid[PATH_MAX]; char outdir[PATH_MAX]; char xymongencmd[PATH_MAX]; char xymonwebenv[PATH_MAX]; char xymongentimeopt[100]; char *xymongen_argv[20]; pid_t childpid; int childstat; char htmldelim[100]; char startstr[20]; int argi, newargi; char *envarea = NULL; char *useragent; int usemultipart = 1; newargi = 0; xymongen_argv[newargi++] = xymongencmd; xymongen_argv[newargi++] = xymongentimeopt; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else { xymongen_argv[newargi++] = argv[argi]; } } xymongen_argv[newargi++] = outdir; xymongen_argv[newargi++] = NULL; redirect_cgilog("snapshot"); cgidata = cgi_request(); if (cgidata == NULL) { /* Present the query form */ sethostenv("", "", "", colorname(COL_BLUE), NULL); printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); showform(stdout, "snapshot", "snapshot_form", COL_BLUE, getcurrenttime(NULL), NULL, NULL); return 0; } parse_query(); useragent = getenv("HTTP_USER_AGENT"); if (useragent && strstr(useragent, "KHTML")) { /* KHTML (Konqueror, Safari) cannot handle multipart documents. */ usemultipart = 0; } /* * Need to set these up AFTER putting them into xymongen_argv, since we * need to have option parsing done first. */ if (xgetenv("XYMONGEN")) sprintf(xymongencmd, "%s", xgetenv("XYMONGEN")); else sprintf(xymongencmd, "%s/bin/xymongen", xgetenv("XYMONHOME")); snprintf(xymongentimeopt, sizeof(xymongentimeopt), "--snapshot=%u", (unsigned int)starttime); sprintf(dirid, "%lu-%u", (unsigned long)getpid(), (unsigned int)getcurrenttime(NULL)); sprintf(outdir, "%s/%s", xgetenv("XYMONSNAPDIR"), dirid); if (mkdir(outdir, 0755) == -1) errormsg("Cannot create output directory"); sprintf(xymonwebenv, "XYMONWEB=%s/%s", xgetenv("XYMONSNAPURL"), dirid); putenv(xymonwebenv); if (usemultipart) { /* Output the "please wait for report ... " thing */ snprintf(htmldelim, sizeof(htmldelim)-1, "xymonrep-%lu-%u", (unsigned long)getpid(), (unsigned int)getcurrenttime(NULL)); printf("Content-type: multipart/mixed;boundary=%s\n", htmldelim); printf("\n"); printf("%s\n", htmldelim); printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); /* It's ok with these hardcoded values, as they are not used for this page */ sethostenv("", "", "", colorname(COL_BLUE), NULL); sethostenv_report(starttime, starttime, 97.0, 99.995); headfoot(stdout, "snapshot", "", "header", COL_BLUE); strftime(startstr, sizeof(startstr), "%b %d %Y", localtime(&starttime)); printf("<CENTER><A NAME=begindata> </A>\n"); printf("<BR><BR><BR><BR>\n"); printf("<H3>Generating snapshot: %s<BR>\n", htmlquoted(startstr)); printf("<P><P>\n"); fflush(stdout); } /* Go do the report */ childpid = fork(); if (childpid == 0) { execv(xymongencmd, xymongen_argv); } else if (childpid > 0) { wait(&childstat); /* Ignore SIGHUP so we don't get killed during cleanup of XYMONSNAPDIR */ signal(SIGHUP, SIG_IGN); if (WIFEXITED(childstat) && (WEXITSTATUS(childstat) != 0) ) { if (usemultipart) printf("%s\n\n", htmldelim); printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); errormsg("Could not generate report"); } else { /* Send the browser off to the report */ if (usemultipart) { printf("Done...<P></BODY></HTML>\n"); fflush(stdout); printf("%s\n\n", htmldelim); } printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); printf("<HTML><HEAD>\n"); printf("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0; URL=%s/%s/\"\n", xgetenv("XYMONSNAPURL"), dirid); printf("</HEAD><BODY BGCOLOR=\"000000\"></BODY></HTML>\n"); if (usemultipart) printf("\n%s\n", htmldelim); fflush(stdout); } cleandir(xgetenv("XYMONSNAPDIR")); } else { if (usemultipart) printf("%s\n\n", htmldelim); printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); errormsg("Fork failed"); } return 0; }
int main(int argc, char *argv[]) { strbuffer_t *inbuf; char *ackbuf; char *subjectline = NULL; char *returnpathline = NULL; char *fromline = NULL; char *firsttxtline = NULL; int inheaders = 1; char *p; pcre *subjexp; const char *errmsg; int errofs, result; int ovector[30]; char cookie[10]; int duration = 0; int argi; char *envarea = NULL; for (argi=1; (argi < argc); argi++) { if (strcmp(argv[argi], "--debug") == 0) { debug = 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); } } initfgets(stdin); inbuf = newstrbuffer(0); while (unlimfgets(inbuf, stdin)) { sanitize_input(inbuf, 0, 0); if (!inheaders) { /* We're in the message body. Look for a "delay=N" line here. */ if ((strncasecmp(STRBUF(inbuf), "delay=", 6) == 0) || (strncasecmp(STRBUF(inbuf), "delay ", 6) == 0)) { duration = durationvalue(STRBUF(inbuf)+6); continue; } else if ((strncasecmp(STRBUF(inbuf), "ack=", 4) == 0) || (strncasecmp(STRBUF(inbuf), "ack ", 4) == 0)) { /* Some systems cannot generate a subject. Allow them to ack * via text in the message body. */ subjectline = (char *)malloc(STRBUFLEN(inbuf) + 1024); sprintf(subjectline, "Subject: Xymon [%s]", STRBUF(inbuf)+4); } else if (*STRBUF(inbuf) && !firsttxtline) { /* Save the first line of the message body, but ignore blank lines */ firsttxtline = strdup(STRBUF(inbuf)); } continue; /* We don't care about the rest of the message body */ } /* See if we're at the end of the mail headers */ if (inheaders && (STRBUFLEN(inbuf) == 0)) { inheaders = 0; continue; } /* Is it one of those we want to keep ? */ if (strncasecmp(STRBUF(inbuf), "return-path:", 12) == 0) returnpathline = strdup(skipwhitespace(STRBUF(inbuf)+12)); else if (strncasecmp(STRBUF(inbuf), "from:", 5) == 0) fromline = strdup(skipwhitespace(STRBUF(inbuf)+5)); else if (strncasecmp(STRBUF(inbuf), "subject:", 8) == 0) subjectline = strdup(skipwhitespace(STRBUF(inbuf)+8)); } freestrbuffer(inbuf); /* No subject ? No deal */ if (subjectline == NULL) { dbgprintf("Subject-line not found\n"); return 1; } /* Get the alert cookie */ subjexp = pcre_compile(".*(Xymon|Hobbit|BB)[ -]* \\[*(-*[0-9]+)[\\]!]*", PCRE_CASELESS, &errmsg, &errofs, NULL); if (subjexp == NULL) { dbgprintf("pcre compile failed - 1\n"); return 2; } result = pcre_exec(subjexp, NULL, subjectline, strlen(subjectline), 0, 0, ovector, (sizeof(ovector)/sizeof(int))); if (result < 0) { dbgprintf("Subject line did not match pattern\n"); return 3; /* Subject did not match what we expected */ } if (pcre_copy_substring(subjectline, ovector, result, 2, cookie, sizeof(cookie)) <= 0) { dbgprintf("Could not find cookie value\n"); return 4; /* No cookie */ } pcre_free(subjexp); /* See if there's a "DELAY=" delay-value also */ subjexp = pcre_compile(".*DELAY[ =]+([0-9]+[mhdw]*)", PCRE_CASELESS, &errmsg, &errofs, NULL); if (subjexp == NULL) { dbgprintf("pcre compile failed - 2\n"); return 2; } result = pcre_exec(subjexp, NULL, subjectline, strlen(subjectline), 0, 0, ovector, (sizeof(ovector)/sizeof(int))); if (result >= 0) { char delaytxt[4096]; if (pcre_copy_substring(subjectline, ovector, result, 1, delaytxt, sizeof(delaytxt)) > 0) { duration = durationvalue(delaytxt); } } pcre_free(subjexp); /* See if there's a "msg" text also */ subjexp = pcre_compile(".*MSG[ =]+(.*)", PCRE_CASELESS, &errmsg, &errofs, NULL); if (subjexp == NULL) { dbgprintf("pcre compile failed - 3\n"); return 2; } result = pcre_exec(subjexp, NULL, subjectline, strlen(subjectline), 0, 0, ovector, (sizeof(ovector)/sizeof(int))); if (result >= 0) { char msgtxt[4096]; if (pcre_copy_substring(subjectline, ovector, result, 1, msgtxt, sizeof(msgtxt)) > 0) { firsttxtline = strdup(msgtxt); } } pcre_free(subjexp); /* Use the "return-path:" header if we didn't see a From: line */ if ((fromline == NULL) && returnpathline) fromline = returnpathline; if (fromline) { /* Remove '<' and '>' from the fromline - they mess up HTML */ while ((p = strchr(fromline, '<')) != NULL) *p = ' '; while ((p = strchr(fromline, '>')) != NULL) *p = ' '; } /* Setup the acknowledge message */ if (duration == 0) duration = 60; /* Default: Ack for 60 minutes */ if (firsttxtline == NULL) firsttxtline = "<No cause specified>"; ackbuf = (char *)malloc(4096 + strlen(firsttxtline) + (fromline ? strlen(fromline) : 0)); p = ackbuf; p += sprintf(p, "xymondack %s %d %s", cookie, duration, firsttxtline); if (fromline) { p += sprintf(p, "\nAcked by: %s", fromline); } if (debug) { printf("%s\n", ackbuf); return 0; } sendmessage(ackbuf, NULL, XYMON_TIMEOUT, NULL); return 0; }
int main(int argc, char *argv[]) { void *hostwalk, *clonewalk; int argi; char *envarea = NULL; strbuffer_t *outbuf; char msgline[4096]; char oneurl[10240]; int gotany = 0; enum { OP_INITIAL, OP_YES, OP_NO } gotonepage = OP_INITIAL; /* Tracks if all matches are on one page */ char *onepage = NULL; /* If gotonepage==OP_YES, then this is the page */ /*[wm] regex support */ #define BUFSIZE 256 regex_t re; char re_errstr[BUFSIZE]; int re_status; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } } redirect_cgilog("findhost"); cgidata = cgi_request(); if (cgidata == NULL) { /* Present the query form */ sethostenv("", "", "", colorname(COL_BLUE), NULL); printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); showform(stdout, "findhost", "findhost_form", COL_BLUE, getcurrenttime(NULL), NULL, NULL); return 0; } parse_query(); if ( (re_status = regcomp(&re, pSearchPat, re_flag)) != 0 ) { regerror(re_status, &re, re_errstr, BUFSIZE); print_header(); printf("<tr><td align=left><font color=red>%s</font></td>\n", pSearchPat); printf("<td align=left><font color=red>%s</font></td></tr>\n", re_errstr); print_footer(); return 0; } outbuf = newstrbuffer(0); load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn()); hostwalk = first_host(); while (hostwalk) { /* * [wm] - Allow the search to be done on the hostname * also on the "displayname" and the host comment * Maybe this should be implemented by changing the HTML form, but until than.. * we're supposing that hostname will NEVER be null */ char *hostname, *displayname, *comment, *ip; hostname = xmh_item(hostwalk, XMH_HOSTNAME); displayname = xmh_item(hostwalk, XMH_DISPLAYNAME); comment = xmh_item(hostwalk, XMH_COMMENT); ip = xmh_item(hostwalk, XMH_IP); if ( regexec (&re, hostname, (size_t)0, NULL, 0) == 0 || (regexec(&re, ip, (size_t)0, NULL, 0) == 0) || (displayname && regexec (&re, displayname, (size_t)0, NULL, 0) == 0) || (comment && regexec (&re, comment, (size_t)0, NULL, 0) == 0) ) { /* match */ addtobuffer(outbuf, "<tr>\n"); sprintf(msgline, "<td align=left> %s </td>\n", displayname ? displayname : hostname); addtobuffer(outbuf, msgline); sprintf(oneurl, "%s/%s/#%s", xgetenv("XYMONWEB"), xmh_item(hostwalk, XMH_PAGEPATH), hostname); sprintf(msgline, "<td align=left> <a href=\"%s\">%s</a>\n", oneurl, xmh_item(hostwalk, XMH_PAGEPATHTITLE)); addtobuffer(outbuf, msgline); gotany++; /* See if all of the matches so far are on one page */ switch (gotonepage) { case OP_INITIAL: gotonepage = OP_YES; onepage = xmh_item(hostwalk, XMH_PAGEPATH); break; case OP_YES: if (strcmp(onepage, xmh_item(hostwalk, XMH_PAGEPATH)) != 0) gotonepage = OP_NO; break; case OP_NO: break; } clonewalk = next_host(hostwalk, 1); while (clonewalk && (strcmp(xmh_item(hostwalk, XMH_HOSTNAME), xmh_item(clonewalk, XMH_HOSTNAME)) == 0)) { sprintf(msgline, "<br><a href=\"%s/%s/#%s\">%s</a>\n", xgetenv("XYMONWEB"), xmh_item(clonewalk, XMH_PAGEPATH), xmh_item(clonewalk, XMH_HOSTNAME), xmh_item(clonewalk, XMH_PAGEPATHTITLE)); addtobuffer(outbuf, msgline); clonewalk = next_host(clonewalk, 1); gotany++; } addtobuffer(outbuf, "</td>\n</tr>\n"); hostwalk = clonewalk; } else { hostwalk = next_host(hostwalk, 0); } } regfree (&re); /*[wm] - free regex compiled patern */ if (dojump) { if (gotany == 1) { printf("Location: %s%s\n\n", xgetenv("XYMONWEBHOST"), oneurl); return 0; } else if ((gotany > 1) && (gotonepage == OP_YES)) { printf("Location: %s%s/%s/\n\n", xgetenv("XYMONWEBHOST"), xgetenv("XYMONWEB"), onepage); return 0; } } print_header(); if (!gotany) { printf("<tr><td align=left>%s</td><td align=left>Not found</td></tr>\n", pSearchPat); } else { printf("%s", grabstrbuffer(outbuf)); } print_footer(); /* [wm] - Free the strdup allocated memory */ if (pSearchPat) xfree(pSearchPat); return 0; }
int main(int argc, char *argv[]) { char *envarea = NULL; char *server = NULL; char *cookie, *pagefilter = ""; char *filter = NULL; char *heading = NULL; int showcolors = 1; int showcolumn = 0; int addlink = 0; int allhosts = 0; int summary = 0; int embedded = 0; char *req, *board, *l; int argi, res; sendreturn_t *sres; init_timestamp(); for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if ( argnmatch(argv[argi], "--column=") || argnmatch(argv[argi], "--test=")) { char *p = strchr(argv[argi], '='); int needed; needed = 10 + strlen(p); if (filter) needed += strlen(filter); filter = (char *)(filter ? realloc(filter, needed) : calloc(1, needed)); sprintf(filter + strlen(filter), " test=%s", p+1); if (!heading) { heading = (char *)malloc(1024 + strlen(p) + strlen(timestamp)); sprintf(heading, "%s report on %s", p+1, timestamp); } } else if (argnmatch(argv[argi], "--filter=")) { char *p = strchr(argv[argi], '='); int needed; needed = 10 + strlen(p); if (filter) needed += strlen(filter); filter = (char *)(filter ? realloc(filter, needed) : calloc(1, needed)); sprintf(filter + strlen(filter), " %s", p+1); } else if (argnmatch(argv[argi], "--heading=")) { char *p = strchr(argv[argi], '='); heading = strdup(p+1); } else if (strcmp(argv[argi], "--show-column") == 0) { showcolumn = 1; } else if (strcmp(argv[argi], "--show-test") == 0) { showcolumn = 1; } else if (strcmp(argv[argi], "--show-colors") == 0) { showcolors = 1; } else if (strcmp(argv[argi], "--show-summary") == 0) { summary = 1; } else if (strcmp(argv[argi], "--show-message") == 0) { summary = 0; } else if (strcmp(argv[argi], "--link") == 0) { addlink = 1; } else if (strcmp(argv[argi], "--no-colors") == 0) { showcolors = 0; } else if (strcmp(argv[argi], "--all") == 0) { allhosts = 1; } else if (strcmp(argv[argi], "--embedded") == 0) { embedded = 1; } } if (!allhosts) { /* Setup the filter we use for the report */ cookie = get_cookie("pagepath"); if (cookie && *cookie) { pcre *dummy; char *re = (char *)malloc(8 + 2*strlen(cookie)); sprintf(re, "^%s$|^%s/.+", cookie, cookie); dummy = compileregex(re); if (dummy) { freeregex(dummy); pagefilter = malloc(10 + strlen(re)); sprintf(pagefilter, "page=%s", re); } } } sres = newsendreturnbuf(1, NULL); req = malloc(1024 + strlen(pagefilter) + strlen(filter)); sprintf(req, "xymondboard fields=hostname,testname,color,msg %s %s", pagefilter, filter); res = sendmessage(req, server, XYMON_TIMEOUT, sres); board = getsendreturnstr(sres, 1); freesendreturnbuf(sres); if (res != XYMONSEND_OK) return 1; if (!embedded) { printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); printf("<html><head><title>%s</title></head>\n", htmlquoted(heading)); printf("<body>"); printf("<table border=1 cellpadding=5><tr><th>%s</th><th align=left>Status</th></tr>\n", (showcolumn ? "Host/Column" : "Host")); } l = board; while (l && *l) { char *hostname, *testname = NULL, *colorstr = NULL, *msg = NULL, *p; char *eoln = strchr(l, '\n'); if (eoln) *eoln = '\0'; hostname = l; p = strchr(l, '|'); if (p) { *p = '\0'; l = testname = p+1; } p = strchr(l, '|'); if (p) { *p = '\0'; l = colorstr = p+1; } p = strchr(l, '|'); if (p) { *p = '\0'; l = msg = p+1; } if (hostname && testname && colorstr && msg) { char *msgeol; nldecode(msg); msgeol = strchr(msg, '\n'); if (msgeol) { /* Skip the first status line */ msg = msgeol + 1; } printf("<tr><td align=left valign=top><b>"); if (addlink) printf("<a href=\"%s\">%s</a>", hostsvcurl(hostname, xgetenv("INFOCOLUMN"), 1), htmlquoted(hostname)); else printf("%s", htmlquoted(hostname)); if (showcolumn) { printf("<br>"); if (addlink) printf("<a href=\"%s\">%s</a>", hostsvcurl(hostname, testname, 1), htmlquoted(testname)); else printf("%s", htmlquoted(testname)); } if (showcolors) printf(" - %s", colorstr); printf("</b></td>\n"); printf("<td><pre>\n"); if (summary) { int firstline = 1; char *bol, *eol; bol = msg; while (bol) { eol = strchr(bol, '\n'); if (eol) *eol = '\0'; if (firstline) { if (!isspace((int)*bol)) { printf("%s\n", bol); firstline = 0; } } else if ((*bol == '&') && (strncmp(bol, "&green", 6) != 0)) { printf("%s\n", bol); } bol = (eol ? eol+1 : NULL); } } else { printf("%s", msg); } printf("</pre></td></tr>\n"); } if (eoln) l = eoln+1; else l = NULL; } if (!embedded) printf("</table></body></html>\n"); return 0; }
int main(int argc, char *argv[]) { char *msg; int running; int argi, seq; int recentperiod = 3600; int maxrecentcount = 5; int logdirfull = 0; int minlogspace = 5; struct sigaction sa; /* Handle program options. */ for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--logdir=")) { clientlogdir = strchr(argv[argi], '=')+1; } else if (argnmatch(argv[argi], "--recent-period=")) { char *p = strchr(argv[argi], '='); recentperiod = 60*atoi(p+1); } else if (argnmatch(argv[argi], "--recent-count=")) { char *p = strchr(argv[argi], '='); maxrecentcount = atoi(p+1); } else if (argnmatch(argv[argi], "--minimum-free=")) { minlogspace = atoi(strchr(argv[argi], '=')+1); } else if (strcmp(argv[argi], "--debug") == 0) { /* * A global "debug" variable is available. If * it is set, then "dbgprintf()" outputs debug messages. */ debug = 1; } else if (net_worker_option(argv[argi])) { /* Handled in the subroutine */ } } if (clientlogdir == NULL) clientlogdir = xgetenv("CLIENTLOGS"); if (clientlogdir == NULL) { clientlogdir = (char *)malloc(strlen(xgetenv("XYMONVAR")) + 10); sprintf(clientlogdir, "%s/hostdata", xgetenv("XYMONVAR")); } save_errbuf = 0; /* Do the network stuff if needed */ net_worker_run(ST_HOSTDATA, LOC_STICKY, update_locator_hostdata); setup_signalhandler("xymond_hostdata"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; signal(SIGCHLD, SIG_IGN); sigaction(SIGHUP, &sa, NULL); signal(SIGPIPE, SIG_DFL); savetimes = xtreeNew(strcasecmp); running = 1; while (running) { char *eoln, *restofmsg, *p; char *metadata[MAX_META+1]; int metacount; msg = get_xymond_message(C_CLICHG, "xymond_hostdata", &seq, NULL); if (msg == NULL) { /* * get_xymond_message will return NULL if xymond_channel closes * the input pipe. We should shutdown when that happens. */ running = 0; continue; } if (nextfscheck < gettimer()) { logdirfull = (chkfreespace(clientlogdir, minlogspace, minlogspace) != 0); if (logdirfull) errprintf("Hostdata directory %s has less than %d%% free space - disabling save of data for 5 minutes\n", clientlogdir, minlogspace); nextfscheck = gettimer() + 300; } /* Split the message in the first line (with meta-data), and the rest */ eoln = strchr(msg, '\n'); if (eoln) { *eoln = '\0'; restofmsg = eoln+1; } else { restofmsg = ""; } metacount = 0; memset(&metadata, 0, sizeof(metadata)); p = gettok(msg, "|"); while (p && (metacount < MAX_META)) { metadata[metacount++] = p; p = gettok(NULL, "|"); } metadata[metacount] = NULL; if (strncmp(metadata[0], "@@clichg", 8) == 0) { xtreePos_t handle; savetimes_t *itm; int i, recentcount; time_t now = gettimer(); char hostdir[PATH_MAX]; char fn[PATH_MAX]; FILE *fd; /* metadata[3] is the hostname */ handle = xtreeFind(savetimes, metadata[3]); if (handle != xtreeEnd(savetimes)) { itm = (savetimes_t *)xtreeData(savetimes, handle); } else { itm = (savetimes_t *)calloc(1, sizeof(savetimes_t)); itm->hostname = strdup(metadata[3]); xtreeAdd(savetimes, itm->hostname, itm); } /* See how many times we've saved the hostdata recently (within the past 'recentperiod' seconds) */ for (i=0, recentcount=0; ((i < 12) && (itm->tstamp[i] > (now - recentperiod))); i++) recentcount++; /* If it's been saved less than 'maxrecentcount' times, then save it. Otherwise just drop it */ if (!logdirfull && (recentcount < maxrecentcount)) { int written, closestatus, ok = 1; for (i = 10; (i > 0); i--) itm->tstamp[i+1] = itm->tstamp[i]; itm->tstamp[0] = now; sprintf(hostdir, "%s/%s", clientlogdir, metadata[3]); mkdir(hostdir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); sprintf(fn, "%s/%s", hostdir, metadata[4]); fd = fopen(fn, "w"); if (fd == NULL) { errprintf("Cannot create file %s: %s\n", fn, strerror(errno)); continue; } written = fwrite(restofmsg, 1, strlen(restofmsg), fd); if (written != strlen(restofmsg)) { errprintf("Cannot write hostdata file %s: %s\n", fn, strerror(errno)); closestatus = fclose(fd); /* Ignore any close errors */ ok = 0; } else { closestatus = fclose(fd); if (closestatus != 0) { errprintf("Cannot write hostdata file %s: %s\n", fn, strerror(errno)); ok = 0; } } if (!ok) remove(fn); } } /* * A "shutdown" message is sent when the master daemon * terminates. The child workers should shutdown also. */ else if (strncmp(metadata[0], "@@shutdown", 10) == 0) { running = 0; continue; } else if (strncmp(metadata[0], "@@idle", 6) == 0) { /* Ignored */ continue; } /* * A "logrotate" message is sent when the Xymon logs are * rotated. The child workers must re-open their logfiles, * typically stdin and stderr - the filename is always * provided in the XYMONCHANNEL_LOGFILENAME environment. */ else if (strncmp(metadata[0], "@@logrotate", 11) == 0) { char *fn = xgetenv("XYMONCHANNEL_LOGFILENAME"); if (fn && strlen(fn)) { reopen_file(fn, "a", stdout); reopen_file(fn, "a", stderr); } continue; } else if ((metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) { /* @@drophost|timestamp|sender|hostname */ char hostdir[PATH_MAX]; snprintf(hostdir, sizeof(hostdir), "%s/%s", clientlogdir, basename(metadata[3])); dropdirectory(hostdir, 1); } else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) { /* @@renamehost|timestamp|sender|hostname|newhostname */ char oldhostdir[PATH_MAX], newhostdir[PATH_MAX]; snprintf(oldhostdir, sizeof(oldhostdir), "%s/%s", clientlogdir, basename(metadata[3])); snprintf(newhostdir, sizeof(newhostdir), "%s/%s", clientlogdir, basename(metadata[4])); rename(oldhostdir, newhostdir); if (net_worker_locatorbased()) locator_rename_host(metadata[3], metadata[4], ST_HOSTDATA); } else if (strncmp(metadata[0], "@@reload", 8) == 0) { /* Do nothing */ } } 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; }
int main(int argc, char *argv[]) { tasklist_t *twalk, *dwalk; grouplist_t *gwalk; int argi; int daemonize = 1; int verbose = 0; char *config = "/etc/tasks.cfg"; char *logfn = NULL; char *pidfn = NULL; pid_t cpid; int status; struct sigaction sa; char *envarea = NULL; for (argi=1; (argi < argc); argi++) { if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (strcmp(argv[argi], "--no-daemon") == 0) { daemonize = 0; } else if (strcmp(argv[argi], "--verbose") == 0) { verbose = 1; } else if (argnmatch(argv[argi], "--config=")) { char *p = strchr(argv[argi], '='); config = strdup(expand_env(p+1)); } else if (argnmatch(argv[argi], "--log=")) { char *p = strchr(argv[argi], '='); logfn = strdup(expand_env(p+1)); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--pidfile=")) { char *p = strchr(argv[argi], '='); pidfn = strdup(expand_env(p+1)); } else if (strcmp(argv[argi], "--dump") == 0) { /* Dump configuration */ forcereload=1; load_config(config); forcereload=0; for (gwalk = grouphead; (gwalk); gwalk = gwalk->next) { if (gwalk->maxuse > 1) printf("GROUP %s %d\n", gwalk->groupname, gwalk->maxuse); } printf("\n"); for (twalk = taskhead; (twalk); twalk = twalk->next) { printf("[%s]\n", twalk->key); printf("\tCMD %s\n", twalk->cmd); if (twalk->disabled) printf("\tDISABLED\n"); if (twalk->group) printf("\tGROUP %s\n", twalk->group->groupname); if (twalk->depends) printf("\tNEEDS %s\n", twalk->depends->key); if (twalk->interval > 0) printf("\tINTERVAL %d\n", twalk->interval); if (twalk->cronstr) printf("\tCRONDATE %s\n", twalk->cronstr); if (twalk->maxruntime) printf("\tMAXTIME %d\n", twalk->maxruntime); if (twalk->logfile) printf("\tLOGFILE %s\n", twalk->logfile); if (twalk->envfile) printf("\tENVFILE %s\n", twalk->envfile); if (twalk->envarea) printf("\tENVAREA %s\n", twalk->envarea); if (twalk->onhostptn) printf("\tONHOST %s\n", twalk->onhostptn); printf("\n"); } fflush(stdout); return 0; } else { fprintf(stderr,"%s: Unsupported argument: %s\n",argv[0],argv[argi]); fflush(stderr); return 1; } } /* Go daemon */ if (daemonize) { pid_t childpid; /* Become a daemon */ childpid = fork(); if (childpid < 0) { /* Fork failed */ errprintf("Could not fork child\n"); exit(1); } else if (childpid > 0) { /* Parent exits */ if (pidfn) { FILE *pidfd = fopen(pidfn, "w"); if (pidfd) { fprintf(pidfd, "%d\n", (int)childpid); fclose(pidfd); } } exit(0); } /* Child (daemon) continues here */ setsid(); } /* If using a logfile, switch stdout and stderr to go there */ if (logfn) { /* Should we close stdin here ? No ... */ reopen_file("/dev/null", "r", stdin); reopen_file(logfn, "a", stdout); reopen_file(logfn, "a", stderr); } save_errbuf = 0; setup_signalhandler("xymonlaunch"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; sigaction(SIGHUP, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGCHLD, &sa, NULL); errprintf("xymonlaunch starting\n"); while (running) { time_t now = gettimer(); if (now >= nextcfgload) { load_config(config); nextcfgload = (now + 30); } if (logfn && dologswitch) { reopen_file(logfn, "a", stdout); reopen_file(logfn, "a", stderr); dologswitch = 0; } /* Pick up children that have terminated */ while ((cpid = wait3(&status, WNOHANG, NULL)) > 0) { for (twalk = taskhead; (twalk && (twalk->pid != cpid)); twalk = twalk->next); if (twalk) { twalk->pid = 0; twalk->beingkilled = 0; if (WIFEXITED(status)) { twalk->exitcode = WEXITSTATUS(status); if (twalk->exitcode) { errprintf("Task %s terminated, status %d\n", twalk->key, twalk->exitcode); twalk->failcount++; } else { twalk->failcount = 0; } } else if (WIFSIGNALED(status)) { twalk->exitcode = -WTERMSIG(status); twalk->failcount++; errprintf("Task %s terminated by signal %d\n", twalk->key, abs(twalk->exitcode)); } if (twalk->group) twalk->group->currentuse--; /* Tasks that depend on this task should be killed ... */ for (dwalk = taskhead; (dwalk); dwalk = dwalk->next) { if ((dwalk->depends == twalk) && (dwalk->pid > 0)) { dwalk->beingkilled = 1; kill(dwalk->pid, SIGTERM); } } } } /* See what new tasks need to get going */ dbgprintf("\n"); dbgprintf("Starting tasklist scan\n"); crongettime(); for (twalk = taskhead; (twalk); twalk = twalk->next) { if ( (twalk->pid == 0) && !twalk->disabled && ( ((twalk->interval >= 0) && (now >= (twalk->laststart + twalk->interval))) || /* xymon interval condition */ (twalk->crondate && ((twalk->laststart + 55) < now) && cronmatch(twalk->crondate)) /* cron date */ ) ) { if (twalk->depends && ((twalk->depends->pid == 0) || (twalk->depends->laststart > (now - 5)))) { dbgprintf("Postponing start of %s due to %s not yet running\n", twalk->key, twalk->depends->key); continue; } if (twalk->group && (twalk->group->currentuse >= twalk->group->maxuse)) { dbgprintf("Postponing start of %s due to group %s being busy\n", twalk->key, twalk->group->groupname); continue; } if ((twalk->failcount > MAX_FAILS) && ((twalk->laststart + 600) < now)) { dbgprintf("Releasing %s from failure hold\n", twalk->key); twalk->failcount = 0; } if (twalk->failcount > MAX_FAILS) { dbgprintf("Postponing start of %s due to multiple failures\n", twalk->key); continue; } if (twalk->laststart > (now - 5)) { dbgprintf("Postponing start of %s, will not try more than once in 5 seconds\n", twalk->key); continue; } dbgprintf("About to start task %s\n", twalk->key); twalk->laststart = now; twalk->pid = fork(); if (twalk->pid == 0) { /* Exec the task */ char *cmd; char **cmdargs = NULL; static char tasksleepenv[20],bbsleepenv[20]; /* Setup environment */ if (twalk->envfile) { dbgprintf("%s -> Loading environment from %s area %s\n", twalk->key, expand_env(twalk->envfile), (twalk->envarea ? twalk->envarea : "")); loadenv(expand_env(twalk->envfile), twalk->envarea); } /* Setup TASKSLEEP to match the interval */ sprintf(tasksleepenv, "TASKSLEEP=%d", twalk->interval); sprintf(bbsleepenv, "BBSLEEP=%d", twalk->interval); /* For compatibility */ putenv(tasksleepenv); putenv(bbsleepenv); /* Setup command line and arguments */ cmdargs = setup_commandargs(twalk->cmd, &cmd); /* Point stdout/stderr to a logfile, if requested */ if (twalk->logfile) { char *logfn = expand_env(twalk->logfile); dbgprintf("%s -> Assigning stdout/stderr to log '%s'\n", twalk->key, logfn); reopen_file(logfn, "a", stdout); reopen_file(logfn, "a", stderr); } /* Go! */ dbgprintf("%s -> Running '%s', XYMONHOME=%s\n", twalk->key, cmd, xgetenv("XYMONHOME")); execvp(cmd, cmdargs); /* Should never go here */ errprintf("Could not start task %s using command '%s': %s\n", twalk->key, cmd, strerror(errno)); exit(0); } else if (twalk->pid == -1) { /* Fork failed */ errprintf("Fork failed!\n"); twalk->pid = 0; } else { if (twalk->group) twalk->group->currentuse++; if (verbose) errprintf("Task %s started with PID %d\n", twalk->key, (int)twalk->pid); } } else if (twalk->pid > 0) { dbgprintf("Task %s active with PID %d\n", twalk->key, (int)twalk->pid); if (twalk->maxruntime && ((now - twalk->laststart) > twalk->maxruntime)) { errprintf("Killing hung task %s (PID %d) after %d seconds\n", twalk->key, (int)twalk->pid, (now - twalk->laststart)); kill(twalk->pid, (twalk->beingkilled ? SIGKILL : SIGTERM)); twalk->beingkilled = 1; /* Next time it's a real kill */ } } } sleep(5); } /* Shutdown running tasks */ for (twalk = taskhead; (twalk); twalk = twalk->next) { if (twalk->pid) kill(twalk->pid, SIGTERM); } if (pidfn) unlink(pidfn); return 0; }
int main(int argc, char *argv[]) { int argi; char *envarea = NULL; char *hffile = "ghosts"; int bgcolor = COL_BLUE; char *ghosts = NULL; sendreturn_t *sres; for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (argnmatch(argv[argi], "--hffile=")) { char *p = strchr(argv[argi], '='); hffile = strdup(p+1); } } load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn()); parse_query(); switch (outform) { case O_HTML: fprintf(stdout, "Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); headfoot(stdout, hffile, "", "header", bgcolor); break; case O_TXT: fprintf(stdout, "Content-type: text/plain\n\n"); break; } sres = newsendreturnbuf(1, NULL); if (sendmessage("ghostlist", NULL, XYMON_TIMEOUT, sres) == XYMONSEND_OK) { char *bol, *eoln, *name, *sender, *timestr; time_t tstamp, now; int count, idx; ghost_t *ghosttable; ghosts = getsendreturnstr(sres, 1); /* Count the number of lines */ for (bol = ghosts, count=0; (bol); bol = strchr(bol, '\n')) { if (*bol == '\n') bol++; count++; } ghosttable = (ghost_t *)calloc(count+1, sizeof(ghost_t)); idx = count = 0; tstamp = now = getcurrenttime(NULL); bol = ghosts; while (bol) { name = sender = timestr = NULL; eoln = strchr(bol, '\n'); if (eoln) *eoln = '\0'; name = strtok(bol, "|"); if (name) sender = strtok(NULL, "|"); if (sender) timestr = strtok(NULL, "|"); if (timestr) tstamp = atol(timestr); if (name && sender && timestr && (tstamp > (now - maxage))) { int i1, i2, i3, i4; sscanf(sender, "%d.%d.%d.%d", &i1, &i2, &i3, &i4); ghosttable[idx].sender = sender; ghosttable[idx].senderval = (i1 << 24) + (i2 << 16) + (i3 << 8) + i4; ghosttable[idx].name = name; ghosttable[idx].tstamp = tstamp; find_candidate(&ghosttable[idx]); idx++; count++; } if (eoln) eoln++; bol = eoln; } switch (sorttype) { case S_NAME: qsort(&ghosttable[0], count, sizeof(ghost_t), hostname_compare); break; case S_SENDER: qsort(&ghosttable[0], count, sizeof(ghost_t), sender_compare); break; case S_TIME: qsort(&ghosttable[0], count, sizeof(ghost_t), time_compare); break; } if (outform == O_HTML) { fprintf(stdout, "<table align=center>\n"); fprintf(stdout, "<tr>"); fprintf(stdout, "<th align=left><a href=\"ghostlist.sh?SORT=name&MAXAGE=%d\">Hostname</a></th>", maxage); fprintf(stdout, "<th align=left><a href=\"ghostlist.sh?SORT=sender&MAXAGE=%d\">Sent from</a></th>", maxage); fprintf(stdout, "<th align=left>Candidate</th>"); fprintf(stdout, "<th align=right><a href=\"ghostlist.sh?SORT=time&MAXAGE=%d\">Report age</a></th>", maxage); fprintf(stdout, "</tr>\n"); } for (idx = 0; (idx < count); idx++) { if (!ghosttable[idx].name) continue; if (!ghosttable[idx].sender) continue; switch (outform) { case O_HTML: fprintf(stdout, "<tr><td align=left>%s</td><td align=left>%s</td>", ghosttable[idx].name, ghosttable[idx].sender); if (ghosttable[idx].candidate) { fprintf(stdout, "<td align=left><a href=\"%s\">%s</a></td>", hostsvcurl(xmh_item(ghosttable[idx].candidate, XMH_HOSTNAME), xgetenv("INFOCOLUMN"), 1), xmh_item(ghosttable[idx].candidate, XMH_HOSTNAME)); } else { fprintf(stdout, "<td> </td>"); } fprintf(stdout, "<td align=right>%ld:%02ld</td></tr>\n", (now - ghosttable[idx].tstamp)/60, (now - ghosttable[idx].tstamp)%60); break; case O_TXT: fprintf(stdout, "%s\t\t%s\n", ghosttable[idx].sender, ghosttable[idx].name); break; } } if (outform == O_HTML) { fprintf(stdout, "</table>\n"); fprintf(stdout, "<br><br><center><a href=\"ghostlist.sh?SORT=%s&MAXAGE=%d&TEXT\">Text report</a></center>\n", htmlquoted(sortstring), maxage); } } else fprintf(stdout, "<h3><center>Failed to retrieve ghostlist from server</center></h3>\n"); freesendreturnbuf(sres); if (outform == O_HTML) { headfoot(stdout, hffile, "", "footer", bgcolor); } return 0; }
int main(int argc, char *argv[]) { char *msg; int argi; struct sigaction sa; char *exthandler = NULL; char *extids = NULL; char *processor = NULL; struct sockaddr_un ctlsockaddr; int ctlsocket; /* Handle program options. */ for (argi = 1; (argi < argc); argi++) { if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (argnmatch(argv[argi], "--rrddir=")) { char *p = strchr(argv[argi], '='); rrddir = strdup(p+1); } else if (argnmatch(argv[argi], "--extra-script=")) { char *p = strchr(argv[argi], '='); exthandler = strdup(p+1); } else if (argnmatch(argv[argi], "--extra-tests=")) { char *p = strchr(argv[argi], '='); extids = strdup(p+1); } else if (argnmatch(argv[argi], "--processor=")) { char *p = strchr(argv[argi], '='); processor = strdup(p+1); } else if (strcmp(argv[argi], "--no-cache") == 0) { use_rrd_cache = 0; } else if (net_worker_option(argv[argi])) { /* Handled in the subroutine */ } } save_errbuf = 0; if ((rrddir == NULL) && xgetenv("XYMONRRDS")) { rrddir = strdup(xgetenv("XYMONRRDS")); } if (exthandler && extids) setup_exthandler(exthandler, extids); /* Do the network stuff if needed */ net_worker_run(ST_RRD, LOC_STICKY, update_locator_hostdata); setup_signalhandler("xymond_rrd"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; sigaction(SIGHUP, &sa, NULL); sigaction(SIGCHLD, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); signal(SIGPIPE, SIG_DFL); /* Setup the control socket that receives cache-flush commands */ memset(&ctlsockaddr, 0, sizeof(ctlsockaddr)); sprintf(ctlsockaddr.sun_path, "%s/rrdctl.%d", xgetenv("XYMONTMP"), getpid()); unlink(ctlsockaddr.sun_path); /* In case it was accidentally left behind */ ctlsockaddr.sun_family = AF_UNIX; ctlsocket = socket(AF_UNIX, SOCK_DGRAM, 0); if (ctlsocket == -1) { errprintf("Cannot create cache-control socket (%s)\n", strerror(errno)); return 1; } fcntl(ctlsocket, F_SETFL, O_NONBLOCK); if (bind(ctlsocket, (struct sockaddr *)&ctlsockaddr, sizeof(ctlsockaddr)) == -1) { errprintf("Cannot bind to cache-control socket (%s)\n", strerror(errno)); return 1; } /* Linux obeys filesystem permissions on the socket file, so make it world-accessible */ if (chmod(ctlsockaddr.sun_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) { errprintf("Setting permissions on cache-control socket failed: %s\n", strerror(errno)); } /* Load the RRD definitions */ load_rrddefs(); /* If we are passing data to an external processor, create the pipe to it */ setup_extprocessor(processor); running = 1; while (running) { char *eoln, *restofmsg = NULL; char *metadata[MAX_META+1]; int metacount; char *p; char *hostname = NULL, *testname = NULL, *sender = NULL, *classname = NULL, *pagepaths = NULL; xymonrrd_t *ldef = NULL; time_t tstamp; int childstat; ssize_t n; char ctlbuf[PATH_MAX]; int gotcachectlmessage; time_t now; /* See if we have any cache-control messages pending */ do { n = recv(ctlsocket, ctlbuf, sizeof(ctlbuf), 0); gotcachectlmessage = (n > 0); if (gotcachectlmessage) { /* We have a control message */ char *bol, *eol; ctlbuf[n] = '\0'; bol = ctlbuf; do { eol = strchr(bol, '\n'); if (eol) *eol = '\0'; rrdcacheflushhost(bol); if (eol) { bol = eol+1; } else bol = NULL; } while (bol && *bol); } } while (gotcachectlmessage); /* Get next message */ msg = get_xymond_message(C_LAST, argv[0], &seq, NULL); if (msg == NULL) { running = 0; continue; } now = gettimer(); if (reloadtime < now) { /* Reload configuration files */ load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn()); load_client_config(NULL); reloadtime = now + 600; } /* Split the message in the first line (with meta-data), and the rest */ eoln = strchr(msg, '\n'); if (eoln) { *eoln = '\0'; restofmsg = eoln+1; } /* Parse the meta-data */ metacount = 0; memset(&metadata, 0, sizeof(metadata)); p = gettok(msg, "|"); while (p && (metacount < MAX_META)) { metadata[metacount++] = p; p = gettok(NULL, "|"); } metadata[metacount] = NULL; if ((metacount >= 14) && (strncmp(metadata[0], "@@status", 8) == 0)) { /* * @@status|timestamp|sender|origin|hostname|testname|expiretime|color|testflags|\ * prevcolor|changetime|ackexpiretime|ackmessage|disableexpiretime|disablemessage|\ * clienttstamp|flapping|classname|pagepaths */ int color = parse_color(metadata[7]); switch (color) { case COL_GREEN: case COL_YELLOW: case COL_RED: case COL_BLUE: /* Blue is OK, because it only arrives here when an update is sent */ tstamp = atoi(metadata[1]); sender = metadata[2]; hostname = metadata[4]; testname = metadata[5]; classname = (metadata[17] ? metadata[17] : ""); pagepaths = (metadata[18] ? metadata[18] : ""); ldef = find_xymon_rrd(testname, metadata[8]); update_rrd(hostname, testname, restofmsg, tstamp, sender, ldef, classname, pagepaths); break; default: /* Ignore reports with purple, blue or clear - they have no data we want. */ break; } } else if ((metacount > 5) && (strncmp(metadata[0], "@@data", 6) == 0)) { /* @@data|timestamp|sender|origin|hostname|testname|classname|pagepaths */ tstamp = atoi(metadata[1]); sender = metadata[2]; hostname = metadata[4]; testname = metadata[5]; classname = (metadata[6] ? metadata[6] : ""); pagepaths = (metadata[7] ? metadata[7] : ""); ldef = find_xymon_rrd(testname, ""); update_rrd(hostname, testname, restofmsg, tstamp, sender, ldef, classname, pagepaths); } else if (strncmp(metadata[0], "@@shutdown", 10) == 0) { running = 0; continue; } else if (strncmp(metadata[0], "@@idle", 6) == 0) { /* Ignored */ continue; } else if (strncmp(metadata[0], "@@logrotate", 11) == 0) { char *fn = xgetenv("XYMONCHANNEL_LOGFILENAME"); if (fn && strlen(fn)) { freopen(fn, "a", stdout); freopen(fn, "a", stderr); } continue; } else if (strncmp(metadata[0], "@@reload", 8) == 0) { reloadtime = 0; } else if ((metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) { char hostdir[PATH_MAX]; hostname = metadata[3]; MEMDEFINE(hostdir); sprintf(hostdir, "%s/%s", rrddir, hostname); dropdirectory(hostdir, 1); MEMUNDEFINE(hostdir); } else if ((metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) { /* * Not implemented. Mappings of testnames -> rrd files is * too complex, so on the rare occasion that a single test * is deleted, they will have to delete the rrd files themselves. */ } else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) { char oldhostdir[PATH_MAX]; char newhostdir[PATH_MAX]; char *newhostname; MEMDEFINE(oldhostdir); MEMDEFINE(newhostdir); hostname = metadata[3]; newhostname = metadata[4]; sprintf(oldhostdir, "%s/%s", rrddir, hostname); sprintf(newhostdir, "%s/%s", rrddir, newhostname); rename(oldhostdir, newhostdir); if (net_worker_locatorbased()) locator_rename_host(hostname, newhostname, ST_RRD); MEMUNDEFINE(newhostdir); MEMUNDEFINE(oldhostdir); } else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) { /* Not implemented. See "droptest". */ } /* * We fork a subprocess when processing drophost requests. * Pickup any finished child processes to avoid zombies */ while (wait3(&childstat, WNOHANG, NULL) > 0) ; } /* Flush all cached updates to disk */ errprintf("Shutting down, flushing cached updates to disk\n"); rrdcacheflushall(); errprintf("Cache flush completed\n"); /* Close the external processor */ shutdown_extprocessor(); /* Close the control socket */ close(ctlsocket); unlink(ctlsockaddr.sun_path); return 0; }
int main(int argc, char *argv[]) { int argi; char *envarea = NULL; char *xymonmsg; for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (argnmatch(argv[argi], "--level=")) { char *p = strchr(argv[argi], '='); level = atoi(p+1); } else if (argnmatch(argv[argi], "--validity=")) { char *p = strchr(argv[argi], '='); validity = atoi(p+1); } else if (argnmatch(argv[argi], "--sender=")) { char *p = strchr(argv[argi], '='); ackedby = strdup(p+1); } } redirect_cgilog("ackinfo"); parse_query(); if (hostname && *hostname && testname && *testname && ((level == 0) || (validity>0)) && ackmsg && *ackmsg) { char *p; /* Get the login username */ if (!ackedby) ackedby = getenv("REMOTE_USER"); if (!ackedby) ackedby = "UnknownUser"; if (validity == -1) validity = 30; /* 30 minutes */ validity = validity*60; p = strchr(ackmsg, '\n'); if (p) *p = '\0'; /* ackinfo HOST.TEST\nlevel\nvaliduntil\nackedby\nmsg */ xymonmsg = (char *)malloc(1024 + strlen(hostname) + strlen(testname) + strlen(ackedby) + strlen(ackmsg)); sprintf(xymonmsg, "ackinfo %s.%s\n%d\n%d\n%s\n%s\n", hostname, testname, level, validity, ackedby, ackmsg); sendmessage(xymonmsg, NULL, XYMON_TIMEOUT, NULL); } else { xymonmsg = (char *)malloc(1024 + (hostname ? strlen(hostname) : 9) + (testname ? strlen(testname) : 9) + (ackmsg ? strlen(ackmsg) : 9)); sprintf(xymonmsg, "error in input params: hostname=%s, testname=%s, ackmsg=%s, validity=%d\n", (hostname ? hostname : "<unknown>"), (testname ? testname : "<unknown>"), (ackmsg ? ackmsg : "<unknown>"), validity); } fprintf(stdout, "Content-type: %s\n", xgetenv("HTMLCONTENTTYPE")); fprintf(stdout, "Location: %s\n", getenv("HTTP_REFERER")); fprintf(stdout, "\n"); fprintf(stdout, "Sent to xymond:\n%s\n", htmlquoted(xymonmsg)); return 0; }
int main(int argc, char *argv[]) { int daemonize = 0; int lsocket; struct sockaddr_in laddr; struct sigaction sa; int argi, opt; libxymon_init(argv[0]); /* Dont save the output from errprintf() */ save_errbuf = 0; memset(&laddr, 0, sizeof(laddr)); laddr.sin_addr.s_addr = htonl(INADDR_ANY); laddr.sin_port = htons(1984); laddr.sin_family = AF_INET; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--listen=")) { char *locaddr, *p; int locport; locaddr = strchr(argv[argi], '=')+1; p = strchr(locaddr, ':'); if (p) { locport = atoi(p+1); *p = '\0'; } else locport = 1984; memset(&laddr, 0, sizeof(laddr)); laddr.sin_port = htons(locport); laddr.sin_family = AF_INET; if (inet_aton(locaddr, (struct in_addr *) &laddr.sin_addr.s_addr) == 0) { errprintf("Invalid listen address %s\n", locaddr); return 1; } } else if (strcmp(argv[argi], "--daemon") == 0) { daemonize = 1; } else if (strcmp(argv[argi], "--no-daemon") == 0) { daemonize = 0; } else if (standardoption(argv[argi])) { if (showhelp) return 0; } } /* Set up a socket to listen for new connections */ lsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (lsocket == -1) { errprintf("Cannot create listen socket (%s)\n", strerror(errno)); return 1; } opt = 1; setsockopt(lsocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (bind(lsocket, (struct sockaddr *)&laddr, sizeof(laddr)) == -1) { errprintf("Cannot bind to listener address (%s)\n", strerror(errno)); return 1; } /* Make it non-blocking */ fcntl(lsocket, F_SETFL, O_NONBLOCK); /* Redirect logging to the logfn, if requested */ if (logfn) { reopen_file(logfn, "a", stdout); reopen_file(logfn, "a", stderr); } errprintf("Xymon locator version %s starting\n", VERSION); errprintf("Listening on %s:%d\n", inet_ntoa(laddr.sin_addr), ntohs(laddr.sin_port)); if (daemonize) { pid_t childpid; reopen_file("/dev/null", "r", stdin); /* Become a daemon */ childpid = fork(); if (childpid < 0) { /* Fork failed */ errprintf("Could not fork\n"); exit(1); } else if (childpid > 0) { /* Parent - exit */ exit(0); } /* Child (daemon) continues here */ setsid(); } setup_signalhandler("xymond_locator"); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigmisc_handler; sigaction(SIGHUP, &sa, NULL); sigaction(SIGTERM, &sa, NULL); tree_init(); load_state(); do { ssize_t n; struct sockaddr_in remaddr; socklen_t remaddrsz; char buf[32768]; fd_set fdread; /* Wait for a message */ FD_ZERO(&fdread); FD_SET(lsocket, &fdread); n = select(lsocket+1, &fdread, NULL, NULL, NULL); if (n == -1) { /* Select error */ errprintf("select error, aborting: %s\n", strerror(errno)); keeprunning = 0; continue; } /* We know there is some data */ remaddrsz = sizeof(remaddr); n = recvfrom(lsocket, buf, sizeof(buf), 0, (struct sockaddr *)&remaddr, &remaddrsz); if (n == -1) { /* We may get EAGAIN if there is not a full message yet */ if (errno != EAGAIN) { errprintf("Recv error: %s\n", strerror(errno)); } continue; } else if (n == 0) { continue; } buf[n] = '\0'; dbgprintf("Got message from %s:%d : '%s'\n", inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port), buf); handle_request(buf); n = sendto(lsocket, buf, strlen(buf)+1, 0, (struct sockaddr *)&remaddr, remaddrsz); if (n == -1) { if (errno == EAGAIN) { errprintf("Out-queue full to %s, dropping response\n", inet_ntoa(remaddr.sin_addr)); } else { errprintf("Send failure %s while sending to %s\n", strerror(errno), inet_ntoa(remaddr.sin_addr)); } } } while (keeprunning); save_state(); return 0; }
int main(int argc, char *argv[]) { int argi; char *envarea = NULL; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (argnmatch(argv[argi], "--top")) { topcount = 10; webfile_hf = "topchanges"; webfile_form = "topchanges_form"; maxminutes = -1; maxcount = -1; } else if (strcmp(argv[argi], "--debug=")) { debug = 1; } } redirect_cgilog("eventlog"); load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn()); fprintf(stdout, "Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); cgidata = cgi_request(); if (cgidata == NULL) { /* Present the query form */ sethostenv("", "", "", colorname(COL_BLUE), NULL); showform(stdout, webfile_hf, webfile_form, COL_BLUE, getcurrenttime(NULL), NULL, NULL); return 0; } *periodstring = '\0'; parse_query(); if ((*periodstring == '\0') && (fromtime || totime)) { if (fromtime && totime) sprintf(periodstring, "Events between %s - %s", fromtime, totime); else if (fromtime) sprintf(periodstring, "Events since %s", fromtime); else if (totime) sprintf(periodstring, "Events until %s", totime); } /* Now generate the webpage */ headfoot(stdout, webfile_hf, "", "header", COL_GREEN); fprintf(stdout, "<center>\n"); if (topcount == 0) { do_eventlog(stdout, maxcount, maxminutes, fromtime, totime, pageregex, expageregex, hostregex, exhostregex, testregex, extestregex, colorregex, ignoredialups, NULL, NULL, NULL, NULL, counttype, summarybar, periodstring); } else { countlist_t *hcounts, *scounts; event_t *events; time_t firstevent, lastevent; do_eventlog(NULL, -1, -1, fromtime, totime, pageregex, expageregex, hostregex, exhostregex, testregex, extestregex, colorregex, ignoredialups, NULL, &events, &hcounts, &scounts, counttype, XYMON_S_NONE, NULL); lastevent = (totime ? eventreport_time(totime) : getcurrenttime(NULL)); if (fromtime) { firstevent = eventreport_time(fromtime); } else if (events) { event_t *ewalk; ewalk = events; while (ewalk->next) ewalk = ewalk->next; firstevent = ewalk->eventtime; } else firstevent = 0; show_topchanges(stdout, hcounts, scounts, events, topcount, firstevent, lastevent); } fprintf(stdout, "</center>\n"); headfoot(stdout, webfile_hf, "", "footer", COL_GREEN); return 0; }
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 main(int argc, char *argv[]) { char *msg; int seq; int argi; int alertcolors, alertinterval; char *configfn = NULL; char *checkfn = NULL; int checkpointinterval = 900; char acklogfn[PATH_MAX]; FILE *acklogfd = NULL; char notiflogfn[PATH_MAX]; FILE *notiflogfd = NULL; char *tracefn = NULL; struct sigaction sa; int configchanged; time_t lastxmit = 0; MEMDEFINE(acklogfn); MEMDEFINE(notiflogfn); libxymon_init(argv[0]); /* Dont save the error buffer */ save_errbuf = 0; /* Load alert config */ alertcolors = colorset(xgetenv("ALERTCOLORS"), ((1 << COL_GREEN) | (1 << COL_BLUE))); alertinterval = 60*atoi(xgetenv("ALERTREPEAT")); /* Create our loookup-trees */ hostnames = xtreeNew(strcasecmp); testnames = xtreeNew(strcasecmp); locations = xtreeNew(strcasecmp); for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--config=")) { configfn = strdup(strchr(argv[argi], '=')+1); } else if (argnmatch(argv[argi], "--checkpoint-file=")) { checkfn = strdup(strchr(argv[argi], '=')+1); } else if (argnmatch(argv[argi], "--checkpoint-interval=")) { char *p = strchr(argv[argi], '=') + 1; checkpointinterval = atoi(p); } else if (argnmatch(argv[argi], "--dump-config")) { load_alertconfig(configfn, alertcolors, alertinterval); dump_alertconfig(1); return 0; } else if (argnmatch(argv[argi], "--cfid")) { include_configid = 1; } else if (argnmatch(argv[argi], "--test")) { char *testhost = NULL, *testservice = NULL, *testpage = NULL, *testcolor = "red", *testgroups = NULL; void *hinfo; int testdur = 0; FILE *logfd = NULL; activealerts_t *awalk = NULL; int paramno = 0; argi++; if (argi < argc) testhost = argv[argi]; argi++; if (argi < argc) testservice = argv[argi]; argi++; while (argi < argc) { if (strncasecmp(argv[argi], "--duration=", 11) == 0) { testdur = durationvalue(strchr(argv[argi], '=')+1); } else if (strncasecmp(argv[argi], "--color=", 8) == 0) { testcolor = strchr(argv[argi], '=')+1; } else if (strncasecmp(argv[argi], "--group=", 8) == 0) { testgroups = strchr(argv[argi], '=')+1; } else if (strncasecmp(argv[argi], "--time=", 7) == 0) { fakestarttime = (time_t)atoi(strchr(argv[argi], '=')+1); } else { paramno++; if (paramno == 1) testdur = atoi(argv[argi]); else if (paramno == 2) testcolor = argv[argi]; else if (paramno == 3) fakestarttime = (time_t) atoi(argv[argi]); } argi++; } if ((testhost == NULL) || (testservice == NULL)) { printf("Usage: xymond_alert --test HOST SERVICE [options]\n"); printf("Possible options:\n\t[--duration=MINUTES]\n\t[--color=COLOR]\n\t[--group=GROUPNAME]\n\t[--time=TIMESPEC]\n"); return 1; } load_hostnames(xgetenv("HOSTSCFG"), NULL, get_fqdn()); hinfo = hostinfo(testhost); if (hinfo) { testpage = strdup(xmh_item(hinfo, XMH_ALLPAGEPATHS)); } else { errprintf("Host not found in hosts.cfg - assuming it is on the top page\n"); testpage = ""; } awalk = (activealerts_t *)calloc(1, sizeof(activealerts_t)); awalk->hostname = find_name(hostnames, testhost); awalk->testname = find_name(testnames, testservice); awalk->location = find_name(locations, testpage); awalk->ip = strdup("127.0.0.1"); awalk->color = awalk->maxcolor = parse_color(testcolor); awalk->pagemessage = "Test of the alert configuration"; awalk->eventstart = getcurrenttime(NULL) - testdur*60; awalk->groups = (testgroups ? strdup(testgroups) : NULL); awalk->state = A_PAGING; awalk->cookie = 12345; awalk->next = NULL; logfd = fopen("/dev/null", "w"); starttrace(NULL); testonly = 1; load_alertconfig(configfn, alertcolors, alertinterval); load_holidays(0); send_alert(awalk, logfd); return 0; } else if (argnmatch(argv[argi], "--trace=")) { tracefn = strdup(strchr(argv[argi], '=')+1); starttrace(tracefn); } else if (net_worker_option(argv[argi])) { /* Handled in the subroutine */ } else if (standardoption(argv[argi])) { if (showhelp) return 0; } else { errprintf("Unknown option '%s'\n", argv[argi]); } } /* Do the network stuff if needed */ net_worker_run(ST_ALERT, LOC_SINGLESERVER, NULL); if (checkfn) { load_checkpoint(checkfn); nextcheckpoint = gettimer() + checkpointinterval; dbgprintf("Next checkpoint at %d, interval %d\n", (int) nextcheckpoint, checkpointinterval); } setup_signalhandler("xymond_alert"); /* Need to handle these ourselves, so we can shutdown and save state-info */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_handler; sigaction(SIGPIPE, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGCHLD, &sa, NULL); sigaction(SIGUSR1, &sa, NULL); sigaction(SIGHUP, &sa, NULL); if (xgetenv("XYMONSERVERLOGS")) { sprintf(acklogfn, "%s/acknowledge.log", xgetenv("XYMONSERVERLOGS")); acklogfd = fopen(acklogfn, "a"); sprintf(notiflogfn, "%s/notifications.log", xgetenv("XYMONSERVERLOGS")); notiflogfd = fopen(notiflogfn, "a"); } /* * The general idea here is that this loop handles receiving of alert- * and ack-messages from the master daemon, and maintains a list of * host+test combinations that may have alerts going out. * * This module does not deal with any specific alert-configuration, * it just picks up the alert messages, maintains the list of * known tests that are in some sort of critical condition, and * periodically pushes alerts to the do_alert.c module for handling. * * The only modification of alerts that happen here is the handling * of when the next alert is due. It calls into the next_alert() * routine to learn when an alert should be repeated, and also * deals with Acknowledgments that stop alerts from going out for * a period of time. */ while (running) { char *eoln, *restofmsg; char *metadata[20]; char *p; int metacount; char *hostname = NULL, *testname = NULL; struct timespec timeout; time_t now, nowtimer; int anytogo; activealerts_t *awalk; int childstat; nowtimer = gettimer(); if (checkfn && (nowtimer > nextcheckpoint)) { dbgprintf("Saving checkpoint\n"); nextcheckpoint = nowtimer + checkpointinterval; save_checkpoint(checkfn); if (acklogfd) acklogfd = freopen(acklogfn, "a", acklogfd); if (notiflogfd) notiflogfd = freopen(notiflogfn, "a", notiflogfd); } timeout.tv_sec = 60; timeout.tv_nsec = 0; msg = get_xymond_message(C_PAGE, "xymond_alert", &seq, &timeout); if (msg == NULL) { running = 0; continue; } /* See what time it is - must happen AFTER the timeout */ now = getcurrenttime(NULL); /* Split the message in the first line (with meta-data), and the rest */ eoln = strchr(msg, '\n'); if (eoln) { *eoln = '\0'; restofmsg = eoln+1; } else { restofmsg = ""; } /* * Now parse the meta-data into elements. * We use our own "gettok()" routine which works * like strtok(), but can handle empty elements. */ metacount = 0; memset(&metadata, 0, sizeof(metadata)); p = gettok(msg, "|"); while (p && (metacount < 19)) { metadata[metacount] = p; metacount++; p = gettok(NULL, "|"); } metadata[metacount] = NULL; if (metacount > 3) hostname = metadata[3]; if (metacount > 4) testname = metadata[4]; if ((metacount > 10) && (strncmp(metadata[0], "@@page", 6) == 0)) { /* @@page|timestamp|sender|hostname|testname|hostip|expiretime|color|prevcolor|changetime|location|cookie|osname|classname|grouplist|modifiers */ int newcolor, newalertstatus, oldalertstatus; dbgprintf("Got page message from %s:%s\n", hostname, testname); traceprintf("@@page %s:%s:%s=%s\n", hostname, testname, metadata[10], metadata[7]); awalk = find_active(hostname, testname); if (awalk == NULL) { char *hwalk = find_name(hostnames, hostname); char *twalk = find_name(testnames, testname); char *pwalk = find_name(locations, metadata[10]); awalk = (activealerts_t *)calloc(1, sizeof(activealerts_t)); awalk->hostname = hwalk; awalk->testname = twalk; awalk->location = pwalk; awalk->cookie = -1; awalk->state = A_DEAD; /* * Use changetime here, if we restart the alert module then * this gets the duration values more right than using "now". * Also, define this only when a new alert arrives - we should * NOT clear this when a status goes yellow->red, or if it * flaps between yellow and red. */ awalk->eventstart = atoi(metadata[9]); add_active(awalk->hostname, awalk); traceprintf("New record\n"); } newcolor = parse_color(metadata[7]); oldalertstatus = ((alertcolors & (1 << awalk->color)) != 0); newalertstatus = ((alertcolors & (1 << newcolor)) != 0); traceprintf("state %d->%d\n", oldalertstatus, newalertstatus); if (newalertstatus) { /* It's in an alert state. */ awalk->color = newcolor; awalk->state = A_PAGING; if (newcolor > awalk->maxcolor) { if (awalk->maxcolor != 0) { /* * Severity has increased (yellow -> red). * Clear the repeat-interval, and set maxcolor to * the new color. If it drops to yellow again, * maxcolor stays at red, so a test that flaps * between yellow and red will only alert on red * the first time, and then follow the repeat * interval. */ dbgprintf("Severity increased, cleared repeat interval: %s/%s %s->%s\n", awalk->hostname, awalk->testname, colorname(awalk->maxcolor), colorname(newcolor)); clear_interval(awalk); } awalk->maxcolor = newcolor; } } else { /* * Send one "recovered" message out now, then go to A_DEAD. * Dont update the color here - we want recoveries to go out * only if the alert color triggered an alert */ awalk->state = (newcolor == COL_BLUE) ? A_DISABLED : A_RECOVERED; } if (oldalertstatus != newalertstatus) { dbgprintf("Alert status changed from %d to %d\n", oldalertstatus, newalertstatus); clear_interval(awalk); } if (awalk->ip) xfree(awalk->ip); awalk->ip = strdup(metadata[5]); awalk->cookie = atoi(metadata[11]); if (awalk->osname) xfree(awalk->osname); awalk->osname = (metadata[12] ? strdup(metadata[12]) : NULL); if (awalk->classname) xfree(awalk->classname); awalk->classname = (metadata[13] ? strdup(metadata[13]) : NULL); if (awalk->groups) xfree(awalk->groups); awalk->groups = (metadata[14] ? strdup(metadata[14]) : NULL); if (awalk->pagemessage) xfree(awalk->pagemessage); if (metadata[15]) { /* Modifiers are more interesting than the message itself */ awalk->pagemessage = (char *)malloc(strlen(awalk->hostname) + strlen(awalk->testname) + strlen(colorname(awalk->color)) + strlen(metadata[15]) + strlen(restofmsg) + 10); sprintf(awalk->pagemessage, "%s:%s %s\n%s\n%s", awalk->hostname, awalk->testname, colorname(awalk->color), metadata[15], restofmsg); } else { awalk->pagemessage = strdup(restofmsg); } } else if ((metacount > 5) && (strncmp(metadata[0], "@@ack", 5) == 0)) { /* @@ack|timestamp|sender|hostname|testname|hostip|expiretime */ /* * An ack is handled simply by setting the next * alert-time to when the ack expires. */ time_t nextalert = atoi(metadata[6]); dbgprintf("Got ack message from %s:%s\n", hostname, testname); traceprintf("@@ack: %s:%s now=%d, ackeduntil %d\n", hostname, testname, (int)now, (int)nextalert); awalk = find_active(hostname, testname); if (acklogfd) { int cookie = (awalk ? awalk->cookie : -1); int color = (awalk ? awalk->color : 0); fprintf(acklogfd, "%d\t%d\t%d\t%d\t%s\t%s.%s\t%s\t%s\n", (int)now, cookie, (int)((nextalert - now) / 60), cookie, "np_filename_not_used", hostname, testname, colorname(color), nlencode(restofmsg)); fflush(acklogfd); } if (awalk && (awalk->state == A_PAGING)) { traceprintf("Record updated\n"); awalk->state = A_ACKED; awalk->nextalerttime = nextalert; if (awalk->ackmessage) xfree(awalk->ackmessage); awalk->ackmessage = strdup(restofmsg); } else { traceprintf("No record\n"); } } else if ((metacount > 4) && (strncmp(metadata[0], "@@notify", 5) == 0)) { /* @@notify|timestamp|sender|hostname|testname|pagepath */ char *hwalk = find_name(hostnames, hostname); char *twalk = find_name(testnames, testname); char *pwalk = find_name(locations, (metadata[5] ? metadata[5] : "")); awalk = (activealerts_t *)calloc(1, sizeof(activealerts_t)); awalk->hostname = hwalk; awalk->testname = twalk; awalk->location = pwalk; awalk->cookie = -1; awalk->pagemessage = strdup(restofmsg); awalk->eventstart = getcurrenttime(NULL); awalk->state = A_NOTIFY; add_active(awalk->hostname, awalk); } else if ((metacount > 3) && ((strncmp(metadata[0], "@@drophost", 10) == 0) || (strncmp(metadata[0], "@@dropstate", 11) == 0))) { /* @@drophost|timestamp|sender|hostname */ /* @@dropstate|timestamp|sender|hostname */ xtreePos_t handle; handle = xtreeFind(hostnames, hostname); if (handle != xtreeEnd(hostnames)) { alertanchor_t *anchor = (alertanchor_t *)xtreeData(hostnames, handle); for (awalk = anchor->head; (awalk); awalk = awalk->next) awalk->state = A_DEAD; } } else if ((metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) { /* @@droptest|timestamp|sender|hostname|testname */ awalk = find_active(hostname, testname); if (awalk) awalk->state = A_DEAD; } else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) { /* @@renamehost|timestamp|sender|hostname|newhostname */ /* * We handle rename's simply by dropping the alert. If there is still an * active alert for the host, it will have to be dealt with when the next * status update arrives. */ xtreePos_t handle; handle = xtreeFind(hostnames, hostname); if (handle != xtreeEnd(hostnames)) { alertanchor_t *anchor = (alertanchor_t *)xtreeData(hostnames, handle); for (awalk = anchor->head; (awalk); awalk = awalk->next) awalk->state = A_DEAD; } } else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) { /* @@renametest|timestamp|sender|hostname|oldtestname|newtestname */ /* * We handle rename's simply by dropping the alert. If there is still an * active alert for the host, it will have to be dealt with when the next * status update arrives. */ awalk = find_active(hostname, testname); if (awalk) awalk->state = A_DEAD; } else if (strncmp(metadata[0], "@@shutdown", 10) == 0) { running = 0; errprintf("Got a shutdown message\n"); continue; } else if (strncmp(metadata[0], "@@logrotate", 11) == 0) { char *fn = xgetenv("XYMONCHANNEL_LOGFILENAME"); if (fn && strlen(fn)) { reopen_file(fn, "a", stdout); reopen_file(fn, "a", stderr); if (tracefn) { stoptrace(); starttrace(tracefn); } } continue; } else if (strncmp(metadata[0], "@@reload", 8) == 0) { /* Nothing ... right now */ } else if (strncmp(metadata[0], "@@idle", 6) == 0) { /* Timeout */ } /* * When a burst of alerts happen, we get lots of alert messages * coming in quickly. So lets handle them in bunches and only * do the full alert handling once every 10 secs - that lets us * combine a bunch of alerts into one transmission process. */ if (nowtimer < (lastxmit+10)) continue; lastxmit = nowtimer; /* * Loop through the activealerts list and see if anything is pending. * This is an optimization, we could just as well just fork off the * notification child and let it handle all of it. But there is no * reason to fork a child process unless it is going to do something. */ configchanged = load_alertconfig(configfn, alertcolors, alertinterval); configchanged += load_holidays(0); anytogo = 0; for (awalk = alistBegin(); (awalk); awalk = alistNext()) { int anymatch = 0; switch (awalk->state) { case A_NORECIP: if (!configchanged) break; /* The configuration has changed - switch NORECIP -> PAGING */ awalk->state = A_PAGING; clear_interval(awalk); /* Fall through */ case A_PAGING: if (have_recipient(awalk, &anymatch)) { if (awalk->nextalerttime <= now) anytogo++; } else { if (!anymatch) { awalk->state = A_NORECIP; cleanup_alert(awalk); } } break; case A_ACKED: if (awalk->nextalerttime <= now) { /* An ack has expired, so drop the ack message and switch to A_PAGING */ anytogo++; if (awalk->ackmessage) xfree(awalk->ackmessage); awalk->state = A_PAGING; } break; case A_RECOVERED: case A_DISABLED: case A_NOTIFY: anytogo++; break; case A_DEAD: break; } } dbgprintf("%d alerts to go\n", anytogo); if (anytogo) { pid_t childpid; childpid = fork(); if (childpid == 0) { /* The child */ start_alerts(); for (awalk = alistBegin(); (awalk); awalk = alistNext()) { switch (awalk->state) { case A_PAGING: if (awalk->nextalerttime <= now) { send_alert(awalk, notiflogfd); } break; case A_ACKED: /* Cannot be A_ACKED unless the ack is still valid, so no alert. */ break; case A_RECOVERED: case A_DISABLED: case A_NOTIFY: send_alert(awalk, notiflogfd); break; case A_NORECIP: case A_DEAD: break; } } finish_alerts(); /* Child does not continue */ exit(0); } else if (childpid < 0) { errprintf("Fork failed, cannot send alerts: %s\n", strerror(errno)); } } /* Update the state flag and the next-alert timestamp */ for (awalk = alistBegin(); (awalk); awalk = alistNext()) { switch (awalk->state) { case A_PAGING: if (awalk->nextalerttime <= now) awalk->nextalerttime = next_alert(awalk); break; case A_NORECIP: break; case A_ACKED: /* Still cannot get here except if ack is still valid */ break; case A_RECOVERED: case A_DISABLED: case A_NOTIFY: awalk->state = A_DEAD; /* Fall through */ case A_DEAD: cleanup_alert(awalk); break; } } clean_all_active(); /* Pickup any finished child processes to avoid zombies */ while (wait3(&childstat, WNOHANG, NULL) > 0) ; } if (checkfn) save_checkpoint(checkfn); if (acklogfd) fclose(acklogfd); if (notiflogfd) fclose(notiflogfd); stoptrace(); MEMUNDEFINE(notiflogfn); MEMUNDEFINE(acklogfn); if (termsig >= 0) { errprintf("Terminated by signal %d\n", termsig); } return 0; }
int main(int argc, char *argv[]) { char dirid[PATH_MAX]; char outdir[PATH_MAX]; char xymonwebenv[PATH_MAX]; char xymongencmd[PATH_MAX]; char xymongentimeopt[100]; char csvdelimopt[100]; char *xymongen_argv[20]; pid_t childpid; int childstat; char htmldelim[100]; char startstr[30], endstr[30]; int cleanupoldreps = 1; int argi, newargi; char *envarea = NULL; char *useragent = NULL; int usemultipart = 1; newargi = 0; xymongen_argv[newargi++] = xymongencmd; xymongen_argv[newargi++] = xymongentimeopt; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else if (strcmp(argv[1], "--noclean") == 0) { cleanupoldreps = 0; } else { xymongen_argv[newargi++] = argv[argi]; } } redirect_cgilog("report"); cgidata = cgi_request(); if (cgidata == NULL) { /* Present the query form */ sethostenv("", "", "", colorname(COL_BLUE), NULL); printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); showform(stdout, "report", "report_form", COL_BLUE, getcurrenttime(NULL)-86400, NULL, NULL); return 0; } useragent = getenv("HTTP_USER_AGENT"); if (useragent && strstr(useragent, "KHTML")) { /* KHTML (Konqueror, Safari) cannot handle multipart documents. */ usemultipart = 0; } envcheck(reqenv); parse_query(); /* * We need to set these variables up AFTER we have put them into the xymongen_argv[] array. * We cannot do it before, because we need the environment that the command-line options * might provide. */ if (xgetenv("XYMONGEN")) sprintf(xymongencmd, "%s", xgetenv("XYMONGEN")); else sprintf(xymongencmd, "%s/bin/xymongen", xgetenv("XYMONHOME")); snprintf(xymongentimeopt, sizeof(xymongentimeopt)-1,"--reportopts=%u:%u:1:%s", (unsigned int)starttime, (unsigned int)endtime, style); sprintf(dirid, "%u-%u", (unsigned int)getpid(), (unsigned int)getcurrenttime(NULL)); if (!csvoutput) { sprintf(outdir, "%s/%s", xgetenv("XYMONREPDIR"), dirid); mkdir(outdir, 0755); xymongen_argv[newargi++] = outdir; sprintf(xymonwebenv, "XYMONWEB=%s/%s", xgetenv("XYMONREPURL"), dirid); putenv(xymonwebenv); } else { sprintf(outdir, "--csv=%s/%s.csv", xgetenv("XYMONREPDIR"), dirid); xymongen_argv[newargi++] = outdir; sprintf(csvdelimopt, "--csvdelim=%c", csvdelim); xymongen_argv[newargi++] = csvdelimopt; } xymongen_argv[newargi++] = NULL; if (usemultipart) { /* Output the "please wait for report ... " thing */ snprintf(htmldelim, sizeof(htmldelim)-1, "xymonrep-%u-%u", (int)getpid(), (unsigned int)getcurrenttime(NULL)); printf("Content-type: multipart/mixed;boundary=%s\n", htmldelim); printf("\n"); printf("--%s\n", htmldelim); printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); /* It's ok with these hardcoded values, as they are not used for this page */ sethostenv("", "", "", colorname(COL_BLUE), NULL); sethostenv_report(starttime, endtime, 97.0, 99.995); headfoot(stdout, "repnormal", "", "header", COL_BLUE); strftime(startstr, sizeof(startstr), "%b %d %Y", localtime(&starttime)); strftime(endstr, sizeof(endstr), "%b %d %Y", localtime(&endtime)); printf("<CENTER><A NAME=begindata> </A>\n"); printf("<BR><BR><BR><BR>\n"); printf("<H3>Generating report for the period: %s", htmlquoted(startstr)); printf(" - %s ", htmlquoted(endstr)); printf("(%s)<BR>\n", htmlquoted(style)); printf("<P><P>\n"); fflush(stdout); } /* Go do the report */ childpid = fork(); if (childpid == 0) { execv(xymongencmd, xymongen_argv); } else if (childpid > 0) { wait(&childstat); /* Ignore SIGHUP so we dont get killed during cleanup of XYMONREPDIR */ signal(SIGHUP, SIG_IGN); if (WIFEXITED(childstat) && (WEXITSTATUS(childstat) != 0) ) { char msg[4096]; if (usemultipart) printf("--%s\n\n", htmldelim); sprintf(msg, "Could not generate report.<br>\nCheck that the %s/www/rep/ directory has permissions '-rwxrwxr-x' (775)<br>\n and that is is set to group %d", xgetenv("XYMONHOME"), (int)getgid()); errormsg(msg); } else { /* Send the browser off to the report */ if (usemultipart) { printf("Done...Report is <A HREF=\"%s/%s/%s\">here</a>.</P></BODY></HTML>\n", xgetenv("XYMONREPURL"), dirid, suburl); fflush(stdout); printf("--%s\n\n", htmldelim); } printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); printf("<HTML><HEAD>\n"); if (!csvoutput) { printf("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0; URL=%s/%s/%s\"\n", xgetenv("XYMONREPURL"), dirid, suburl); printf("</HEAD><BODY>Report is available <a href=\"%s/%s/%s\">here</a></BODY></HTML>\n", xgetenv("XYMONREPURL"), dirid, suburl); } else { printf("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0; URL=%s/%s.csv\"\n", xgetenv("XYMONREPURL"), dirid); printf("</HEAD><BODY>Report is available <a href=\"%s/%s.csv\">here</a></BODY></HTML>\n", xgetenv("XYMONREPURL"), dirid); } if (usemultipart) printf("\n--%s\n", htmldelim); fflush(stdout); } if (cleanupoldreps) cleandir(xgetenv("XYMONREPDIR")); } else { if (usemultipart) printf("--%s\n\n", htmldelim); printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); errormsg("Fork failed"); } return 0; }
int main(int argc, char *argv[]) { int argi; DIR *histdir = NULL; struct dirent *hent; struct stat st; time_t cutoff = 0; int dropsvcs = 0; int dropfiles = 0; int droplogs = 0; char *envarea = NULL; for (argi = 1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--cutoff=")) { char *p = strchr(argv[argi], '='); cutoff = atoi(p+1); } else if (argnmatch(argv[argi], "--outdir=")) { char *p = strchr(argv[argi], '='); outdir = strdup(p+1); } else if (strcmp(argv[argi], "--drop") == 0) { dropfiles = 1; } else if (strcmp(argv[argi], "--dropsvcs") == 0) { dropsvcs = 1; } else if (strcmp(argv[argi], "--droplogs") == 0) { droplogs = 1; } else if (strcmp(argv[argi], "--progress") == 0) { progressinfo = 100; } else if (argnmatch(argv[argi], "--progress=")) { char *p = strchr(argv[argi], '='); progressinfo = atoi(p+1); } else if (strcmp(argv[argi], "--debug") == 0) { debug = 1; } else if (strcmp(argv[argi], "--help") == 0) { printf("Usage:\n\n\t%s --cutoff=TIME\n\nTIME is in seconds since epoch\n", argv[0]); return 0; } 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); } } if (cutoff == 0) { errprintf("Must have a cutoff-time\n"); return 1; } if (chdir(xgetenv("BBHIST")) == -1) { errprintf("Cannot cd to history directory: %s\n", strerror(errno)); return 1; } histdir = opendir("."); if (!histdir) { errprintf("Cannot read history directory: %s\n", strerror(errno)); return 1; } load_hostnames(xgetenv("BBHOSTS"), NULL, get_fqdn()); /* First scan the directory for all files, and pick up the ones we want to process */ while ((hent = readdir(histdir)) != NULL) { char *hostname = NULL; char hostip[IP_ADDR_STRLEN]; int ghosthandling = 1; if (stat(hent->d_name, &st) == -1) { errprintf("Odd entry %s - cannot stat: %s\n", hent->d_name, strerror(errno)); continue; } if ((*(hent->d_name) == '.') || S_ISDIR(st.st_mode)) continue; if (strcmp(hent->d_name, "allevents") == 0) { /* Special all-hosts-services event log */ add_to_filelist(hent->d_name, F_ALLEVENTS); continue; } hostname = knownhost(hent->d_name, hostip, ghosthandling); if (hostname) { /* Host history file. */ add_to_filelist(hent->d_name, F_HOSTHISTORY); } else { char *delim, *p, *hname, *tname; delim = strrchr(hent->d_name, '.'); if (!delim) { /* It's a host history file (no dot in filename), but the host does not exist */ errprintf("Orphaned host-history file %s - no host\n", hent->d_name); if (dropfiles) add_to_filelist(hent->d_name, F_DROPIT); continue; } *delim = '\0'; hname = strdup(hent->d_name); tname = delim+1; *delim = '.'; p = strchr(hname, ','); while (p) { *p = '.'; p = strchr(p, ','); } hostname = knownhost(hname, hostip, ghosthandling); if (!hostname) { errprintf("Orphaned service-history file %s - no host\n", hent->d_name); if (dropfiles) add_to_filelist(hent->d_name, F_DROPIT); } else if (dropsvcs && !validstatus(hostname, tname)) { errprintf("Orphaned service-history file %s - no service\n", hent->d_name); if (dropfiles) add_to_filelist(hent->d_name, F_DROPIT); } else { /* Service history file */ add_to_filelist(hent->d_name, F_SERVICEHISTORY); } xfree(hname); } } closedir(histdir); /* Then process the files */ if (progressinfo) errprintf("Starting trim of %d history-logs\n", totalitems); trim_files(cutoff); /* Process statuslogs also ? */ if (!droplogs) return 0; flhead = NULL; /* Dirty - we should clean it up properly - but I dont care */ totalitems = 0; if (chdir(xgetenv("BBHISTLOGS")) == -1) { errprintf("Cannot cd to historical statuslogs directory: %s\n", strerror(errno)); return 1; } histdir = opendir("."); if (!histdir) { errprintf("Cannot read historical statuslogs directory: %s\n", strerror(errno)); return 1; } while ((hent = readdir(histdir)) != NULL) { if (stat(hent->d_name, &st) == -1) { errprintf("Odd entry %s - cannot stat: %s\n", hent->d_name, strerror(errno)); continue; } if ((*(hent->d_name) == '.') || !S_ISDIR(st.st_mode)) continue; if (knownloghost(hent->d_name)) { add_to_filelist(hent->d_name, F_PURGELOGS); } else { add_to_filelist(hent->d_name, F_DROPIT); } } closedir(histdir); if (progressinfo) errprintf("Starting trim of %d status-log collections\n", totalitems); trim_logs(cutoff); return 0; }
int main (int argc, char **argv) { int argi; char *configfn = NULL; int cfgcheck = 0; int mibcheck = 0; libxymon_init(argv[0]); for (argi = 1; (argi < argc); argi++) { if (standardoption(argv[argi])) { if (showhelp) return 0; } else if (strcmp(argv[argi], "--cfgcheck") == 0) { cfgcheck = 1; } else if (strcmp(argv[argi], "--mibcheck") == 0) { mibcheck = 1; } else if (argnmatch(argv[argi], "--timeout=")) { char *p = strchr(argv[argi], '='); timeout = 1000000*atoi(p+1); } else if (argnmatch(argv[argi], "--retries=")) { char *p = strchr(argv[argi], '='); retries = atoi(p+1); } else if (argnmatch(argv[argi], "--concurrency=")) { char *p = strchr(argv[argi], '='); max_pending_requests = atoi(p+1); } else if (argnmatch(argv[argi], "--report=")) { char *p = strchr(argv[argi], '='); reportcolumn = strdup(p+1); timing = 1; } else if (*argv[argi] != '-') { configfn = strdup(argv[argi]); } } add_timestamp("xymon-snmpcollect startup"); netsnmp_register_loghandler(NETSNMP_LOGHANDLER_STDERR, 7); init_snmp("xymon-snmpcollect"); snmp_mib_toggle_options("e"); /* Like -Pe: Dont show MIB parsing errors */ snmp_out_toggle_options("qn"); /* Like -Oqn: OID's printed as numbers, values printed without type */ readmibs(NULL, mibcheck); if (configfn == NULL) { configfn = (char *)malloc(PATH_MAX); sprintf(configfn, "%s/etc/snmphosts.cfg", xgetenv("XYMONHOME")); } readconfig(configfn, mibcheck); if (cfgcheck) return 0; add_timestamp("Configuration loaded"); resolvekeys(); add_timestamp("Keys lookup complete"); getdata(); stophosts(); add_timestamp("Data retrieved"); sendresult(); add_timestamp("Results transmitted"); if (reportcolumn) egoresult(COL_GREEN, reportcolumn); xfree(configfn); return 0; }
int main(int argc, char *argv[]) { char *msg; int running; int argi, seq; struct timespec *timeout = NULL; pcre *hostexp = NULL; pcre *exhostexp = NULL; pcre *testexp = NULL; pcre *extestexp = NULL; pcre *colorexp = NULL; const char *errmsg = NULL; int errofs = 0; FILE *logfd = stdout; int batchtimeout = 30; char *batchcmd = NULL; strbuffer_t *batchbuf = NULL; time_t lastmsgtime = 0; /* Handle program options. */ for (argi = 1; (argi < argc); argi++) { if (strcmp(argv[argi], "--debug") == 0) { /* * A global "debug" variable is available. If * it is set, then "dbgprintf()" outputs debug messages. */ debug = 1; } else if (strncmp(argv[argi], "--timeout=", 10) == 0) { /* * You can have a timeout when waiting for new * messages. If it happens, you will get a "@@idle\n" * message with sequence number 0. * If you dont want a timeout, just pass a NULL for the timeout parameter. */ timeout = (struct timespec *)(malloc(sizeof(struct timespec))); timeout->tv_sec = (atoi(argv[argi]+10)); timeout->tv_nsec = 0; } else if (argnmatch(argv[argi], "--hosts=")) { char *exp = strchr(argv[argi], '=') + 1; hostexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL); if (hostexp == NULL) printf("Invalid expression '%s'\n", exp); } else if (argnmatch(argv[argi], "--exhosts=")) { char *exp = strchr(argv[argi], '=') + 1; exhostexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL); if (exhostexp == NULL) printf("Invalid expression '%s'\n", exp); } else if (argnmatch(argv[argi], "--tests=")) { char *exp = strchr(argv[argi], '=') + 1; testexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL); if (testexp == NULL) printf("Invalid expression '%s'\n", exp); } else if (argnmatch(argv[argi], "--extests=")) { char *exp = strchr(argv[argi], '=') + 1; extestexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL); if (extestexp == NULL) printf("Invalid expression '%s'\n", exp); } else if (argnmatch(argv[argi], "--colors=")) { char *exp = strchr(argv[argi], '=') + 1; colorexp = pcre_compile(exp, PCRE_CASELESS, &errmsg, &errofs, NULL); if (colorexp == NULL) printf("Invalid expression '%s'\n", exp); } else if (argnmatch(argv[argi], "--outfile=")) { char *fn = strchr(argv[argi], '=') + 1; logfd = fopen(fn, "a"); if (logfd == NULL) { printf("Cannot open logfile %s: %s\n", fn, strerror(errno)); logfd = stdout; } } else if (argnmatch(argv[argi], "--batch-timeout=")) { char *p = strchr(argv[argi], '='); batchtimeout = atoi(p+1); timeout = (struct timespec *)(malloc(sizeof(struct timespec))); timeout->tv_sec = batchtimeout; timeout->tv_nsec = 0; } else if (argnmatch(argv[argi], "--batch-command=")) { char *p = strchr(argv[argi], '='); batchcmd = strdup(p+1); batchbuf = newstrbuffer(0); } else { printf("Unknown option %s\n", argv[argi]); printf("Usage: %s [--hosts=EXP] [--tests=EXP] [--exhosts=EXP] [--extests=EXP] [--color=EXP] [--outfile=FILENAME] [--batch-timeout=N] [--batch-command=COMMAND]\n", argv[0]); return 0; } } signal(SIGCHLD, SIG_IGN); running = 1; while (running) { char *eoln, *restofmsg, *p; char *metadata[MAX_META+1]; int metacount; msg = get_hobbitd_message(C_LAST, argv[0], &seq, timeout); if (msg == NULL) { /* * get_hobbitd_message will return NULL if hobbitd_channel closes * the input pipe. We should shutdown when that happens. */ running = 0; continue; } /* * Now we have a message. So do something with it. * * The first line of the message is always a '|' separated * list of meta-data about the message. After the first * line, the content varies by channel. */ /* Split the message in the first line (with meta-data), and the rest */ eoln = strchr(msg, '\n'); if (eoln) { *eoln = '\0'; restofmsg = eoln+1; } else { restofmsg = ""; } /* * Now parse the meta-data into elements. * We use our own "gettok()" routine which works * like strtok(), but can handle empty elements. */ metacount = 0; memset(&metadata, 0, sizeof(metadata)); p = gettok(msg, "|"); while (p && (metacount < MAX_META)) { metadata[metacount++] = p; p = gettok(NULL, "|"); } metadata[metacount] = NULL; /* * A "shutdown" message is sent when the master daemon * terminates. The child workers should shutdown also. */ if (strncmp(metadata[0], "@@shutdown", 10) == 0) { printf("Shutting down\n"); running = 0; continue; } /* * A "logrotate" message is sent when the Hobbit logs are * rotated. The child workers must re-open their logfiles, * typically stdin and stderr - the filename is always * provided in the HOBBITCHANNEL_LOGFILENAME environment. */ else if (strncmp(metadata[0], "@@logrotate", 11) == 0) { char *fn = xgetenv("HOBBITCHANNEL_LOGFILENAME"); if (fn && strlen(fn)) { freopen(fn, "a", stdout); freopen(fn, "a", stderr); } continue; } /* * An "idle" message appears when get_hobbitd_message() * exceeds the timeout setting (ie. you passed a timeout * value). This allows your worker module to perform * some internal processing even though no messages arrive. */ else if (strncmp(metadata[0], "@@idle", 6) == 0) { dbgprintf("Got an 'idle' message\n"); } /* * The "drophost", "droptest", "renamehost" and "renametst" * indicates that a host/test was deleted or renamed. If the * worker module maintains some internal storage (in memory * or persistent file-storage), it should act on these * messages to maintain data consistency. */ else if ((metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) { dbgprintf("Got a 'drophost' message for host '%s'\n", metadata[3]); } else if ((metacount > 3) && (strncmp(metadata[0], "@@dropstate", 11) == 0)) { dbgprintf("Got a 'dropstate' message for host '%s'\n", metadata[3]); } else if ((metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) { dbgprintf("Got a 'droptest' message for host '%s' test '%s'\n", metadata[3], metadata[4]); } else if ((metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) { dbgprintf("Got a 'renamehost' message for host '%s' -> '%s'\n", metadata[3], metadata[4]); } else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) { dbgprintf("Got a 'renametest' message for host '%s' test '%s' -> '%s'\n", metadata[3], metadata[4], metadata[5]); } /* * Process this message. */ else { int ovector[30]; int match, i; char *hostname = metadata[4]; char *testname = metadata[5]; char *color = metadata[7]; /* See if we should handle the batched messages we've got */ if (batchcmd && ((lastmsgtime + batchtimeout) < gettimer()) && (STRBUFLEN(batchbuf) > 0)) { pid_t childpid = fork(); int childres = 0; if (childpid < 0) { /* Fork failed! */ errprintf("Fork failed: %s\n", strerror(errno)); } else if (childpid == 0) { /* Child */ FILE *cmdpipe = popen(batchcmd, "w"); if (cmdpipe) { /* Write the data to the batch command pipe */ int n, bytesleft = STRBUFLEN(batchbuf); char *outp = STRBUF(batchbuf); while (bytesleft) { n = fwrite(outp, 1, bytesleft, cmdpipe); if (n >= 0) { bytesleft -= n; outp += n; } else { errprintf("Error while writing data to batch command\n"); bytesleft = 0; } } childres = pclose(cmdpipe); } else { errprintf("Could not open pipe to batch command '%s'\n", batchcmd); childres = 127; } exit(childres); } else if (childpid > 0) { /* Parent continues */ } clearstrbuffer(batchbuf); } if (hostexp) { match = (pcre_exec(hostexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); if (!match) continue; } if (exhostexp) { match = (pcre_exec(exhostexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); if (match) continue; } if (testexp) { match = (pcre_exec(testexp, NULL, testname, strlen(testname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); if (!match) continue; } if (exhostexp) { match = (pcre_exec(extestexp, NULL, testname, strlen(testname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); if (match) continue; } if (colorexp) { match = (pcre_exec(colorexp, NULL, color, strlen(color), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); if (!match) continue; } lastmsgtime = gettimer(); if (batchcmd) { addtobuffer(batchbuf, "## "); for (i=0; (i < metacount); i++) { addtobuffer(batchbuf, metadata[i]); addtobuffer(batchbuf, " "); } addtobuffer(batchbuf, "\n"); addtobuffer(batchbuf, restofmsg); addtobuffer(batchbuf, "\n"); } else { fprintf(logfd, "## "); for (i=0; (i < metacount); i++) fprintf(logfd, "%s ", metadata[i]); fprintf(logfd, "\n"); fprintf(logfd, "%s\n", restofmsg); } } } return 0; }