/* wusage 3.2. Copyright 1993, 1994, Quest Protein Database Center,
   Cold Spring Harbor Labs. Permission granted to copy and distribute
   this work provided that this notice remains intact. Modified
   versions should be cleared through Quest first; if this is not
   done, any modified version of the program must be clearly labeled
   as such. 

   By Thomas Boutell, 11/93 - 6/94. Please contact boutell@cshl.org
   with any questions regarding this software. */
    
#include <stdio.h>
#include <string.h>
#ifndef Mips
#include <stdlib.h>
#endif
#include <time.h>
#include <sys/types.h>
#ifdef VMS
#include ctype
#else
#include <ctype.h>
#endif
#include "configure.h"
#include "usage.h"
#include "wusage.h"
#include "chart.h"

#define TIME_FMT "%a %h %e %T %Y"
#define COMMON_TIME_FMT "%e/%h/%Y:%T"
#define PLEXUS_TIME_FMT "%h %e %T %Y"

#define MAXSTRINGLEN 1000

char *mystrptime(/* char *buf, char *fmt, struct tm *tm */);

void site_access(/* char *site */);
void item_access(/* char *item */);
void site_output();
void item_output();
int site_compare(/* int *s1, int *s2 */);
int item_compare(/* int *s1, int *s2 */);
void finish(/* int html, int weekly, int week_done */);
int flush_to_time(/* item_t_gm, html, totalonly, values, week_done, 
	weeksreturn */);

static char *weeks[WEEKS_MAX];

static int allsites = 0;
int start_none = 1;
int end_none = 1;
struct tm start_t;
struct tm end_t;
struct tm item_t;
time_t start_t_gm;
time_t end_t_gm;
time_t item_t_gm;
time_t week_t_gm;

void output();
void reset();

#define checkbinary() { if (i == (argc-1)) { \
	fprintf(stderr, "Missing argument.\n"); \
	usage(); \
	exit(-1); \
} }

FILE *out;
void finish();

static char *sites[SITES_MAX];
static int site_accs[SITES_MAX];
static int sites_t = 0;
static int accesses;
static int indexed;
static int week;

int wildfind(/* char *item, char **table, int table_size */);

int main(argc, argv)
	int argc;
	char *argv[]; 
{
	int i;
	mystrptime("Tue Jan 1 00:00:01 1980", TIME_FMT, &start_t); 
	mystrptime("Fri Jan 1 00:00:01 2010", TIME_FMT, &end_t); 
	for (i=1; (i<argc); i++) {
		if (!strcmp(argv[i], "-a")) {
			allsites = 1;
		} else if (!strcmp(argv[i], "-c")) {
			checkbinary();
			configfile = argv[i+1];
			i++;
		} else {
			usage();
			exit(-1);
		}		
	}	
	configure();
	if (domainMakeChart) {
		chartSetup(domainNameDefault);
	}
	wusage(0, 1, 0, 0, 0);
	if (domainMakeChart) {
		chartShutdown();
	}
	return 0;
}

void wusage(totalonly, html, weekly, values, weeksreturn)
	int totalonly;
	int html;
	int weekly; 
	int *values;
	int *weeksreturn;
{
	char *site;
	char *date;
	char *method;
	char *item;
	int week_done = 0;
	char buf[513];
	FILE *in;
	week = 1;
	if (totalonly) {
		*weeksreturn = week;
	}
	if (weekly) {
		char s[MAXSTRINGLEN];
		FILE *in;
		sprintf(s, "%s/status", filepath);
		in = fopen(s, "r");
		if (in) {
			int i;
			time_t now;
			time_t w_t_gm;
			fgets(s, 80, in);
			week = atoi(s);
			if (totalonly) {
				*weeksreturn = week-1;
			}
			fgets(s, 80, in);
			mystrptime(s, TIME_FMT, &start_t); 
			start_t_gm = mktime(&start_t);
			start_none = 0;
			fclose(in);
			w_t_gm = start_t_gm - 86400*7*(week-1);
			for (i=0; (i<week-1); i++) {
				weeks[i] = mystrdup(ctime(&w_t_gm));
				w_t_gm += 86400*7;
			}
			time(&now);
			if (totalonly) {
				int i;
				for (i=0; (i<week-1); i++) {
					FILE *in;
					char s[MAXSTRINGLEN];
					int t;
					sprintf(s, "%s/week%d.total", 
						filepath, i);
					in = fopen(s, "r"); 
					fscanf(in, "%d", &t);
					values[i] = t;
					fclose(in);
				}
			}
			if ((now - start_t_gm) < 86400*7) {
				/* Only full weeks! */
				reset();
				finish(html, weekly, week_done);
				return;
			}
		}
	}
	if (html) {
		if (weekly) {				
			char s[MAXSTRINGLEN];
			sprintf(s, "%s/week%d.html", filepath, week-1);
			out = fopen(s, "w");
			if (!out) {
				fprintf(stderr,
	"Can't open file-- directory probably missing: %s\n", filepath);
				exit(-1);
			}
		} else {
			char s[MAXSTRINGLEN];
			sprintf(s, "%s/index.html", filepath);
			out = fopen(s, "w");
			if (!out) {
				fprintf(stderr,
	"Can't open file-- directory probably missing: %s\n", filepath);
				exit(-1);
			}
		}
	}
	start_t_gm = mktime(&start_t);
	if (weekly) {
		if (start_none) {
			week_t_gm = 0;
		} else {
			week_t_gm = start_t_gm;
		}
	}
	end_t_gm = mktime(&end_t);
	in = fopen(logfile, "r");	
	if (!in) {
		fprintf(stderr, "Couldn't open %s\n", logfile);
		exit(-1);
	}
	if (!(html && (!weekly))) {
		while (!feof(in)) {
			char *sp;
			int ignored, hidden, site_ignored;
			if (!fgets(buf, 512, in)) {
				break;
			}
			if (logtype == LOG_NCSA_OLD) {
				/* Old NCSA-style log */
				if (!(site = strtok(buf, " "))) {
					continue;
				}
				if (!(date = strtok(0, "]"))) {
					continue;
				}
				date++;
				mystrptime(date, TIME_FMT, &item_t);
				method = strtok(0, " ");
				if (!method) {
					continue;
				}
				item = strtok(0, "\n");
				if (!item) {
					continue;
				}
			} else if (logtype == LOG_CERN_OLD) {
				/* Old CERN-style log */
				char *s;
				s = mystrptime(buf, TIME_FMT, &item_t);
				while (s[0] == ' ') {
					s++;
				}
				if (!(site = strtok(s, " "))) {
					continue;
				}
				method = strtok(0, " ");
				if (!method) {
					continue;
				}
				if (strcmp(method, "TESTCOMMAND") == 0) {
					continue;
				}	
				item = strtok(0, "\n");
				if (!item) {
					continue;
				}
			} else if (logtype == LOG_PLEXUS) {
				/* Plexus server log */
				char *site_s;
				char *day_s;
				char *month_s;
				char *date_s;
				char *time_s;
				char *zone_s;
				char *year_s;
				char *type_s;
				char *request_s;
				char sat[MAXSTRINGLEN];
				if (!(strncmp("----", buf, 4))) {
					continue;
				}
				if (!(site_s = strtok(buf, " "))) {
					continue;
				}
				if (!(day_s = strtok(0, " "))) {
					continue;
				}
				if (!(month_s = strtok(0, " "))) {
					continue;
				}
				if (!(date_s = strtok(0, " "))) {
					continue;
				}
				if (!(time_s = strtok(0, " "))) {
					continue;
				}
				if (!(zone_s = strtok(0, " "))) {
					continue;
				}
				if (!(year_s = strtok(0, " "))) {
					continue;
				}
				if (!(type_s = strtok(0, " "))) {
					continue;
				}
				if (!(request_s = strtok(0, " "))) {
					continue;
				}
				site = site_s;
				item = request_s;
				sprintf (sat, "%s %s %s %s",
					month_s, date_s, time_s, year_s);
				mystrptime(sat, PLEXUS_TIME_FMT, &item_t);
			} else {
				/* New-style log */
				char *site_s;
				char *time_s;
				char *request_s;
				char *sat;
				site_s = buf;	
				sat = strchr(buf, ' ');
				if (!sat) {
					continue;
				}
				time_s = sat+1;
				*sat = '\0';
				time_s = strchr(time_s, '[');
				if (!time_s) {
					continue;
				}
				sat = strchr(time_s, ']');
				if (!sat) {
					continue;
				}
				time_s++;
				request_s = sat+1;
				*sat = '\0';
				request_s = strchr(request_s, '\"');
				if (!request_s) {
					continue;
				}
				request_s++;
				sat = strchr(request_s, '\"');
				if (!sat) {
					continue;
				}
				*sat = '\0';
				site = site_s;
				sat = strchr(request_s, ' ');
				if (!sat) {
					continue;
				} 
				item = sat+1;
				sat = strchr(item, ' ');
				if (sat) {
					*sat = '\0';
				} 
				mystrptime(time_s, COMMON_TIME_FMT, &item_t);
			}		
			stringtolower(site);
			/* Get rid of identity check stuff */
			while (sp = strstr(site, "@")) {
				site = sp + 1;
			}
			item_t_gm = mktime(&item_t);
			/* Skip anything not in the time range specified */
			if (((!start_none) && (item_t_gm < start_t_gm)) || 
				((!end_none) && (item_t_gm > end_t_gm))) {
				continue;
			} 
			if (weekly) {
				if (!flush_to_time(item_t_gm, html,
					totalonly, values, &week_done,
					weeksreturn)) {
					return;
				}
			}
			sp = strchr(item, ' ');
			/* Anything after space is uninteresting */
			if (sp) {
				*sp = '\0';
			}	
			/* truncate "/index.html" and variations
				thereon so they merge with "/" */
			sp = strstr(item, "index.html");
			if (sp) {
				*sp = '\0';
			} else {
				sp = strstr(item, "Welcome.html");
				if (sp) {
					*sp = '\0';
				} else {
					sp = strstr(item, "welcome.html");
					if (sp) {
						*sp = '\0';
					}
				}
			}
			/* Remove any trailing slash for further merges,
				EXCEPT for root. */ 
			if (strlen(item) > 1) {
				if (item[strlen(item)-1] == '/') {
					item[strlen(item)-1] = '\0';
				}
			}
			site_ignored = wildfind(site, 
				ignored_sites, ignored_sites_t);
			ignored = wildfind(item, 
				ignored_items, ignored_items_t);
			hidden = wildfind(item, 
				hidden_items, hidden_items_t);
			if (!(ignored || hidden || site_ignored)) {
				site_access(site);
				item_access(item);
			} 
			if (!(ignored || site_ignored)) {
				accesses++;
				if (weekly && (!totalonly)) {
					chartAdd(site);
				}
			}
			if (strstr(item, "?")) {
				indexed++;
			}
		}
	}
	fclose(in);
	if (!totalonly) {
		output(weekly);
	}
	if (weekly) {
		time_t now;
		time(&now);
		if (!flush_to_time(now, html, totalonly, values, 
			&week_done)) {
			return;
		}
	}
	reset();
	finish(html, weekly, week_done);
	return;
}		

void copy_file(/* FILE *out, char *fname */);

void finish(html, weekly, week_done)
	int html;
	int weekly; 
	int week_done;
{
	if (html) {
		fclose(out);
		if (weekly) {
			FILE *note;
			int i;
			char s[MAXSTRINGLEN];
			sprintf(s, "%s/list.html", filepath);
			note = fopen(s, "w");
			if (!note) {
				fprintf(stderr,
	"Can't open file-- directory probably missing: %s\n", filepath);
				exit(-1);
			}
			fprintf(note, "<H2>Usage by Week</H2>\n");
#ifdef VMS
			fprintf(note, "<IMG SRC=\"usage_graph.gif\">\n");
#else
			fprintf(note, "<IMG SRC=\"usage.graph.gif\">\n");
#endif
			fprintf(note, "<H3>Weeks beginning...</H3>\n");
			fprintf(note, "<UL>\n");
			if (!week_done) {
				/* If we never got started, we're
					a week ahead of where we
					should be */
				week--;
			}
			for (i=(week-1); (i>=0); i--) {
				fprintf(note, 
			"<LI><A HREF=\"%s/week%d.html\">%s</A>\n", 
					webpath, i, weeks[i]);
			}
			fprintf(note, "</UL>\n");
			fclose(note);
			if (week_done) {
				/* Don't touch status unless week was done */
				char s[MAXSTRINGLEN];
				sprintf(s, "%s/status", filepath);
				note = fopen(s, "w");
				if (!note) {
					fprintf(stderr,
		"Can't open file-- directory probably missing: %s\n", filepath);
					exit(-1);
				}
				fprintf(note, "%d\n", week+1);
				fprintf(note, "%s\n", ctime(&week_t_gm));
				fclose(note);
			}
		} else {
			char s[MAXSTRINGLEN], s2[MAXSTRINGLEN];			
			FILE *in;
			FILE *out;
			int ch;
			wusage(0, 1, 1, 0, 0);
			sprintf(s, "%s/tmp.html", filepath);
			if (!(out = fopen(s, "w"))) {
				fprintf(stderr, "Can't open %s/tmp.html\n");
				exit(0);
			}
			sprintf(s, "%s/index.html", filepath);
			in = fopen(s, "r");
			if (!(in = fopen(s, "r"))) {
				fprintf(stderr, "Can't open %s/index.html\n");
				exit(0);
			}
			while (!feof(in)) {
				ch = getc(in);
				if (ch == EOF) {
					break;
				}
				putc(ch, out);
			}
			fclose(in);
			sprintf(s, "%s/list.html", filepath);
			in = fopen(s, "r");
			if (!(in = fopen(s, "r"))) {
				fprintf(stderr, "Can't open %s/list.html\n");
				exit(0);
			}
			while (!feof(in)) {
				ch = getc(in);
				if (ch == EOF) {
					break;
				}
				putc(ch, out);
			}
			fclose(in);
			if (has_suffix) {
				copy_file(out, suffix);
			}
			fclose(out);
			sprintf(s, "%s/tmp.html", filepath);
			sprintf(s2, "%s/index.html", filepath);
			rename(s, s2);	
			graphs();
		}
	}
}
					
static int lastweekoutput = (-1);

void output(weekly)
	int weekly;
{
	/* Don't output twice */
	if (weekly && (week == lastweekoutput)) {
		return;
	} 
	if (weekly) {
		lastweekoutput = week;
	}
	fprintf(out, "<TITLE>%s Server Usage</TITLE>\n",
		servername);
	fprintf(out, "<H1>%s Server Usage</H1>\n",
		servername);
	if (has_prefix) {
		copy_file(out, prefix);
	}
	if (weekly) {
		FILE *chart;
		char s[81];
		weeks[week-1] = mystrdup(ctime(&week_t_gm));
		fprintf(out, 
			"<H2>Week of %s</H2>\n", weeks[week-1]);
		fprintf(out, "<UL>\n");
		fprintf(out, "<LI>Total accesses: %d\n", accesses);
		fprintf(out, "<LI>Total index accesses: %d\n", indexed);
		if (domainMakeChart) {
			fprintf(out, "<LI>Distribution by Domain:\n");
			fprintf(out, "<P><IMG SRC=\"chart%d.gif\"><P>", week-1);
			sprintf(s, "%s/chart%d.gif", filepath, week-1);
			if (chart = fopen(s, "w")) {
				chartGif(chart);
				fclose(chart);
			}
			chartHtml(out);
			chartReset();
		}
		site_output();
		item_output();
		fprintf(out, "</UL>\n");
	} else {
		/* Do nothing- we don't output global totals anymore-
			too painful and not very meaningful */
	}
	if (weekly) {
		fprintf(out, 
		"<H4><A HREF=\"%s/index.html\">Up to usage page</A></H4>\n", 
		webpath);
		if (has_suffix) {
			copy_file(out, suffix);
		}
	} 
}

void reset() {
	int i;
	for (i=0; (i<sites_t); i++) {
		free(sites[i]);
	}
	for (i=0; (i<items_t); i++) {
		free(items[i]);
	}
	accesses = 0;
	sites_t = 0;
	items_t = 0;
	indexed = 0;
}


void site_access(site)
	char *site;
{
	int i;
	int found = 0;
	for (i=0; (i<sites_t); i++) {
		if (!strcmp(sites[i], site)) {
			site_accs[i]++;
			found = 1;
			break;
		}
	}
	if (!found) {
		site_accs[i] = 1;
		sites[sites_t++] = mystrdup(site);
	}
}
				
void item_access(item)
	char *item; 
{
	int i;
	int found = 0;
	for (i=0; (i<items_t); i++) {
		if (!strcmp(items[i], item)) {
			item_accs[i]++;
			found = 1;
			break;
		}
	}
	if (!found) {
		items[items_t] = mystrdup(item);
		item_accs[items_t] = 1;
		items_t++;
	}
}

int site_o[SITES_MAX];
int item_o[ITEMS_MAX];
 
void site_output() {
	int i;
	int m;
	for (i=0; (i<sites_t); i++) {
		site_o[i] = i;
	}
	qsort(site_o, sites_t, sizeof(int), site_compare);
	if (allsites) {
		m = sites_t;
	} else {
		m = 10;
		if (m > sites_t) {
			m = sites_t;
		}
	}
	fprintf(out, "<LI>%d sites accessing server most:\n", m);
	fprintf(out, "<UL>\n");
	for (i=0; (i<m); i++) {
		int o = site_o[i];
		fprintf(out, 
			"<LI>%s %d\n", sites[o], site_accs[o]);
	}
	fprintf(out, "</UL>\n");
}

void item_output() {
	int i;
	int m;
	for (i=0; (i<items_t); i++) {
		item_o[i] = i;
	}
	qsort(item_o, items_t, sizeof(int), item_compare);
	m = 10;
	if (m > items_t) {
		m = items_t;
	}
	fprintf(out, "<LI>%d items accessed most:\n", m);
	fprintf(out, "<UL>\n");
	for (i=0; (i<m); i++) {
		int o = item_o[i];
		/* Make root look like root */
		if (strlen(items[o]) == 0) {
			fprintf(out, "<LI>/ %d\n", item_accs[o]);
		} else {
			fprintf(out, "<LI>%s %d\n", 
				items[o], item_accs[o]);
		}
	}
	fprintf(out, "</UL>\n");
}

int site_compare(s1, s2)
	int *s1; 
	int *s2; 
{
	return  - (site_accs[*s1] - site_accs[*s2]);
}

int item_compare(s1, s2)
	int *s1;
	int *s2;
{
	return - (item_accs[*s1] - item_accs[*s2]);
}

void usage() {
	fprintf(stderr, 
		"Usage: wusage -c file [-a]\n");
	fprintf(stderr, "Where:\n");
	fprintf(stderr, "-c specifies the configuration file (required)\n");
	fprintf(stderr, "-a specifies that all sites should be listed\n");
}

int wildfind(item, table, table_size)
	char *item;
	char **table;
	int table_size;
{
	int i;
	for (i=0; (i<table_size); i++) {
		int skip = 0;
		char *m = table[i];
		char *it = item;
		while ((*m) != '\0') {
			char mc = *m;
			char ic = *it;
			if (mc == '*') {
				char *after;
				char *find;
				int span;
				span = strcspn(m+1, "*?");
				if (span == 0) {
					return 1;
				}
				find = (char*)malloc(sizeof(char)*(span+1));
				strncpy(find, m+1, span);   
				find[span] = '\0';           
				after = strstr(it, find);    
				if (after) {
					it = after-1;        
				} else {
					skip = 1;
					break;
				}
			} else if (mc == '?') {
				/* No action needed, always matches */	
			} else if (mc != ic) {
				break;
			}
			m++;                                 
			it++;                                
		}
		if (!skip) {
			if (((*m) == '\0') && ((*it) == '\0')) {
				return 1;
			}
		}
	}
	return 0;
}	


/* A very limited implementation to plug the hole in SysV. Should work
	fine for the format output by ctime(), which is our concern. 
	Only knows English month names, however; you will need to
	patch it for other locales. I am willing to improve on this
	but don't have the necessary information about locale support
	in C, and fear falling into yet another incompatibility hole. */

int monthlen[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

static char *parseweekday(/* char *buf, struct tm *tm */);
static char *parsemonth(/* char *buf, struct tm *tm */);
static char *parseday(/* char *buf, struct tm *tm */);
static char *parsetimecolon(/* char *buf, struct tm *tm */);
static char *parsefullyear(/* char *buf, struct tm *tm */);

char *mystrptime(buf, fmt, tm)
	char *buf;
	char *fmt;
	struct tm *tm; 
{
	int i;
	int s;
	int m4, m20, m100, m400;
	char *obuf = buf;
	enum state {
		state_normal, state_escape
	};	

	/* Cheat to get the zone, et cetera, into the tm struct */
	time_t now;
	time(&now);
	*tm = *(localtime(&now));

	s = state_normal;	
	while ((*fmt) != '\0') {
		char c;
		c = *fmt;
		fmt++;
		switch(s) {
			case state_normal:
				if (c == '%') {
					s = state_escape;
				}
				break;
			case state_escape:
				switch(c) {
					case 'a':
						buf = parseweekday(buf, tm);
						break;
					case 'h':
						buf = parsemonth(buf, tm);
						break;
					case 'e':
						buf = parseday(buf, tm);
						break;
					case 'T':
						buf = parsetimecolon(buf, tm);
						break;
					case 'Y':
						buf = parsefullyear(buf, tm);
						break;
					default:
						fprintf(stderr,
	"mystrptime: sorry, unsupported format flag: %c\n", c);
						break;
				}
				s = state_normal;
				break;
			default:
				/* ???? */
				break;
		}	
	}
	/* Now the yday problem (oh such fun!) */
	tm->tm_yday = 0;
	for (i=0; (i<(tm->tm_mon)); i++) {
		tm->tm_yday += monthlen[i];
	}
	/* Leap years */
	m4 = tm->tm_year % 4;
	m20 = tm->tm_year % 20;
	m100 = tm->tm_year % 100;
	m400 = tm->tm_year % 400;
	if ((!m4) && (m20 || ((!m100) && m400))) {
		if (tm->tm_mon > 1) {
			tm->tm_yday += 1;
		}
	} 
	tm->tm_yday += tm->tm_mday;
	return buf;
}

static char *daynames[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };			
static char *parseweekday(buf, tm)
	char *buf;
	struct tm *tm;
{
	int i;
	for (i=0; (i<7); i++) {
		if (strncmp(buf, daynames[i], 3) == 0) {
			tm->tm_wday = i+1;
			break;
		}
	}
	return buf+4;
}
		
static char *monthnames[] = {
	"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
	"Sep", "Oct", "Nov", "Dec"
};

static char *parsemonth(buf, tm)
	char *buf;
	struct tm *tm;
{
	int i;
	for (i=0; (i<12); i++) {
		if (strncmp(buf, monthnames[i], 3) == 0) {
			tm->tm_mon = i;
			break;
		}
	}
	return buf+4;
}
		
static char *parseday(buf, tm)
	char *buf;
	struct tm *tm; 
{
	tm->tm_mday = atoi(buf);
	return buf+3;
}

static char *parsetimecolon(buf, tm)
	char *buf;
	struct tm *tm; 
{
	tm->tm_hour = atoi(buf);
	tm->tm_min = atoi(buf+3);
	tm->tm_sec = atoi(buf+6);
	return buf+9;
}

static char *parsefullyear(buf, tm)
	char *buf;
	struct tm *tm;
{
	while ((*buf) != '\0') {
		char c = *buf;
		if (isdigit(c)) {
			tm->tm_year = atoi(buf) - 1900;
			return buf+4;
		}
		buf++;
	}	
	/* Bad news, but what can we do? */
	return buf;
}

int flush_to_time(item_t_gm, html, totalonly, values, week_done, weeksreturn)
	time_t item_t_gm;
	int html;
	int totalonly;
	int *values;
	int *week_done;
	int *weeksreturn;
{
	if (week_t_gm == 0) {
		/* Tick back to Sunday midnight */
		week_t_gm = 
			(item_t_gm - item_t.tm_wday * 86400 -
			item_t.tm_hour * 3600 - 
			item_t.tm_min * 60 -
			item_t.tm_sec);
	}
	while (item_t_gm - week_t_gm >= 86400*7) {
		time_t now;
		char s[MAXSTRINGLEN];
		if (totalonly) {
			*values = accesses;
			values++;
			*weeksreturn = week;
		} else {
			/* We're only called in weekly mode */
			output(1);
		}
		if (html) {
			fclose(out);
		}
		sprintf(s,
			"%s/week%d.total", 
			filepath,
			week-1);
		(*week_done) = 1;
		out = fopen(s, "w");
		if (!out) {
			fprintf(stderr,
"Can't open file-- directory probably missing: %s\n", filepath);
			exit(-1);
		}
		fprintf(out, "%d\n", accesses);
		fclose(out);
		week_t_gm += 86400*7;
		time(&now);
		if ((now - week_t_gm) < 86400*7) {
			/* Only full weeks! */
			reset();
			finish(html, 1, week_done);
			return 0;
		}
		week++;
		if (html) {
			char s[MAXSTRINGLEN];
			sprintf(s, 
			"%s/week%d.html", 
				filepath, week-1);
			out = fopen(s, "w");
			if (!out) {
				fprintf(stderr,
	"Can't open file-- directory probably missing: %s\n", filepath);
				exit(-1);
			}
		}
		reset();
	}
	return 1;
}

void copy_file(out, fname)
	FILE *out;
	char *fname;
{
	FILE *in;
	in = fopen(fname, "r");
	if (!in) {
		return;
	}
	while (!feof(in)) {
		int ch;
		ch = getc(in);
		if (ch == EOF) {
			break;
		}
		putc(ch, out);
	}
	fclose(in);
}

