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.