state_t *init_state(char *filename, logdata_t *log) { FILE *fd = NULL; char *p; char *hostname; char *testname; char *testnameidx; state_t *newstate; char fullfn[PATH_MAX]; host_t *host; struct stat log_st; time_t now = getcurrenttime(NULL); time_t histentry_start; int logexpired = 0; int propagating, isacked; dbgprintf("init_state(%s, %d, ...)\n", textornull(filename)); /* Ignore summary files and dot-files (this catches "." and ".." also) */ if ( (strncmp(filename, "summary.", 8) == 0) || (filename[0] == '.')) { return NULL; } if (reportstart || snapshot) { /* Dont do reports for info- and trends-columns */ p = strrchr(filename, '.'); if (p == NULL) return NULL; p++; if (strcmp(p, xgetenv("INFOCOLUMN")) == 0) return NULL; if (strcmp(p, xgetenv("TRENDSCOLUMN")) == 0) return NULL; /* * When doing reports, we are scanning the BBHIST directory. It may * contain files that are named as a host only (no test-name). * Skip those. */ if (find_host(filename)) return NULL; } if (!reportstart && !snapshot) { hostname = strdup(log->hostname); testname = strdup(log->testname); logexpired = (log->validtime < now); } else { sprintf(fullfn, "%s/%s", xgetenv("BBHIST"), filename); /* Check that we can access this file */ if ( (stat(fullfn, &log_st) == -1) || (!S_ISREG(log_st.st_mode)) || ((fd = fopen(fullfn, "r")) == NULL) ) { errprintf("Weird file '%s' skipped\n", fullfn); return NULL; } /* Pick out host- and test-name */ logexpired = (log_st.st_mtime < now); hostname = strdup(filename); p = strrchr(hostname, '.'); /* Skip files that have no '.' in filename */ if (p) { /* Pick out the testname ... */ *p = '\0'; p++; testname = strdup(p); /* ... and change hostname back into normal form */ for (p=hostname; (*p); p++) { if (*p == ',') *p='.'; } } else { xfree(hostname); fclose(fd); return NULL; } } /* Must do these first to get the propagation value for the statistics */ host = find_host(hostname); isacked = (log->acktime > now); propagating = checkpropagation(host, testname, log->color, isacked); /* Count all of the real columns */ if ( (strcmp(testname, xgetenv("INFOCOLUMN")) != 0) && (strcmp(testname, xgetenv("TRENDSCOLUMN")) != 0) ) { statuscount++; switch (log->color) { case COL_RED: case COL_YELLOW: if (propagating) colorcount[log->color] += 1; else colorcount_noprop[log->color] += 1; break; default: colorcount[log->color] += 1; break; } } testnameidx = (char *)malloc(strlen(testname) + 3); sprintf(testnameidx, ",%s,", testname); if (unwantedcolumn(hostname, testname) || (ignorecolumns && strstr(ignorecolumns, testnameidx))) { xfree(hostname); xfree(testname); xfree(testnameidx); if (fd) fclose(fd); return NULL; /* Ignore this type of test */ } xfree(testnameidx); newstate = (state_t *) calloc(1, sizeof(state_t)); newstate->entry = (entry_t *) calloc(1, sizeof(entry_t)); newstate->next = NULL; newstate->entry->column = find_or_create_column(testname, 1); newstate->entry->color = -1; strcpy(newstate->entry->age, ""); newstate->entry->oldage = 0; newstate->entry->propagate = 1; newstate->entry->testflags = NULL; newstate->entry->skin = NULL; newstate->entry->repinfo = NULL; newstate->entry->causes = NULL; newstate->entry->histlogname = NULL; newstate->entry->shorttext = NULL; if (host) { newstate->entry->alert = checkalert(host->alerts, testname); /* If no WAP's specified, default all tests to be on WAP page */ newstate->entry->onwap = (host->waps ? checkalert(host->waps, testname) : 1); } else { dbgprintf(" hostname %s not found\n", hostname); newstate->entry->alert = newstate->entry->onwap = 0; } newstate->entry->sumurl = NULL; if (reportstart) { /* Determine "color" for this test from the historical data */ newstate->entry->repinfo = (reportinfo_t *) calloc(1, sizeof(reportinfo_t)); newstate->entry->color = parse_historyfile(fd, newstate->entry->repinfo, (dynamicreport ? NULL: hostname), (dynamicreport ? NULL : testname), reportstart, reportend, 0, (host ? host->reportwarnlevel : reportwarnlevel), reportgreenlevel, (host ? host->reportwarnstops : reportwarnstops), (host ? host->reporttime : NULL)); newstate->entry->causes = (dynamicreport ? NULL : save_replogs()); } else if (snapshot) { time_t fileage = snapshot - histentry_start; newstate->entry->color = history_color(fd, snapshot, &histentry_start, &newstate->entry->histlogname); newstate->entry->oldage = (fileage >= recentgif_limit); newstate->entry->fileage = fileage; strcpy(newstate->entry->age, agestring(fileage)); } else { time_t fileage = (now - log->lastchange); newstate->entry->color = log->color; newstate->entry->testflags = strdup(log->testflags); if (testflag_set(newstate->entry, 'D')) newstate->entry->skin = dialupskin; if (testflag_set(newstate->entry, 'R')) newstate->entry->skin = reverseskin; newstate->entry->shorttext = strdup(log->msg); newstate->entry->acked = isacked; newstate->entry->oldage = (fileage >= recentgif_limit); newstate->entry->fileage = (log->lastchange ? fileage : -1); if (log->lastchange == 0) strcpy(newstate->entry->age, ""); else strcpy(newstate->entry->age, agestring(fileage)); } if (purplelog && (newstate->entry->color == COL_PURPLE)) { fprintf(purplelog, "%s %s%s\n", hostname, testname, (host ? " (expired)" : " (unknown host)")); } newstate->entry->propagate = propagating; dbgprintf("init_state: hostname=%s, testname=%s, color=%d, acked=%d, age=%s, oldage=%d, propagate=%d, alert=%d\n", textornull(hostname), textornull(testname), newstate->entry->color, newstate->entry->acked, textornull(newstate->entry->age), newstate->entry->oldage, newstate->entry->propagate, newstate->entry->alert); if (host) { hostlist_t *l; /* Add this state entry to the host's list of state entries. */ newstate->entry->next = host->entries; host->entries = newstate->entry; /* There may be multiple host entries, if a host is * listed in several locations in bb-hosts (for display purposes). * This is handled by updating ALL of the cloned host records. * Bug reported by Bluejay Adametz of Fuji. */ /* Cannot use "find_host()" here, as we need the hostlink record, not the host record */ l = find_hostlist(hostname); /* Walk through the clone-list and set the "entries" for all hosts */ for (l=l->clones; (l); l = l->clones) l->hostentry->entries = host->entries; } else { /* No host for this test - must be missing from bb-hosts */ newstate->entry->next = NULL; } xfree(hostname); xfree(testname); if (fd) fclose(fd); return newstate; }
int main(int argc, char *argv[]) { char histlogfn[PATH_MAX]; char tailcmd[PATH_MAX]; FILE *fd; time_t start1d, start1w, start4w, start1y; reportinfo_t repinfo1d, repinfo1w, repinfo4w, repinfo1y, dummyrep; replog_t *log1d, *log1w, *log4w, *log1y; char *p; 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], "--no-svcid") == 0) { wantserviceid = 0; } } redirect_cgilog("bb-hist"); envcheck(reqenv); cgidata = cgi_request(); parse_query(); /* Build our own URL */ sprintf(selfurl, "%s", histcgiurl(hostname, service)); p = selfurl + strlen(selfurl); sprintf(p, "&BARSUMS=%d", barsums); if (strlen(ip)) { p = selfurl + strlen(selfurl); sprintf(p, "&IP=%s", ip); } if (entrycount) { p = selfurl + strlen(selfurl); sprintf(p, "&ENTRIES=%d", entrycount); } else strcat(selfurl, "&ENTRIES=ALL"); if (usepct) { /* Must modify 4-week charts to be 5-weeks, or the last day is 19% of the bar */ /* * Percent-based charts look awful with 24 hours / 7 days / 28 days / 12 months as basis * because these numbers dont divide into 100 neatly. So the last item becomes * too large (worst with the 28-day char: 100/28 = 3, last becomes (100-27*3) = 19% wide). * So adjust the periods to something that matches percent-based calculations better. */ len1d = 25; bartitle1d = "25 hour summary"; len1w = 10; bartitle1w = "10 day summary"; len4w = 33; bartitle4w = "33 day summary"; len1y = 10; bartitle1y = "10 month summary"; } sprintf(histlogfn, "%s/%s.%s", xgetenv("BBHIST"), commafy(hostname), service); fd = fopen(histlogfn, "r"); if (fd == NULL) { errormsg("Cannot open history file"); } log1d = log1w = log4w = log1y = NULL; if (req_endtime == 0) req_endtime = time(NULL); /* * Calculate the beginning time of each colorbar. We go back the specified length * of time, except 1 second - so days are from midnight -> 23:59:59 etc. */ start1d = calc_time(req_endtime, -len1d, ALIGN_HOUR, END_UNCHANGED) + 1; start1w = calc_time(req_endtime, -len1w, ALIGN_DAY, END_UNCHANGED) + 1; start4w = calc_time(req_endtime, -len4w, ALIGN_DAY, END_UNCHANGED) + 1; start1y = calc_time(req_endtime, -len1y, ALIGN_MONTH, END_UNCHANGED) + 1; /* * Collect data for the color-bars and summaries. Multiple scans over the history file, * but doing it all in one go would be hideously complex. */ if (barsums & BARSUM_1D) { parse_historyfile(fd, &repinfo1d, NULL, NULL, start1d, req_endtime, 1, reportwarnlevel, reportgreenlevel, NULL); log1d = save_replogs(); } if (barsums & BARSUM_1W) { parse_historyfile(fd, &repinfo1w, NULL, NULL, start1w, req_endtime, 1, reportwarnlevel, reportgreenlevel, NULL); log1w = save_replogs(); } if (barsums & BARSUM_4W) { parse_historyfile(fd, &repinfo4w, NULL, NULL, start4w, req_endtime, 1, reportwarnlevel, reportgreenlevel, NULL); log4w = save_replogs(); } if (barsums & BARSUM_1Y) { parse_historyfile(fd, &repinfo1y, NULL, NULL, start1y, req_endtime, 1, reportwarnlevel, reportgreenlevel, NULL); log1y = save_replogs(); } if (entrycount == 0) { /* All entries - just rewind the history file and do all of them */ rewind(fd); parse_historyfile(fd, &dummyrep, NULL, NULL, 0, time(NULL), 1, reportwarnlevel, reportgreenlevel, NULL); fclose(fd); } else { /* Last 50 entries - we cheat and use "tail" in a pipe to pick the entries */ fclose(fd); sprintf(tailcmd, "tail -%d %s", entrycount, histlogfn); fd = popen(tailcmd, "r"); if (fd == NULL) errormsg("Cannot run tail on the histfile"); parse_historyfile(fd, &dummyrep, NULL, NULL, 0, time(NULL), 1, reportwarnlevel, reportgreenlevel, NULL); pclose(fd); } /* Now generate the webpage */ printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); generate_history(stdout, hostname, service, ip, req_endtime, start1d, &repinfo1d, log1d, start1w, &repinfo1w, log1w, start4w, &repinfo4w, log4w, start1y, &repinfo1y, log1y, entrycount, reploghead); return 0; }