This is output.c in view mode; [Download] [Up]
/*** analog 1.9beta ***/ /* Please read Readme.html, or http://www.statslab.cam.ac.uk/~sret1/analog/ */ /*** output.c; the output functions, obviously. ***/ #include "analhea2.h" /* A few variables global to this file */ int total_succ_reqs, total_fail_reqs, total_other_reqs; int total_succ_reqs7, total_fail_reqs7, total_other_reqs7; /*** The first function prints the "goto" line; links to all reports except possibly one (the one we're on). If called gotos('\0') won't omit one. If called gotos('z') will omit 'Top'. ***/ void gotos(FILE *outf, char c) { extern char reportorder[]; extern flag bq, Bq, cq, dq, Dq, eq, fq, hq, Hq, iq, mq, oq, rq, Sq, Wq, xq; char *i; if (xq) { fprintf(outf, "\n\n<p>(<b>Go To</b>"); if (c != 'z') fprintf(outf, ": <a HREF=\"#Top\">Top</a>"); for (i = reportorder; *i != '\0'; i++) { if (c != *i) { /* o/wise we don't want this one */ switch(*i) { case 'b': if (bq) fprintf(outf, ": <a HREF=\"#Browser\">Browser summary</a>"); break; case 'B': if (Bq) fprintf(outf, ": <a HREF=\"#FullBrowser\">Browser report</a>"); break; case 'c': if (cq) fprintf(outf, ": <a HREF=\"#Status\">Status code report</a>"); break; case 'd': if (dq) fprintf(outf, ": <a HREF=\"#Daily\">Daily summary</a>"); break; case 'D': if (Dq) fprintf(outf, ": <a HREF=\"#FullDaily\">Daily report</a>"); break; case 'e': if (eq) fprintf(outf, ": <a HREF=\"#Error\">Error report</a>"); break; case 'f': if (fq) fprintf(outf, ": <a HREF=\"#Referer\">Referer report</a>"); break; case 'H': if (Hq) fprintf(outf, ": <a HREF=\"#FullHourly\">Hourly report</a>"); break; case 'h': if (hq) fprintf(outf, ": <a HREF=\"#Hourly\">Hourly summary</a>"); break; case 'i': if (iq) fprintf(outf, ": <a HREF=\"#Directory\">Directory report</a>"); break; case 'm': if (mq) fprintf(outf, ": <a HREF=\"#Monthly\">Monthly report</a>"); break; case 'o': if (oq) fprintf(outf, ": <a HREF=\"#Domain\">Domain report</a>"); break; case 'r': if (rq) fprintf(outf, ": <a HREF=\"#Request\">Request report</a>"); break; case 'S': if (Sq) fprintf(outf, ": <a HREF=\"#Host\">Host report</a>"); break; case 'W': if (Wq) fprintf(outf, ": <a HREF=\"#Weekly\">Weekly report</a>"); break; } /* end switch */ } /* end if this i wanted */ } /* end for i */ fprintf(outf, ")\n"); } /* end if xq */ } /* end function gotos() */ /*** Next, to print strings with HTML reserved characters translated ***/ void htmlputc(char c, FILE *outf) { if (c == '<') fprintf(outf, "<"); else if (c == '>') fprintf(outf, ">"); else if (c == '&') fprintf(outf, "&"); else if (c == '"') fprintf(outf, """); else putc(c, outf); } void htmlfprintf(FILE *outf, char string[MAXSTRINGLENGTH]) { char *c; for (c = string; *c != '\0'; c++) htmlputc(*c, outf); } /*** Now a little routine to find the correct divider for large numbers of bytes. Also sets bprefix[0] as a side effect. ***/ double finddivider(double bytes, char *bprefix) { extern flag rawbytes; double bdivider; if (rawbytes) bdivider = 1.0; else for (bdivider = 1; bytes / bdivider >= 999999.5; bdivider *= 1024) ; /* run bdivider to right multiplier */ if (bdivider == 1.0) *bprefix = '\0'; else if (bdivider == 1024.0) *bprefix = 'k'; else if (bdivider == 1048576.0) *bprefix = 'M'; else if (bdivider == 1073741824.0) *bprefix = 'G'; else if (bdivider == 1099511627776.0) *bprefix = 'T'; else /* 10^6 terabytes should be enough. Just about. */ *bprefix = '?'; return(bdivider); } /*** print a line across the page, assuming ASCII mode ***/ void asciiline(FILE *outf) { extern int pagewidth; int i; for (i = 0; i < pagewidth; i++) fprintf(outf, "-"); fprintf(outf, "\n\n"); } /*** a barchart bar, length n, within <pre><tt> ***/ void barplot(FILE *outf, int n) { extern int aq; extern flag graphical; extern char imagedir[]; extern char markchar; int i, k; flag first = TRUE; if (aq || !graphical) { for ( ; n > 0; n--) fprintf(outf, "%c", markchar); } else { for (k = 32; k >= 1; k /= 2) { while (n >= k) { fprintf(outf, "<img src=\""); htmlfprintf(outf, imagedir); fprintf(outf, "bar%d.gif\" alt=\"", k); if (first) { for (i = n; i > 0; i--) htmlputc(markchar, outf); first = FALSE; } fprintf(outf, "\">"); n -= k; } } } } /*** A nasty header bit. Return rough floor -- accurate if negative. ***/ int whatincluded(FILE *outf, int sortby, char *minreqstr, char *minbytestr, char singular[20], char plural[21], flag subdoms) { extern double bytefloor(); /* in hash.c */ extern int reqfloor(); /* in hash.c */ extern void doublefprintf(); /* in utils.c */ extern double total_bytes; int genfloor; int tempint; char tempc; if (sortby == BYBYTES) { if (minbytestr[0] == '-') { genfloor = (int)bytefloor(total_bytes, minbytestr); if (genfloor == -1) fprintf(outf, "Printing the first %s", singular); else fprintf(outf, "Printing the first %d %s", -genfloor, plural); } else { fprintf(outf, "Printing all %s", plural); genfloor = (int)(ceil(bytefloor(total_bytes, minbytestr))); if (genfloor > 0) { fprintf(outf, " with at least "); tempint = MAX((int)strlen(minbytestr) - 1, 0); if (minbytestr[tempint] == '%') { minbytestr[tempint] = '\0'; doublefprintf(outf, atof(minbytestr)); fprintf(outf, "%% of the traffic"); } else if (minbytestr[tempint] == 'k' || minbytestr[tempint] == 'M' || minbytestr[tempint] == 'G' || minbytestr[tempint] == 'T') { tempc = minbytestr[tempint]; minbytestr[tempint] = '\0'; doublefprintf(outf, atof(minbytestr)); fprintf(outf, " %cbytes of traffic", tempc); } else { doublefprintf(outf, atof(minbytestr)); fprintf(outf, " bytes of traffic"); } } } if (subdoms) fprintf(outf, ".\n"); else fprintf(outf, ",%ssorted by amount of traffic.\n", (genfloor > 0)?"\n ":" "); } else { /* sortby not BYBYTES */ genfloor = reqfloor(total_succ_reqs, minreqstr); if (minreqstr[0] == '-') { if (genfloor == -1) fprintf(outf, "Printing the first %s", singular); else fprintf(outf, "Printing the first %d %s", -genfloor, plural); } else { fprintf(outf, "Printing all %s", plural); if (genfloor > 0) { fprintf(outf, " with at least "); tempint = MAX((int)strlen(minreqstr) - 1, 0); if (minreqstr[tempint] == '%') { minreqstr[tempint] = '\0'; doublefprintf(outf, atof(minreqstr)); fprintf(outf, "%% of the requests"); } else fprintf(outf, "%d request%s", atoi(minreqstr), atoi(minreqstr) == 1?"":"s"); } } if (subdoms) fprintf(outf, ".\n"); else if (sortby == BYREQUESTS) fprintf(outf, ",%ssorted by number of requests.\n", (genfloor > 0)?"\n ":" "); else if (sortby == ALPHABETICAL) fprintf(outf, ",%ssorted alphabetically.\n", (genfloor > 0)?"\n ":" "); else fprintf(outf, ", unsorted.\n"); } return(genfloor); } /*** Generic output function for generic objects ***/ void genout(FILE *outf, struct genstruct *sorthead, int sortby, char *minreqstr, char *minbytestr, int max_reqs, double max_bytes, char *wantcols, char anchor[10], char title[17], char singular[13], char plural[14], char codeletter, flag alphahost, /* alphabetical host sort? */ flag byq, int kq, /* pagelinks? */ char baseurl[MAXSTRINGLENGTH]) { extern char *reversehostname(); /* in alias.c */ extern flag included(); /* in alias.c */ extern int pagewidth; extern int dirlevel; extern int host_max_length; extern int aq; extern flag rawbytes; extern double total_bytes; extern struct include *ispagehead; struct genstruct *p; int fieldwidth, bfieldwidth, graphwidth; int genfloor; double bdivider; char bprefix[2]; char *cols; double pc; int pc1, pc2; int i, j, tempint; char *tempc; bprefix[0] = '\0'; bprefix[1] = '\0'; if (!aq) { fprintf(outf, "\n\n<hr>\n<h2><a NAME=\"%s\">%s</a></h2>\n\n", anchor, title); gotos(outf, codeletter); fprintf(outf, "<p>"); } else { fprintf(outf, "%s\n", title); for (tempc = title; *tempc != '\0'; tempc++) fprintf(outf, "-"); fprintf(outf, "\n"); } genfloor = whatincluded(outf, sortby, minreqstr, minbytestr, singular, plural, FALSE); if (codeletter == 'i') { if (!aq) fprintf(outf, "<br>"); fprintf(outf, "Printing directories to depth %d.\n", dirlevel); } if (aq) fprintf(outf, "\n"); else fprintf(outf, "<pre>"); tempint = 10000; for (fieldwidth = 5; max_reqs / tempint >= 10; fieldwidth++) tempint *= 10; if (byq) { if (rawbytes) { tempint = 100000; for (bfieldwidth = 6; max_bytes / tempint >= 10; bfieldwidth++) tempint *= 10; } else bfieldwidth = 6; bdivider = finddivider(max_bytes, bprefix); } for (cols = wantcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': for (i = 5; i < fieldwidth; i++) fprintf(outf, " "); fprintf(outf, "#reqs: "); break; case 'r': fprintf(outf, " %%reqs: "); break; case 'B': if (byq) { for (i = 6; i < bfieldwidth; i++) fprintf(outf, " "); fprintf(outf, "%sbytes: ", bprefix[0] == '\0'?" ":bprefix); } break; case 'b': if (byq) fprintf(outf, "%%bytes: "); break; } } fprintf(outf, "%s\n", singular); for (cols = wantcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': for (i = 1; i <= fieldwidth; i++) fprintf(outf, "-"); fprintf(outf, " "); break; case 'r': fprintf(outf, "------ "); break; case 'B': if (byq) { for (i = 1; i <= bfieldwidth; i++) fprintf(outf, "-"); fprintf(outf, " "); } break; case 'b': if (byq) fprintf(outf, "------ "); break; } } for (tempc = singular; *tempc != '\0'; tempc++) fprintf(outf, "-"); fprintf(outf, "\n"); if (genfloor < 0) j = genfloor; else j = 1; if (alphahost) { graphwidth = pagewidth; for (cols = wantcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': graphwidth -= fieldwidth + 2; break; case 'B': graphwidth -= bfieldwidth + 2; break; case 'r': case 'b': graphwidth -= 8; break; } } graphwidth = MIN(graphwidth, host_max_length); } for(p = sorthead; p -> name != NULL && (j++) != 0; p = p -> next) { for (cols = wantcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': fprintf(outf, "%*d: ", fieldwidth, p -> reqs); break; case 'r': pc = (p -> reqs + 0.0) / ((total_succ_reqs + 0.0) / 10000); pc1 = ((int)(pc + 0.5)) / 100; /* whole no. of %reqs */ pc2 = ((int)(pc + 0.5)) % 100; /* remaining 100ths. */ if (pc1 == 100) fprintf(outf, " 100%%: "); else if (pc1 > 0 || pc2 > 0) fprintf(outf, "%2d.%02d%%: ", pc1, pc2); else fprintf(outf, " : "); break; case 'B': if (byq) { if (p -> bytes / bdivider > 0.5) fprintf(outf, "%*.0lf", bfieldwidth, p -> bytes / bdivider); else for (i = 0; i < bfieldwidth; i++) fprintf(outf, " "); fprintf(outf, ": "); } break; case 'b': if (byq) { pc = p -> bytes / (total_bytes / 10000); pc1 = ((int)(pc + 0.5)) / 100; /* whole no. of %bytes */ pc2 = ((int)(pc + 0.5)) % 100; /* remaining 100ths. */ if (pc1 == 100) fprintf(outf, " 100%%: "); else if (pc1 > 0 || pc2 > 0) fprintf(outf, "%2d.%02d%%: ", pc1, pc2); else fprintf(outf, " : "); } break; } } if (alphahost && !isdigit(p -> name[0])) { /* we've swapped the names */ reversehostname(p -> name); /* Also in that case right align names */ for (i = graphwidth - (int)strlen(p -> name); i > 0; i--) fprintf(outf, " "); } if ((kq == 2) || /* if we want to link to everything ... */ (kq == 1 && included(p -> name, ispagehead))) { /* or it is a page, and we want to link to pages */ fprintf(outf, "<a HREF=\""); htmlfprintf(outf, baseurl); htmlfprintf(outf, p -> name); fprintf(outf, "\">"); htmlfprintf(outf, p -> name); fprintf(outf, "</a>"); } else /* (the usual case for most reports) */ if (!aq) htmlfprintf(outf, p -> name); else fprintf(outf, p -> name); fprintf(outf, "\n"); } if (aq) asciiline(outf); else fprintf(outf, "</pre>"); } /*** The domain report is similar to the generic ones. It differs in that the domains are stored in a different structure, and that subdomains must be printed. ***/ void domout(FILE *outf, int firstdom) { extern struct domain *domainhead[]; extern int aq; extern flag byq, rawbytes; extern int domsortby; extern char domminbytestr[], domminreqstr[]; extern char subdomminbytestr[], subdomminreqstr[]; extern int dom_max_reqs; extern double dom_max_bytes; extern int subonumber; extern char domcols[]; extern double total_bytes; int domfloor; struct domain *domp; double bdivider; char bprefix[2]; char *cols; int fieldwidth, bfieldwidth; double pc; int pc1, pc2; int i, j, k, tempint; char *tempp; bprefix[0] = '\0'; bprefix[1] = '\0'; if (!aq) { fprintf(outf, "\n\n<hr>\n<h2><a NAME=\"Domain\">Domain Report</a></h2>\n\n"); gotos(outf, 'o'); } else { fprintf(outf, "Domain Report\n"); fprintf(outf, "-------------\n"); } if (!aq) fprintf(outf, "<p>"); domfloor = whatincluded(outf, domsortby, domminreqstr, domminbytestr, "domain", "domains", FALSE); if (subonumber > 0) { if (!aq) fprintf(outf, "<br>"); whatincluded(outf, domsortby, subdomminreqstr, subdomminbytestr, "requested subdomain", "requested subdomains", TRUE); } if (aq) fprintf(outf, "\n"); else fprintf(outf, "<pre>"); tempint = 10000; for (fieldwidth = 5; dom_max_reqs / tempint >= 10; fieldwidth++) tempint *= 10; if (byq) { if (rawbytes) { tempint = 100000; for (bfieldwidth = 6; dom_max_bytes / tempint >= 10; bfieldwidth++) tempint *= 10; } else bfieldwidth = 6; bdivider = finddivider(dom_max_bytes, bprefix); } for (cols = domcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': for (i = 5; i < fieldwidth; i++) fprintf(outf, " "); if (subonumber > 0) fprintf(outf, " #reqs : "); else fprintf(outf, "#reqs: "); break; case 'r': if (subonumber > 0) fprintf(outf, " %%reqs : "); else fprintf(outf, " %%reqs: "); break; case 'B': if (byq) { for (i = 6; i < bfieldwidth; i++) fprintf(outf, " "); if (subonumber > 0) fprintf(outf, " %sbytes : ", bprefix[0] == '\0'?" ":bprefix); else fprintf(outf, "%sbytes: ", bprefix[0] == '\0'?" ":bprefix); } break; case 'b': if (byq) { if (subonumber > 0) fprintf(outf, " %%bytes : "); else fprintf(outf, "%%bytes: "); } break; } } fprintf(outf, "domain\n"); for (cols = domcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': for (i = 1; i <= fieldwidth; i++) fprintf(outf, "-"); if (subonumber > 0) fprintf(outf, "--"); fprintf(outf, " "); break; case 'r': if (subonumber > 0) fprintf(outf, "--"); fprintf(outf, "------ "); break; case 'B': if (byq) { for (i = 1; i <= bfieldwidth; i++) fprintf(outf, "-"); if (subonumber > 0) fprintf(outf, "--"); fprintf(outf, " "); } break; case 'b': if (byq) { if (subonumber > 0) fprintf(outf, "--"); fprintf(outf, "------ "); } break; } } fprintf(outf, "------\n"); if (domfloor < 0) j = domfloor; else j = 1; for (i = firstdom; i >= 0 && (j++) != 0; i = domainhead[i] -> nexti) { if (!(i == DOMHASHSIZE - 2 && domainhead[i] -> reqs == -1)) { for (cols = domcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': if (subonumber > 0) fprintf(outf, " %*d : ", fieldwidth, domainhead[i] -> reqs); else fprintf(outf, "%*d: ", fieldwidth, domainhead[i] -> reqs); break; case 'r': pc = (domainhead[i] -> reqs + 0.0) / ((total_succ_reqs + 0.0) / 10000); pc1 = ((int)(pc + 0.5)) / 100; /* whole no. of %reqs */ pc2 = ((int)(pc + 0.5)) % 100; /* remaining 100ths. */ if (subonumber > 0) fprintf(outf, " "); if (pc1 == 100) fprintf(outf, " 100%%"); else if (pc1 > 0 || pc2 > 0) fprintf(outf, "%2d.%02d%%", pc1, pc2); else fprintf(outf, " "); if (subonumber > 0) fprintf(outf, " : "); else fprintf(outf, ": "); break; case 'B': if (byq) { if (domainhead[i] -> bytes / bdivider > 0.5) { if (subonumber > 0) fprintf(outf, " %*.0lf ", bfieldwidth, domainhead[i] -> bytes / bdivider); else fprintf(outf, "%*.0lf", bfieldwidth, domainhead[i] -> bytes / bdivider); } else for (k = 0; k < bfieldwidth + 2 * (subonumber > 0); k++) fprintf(outf, " "); fprintf(outf, ": "); } break; case 'b': if (byq) { pc = domainhead[i] -> bytes / (total_bytes / 10000); pc1 = ((int)(pc + 0.5)) / 100; /* whole no. of %bytes */ pc2 = ((int)(pc + 0.5)) % 100; /* remaining 100ths. */ if (subonumber > 0) fprintf(outf, " "); if (pc1 == 100) fprintf(outf, " 100%%"); else if (pc1 > 0 || pc2 > 0) fprintf(outf, "%2d.%02d%%", pc1, pc2); else fprintf(outf, " "); if (subonumber > 0) fprintf(outf, " : "); else fprintf(outf, ": "); } break; } } if (domainhead[i] -> id[0] == '*') /* flagged domains, not real domain names */ fprintf(outf, "[%s]\n", domainhead[i] -> name); else if (domainhead[i] -> name[0] == '?') /* real domain, but don't print name */ fprintf(outf, ".%s\n", domainhead[i] -> id); else fprintf(outf, ".%s (%s)\n", domainhead[i] -> id, domainhead[i] -> name); /* Now print its subdomains too. */ for (domp = domainhead[i] -> next; domp -> name != NULL; domp = domp -> next) { for (cols = domcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': fprintf(outf, "(%*d): ", fieldwidth, domp -> reqs); break; case 'r': pc = (domp -> reqs + 0.0) / ((total_succ_reqs + 0.0) / 10000); pc1 = ((int)(pc + 0.5)) / 100; /* whole no. of %reqs */ pc2 = ((int)(pc + 0.5)) % 100; /* remaining 100ths. */ if (pc1 == 100) fprintf(outf, "( 100%%): "); else if (pc1 > 0 || pc2 > 0) fprintf(outf, "(%2d.%02d%%): ", pc1, pc2); else fprintf(outf, " : "); break; case 'B': if (byq) { if (domp -> bytes / bdivider > 0.5) fprintf(outf, "(%*.0lf)", bfieldwidth, domp -> bytes / bdivider); else for (k = 0; k < bfieldwidth + 2; k++) fprintf(outf, " "); fprintf(outf, ": "); } break; case 'b': if (byq) { pc = domp -> bytes / (total_bytes / 10000); pc1 = ((int)(pc + 0.5)) / 100; /* whole no. of %bytes */ pc2 = ((int)(pc + 0.5)) % 100; /* remaining 100ths. */ if (pc1 == 100) fprintf(outf, "( 100%%): "); else if (pc1 > 0 || pc2 > 0) fprintf(outf, "(%2d.%02d%%): ", pc1, pc2); else fprintf(outf, " : "); } break; } } tempp = domp -> id; while ((tempp = strchr(tempp, '.')) != NULL) { fprintf(outf, " "); /* print two spaces for each dot in name */ tempp++; } if (i == DOMHASHSIZE - 1) fprintf(outf, " "); /* + 2 more for numerical domains */ fprintf(outf, "%s", domp -> id); if (domp -> name[0] != '?') /* print name */ fprintf(outf, " (%s)", domp -> name); fprintf(outf, "\n"); } /* end for domp */ } } /* end for (i = running over domains) */ if (aq) asciiline(outf); else fprintf(outf, "</pre>"); } /*** The date reports aren't quite generic enough to combine completely, but we can go a long way towards it. ***/ /*** First a function for printing out the headers of a report and finding the fieldwidths etc.; then one for printing out each individual line. ***/ void datehead(FILE *outf, int maxreq, double maxbytes, char *wantcols, char *graphtype, char anchor[11], char title[15], char colhead[13], char codeletter, int *unit, int *fieldwidth, int *bfieldwidth, int *graphwidth, double *bdivider) /* NB: colhead: inc. leading spaces. */ /* The last 5 args are returned altered */ { extern void int3printf(); /* in utils.c */ extern int aq; extern flag byq, rawbytes; extern int pagewidth; extern char imagedir[]; extern char markchar; char *cols; char bprefix[2]; int i, j, tempint; char *tempc; bprefix[0] = '\0'; bprefix[1] = '\0'; if (*graphtype == 'b') *graphtype = 'B'; if (!aq) { fprintf(outf, "<hr>\n<h2><a NAME=\"%s\">%s</a></h2>\n", anchor, title); gotos(outf, codeletter); } else { fprintf(outf, "%s\n", title); for (tempc = title; *tempc != '\0'; tempc++) fprintf(outf, "-"); fprintf(outf, "\n"); } tempint = 10000; for (*fieldwidth = 5; maxreq / tempint >= 10; (*fieldwidth)++) tempint *= 10; /* so fieldwidth is log_10(maxreq), but >= 5 */ if (byq) { if (rawbytes || (*graphtype == 'B' && *unit > 0)) { tempint = 100000; for (*bfieldwidth = 6; maxbytes / tempint >= 10; (*bfieldwidth)++) tempint *= 10; } else *bfieldwidth = 6; *bdivider = finddivider(maxbytes, bprefix); } if (*unit <= 0) { /* (o/wise just use the given amount) */ /* Calculate the graphwidth */ *graphwidth = pagewidth - (int)strlen(colhead) - 2; for (cols = wantcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': *graphwidth -= *fieldwidth + 2; break; case 'B': *graphwidth -= *bfieldwidth + 2; break; case 'r': case 'b': *graphwidth -= 8; break; } } *graphwidth = MAX(*graphwidth, MINGRAPHWIDTH); /* must be >= MGW wide */ if (*graphtype == 'B') *unit = (maxbytes - 1) / (*bdivider * *graphwidth); else *unit = (maxreq - 1) / *graphwidth; /* except we want a 'nice' amount, so ... */ /* (Nice amount is 1, 1.5, 2, 2.5, 3, 4, 5, 6, 8 * 10^n */ j = 0; while (*unit > 24) { *unit /= 10; j++; } if (*unit == 6) *unit = 7; else if (*unit == 8) *unit = 9; else if (*unit >= 20) *unit = 24; else if (*unit >= 15) *unit = 19; else if (*unit >= 10) *unit = 14; (*unit)++; for (i = 0; i < j; i++) { *unit *= 10; } } /* end if (*unit <= 0) */ else if (*graphtype == 'B') { /* o/wise unit doesn't make sense */ *bdivider = 1; bprefix[0] = '\0'; } if (!aq) { fprintf(outf, "\n<p>Each unit (<tt><img src=\""); htmlfprintf(outf, imagedir); fprintf(outf, "bar1.gif\" alt=\""); htmlputc(markchar, outf); fprintf(outf, "\"></tt>) represents "); int3printf(outf, *unit); if (*graphtype == 'B') fprintf(outf, " %sbyte%s, or part thereof.", bprefix, (*unit == 1)?"":"s"); else fprintf(outf, " request%s.", (*unit == 1)?"":"s, or part thereof"); fprintf(outf, "\n\n<pre width=%d><tt>\n", pagewidth); } else { fprintf(outf, "\nEach unit (%c) represents ", markchar); int3printf(outf, *unit); if (*graphtype == 'B') fprintf(outf, " %sbyte%s, or part thereof.\n\n", bprefix, (*unit == 1)?"":"s"); else fprintf(outf, " request%s.\n\n", (*unit == 1)?"":"s, or part thereof"); } fprintf(outf, "%s: ", colhead); for (cols = wantcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': for (i = 5; i < *fieldwidth; i++) fprintf(outf, " "); fprintf(outf, "#reqs: "); break; case 'r': fprintf(outf, " %%reqs: "); break; case 'B': if (byq) { for (i = 6; i < *bfieldwidth; i++) fprintf(outf, " "); fprintf(outf, "%sbytes: ", bprefix[0] == '\0'?" ":bprefix); } break; case 'b': if (byq) fprintf(outf, "%%bytes: "); break; } } fprintf(outf, "\n"); for (tempc = colhead; *tempc != '\0'; tempc++) fprintf(outf, "-"); fprintf(outf, " "); for (cols = wantcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': for (i = 1; i <= *fieldwidth; i++) fprintf(outf, "-"); fprintf(outf, " "); break; case 'r': fprintf(outf, "------ "); break; case 'B': if (byq) { for (i = 1; i <= *bfieldwidth; i++) fprintf(outf, "-"); fprintf(outf, " "); } break; case 'b': if (byq) fprintf(outf, "------ "); break; } } fprintf(outf, "\n"); } /* As promised, each separate line. We print name of date in output() though */ void dateline(FILE *outf, int reqs, double bytes, char *wantcols, char graphtype, int fieldwidth, int bfieldwidth, int unit, int bdivider) { extern double total_bytes; extern flag byq; char *cols; double pc; int pc1, pc2; for (cols = wantcols; *cols != '\0'; cols++) { switch(*cols) { case 'R': fprintf(outf, "%*d: ", fieldwidth, reqs); break; case 'r': pc = (reqs + 0.0) / ((total_succ_reqs + 0.0) / 10000); pc1 = ((int)(pc + 0.5)) / 100; /* whole no. of %reqs */ pc2 = ((int)(pc + 0.5)) % 100; /* remaining 100ths. */ if (pc1 == 100) fprintf(outf, " 100%%: "); else if (pc1 > 0 || pc2 > 0) fprintf(outf, "%2d.%02d%%: ", pc1, pc2); else fprintf(outf, " : "); break; case 'B': if (byq) fprintf(outf, "%*.0lf: ", bfieldwidth, bytes / bdivider); break; case 'b': if (byq) { pc = bytes / (total_bytes / 10000); pc1 = ((int)(pc + 0.5)) / 100; /* whole no. of %bytes */ pc2 = ((int)(pc + 0.5)) % 100; /* remaining 100ths. */ if (pc1 == 100) fprintf(outf, " 100%%: "); else if (pc1 > 0 || pc2 > 0) fprintf(outf, "%2d.%02d%%: ", pc1, pc2); else fprintf(outf, " : "); } break; } } if (graphtype == 'B') barplot(outf, (int)(ceil(bytes / (unit * bdivider)))); else barplot(outf, (reqs == 0)?0:((reqs - 1) / unit) + 1); fprintf(outf, "\n"); } /*** The status code report (very simple) ***/ void statusout(FILE *outf) { extern int status[], statusnos[]; extern char statusstrs[NO_STATUS][MAXSTATUSLENGTH]; extern int aq; int fieldwidth; int maxreqs = 0; int i; for (i = 0; i < NO_STATUS; i++) maxreqs = MAX(maxreqs, status[i]); if (!aq) { fprintf(outf, "\n\n<hr>\n<h2><a NAME=\"Status\">Status Code Report</a></h2>\n\n"); gotos(outf, 'c'); fprintf(outf, "<pre>"); } else fprintf(outf, "Status Code Report\n------------------\n\n"); i = 10000; for (fieldwidth = 5; maxreqs / i >= 10; fieldwidth++) i *= 10; for (i = 5; i < fieldwidth; i++) fprintf(outf, " "); fprintf(outf, "#occs: no. description\n"); for (i = 0; i < fieldwidth; i++) fprintf(outf, "-"); fprintf(outf, " ---------------\n"); for (i = 0; i < NO_STATUS; i++) { if (status[i] > 0) { if (statusstrs[i][0] == '0') fprintf(outf, "%*d: %s\n", fieldwidth, status[i], statusstrs[i]); else fprintf(outf, "%*d: %d %s\n", fieldwidth, status[i], statusnos[i], statusstrs[i]); } } if (aq) asciiline(outf); else fprintf(outf, "</pre>"); } /*** Finally in the individual report printing, the error report ***/ void errout(FILE *outf, int errorder[NO_ERRS]) { extern int errors[NO_ERRS]; extern char errs[NO_ERRS][MAXERRLENGTH]; extern int errminreqs; extern int aq; int fieldwidth; int i; if (errors[errorder[0]] >= errminreqs) { /* o/wise no report */ if (!aq) { fprintf(outf, "\n\n<hr>\n<h2><a NAME=\"Error\">Error Report</a></h2>\n\n"); gotos(outf, 'e'); fprintf(outf, "<p>"); } else fprintf(outf, "Error Report\n------------\n"); if (errminreqs == 0) fprintf(outf, "Printing all possible errors, "); else fprintf(outf, "Printing all errors with at least %d occurence%s,\n", errminreqs, (errminreqs == 1)?"":"s"); fprintf(outf, " sorted by number of occurrences."); if (aq) fprintf(outf, "\n\n"); else fprintf(outf, "<pre>"); i = 10000; for (fieldwidth = 5; errors[errorder[0]] / i >= 10; fieldwidth++) i *= 10; for (i = 5; i < fieldwidth; i++) fprintf(outf, " "); fprintf(outf, "#occs: error type\n"); for (i = 0; i < fieldwidth; i++) fprintf(outf, "-"); fprintf(outf, " ----------\n"); for (i = 0; errors[errorder[i]] >= errminreqs && i < NO_ERRS; i++) fprintf(outf, "%*d: %s\n", fieldwidth, errors[errorder[i]], (errs[errorder[i]][0] == '\0')?"[unknown]":errs[errorder[i]]); if (aq) asciiline(outf); else fprintf(outf, "</pre>"); } } /*** Now the main output function which calls all that stuff ***/ void output(struct genstruct *urlsorthead, struct genstruct *dirsorthead, struct genstruct *hostsorthead, int firstdom, struct genstruct *refsorthead, struct genstruct *browsorthead, struct genstruct *fullbrowsorthead, int errorder[]) { extern int dayofdate(); /* in utils.c */ extern int minsbetween(); /* in utils.c */ extern void int3printf(); /* in utils.c */ extern void double3printf(); /* in utils.c */ extern char outfile[]; extern char dayname[7][4]; extern char monthname[12][4]; extern int monthlength[]; extern char hostname[]; extern char logourl[]; extern char hosturl[]; extern char commandname[]; extern char headerfile[]; extern char footerfile[]; extern char reportorder[]; extern flag q7, byq, refbyq, browbyq, kq, warnq; extern flag mback, Dback, Wback, Hback; extern flag xq, dq, Dq, Wq, hq, Hq, mq, Sq, rq, oq, iq, fq, bq, Bq, cq, eq; extern int sq, aq; extern char starttimestr[]; extern struct timestruct firsttime, lasttime, oldtime, totime, starttimec; extern time_t starttime, stoptime; extern int weekbeginson; extern struct monthly *firstm, *lastm; extern struct weekly *firstw, *lastw; extern struct daily *firstd, *lastd; extern struct hourly *firsth, *lasth; extern int dailyreq[], hourlyreq[]; extern double dailybytes[], hourlybytes[]; extern int monthlyunit, weeklyunit, hourlyunit, fullhourlyunit, dailyunit; extern int fulldailyunit; extern int cachereqs, cachereqs7, corrupt_lines, other_lines; extern int no_urls, no_hosts, no_urls7, no_hosts7, no_new_hosts7; extern double total_bytes, total_bytes7; extern int pagewidth; extern int hostsortby, reqsortby, dirsortby; extern int refsortby, browsortby, fullbrowsortby; extern char hostminreqstr[], urlminreqstr[], dirminreqstr[], refminreqstr[]; extern char browminreqstr[], fullbrowminreqstr[]; extern char hostminbytestr[], urlminbytestr[], dirminbytestr[]; extern char refminbytestr[], browminbytestr[], fullbrowminbytestr[]; extern char monthgraph, daygraph, fulldaygraph, hourgraph, fullhourgraph; extern char weekgraph; extern char monthcols[], daycols[], fulldaycols[], hourcols[], weekcols[]; extern char fullhourcols[], reqcols[], dircols[], hostcols[], refcols[]; extern char browcols[], fullbrowcols[]; extern char imagedir[], baseurl[]; extern int reqtype; extern int status[], status7[], statusnos[]; extern int dir_max_reqs, host_max_reqs, url_max_reqs, ref_max_reqs, brow_max_reqs, fullbrow_max_reqs; extern double dir_max_bytes, host_max_bytes, url_max_bytes; FILE *outf; /* the output file */ int totalmins; /* between first and last entries analysed */ int fieldwidth; /* Width we require to print #reqs in */ int bfieldwidth; /* #bytes ditto */ char bprefix[2]; /* kilo, Mega, etc. */ int graphwidth; /* the width left for a graph after columns written */ struct monthly *mp; struct daily *dp; struct weekly *wp; struct hourly *hp; int maxreq; /* within a particular date report */ double maxbytes; double bdivider; int year, monthno, date; flag finished; int i, j, firsti, lasti; char *ro; char tempstr[MAXSTRINGLENGTH]; FILE *tempf; bprefix[0] = '\0'; bprefix[1] = '\0'; total_succ_reqs = cachereqs; total_fail_reqs = 0; total_other_reqs = 0; total_succ_reqs7 = cachereqs7; total_fail_reqs7 = 0; total_other_reqs7 = 0; for (i = 0; i < NO_STATUS; i++) { if (statusnos[i] <= 299 || statusnos[i] == 304) { total_succ_reqs += status[i]; total_succ_reqs7 += status7[i]; } else if (statusnos[i] <= 399) { total_other_reqs += status[i]; total_other_reqs7 += status7[i]; } else { total_fail_reqs += status[i]; total_fail_reqs7 += status7[i]; } } if (STREQ(outfile, "stdout")) outf = stdout; else if ((outf = fopen(outfile, "w")) == NULL) { fprintf(stderr, "%s: Error: failed to open output file %s for writing.\n", commandname, outfile); exit(ERR); /* shouldn't get here because also tested at the beginning */ } /* (unless it's vanished in the meantime or something) */ if (aq == CACHE) fprintf(outf, "CACHE type 1 produced by analog%s. Do not modify or delete!", VERSION); else { if (!aq) { fprintf(outf, "<html>\n<head><title>Web Server Statistics for "); htmlfprintf(outf, hostname); fprintf(outf, "</title></head>\n"); fprintf(outf, "<body>\n<h1><a NAME=\"Top\">"); if (!STREQ(logourl, "none")) { fprintf(outf, "<IMG src=\""); htmlfprintf(outf, logourl); fprintf(outf, "\" alt=\"\"> "); } if (hosturl[0] == '-') { fprintf(outf, "Web Server Statistics</a> for "); htmlfprintf(outf, hostname); } else { fprintf(outf, "Web Server Statistics</a> for <a HREF=\""); htmlfprintf(outf, hosturl); fprintf(outf, "\">"); htmlfprintf(outf, hostname); fprintf(outf, "</a>"); } fprintf(outf, "</h1>\n\n"); } else { fprintf(outf, "Web Server Statistics for %s\n", hostname); fprintf(outf, "=========================="); for (i = (int)strlen(hostname); i > 0; i--) fprintf(outf, "="); fprintf(outf, "\n"); } /* insert header file */ headerfile[MAXSTRINGLENGTH - 5] = '\0'; /* for safety */ if (!STREQ(headerfile, "none")) { if ((tempf = fopen(headerfile, "r")) == NULL) { if (warnq) fprintf(stderr, "%s: Warning: Failed to open headerfile %s: ignoring it.\n", commandname, headerfile); } else { /* can open header file */ if (!aq) fprintf(outf, "<hr>"); else fprintf(outf, "\n"); while(fgets(tempstr, MAXLINELENGTH, tempf) != NULL) fprintf(outf, "%s", tempstr); fclose(tempf); if (tempstr[(int)strlen(tempstr) - 1] != '\n') fprintf(outf, "\n"); if (aq) { for (i = 0; i < pagewidth; i++) fprintf(outf, "-"); } fprintf(outf, "\n"); } } } /* Summary statistics */ if (xq) { if (!aq) fprintf(outf, "<hr>"); fprintf(outf, "\nProgram started at %c%c%c-%c%c-%c%c%c-%c%c%c%c %c%c:%c%c local time.\n", starttimestr[0], starttimestr[1], starttimestr[2], (starttimestr[8]==' ')?'0':starttimestr[8], starttimestr[9], starttimestr[4], starttimestr[5], starttimestr[6], starttimestr[20], starttimestr[21], starttimestr[22], starttimestr[23], starttimestr[11], starttimestr[12], starttimestr[14], starttimestr[15]); if (firsttime.code > oldtime.code) q7 = OFF; if (total_succ_reqs > 0) { totalmins = minsbetween(firsttime.date, firsttime.monthno, firsttime.year, firsttime.hr, firsttime.min, lasttime.date, lasttime.monthno, lasttime.year, lasttime.hr, lasttime.min) + 1; if (!aq) fprintf(outf, "<br>"); fprintf(outf, "Analysed requests from %s-%02d-%s-%d %02d:%02d to %s-%02d-%s-%d %02d:%02d\n (%.1f days).\n\n", dayname[dayofdate(firsttime.date, firsttime.monthno, firsttime.year)], firsttime.date, monthname[firsttime.monthno], firsttime.year, firsttime.hr, firsttime.min, dayname[dayofdate(lasttime.date, lasttime.monthno, lasttime.year)], lasttime.date, monthname[lasttime.monthno], lasttime.year, lasttime.hr, lasttime.min, (double)totalmins / 1440.0); } if (!aq) fprintf(outf, "<p><b>Total completed requests:</b> "); else fprintf(outf, "Total completed requests: "); int3printf(outf, total_succ_reqs); if (q7) { fprintf(outf, " ("); int3printf(outf, total_succ_reqs7); fprintf(outf, ")"); } if (totalmins > 30) { if (!aq) fprintf(outf, "\n<br><b>Average completed requests per day:</b> "); else fprintf(outf, "\nAverage completed requests per day: "); if (total_succ_reqs < 2) fprintf(outf, "0"); else double3printf(outf, ((double)(total_succ_reqs - 1)) * 1440.0 / (totalmins + 0.0)); if (q7) { fprintf(outf, " ("); int3printf(outf, total_succ_reqs7 / 7); fprintf(outf, ")"); } } if (total_fail_reqs > 0) { if (!aq) fprintf(outf, "\n<br><b>Total failed requests:</b> "); else fprintf(outf, "\nTotal failed requests: "); int3printf(outf, total_fail_reqs); if (q7) { fprintf(outf, " ("); int3printf(outf, total_fail_reqs7); fprintf(outf, ")"); } } if (total_other_reqs > 0) { if (!aq) fprintf(outf, "\n<br><b>Total redirected requests:</b> "); else fprintf(outf, "\nTotal redirected requests: "); int3printf(outf, total_other_reqs); if (q7) { fprintf(outf, " ("); int3printf(outf, total_other_reqs7); fprintf(outf, ")"); } } if (rq) { /* These data are not collected o/wise (rq => this > 0) */ if (!aq) fprintf(outf, "\n<br><b>Number of distinct files requested:</b> "); else fprintf(outf, "\nNumber of distinct files requested: "); int3printf(outf, no_urls); if (q7) { fprintf(outf, " ("); int3printf(outf, no_urls7); fprintf(outf, ")"); } } if ((sq == ON || sq == APPROX) && no_hosts > 0) { if (!aq) fprintf(outf, "\n<br><b>%sumber of distinct hosts served:</b> ", (sq == ON)?"N":"Approximate n"); else fprintf(outf, "\n%sumber of distinct hosts served: ", (sq == ON)?"N":"Approximate n"); int3printf(outf, no_hosts); if (q7) { fprintf(outf, " ("); int3printf(outf, no_hosts7); fprintf(outf, ")"); if (!aq) fprintf(outf, "\n<br><b>%sumber of new hosts served in last 7 days:</b> ", (sq == ON)?"N":"Approximate n"); else fprintf(outf, "\n%sumber of new hosts served in last 7 days: ", (sq == ON)?"N":"Approximate n"); int3printf(outf, no_new_hosts7); } } if (corrupt_lines > 0) { if (!aq) fprintf(outf, "\n<br><b>Corrupt logfile lines:</b> "); else fprintf(outf, "\nCorrupt logfile lines: "); int3printf(outf, corrupt_lines); } if (other_lines > 0) { if (!aq) fprintf(outf, "\n<br><b>Unwanted logfile entries:</b> "); else fprintf(outf, "\nUnwanted logfile entries: "); int3printf(outf, other_lines); } if (byq) { if (!aq) fprintf(outf, "\n<br><b>Total data transferred:</b> "); else fprintf(outf, "\nTotal data transferred: "); bdivider = finddivider(total_bytes, bprefix); double3printf(outf, ROUND(total_bytes / bdivider)); fprintf(outf, " %sbytes", bprefix); if (q7) { fprintf(outf, " ("); bdivider = finddivider(total_bytes7, bprefix); double3printf(outf, ROUND(total_bytes7 / bdivider)); fprintf(outf, " %sbytes)", bprefix); } if (totalmins > 30) { if (!aq) fprintf(outf, "\n<br><b>Average data transferred per day:</b> "); else fprintf(outf, "\nAverage data transferred per day: "); bdivider = finddivider((total_bytes * 1440) / (totalmins + 0.0), bprefix); double3printf(outf, ROUND((total_bytes * 1440) / (totalmins + 0.0) / bdivider)); fprintf(outf, " %sbytes", bprefix); if (q7) { fprintf(outf, " ("); bdivider = finddivider(total_bytes7 / 7.0, bprefix); double3printf(outf, ROUND(total_bytes7 / 7.0 / bdivider)); fprintf(outf, " %sbytes)", bprefix); } } } if (q7) { if (!aq) fprintf(outf, "\n<br>"); else fprintf(outf, "\n"); fprintf(outf, "(Figures in parentheses refer to the "); if (starttimec.code > totime.code) fprintf(outf, "7 days to %02d-%s-%4d).", totime.date, monthname[totime.monthno], totime.year); else fprintf(outf, "last 7 days)."); } if (!aq && (mq || Wq || dq || Dq || hq || oq || Sq || iq || rq)) gotos(outf, 'z'); if (aq) { fprintf(outf, "\n"); asciiline(outf); } } /* end if xq */ else if (aq == ASCII) printf("\n"); /* Now for the rest of the reports, in reportorder order */ for (ro = reportorder; *ro != '\0'; ro++) { switch(*ro) { case 'm': /* Monthly report */ if (mq) { maxreq = 0; maxbytes = 0.0; finished = FALSE; for (mp = mback?lastm:firstm; !finished; mp = mp -> next) { for (i = 0; i < 12; i++) { maxreq = MAX(maxreq, mp -> reqs[i]); maxbytes = MAX(maxbytes, mp -> bytes[i]); } if (mp == (mback?firstm:lastm)) finished = TRUE; } datehead(outf, maxreq, maxbytes, monthcols, &monthgraph, "Monthly", "Monthly Report", " month", 'm', &monthlyunit, &fieldwidth, &bfieldwidth, &graphwidth, &bdivider); finished = FALSE; year = (mback?lasttime:firsttime).year; for (mp = mback?lastm:firstm; !finished; mp = mp -> next) { if (mp == firstm) { firsti = firsttime.monthno; if (mback) finished = TRUE; } else firsti = 0; if (mp == lastm) { lasti = lasttime.monthno; if (!mback) finished = TRUE; } else lasti = 11; for (i = mback?lasti:firsti; mback?(i >= firsti):(i <= lasti); i += mback?(-1):1) { /* run through months in chosen order */ fprintf(outf, "%s %d: ", monthname[i], year); dateline(outf, mp -> reqs[i], mp -> bytes[i], monthcols, monthgraph, fieldwidth, bfieldwidth, monthlyunit, bdivider); } year += mback?(-1):1; } if (aq) asciiline(outf); else fprintf(outf, "</tt></pre>"); } break; case 'W': /* Weekly report */ if (Wq) { maxreq = 0; maxbytes = 0.0; finished = FALSE; for (wp = Wback?lastw:firstw; !finished; wp = wp -> next) { maxreq = MAX(maxreq, wp -> reqs); maxbytes = MAX(maxbytes, wp -> bytes); if (wp == (Wback?firstw:lastw)) finished = TRUE; } datehead(outf, maxreq, maxbytes, weekcols, &weekgraph, "Weekly", "Weekly Report", "week beg.", 'W', &weeklyunit, &fieldwidth, &bfieldwidth, &graphwidth, &bdivider); finished = FALSE; for (wp = Wback?lastw:firstw; !finished; wp = wp -> next) { fprintf(outf, "%2d/%s/%02d: ", wp -> start.date, monthname[wp -> start.monthno], wp -> start.year % 100); dateline(outf, wp -> reqs, wp -> bytes, weekcols, weekgraph, fieldwidth, bfieldwidth, weeklyunit, bdivider); if (wp == (Wback?firstw:lastw)) finished = TRUE; } /* end running through weeks */ if (aq) asciiline(outf); else fprintf(outf, "</tt></pre>"); } /* end if Wq */ break; case 'd': /* Daily summary */ if (dq) { maxreq = 0; maxbytes = 0.0; for (i = 0; i <= 6; i++) { maxreq = MAX(maxreq, dailyreq[i]); maxbytes = MAX(maxbytes, dailybytes[i]); } datehead(outf, maxreq, maxbytes, daycols, &daygraph, "Daily", "Daily Summary", "day", 'd', &dailyunit, &fieldwidth, &bfieldwidth, &graphwidth, &bdivider); for(i = 0; i <= 6; i++) { j = (weekbeginson + i) % 7; fprintf(outf, "%s: ", dayname[j]); dateline(outf, dailyreq[j], dailybytes[j], daycols, daygraph, fieldwidth, bfieldwidth, dailyunit, bdivider); } if (aq) asciiline(outf); else fprintf(outf, "</tt></pre>"); } break; case 'D': /* Full daily report */ if (Dq) { maxreq = 0; maxbytes = 0.0; finished = FALSE; for (dp = Dback?lastd:firstd; !finished; dp = dp -> next) { for (i = 0; i < 31; i++) { maxreq = MAX(maxreq, dp -> reqs[i]); maxbytes = MAX(maxbytes, dp -> bytes[i]); } if (dp == (Dback?firstd:lastd)) finished = TRUE; } datehead(outf, maxreq, maxbytes, fulldaycols, &fulldaygraph, "FullDaily", "Daily Report", " date", 'D', &fulldailyunit, &fieldwidth, &bfieldwidth, &graphwidth, &bdivider); finished = FALSE; year = (Dback?lasttime:firsttime).year; monthno = (Dback?lasttime:firsttime).monthno; for (dp = Dback?lastd:firstd; !finished; dp = dp -> next) { if (dp == firstd) { firsti = firsttime.date - 1; if (Dback) finished = TRUE; } else firsti = 0; if (dp == lastd) { lasti = lasttime.date - 1; if (!Dback) finished = TRUE; } else lasti = monthlength[monthno] + ISLEAPFEB(monthno, year) - 1; for (i = Dback?lasti:firsti; Dback?(i >= firsti):(i <= lasti); i += Dback?(-1):1) { /* run through days in chosen order */ fprintf(outf, "%2d/%s/%02d: ", i + 1, monthname[monthno], year % 100); dateline(outf, dp -> reqs[i], dp -> bytes[i], fulldaycols, fulldaygraph, fieldwidth, bfieldwidth, fulldailyunit, bdivider); if (((dayofdate(i + 1, monthno, year) + (!Dback)) % 7 == weekbeginson) && !(finished && i == (Dback?firsti:lasti))) fprintf(outf, "\n"); /* extra blank line after each week (not last) */ } if (Dback) { if ((--monthno) == -1) { monthno = 11; --year; } } else { if ((++monthno) == 12) { monthno = 0; ++year; } } } /* end running through dp's */ if (aq) asciiline(outf); else fprintf(outf, "</tt></pre>"); } /* end if Dq */ break; case 'H': /* Full hourly report */ if (Hq) { maxreq = 0; maxbytes = 0.0; finished = FALSE; for (hp = Hback?lasth:firsth; !finished; hp = hp -> next) { for (i = 0; i < 24; i++) { maxreq = MAX(maxreq, hp -> reqs[i]); maxbytes = MAX(maxbytes, hp -> bytes[i]); } if (hp == (Hback?firsth:lasth)) finished = TRUE; } if (aq != CACHE) datehead(outf, maxreq, maxbytes, fullhourcols, &fullhourgraph, "FullHourly", "Hourly Report", " date:hr", 'H', &fullhourlyunit, &fieldwidth, &bfieldwidth, &graphwidth, &bdivider); finished = FALSE; year = (Hback?lasttime:firsttime).year; monthno = (Hback?lasttime:firsttime).monthno; date = (Hback?lasttime:firsttime).date; for (hp = Hback?lasth:firsth; !finished; hp = hp -> next) { if (hp == firsth) { firsti = firsttime.hr; if (Hback) finished = TRUE; } else firsti = 0; if (hp == lasth) { lasti = lasttime.hr; if (!Hback) finished = TRUE; } else lasti = 23; for (i = Hback?lasti:firsti; Hback?(i >= firsti):(i <= lasti); i += Hback?(-1):1) { /* run through hours in chosen order */ if (aq == CACHE) { if (i == 0 || (hp == firsth && i == firsti)) fprintf(outf, "\n%d%02d%02d%02d", year, monthno + 1, date, i); fprintf(outf, ":%d:%.0lf", hp -> reqs[i], hp -> bytes[i]); } else { fprintf(outf, "%2d/%s/%02d:%02d: ", date, monthname[monthno], year % 100, i); dateline(outf, hp -> reqs[i], hp -> bytes[i], fullhourcols, fullhourgraph, fieldwidth, bfieldwidth, fullhourlyunit, bdivider); if (i == (Hback?0:23) && !finished) fprintf(outf, "\n"); /* extra blank line after each day (not last) */ } } if (Hback) { if ((--date) == 0) { if ((--monthno) == -1) { monthno = 11; --year; } date = monthlength[monthno] + ISLEAPFEB(monthno, year); } } else { if ((++date) > monthlength[monthno] + ISLEAPFEB(monthno, year)) { if ((++monthno) == 12) { monthno = 0; ++year; } date = 1; } } } /* end running through hp's */ if (aq == CACHE) fprintf(outf, ":*\n"); else if (aq) asciiline(outf); else if (!aq) fprintf(outf, "</tt></pre>"); } /* end if Hq */ break; case 'h': /* Hourly summary */ if (hq) { maxreq = 0; maxbytes = 0.0; for (i = 0; i <= 23; i++) { maxreq = MAX(maxreq, hourlyreq[i]); maxbytes = MAX(maxbytes, hourlybytes[i]); } datehead(outf, maxreq, maxbytes, hourcols, &hourgraph, "Hourly", "Hourly Summary", "hr", 'h', &hourlyunit, &fieldwidth, &bfieldwidth, &graphwidth, &bdivider); for(i = 0; i <= 23; i++) { fprintf(outf, "%2d: ", i); dateline(outf, hourlyreq[i], hourlybytes[i], hourcols, hourgraph, fieldwidth, bfieldwidth, hourlyunit, bdivider); } if (aq) asciiline(outf); else fprintf(outf, "</tt></pre>"); } break; case 'o': /* Domain report */ if (oq) domout(outf, firstdom); break; case 'S': /* Host report */ if (Sq) genout(outf, hostsorthead, hostsortby, hostminreqstr, hostminbytestr, host_max_reqs, host_max_bytes, hostcols, "Host", "Host Report", "host", "hosts", 'S', hostsortby == ALPHABETICAL, byq, OFF, ""); break; case 'i': /* Directory report */ if (iq) genout(outf, dirsorthead, dirsortby, dirminreqstr, dirminbytestr, dir_max_reqs, dir_max_bytes, dircols, "Directory", "Directory Report", "directory", "directories", 'i', FALSE, byq, OFF, ""); break; case 'r': /* Request report */ if (rq) { if (aq) kq = 0; /* no links in ASCII output! */ else if (reqtype == PAGES) kq = 2; /* If only printing pages, any linked = all linked */ genout(outf, urlsorthead, reqsortby, urlminreqstr, urlminbytestr, url_max_reqs, url_max_bytes, reqcols, "Request", "Request Report", (reqtype == PAGES)?"page":"file", (reqtype == PAGES)?"pages":"files", 'r', FALSE, byq, kq, baseurl); } break; case 'f': /* Referer report */ if (fq) genout(outf, refsorthead, refsortby, refminreqstr, refminbytestr, ref_max_reqs, 0, refcols, "Referer", "Referer Report", "refering URL", "refering URLs", 'f', FALSE, refbyq, !aq, ""); break; case 'b': /* Browser summary */ if (bq) genout(outf, browsorthead, browsortby, browminreqstr, browminbytestr, brow_max_reqs, 0, browcols, "Browser", "Browser Summary", "browser", "browsers", 'b', FALSE, browbyq, OFF, ""); break; case 'B': /* Full browser report */ if (Bq) genout(outf, fullbrowsorthead, fullbrowsortby, fullbrowminreqstr, fullbrowminbytestr, fullbrow_max_reqs, 0, fullbrowcols, "FullBrowser", "Browser Report", "browser", "browsers", 'B', FALSE, browbyq, OFF, ""); break; case 'c': if (cq) statusout(outf); break; case 'e': if (eq) errout(outf, errorder); break; } /* end switch */ } /* end for ro */ /*** Bit at the bottom of the page ***/ if (aq != CACHE) { if (!aq) fprintf(outf, "\n\n<hr>\n<i>This analysis was produced by <a HREF=\"http://www.statslab.cam.ac.uk/~sret1/analog/\">analog%s</a>.\n", VERSION); else fprintf(outf, "This analysis was produced by analog%s.\n", VERSION); time(&stoptime); stoptime -= starttime; /* so now measures elapsed time */ if (stoptime == 0) { if (!aq) fprintf(outf, "<br><b>Running time:</b> Less than 1 second.</i>\n"); else fprintf(outf, "Running time: Less than 1 second.\n"); } else if (stoptime < 60) { if (!aq) fprintf(outf, "<br><b>Running time:</b> %ld second%s.</i>\n", stoptime, (stoptime == 1)?"":"s"); else fprintf(outf, "Running time: %ld second%s.\n", stoptime, (stoptime == 1)?"":"s"); } else { if (!aq) fprintf(outf, "<br><b>Running time:</b> %ld minute%s, %ld second%s.</i>\n", stoptime / 60, (stoptime / 60 == 1)?"":"s", stoptime % 60, (stoptime % 60 == 1)?"":"s"); else fprintf(outf, "Running time: %ld minute%s, %ld second%s.\n", stoptime / 60, (stoptime / 60 == 1)?"":"s", stoptime % 60, (stoptime % 60 == 1)?"":"s"); } if (!aq && (mq || Wq || dq || Dq || hq || oq || Sq || iq || rq)) { gotos(outf, '\0'); } /* Finally, insert footer file */ footerfile[MAXSTRINGLENGTH - 5] = '\0'; /* for safety */ if (!STREQ(footerfile, "none")) { if ((tempf = fopen(footerfile, "r")) == NULL) { if (warnq) fprintf(stderr, "%s: Warning: Failed to open footer file %s: ignoring it.\n", commandname, footerfile); } else { /* can open footer file */ if (!aq) fprintf(outf, "<hr>"); else { for (i = 0; i < pagewidth; i++) fprintf(outf, "-"); } fprintf(outf, "\n\n"); fflush(stdout); while(fgets(tempstr, MAXLINELENGTH, tempf) != NULL) fprintf(outf, "%s", tempstr); fclose(tempf); if (tempstr[(int)strlen(tempstr) - 1] != '\n') fprintf(outf, "\n"); fprintf(outf, "\n"); } } if (!aq) { if (STREQ(headerfile, "none") && STREQ(footerfile, "none")) { fprintf(outf, "<P> <A HREF=\"http://www.webtechs.com/html-val-svc/\">\n"); fprintf(outf, "<IMG SRC=\""); htmlfprintf(outf, imagedir); fprintf(outf, "html2.gif\"\n"); fprintf(outf, "ALT=\"HTML 2.0 Compliant!\"></A>\n"); } fprintf(outf, "\n</body>\n</html>\n"); } } fclose(outf); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.