예제 #1
0
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;
}
예제 #2
0
char *hostlink_filename(char *hostname)
{
	link_t *link;

	if (!linksloaded) load_all_links();

	link = find_link(hostname);

	return (link ? link->filename : NULL);
}
예제 #3
0
char *hostlink(char *hostname)
{
	static char *linkurl = NULL;
	link_t *link;

	if (linkurl == NULL) linkurl = (char *)malloc(PATH_MAX);
	if (!linksloaded) load_all_links();

	link = find_link(hostname);

	if (link) {
		sprintf(linkurl, "%s/%s", link->urlprefix, link->filename);
		return linkurl;
	}

	return NULL;
}
예제 #4
0
char *columnlink(char *colname)
{
	static char *linkurl = NULL;
	link_t *link;

	if (linkurl == NULL) linkurl = (char *)malloc(PATH_MAX);
	if (!linksloaded) load_all_links();

	link = find_link(colname);
	if (link) {
		sprintf(linkurl, "%s/%s", link->urlprefix, link->filename);
	}
	else if (columndocurl) {
		sprintf(linkurl, columndocurl, colname);
	}
	else {
		*linkurl = '\0';
	}

	return linkurl;
}
예제 #5
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 &quot;Critical Systems&quot; 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;
}
예제 #6
0
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;
}
예제 #7
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(&timestamps);
		addtostatus(timestamps);

		finish_status();
		combo_end();
	}
	else show_timestamps(NULL);

	return 0;
}