/****************************************************************************** * File: wwwstat.c * Author: Jason Freund * Last Edited: 3/2/98 * Purpose: compute hit statistics of web pages, generates various reports * 1) Compile with: gcc -w -g wwwstat.c -o wwwstat -lc * 2) Build temporary interest file: * grep interest .../www/httpd/logs/access_log | grep html >! interest_log * 3) Run wwwstat on that temp file: wwwstat < interest_log >! interest_report * Note: wwwstat assumes all hits are already given in chronological order. * Therefore you cannot concatenate two greps together, otherwise, * the temp file will have two ranges of dates, not in order. *============================================================================== * void Error(char *s, int status) * int GetNextLine(FILE *fp, char *line) * void Usage() * void ParseLine(char *line, Hit *hit); * void InsertList(Hit *hit) * void UniqueUsers() * void GenerateReport() * void Popularity(Hit *docs) * void ChronoHits(Hit *docs, int numdocs) * int DocIndex(Hit *docs, char *docname,int numdocs) ******************************************************************************/ /*includes********************************************************************/ #include #include #include /*defines*********************************************************************/ #define INPUT_LINE_SIZE 200 #define TRUE 1 #define FALSE 0 #define MAXUSERS 10000 #define MAXDOCUMENTS 1000 #define MIN(x,y) (((x)<(y))?(x):(y)) #define MAX(x,y) (((x)>(y))?(x):(y)) /*types***********************************************************************/ typedef struct { char user[INPUT_LINE_SIZE]; char document[INPUT_LINE_SIZE]; int day, month, year; int numhits; } Hit; /*prototypes******************************************************************/ void Error(char *s, int status); int GetNextLine(FILE *fp, char *line); void Usage(); void ParseLine(char *line, Hit *hit); void InsertList(Hit *hit); void UniqueUsers(); int Popularity(Hit *docs); void GenerateReport(); void ChronoHits(Hit *docs, int numdocs); int DocIndex(Hit *docs, char *docname,int numdocs); /*globals*********************************************************************/ Hit HitList[MAXUSERS]; int NumHits; char months[12][5] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; int chrono=3,verbose=1; /****************************************************************************** * void Error(char *s, int status) ******************************************************************************/ void Error(char *s, int status) { fprintf(stderr,"Error: %s\n",s); if (status) exit(status); } /****************************************************************************** * void Usage() ******************************************************************************/ void Usage() { fprintf(stderr,"Usage: wwwstat \n"); fprintf(stderr,"\t[-h] [-verbose ]\n"); fprintf(stderr,"\t[-chrono ] (tally every n days)\n"); fprintf(stderr,"\t< logfile > report\n"); exit(0); } /******************************************************************************** * int GetNextLine(FILE *fp, char *line) * Reads next line of input from fp and returns it in nextline * Returns TRUE if it found a NON-EMPTY line * Returns FALSE if it could not find a NON-EMPTY file or it reached EOF. *******************************************************************************/ int GetNextLine(FILE *fp, char *line) { int i,c; for (i=0;i1) fprintf(stderr,"Parsing Line= %s.\n",line); for (i=0;iuser[i]=0; hit->document[i]=0; } hit->day = hit->month = hit->year = hit->numhits=0; /* parse out user address */ for (i=0;iuser,line,i-1); /* parse out day of month */ daystr[0]=line[i+5]; daystr[1]=line[i+6]; hit->day = atoi(daystr); /* parse out month */ monthstr[0] = line[i+8]; monthstr[1] = line[i+9]; monthstr[2] = line[i+10]; for (k=0;k<12;k++) if (strcmp(monthstr,months[k])==0) break; hit->month = k+1; /* parse out year */ yearstr[0] = line[i+12]; yearstr[1] = line[i+13]; yearstr[2] = line[i+14]; yearstr[3] = line[i+15]; hit->year = atoi(yearstr); /* Parse out document */ for (i=0;idocument[index++]=line[i++]; hit->numhits=0; /* Report -- for debugging only */ /* fprintf(stderr,"Parsing line: %s.\n",line); fprintf(stderr,"User=%s, %d/%d/%d, doc=%s.\n",hit->user, hit->day, hit->month,hit->year, hit->document); fprintf(stderr,"----------------------------------------------\n"); */ } /****************************************************************************** * void InsertList(char *user, Hit *hit) ******************************************************************************/ void InsertList(Hit *hit) { int i; strcpy(HitList[NumHits].user,hit->user); strcpy(HitList[NumHits].document,hit->document); HitList[NumHits].day = hit->day; HitList[NumHits].month = hit->month; HitList[NumHits].year = hit->year; HitList[NumHits].numhits = hit->numhits; NumHits++; if (NumHits>MAXUSERS-2) Error("Too many users",1); } /****************************************************************************** * void UniqueUsers() ******************************************************************************/ void UniqueUsers() { int unique,hits,i,k,j,seenthisone,numusers=0; char temp2[INPUT_LINE_SIZE],temp[INPUT_LINE_SIZE],user[INPUT_LINE_SIZE]; Hit tempuser,users[MAXUSERS]; /* Init stuff */ for (i=0;i=0;k--) { strcpy(temp2,HitList[k].user); if (strcmp(temp2,user)==0) seenthisone=TRUE; } /* Have not seen this user, compute total hits from him. */ if (!seenthisone) { hits=1; for (j=i+1;j=0;k--) { strcpy(temp2,HitList[k].document); if (strcmp(temp2,document)==0) seenthisone=TRUE; } /* Have not seen this document, compute total hits for it. */ if (!seenthisone) { strcpy(docs[numdocs].document,document); hits=1; for (j=i+1;jMAXDOCUMENTS) Error("Too many documents",1); total+=hits; } } /* List docs in structure in order of #hits */ for (i=0;i-1 && index0 && modprint%chrono==0) { buff[0]=0; if (lastmonth<10) sprintf(buff," 0%d/",lastmonth); else sprintf(buff," %d/",lastmonth); if (lastday<10) sprintf(temp,"0%d/%d: ",lastday,lastyear); else sprintf(temp,"%d/%d: ",lastday,lastyear); strcat(buff,temp); for (j=0;j1 && strcmp(argv[1],"-h")==0) Usage(); for (i=1;i