void do_notifylog(FILE *output, int maxcount, int maxminutes, char *fromtime, char *totime, char *pageregex, char *expageregex, char *hostregex, char *exhostregex, char *testregex, char *extestregex, char *rcptregex, char *exrcptregex) { FILE *notifylog; char notifylogfilename[PATH_MAX]; time_t firstevent = 0; time_t lastevent = getcurrenttime(NULL); notification_t *head, *walk; struct stat st; char l[MAX_LINE_LEN]; char title[200]; /* For the PCRE matching */ const char *errmsg = NULL; int errofs = 0; pcre *pageregexp = NULL; pcre *expageregexp = NULL; pcre *hostregexp = NULL; pcre *exhostregexp = NULL; pcre *testregexp = NULL; pcre *extestregexp = NULL; pcre *rcptregexp = NULL; pcre *exrcptregexp = NULL; if (maxminutes && (fromtime || totime)) { fprintf(output, "<B>Only one time interval type is allowed!</B>"); return; } if (fromtime) { firstevent = convert_time(fromtime); if(firstevent < 0) { fprintf(output,"<B>Invalid 'from' time: %s</B>", htmlquoted(fromtime)); return; } } else if (maxminutes) { firstevent = getcurrenttime(NULL) - maxminutes*60; } else { firstevent = getcurrenttime(NULL) - 86400; } if (totime) { lastevent = convert_time(totime); if (lastevent < 0) { fprintf(output,"<B>Invalid 'to' time: %s</B>", htmlquoted(totime)); return; } if (lastevent < firstevent) { fprintf(output,"<B>'to' time must be after 'from' time.</B>"); return; } } if (!maxcount) maxcount = 100; if (pageregex && *pageregex) pageregexp = pcre_compile(pageregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (expageregex && *expageregex) expageregexp = pcre_compile(expageregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (hostregex && *hostregex) hostregexp = pcre_compile(hostregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (exhostregex && *exhostregex) exhostregexp = pcre_compile(exhostregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (testregex && *testregex) testregexp = pcre_compile(testregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (extestregex && *extestregex) extestregexp = pcre_compile(extestregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (rcptregex && *rcptregex) rcptregexp = pcre_compile(rcptregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (exrcptregex && *exrcptregex) exrcptregexp = pcre_compile(exrcptregex, PCRE_CASELESS, &errmsg, &errofs, NULL); sprintf(notifylogfilename, "%s/notifications.log", xgetenv("XYMONSERVERLOGS")); notifylog = fopen(notifylogfilename, "r"); if (notifylog && (stat(notifylogfilename, &st) == 0)) { time_t curtime; int done = 0; /* Find a spot in the notification log file close to where the firstevent time is */ fseeko(notifylog, 0, SEEK_END); do { /* Go back maxcount*80 bytes - one entry is ~80 bytes */ if (ftello(notifylog) > maxcount*80) { unsigned int uicurtime; fseeko(notifylog, -maxcount*80, SEEK_CUR); if (fgets(l, sizeof(l), notifylog) && /* Skip to start of line */ fgets(l, sizeof(l), notifylog)) { /* Sun Jan 7 10:29:08 2007 myhost.disk (130.225.226.90) [email protected] 1168162147 100 */ sscanf(l, "%*s %*s %*u %*u:%*u:%*u %*u %*s %*s %*s %u %*d", &uicurtime); curtime = uicurtime; done = (curtime < firstevent); } else { fprintf(output, "Error reading logfile %s: %s\n", notifylogfilename, strerror(errno)); return; } } else { rewind(notifylog); done = 1; } } while (!done); } head = NULL; while (notifylog && (fgets(l, sizeof(l), notifylog))) { unsigned int etim; time_t eventtime; char hostsvc[MAX_LINE_LEN]; char recipient[MAX_LINE_LEN]; char *hostname, *svcname, *p; int itemsfound, pagematch, hostmatch, testmatch, rcptmatch; notification_t *newrec; void *eventhost; struct htnames_t *eventcolumn; int ovector[30]; itemsfound = sscanf(l, "%*s %*s %*u %*u:%*u:%*u %*u %s %*s %s %u %*d", hostsvc, recipient, &etim); eventtime = etim; if (itemsfound != 3) continue; if (eventtime < firstevent) continue; if (eventtime > lastevent) break; hostname = hostsvc; svcname = strrchr(hostsvc, '.'); if (svcname) { *svcname = '\0'; svcname++; } else svcname = ""; eventhost = hostinfo(hostname); if (!eventhost) continue; /* Dont report hosts that no longer exist */ eventcolumn = getname(svcname, 1); p = strchr(recipient, '['); if (p) *p = '\0'; if (pageregexp) { char *pagename; pagename = xmh_item_multi(eventhost, XMH_PAGEPATH); pagematch = 0; while (!pagematch && pagename) { pagematch = (pcre_exec(pageregexp, NULL, pagename, strlen(pagename), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); pagename = xmh_item_multi(NULL, XMH_PAGEPATH); } } else pagematch = 1; if (!pagematch) continue; if (expageregexp) { char *pagename; pagename = xmh_item_multi(eventhost, XMH_PAGEPATH); pagematch = 0; while (!pagematch && pagename) { pagematch = (pcre_exec(expageregexp, NULL, pagename, strlen(pagename), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); pagename = xmh_item_multi(NULL, XMH_PAGEPATH); } } else pagematch = 0; if (pagematch) continue; if (hostregexp) hostmatch = (pcre_exec(hostregexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else hostmatch = 1; if (!hostmatch) continue; if (exhostregexp) hostmatch = (pcre_exec(exhostregexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else hostmatch = 0; if (hostmatch) continue; if (testregexp) testmatch = (pcre_exec(testregexp, NULL, svcname, strlen(svcname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else testmatch = 1; if (!testmatch) continue; if (extestregexp) testmatch = (pcre_exec(extestregexp, NULL, svcname, strlen(svcname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else testmatch = 0; if (testmatch) continue; if (rcptregexp) rcptmatch = (pcre_exec(rcptregexp, NULL, recipient, strlen(recipient), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else rcptmatch = 1; if (!rcptmatch) continue; if (exrcptregexp) rcptmatch = (pcre_exec(exrcptregexp, NULL, recipient, strlen(recipient), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else rcptmatch = 0; if (rcptmatch) continue; newrec = (notification_t *) malloc(sizeof(notification_t)); newrec->host = eventhost; newrec->service = eventcolumn; newrec->eventtime = eventtime; newrec->recipient = strdup(recipient); newrec->next = head; head = newrec; } if (head) { char *bgcolors[2] = { "#000000", "#000066" }; int bgcolor = 0; int count; struct notification_t *lasttoshow = head; count=0; walk=head; do { count++; lasttoshow = walk; walk = walk->next; } while (walk && (count<maxcount)); if (maxminutes) { sprintf(title, "%d notifications in the past %u minutes", count, (unsigned int)((getcurrenttime(NULL) - lasttoshow->eventtime) / 60)); } else { sprintf(title, "%d notifications sent.", count); } fprintf(output, "<BR><BR>\n"); fprintf(output, "<TABLE SUMMARY=\"Notification log\" BORDER=0>\n"); fprintf(output, "<TR BGCOLOR=\"#333333\">\n"); fprintf(output, "<TD ALIGN=CENTER COLSPAN=4><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", htmlquoted(title)); fprintf(output, "<TR BGCOLOR=\"#333333\"><TH>Time</TH><TH>Host</TH><TH>Service</TH><TH>Recipient</TH></TR>\n"); for (walk=head; (walk != lasttoshow->next); walk=walk->next) { char *hostname = xmh_item(walk->host, XMH_HOSTNAME); fprintf(output, "<TR BGCOLOR=%s>\n", bgcolors[bgcolor]); bgcolor = ((bgcolor + 1) % 2); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", ctime(&walk->eventtime)); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", hostname); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->service->name); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->recipient); } fprintf(output, "</TABLE>\n"); /* Clean up */ walk = head; do { struct notification_t *tmp = walk; walk = walk->next; xfree(tmp->recipient); xfree(tmp); } while (walk); } else { /* No notifications during the past maxminutes */ if (notifylog) sprintf(title, "No notifications sent in the last %d minutes", maxminutes); else strcpy(title, "No notifications logged"); fprintf(output, "<CENTER><BR>\n"); fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title); fprintf(output, "<TR BGCOLOR=\"#333333\">\n"); fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD>\n", htmlquoted(title)); fprintf(output, "</TR>\n"); fprintf(output, "</TABLE>\n"); fprintf(output, "</CENTER>\n"); } if (notifylog) fclose(notifylog); if (pageregexp) pcre_free(pageregexp); if (expageregexp) pcre_free(expageregexp); if (hostregexp) pcre_free(hostregexp); if (exhostregexp) pcre_free(exhostregexp); if (testregexp) pcre_free(testregexp); if (extestregexp) pcre_free(extestregexp); if (rcptregexp) pcre_free(rcptregexp); if (exrcptregexp) pcre_free(exrcptregexp); }
static int eventfilter(void *hinfo, char *testname, pcre *pageregexp, pcre *expageregexp, pcre *hostregexp, pcre *exhostregexp, pcre *testregexp, pcre *extestregexp, int ignoredialups, f_hostcheck hostcheck) { int pagematch, hostmatch, testmatch; char *hostname = xmh_item(hinfo, XMH_HOSTNAME); int ovector[30]; if (ignoredialups && xmh_item(hinfo, XMH_FLAG_DIALUP)) return 0; if (hostcheck && (hostcheck(hostname) == 0)) return 0; if (pageregexp) { char *pagename; pagename = xmh_item_multi(hinfo, XMH_PAGEPATH); pagematch = 0; while (!pagematch && pagename) { pagematch = (pcre_exec(pageregexp, NULL, pagename, strlen(pagename), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); pagename = xmh_item_multi(NULL, XMH_PAGEPATH); } } else pagematch = 1; if (!pagematch) return 0; if (expageregexp) { char *pagename; pagename = xmh_item_multi(hinfo, XMH_PAGEPATH); pagematch = 0; while (!pagematch && pagename) { pagematch = (pcre_exec(expageregexp, NULL, pagename, strlen(pagename), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); pagename = xmh_item_multi(NULL, XMH_PAGEPATH); } } else pagematch = 0; if (pagematch) return 0; if (hostregexp) hostmatch = (pcre_exec(hostregexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else hostmatch = 1; if (!hostmatch) return 0; if (exhostregexp) hostmatch = (pcre_exec(exhostregexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else hostmatch = 0; if (hostmatch) return 0; if (testregexp) testmatch = (pcre_exec(testregexp, NULL, testname, strlen(testname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else testmatch = 1; if (!testmatch) return 0; if (extestregexp) testmatch = (pcre_exec(extestregexp, NULL, testname, strlen(testname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else testmatch = 0; if (testmatch) return 0; return 1; }
void do_acknowledgementslog(FILE *output, int maxcount, int maxminutes, char *fromtime, char *totime, char *pageregex, char *expageregex, char *hostregex, char *exhostregex, char *testregex, char *extestregex, char *rcptregex, char *exrcptregex) { FILE *acknowledgementslog; char acknowledgementslogfilename[PATH_MAX]; time_t firstevent = 0; time_t lastevent = getcurrenttime(NULL); acknowledgements_t *head, *walk; struct stat st; char l[MAX_LINE_LEN]; char title[200]; /* For the PCRE matching */ const char *errmsg = NULL; int errofs = 0; pcre *pageregexp = NULL; pcre *expageregexp = NULL; pcre *hostregexp = NULL; pcre *exhostregexp = NULL; pcre *testregexp = NULL; pcre *extestregexp = NULL; pcre *rcptregexp = NULL; pcre *exrcptregexp = NULL; if (maxminutes && (fromtime || totime)) { fprintf(output, "<B>Only one time interval type is allowed!</B>"); return; } if (fromtime) { firstevent = convert_time(fromtime); if(firstevent < 0) { fprintf(output,"<B>Invalid 'from' time: %s</B>", htmlquoted(fromtime)); return; } } else if (maxminutes) { firstevent = getcurrenttime(NULL) - maxminutes*60; } else { firstevent = getcurrenttime(NULL) - 86400; } if (totime) { lastevent = convert_time(totime); if (lastevent < 0) { fprintf(output,"<B>Invalid 'to' time: %s</B>", htmlquoted(totime)); return; } if (lastevent < firstevent) { fprintf(output,"<B>'to' time must be after 'from' time.</B>"); return; } } if (!maxcount) maxcount = 100; if (pageregex && *pageregex) pageregexp = pcre_compile(pageregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (expageregex && *expageregex) expageregexp = pcre_compile(expageregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (hostregex && *hostregex) hostregexp = pcre_compile(hostregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (exhostregex && *exhostregex) exhostregexp = pcre_compile(exhostregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (testregex && *testregex) testregexp = pcre_compile(testregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (extestregex && *extestregex) extestregexp = pcre_compile(extestregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (rcptregex && *rcptregex) rcptregexp = pcre_compile(rcptregex, PCRE_CASELESS, &errmsg, &errofs, NULL); if (exrcptregex && *exrcptregex) exrcptregexp = pcre_compile(exrcptregex, PCRE_CASELESS, &errmsg, &errofs, NULL); sprintf(acknowledgementslogfilename, "%s/acknowledge.log", xgetenv("XYMONSERVERLOGS")); acknowledgementslog = fopen(acknowledgementslogfilename, "r"); if (acknowledgementslog && (stat(acknowledgementslogfilename, &st) == 0)) { time_t curtime; int done = 0; /* Find a spot in the acknowledgements log file close to where the firstevent time is */ fseeko(acknowledgementslog, 0, SEEK_END); do { /* Go back maxcount*80 bytes - one entry is ~80 bytes */ if (ftello(acknowledgementslog) > maxcount*80) { unsigned int uicurtime; fseeko(acknowledgementslog, -maxcount*80, SEEK_CUR); if (fgets(l, sizeof(l), acknowledgementslog) && /* Skip to start of line */ fgets(l, sizeof(l), acknowledgementslog)) { /* 2015-03-07 18:17:03 myserver disk andy 1 1425724570 1425752223 1425838623 testing message */ if ( sscanf(l, "%*u-%*u-%*u %*u:%*u:%*u %*s %*s %*s %*u %*u %u %*u %*s", &uicurtime) == 0 ) { /* that didnt work - try the old format 1430040985 630949 30 630949 np_filename_not_used myserver.procs red testing log format \nAcked by: andy (127.0.0.1) */ sscanf(l, "%u\t%*u\t%*u\t%*u\tnp_filename_not_used\t%*s\t%*s\t%*s", &uicurtime); } curtime = uicurtime; done = (curtime < firstevent); } else { fprintf(output, "Error reading logfile %s: %s\n", acknowledgementslogfilename, strerror(errno)); return; } } else { rewind(acknowledgementslog); done = 1; } } while (!done); } head = NULL; while (acknowledgementslog && (fgets(l, sizeof(l), acknowledgementslog))) { unsigned int etim; unsigned int valid; int duration; time_t eventtime; time_t validity; char host[MAX_LINE_LEN]; char svc[MAX_LINE_LEN]; char recipient[MAX_LINE_LEN]; char message[MAX_LINE_LEN]; char *hostname, *svcname, *p; int itemsfound, pagematch, hostmatch, testmatch, rcptmatch; acknowledgements_t *newrec; void *eventhost; struct htnames_t *eventcolumn; int ovector[30]; /* 2015-03-07 18:17:03 myserver disk andy 1 1425724570 1425752223 1425838623 testing message */ itemsfound = sscanf(l, "%*u-%*u-%*u %*u:%*u:%*u %s %s %s %*u %*u %u %u %[^\t\n]", host, svc, recipient, &etim, &valid, message); if (itemsfound != 6) { /* 1430040985 630949 30 630949 np_filename_not_used myserver.procs red testing log format \nAcked by: andy (127.0.0.1) */ itemsfound = sscanf(l, "%u\t%*u\t%d\t%*u\tnp_filename_not_used\t%s\t%*s\t%[^\n]", &etim, &duration, host, message); if (itemsfound != 4) continue; p = strrchr(host, '.'); if (p) { *p = '\0'; strcpy(svc,p+1); } /* Xymon uses \n in the ack message, for the "acked by" data. Cut it off. */ p = strstr(message, "\\nAcked by:"); if (p) { strcpy(recipient,p+12); *(p-1) = '\0'; } else { strcpy(recipient,"UnknownUser"); } p = strchr(recipient, '('); if (p) *(p-1) = '\0'; } eventtime = etim; if (eventtime < firstevent) continue; if (eventtime > lastevent) break; validity = duration ? (etim + duration * 60) : valid; hostname = host; svcname = svc; eventhost = hostinfo(hostname); if (!eventhost) continue; /* Dont report hosts that no longer exist */ eventcolumn = getname(svcname, 1); p = strchr(recipient, '['); if (p) *p = '\0'; if (pageregexp) { char *pagename; pagename = xmh_item_multi(eventhost, XMH_PAGEPATH); pagematch = 0; while (!pagematch && pagename) { pagematch = (pcre_exec(pageregexp, NULL, pagename, strlen(pagename), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); pagename = xmh_item_multi(NULL, XMH_PAGEPATH); } } else pagematch = 1; if (!pagematch) continue; if (expageregexp) { char *pagename; pagename = xmh_item_multi(eventhost, XMH_PAGEPATH); pagematch = 0; while (!pagematch && pagename) { pagematch = (pcre_exec(expageregexp, NULL, pagename, strlen(pagename), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); pagename = xmh_item_multi(NULL, XMH_PAGEPATH); } } else pagematch = 0; if (pagematch) continue; if (hostregexp) hostmatch = (pcre_exec(hostregexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else hostmatch = 1; if (!hostmatch) continue; if (exhostregexp) hostmatch = (pcre_exec(exhostregexp, NULL, hostname, strlen(hostname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else hostmatch = 0; if (hostmatch) continue; if (testregexp) testmatch = (pcre_exec(testregexp, NULL, svcname, strlen(svcname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else testmatch = 1; if (!testmatch) continue; if (extestregexp) testmatch = (pcre_exec(extestregexp, NULL, svcname, strlen(svcname), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else testmatch = 0; if (testmatch) continue; if (rcptregexp) rcptmatch = (pcre_exec(rcptregexp, NULL, recipient, strlen(recipient), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else rcptmatch = 1; if (!rcptmatch) continue; if (exrcptregexp) rcptmatch = (pcre_exec(exrcptregexp, NULL, recipient, strlen(recipient), 0, 0, ovector, (sizeof(ovector)/sizeof(int))) >= 0); else rcptmatch = 0; if (rcptmatch) continue; newrec = (acknowledgements_t *) malloc(sizeof(acknowledgements_t)); newrec->host = eventhost; newrec->service = eventcolumn; newrec->eventtime = eventtime; newrec->validity = validity; newrec->recipient = strdup(recipient); newrec->message = strdup(message); newrec->next = head; head = newrec; } if (head) { char *bgcolors[2] = { "#000000", "#000066" }; int bgcolor = 0; int count; struct acknowledgements_t *lasttoshow = head; count=0; walk=head; do { count++; lasttoshow = walk; walk = walk->next; } while (walk && (count<maxcount)); if (maxminutes) { sprintf(title, "%d acknowledgements in the past %u minutes", count, (unsigned int)((getcurrenttime(NULL) - lasttoshow->eventtime) / 60)); } else { sprintf(title, "%d events acknowledged.", count); } fprintf(output, "<BR><BR>\n"); fprintf(output, "<TABLE SUMMARY=\"Acknowledgements log\" BORDER=0>\n"); fprintf(output, "<TR BGCOLOR=\"#333333\">\n"); fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD></TR>\n", htmlquoted(title)); fprintf(output, "<TR BGCOLOR=\"#333333\"><TH>Time</TH><TH>Valid Until</TH><TH>Host</TH><TH>Service</TH><TH>Acknowledged By</TH><TH>Message</TH></TR>\n"); for (walk=head; (walk != lasttoshow->next); walk=walk->next) { char *hostname = xmh_item(walk->host, XMH_HOSTNAME); fprintf(output, "<TR BGCOLOR=%s>\n", bgcolors[bgcolor]); bgcolor = ((bgcolor + 1) % 2); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", ctime(&walk->eventtime)); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", ctime(&walk->validity)); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", hostname); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->service->name); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->recipient); fprintf(output, "<TD ALIGN=LEFT>%s</TD>\n", walk->message); } fprintf(output, "</TABLE>\n"); /* Clean up */ walk = head; do { struct acknowledgements_t *tmp = walk; walk = walk->next; xfree(tmp->recipient); xfree(tmp->message); xfree(tmp); } while (walk); } else { /* No acknowledgements during the past maxminutes */ if (acknowledgementslog) sprintf(title, "No events acknowledged in the last %d minutes", maxminutes); else strcpy(title, "No acknowledgements logged"); fprintf(output, "<CENTER><BR>\n"); fprintf(output, "<TABLE SUMMARY=\"%s\" BORDER=0>\n", title); fprintf(output, "<TR BGCOLOR=\"#333333\">\n"); fprintf(output, "<TD ALIGN=CENTER COLSPAN=6><FONT SIZE=-1 COLOR=\"#33ebf4\">%s</FONT></TD>\n", htmlquoted(title)); fprintf(output, "</TR>\n"); fprintf(output, "</TABLE>\n"); fprintf(output, "</CENTER>\n"); } if (acknowledgementslog) fclose(acknowledgementslog); if (pageregexp) pcre_free(pageregexp); if (expageregexp) pcre_free(expageregexp); if (hostregexp) pcre_free(hostregexp); if (exhostregexp) pcre_free(exhostregexp); if (testregexp) pcre_free(testregexp); if (extestregexp) pcre_free(extestregexp); if (rcptregexp) pcre_free(rcptregexp); if (exrcptregexp) pcre_free(exrcptregexp); }