home *** CD-ROM | disk | FTP | other *** search
- /*** glog35.c -- analysis tool for Unix gopherd logs ***/
- /******************** START CONFIGURATION ***************************/
-
- /* Define NODETAIL if you don't want detail listings to be kept. Detail
- * listings can double the pointer memory required and slow things down.
- */
-
- /* #define NODETAIL */ /* uncomment if you DON'T want detail listings */
- /* #define DETAIL_TOTAL*/ /* uncomment if you WANT detail percentages to
- be out out the total number of connections */
- /* #define NOSEARCHTXT */ /* uncomment if you DON'T want to output WHAT */
- /* was searched for */
- /* #define HCASEMATTERS */ /* uncomment if case matters for hostnames */
-
- #define MAXGLINESIZE 500 /* Maximum length of a gopher log line */
- /******************** END CONFIGURATION ***************************/
- /* That was really hard wasn't it :) */
-
- /* Bug Reports/suggestions goto */
- #define EMAIL "awick@csugrad.cs.vt.edu"
-
- #define GLOG_VERSION "Gopher Log Analyzer 3.5"
-
- /* Version 3.5 ?/?/94 awick
- * Added Domain Reports
- * Added -s? sort of reports and histograms, not plots though
- * Changed some shorts to ints
- * Lowers the case of all hostnames now, unless above uncommented
- * Only keep track of reports need, saves memory and time.
- * Increased speed of adding data (special InsertDates now)
- *
- * Version 3.4 4/4/94 awick
- * Improved coding efficiency in ProcessLine() routine
- * Fixed bug when identifying NOPASV ftp types (previously they went
- * into the error log). If you use the NOPASV patch, you know what I mean.
- * Search Type now shows what word(s) was(were) searched for...UNLESS
- * NOSEARCHTXT defined
- * Cleaned up the code alot, and changed the way reports are produced
- * Added the -g histograms option
- * Added the -a averaging/estimating stuff
- * Added the -i infile support
- * Added the -o outfile support
- * Added support for VMS dennis_sherman@unc.edu
- *
- * Version 3.3 7/20/93 jdc@selway.umt.edu
- * fixed up main() routine so that: errors on the command line (or -h as
- * first parameter) cause glog to print the help information and abort.
- * fixed up PrintHelp() routine so help message is more understandable
- * changed FILETYPE character from ' ' to 'I' (What about Image?)
- *
- * Version 3.2
- * Fixed a small bug with search
- *
- * Version 3.1 7/11/93 Andy Wick - awick@csugrad.cs.vt.edu
- * Added supported for the "missing" gopher types, time plots, month
- * reports and several other things that I forgot :)
- * Also added -b and -e options.
- *
- * Version 3.0
- * by: Andy Wick - awick@csugrad.cs.vt.edu
- * This version is an almost TOTAL rewrite of glog. It now reads all
- * the information into memory before it does ANYTHING. It then goes
- * through the arguments one at a time. So in order to effect something
- * you must change it before the report. ie. Argument order matters now.
- *
- * Version 2.2
- * by: Chuck Shotton - cshotton@oac.hsc.uth.tmc.edu
- *
- * Version 2.1 12/29.92
- * by: Michael Mealling - Georgia Institute of Technology
- * Office of Information Technology
- * michael.meallingl@oit.gatech.edu
- *
- * Versions 1.0 6/17/92
- * by: Chuck Shotton - U of Texas Health Science Center - Houston,
- * Office of Academic Computing
- * cshotton@oac.hsc.uth.tmc.edu
- */
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- /* Some machines don't have a stdlib. You can remove it if need be
- * it is here for type checking, usually :)
- */
- #include <stdlib.h>
- #ifdef THINK_C
- #include <console.h>
- #endif
-
- /********************** THINGS THAT EFFECT INPUT/OUTPUT ********************/
-
- /* These are the different types of data that are currently reconized.
- Each must be unique and it only effects the output. */
- #define FILETYPE 'I'
- #define BINARYTYPE 'B'
- #define SOUNDTYPE 'S'
- #define DIRTYPE 'D'
- #define MAILDIRTYPE 'M'
- #define FTPTYPE 'F'
- #define RANGETYPE 'R'
- #define SEARCHTYPE '?'
-
- char *ROOTNAME = "Root Connections";
- char *AverageStrs[6] = {""," per year"," per month"," per week"," per day",
- " per hour"};
-
- /* How they are in your gopher log file */
- char Days[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
- char Months[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
- /* The base file name for gnuplot reports */
- char DEFAULTBASE[7] = "gopher";
- /**********************************************************************/
-
- /* GENERAL STUFF */
- typedef unsigned char byte;
-
- /* Error log link list */
- typedef struct enode_list {
- char *data;
- struct enode_list *next;
- } ELIST_REC, *ELIST_PTR;
-
- /* GOPHER LINE STUFF */
-
- /* One line of the gopher log is stored in here */
- typedef struct gopher_line {
- byte day;
- byte month;
- byte hour;
- byte date;
- char *hostname;
- char *domainname;
- char *path;
- char type;
- } GOPHER_REC, *GOPHER_PTR;
-
- /* A Linked list of gopher lines */
- typedef struct node_list {
- GOPHER_PTR data;
- long int hits;
- struct node_list *next;
- } LIST_REC, *LIST_PTR;
-
- /* Main tree */
- typedef struct node_rec {
- GOPHER_PTR data;
- #ifndef NODETAIL
- LIST_REC *llist;
- #endif
- long int hits;
- struct node_rec *left, *right;
- } NODE_REC, *NODE_PTR;
-
- /* The cruft list is a general list for things that aren't parse-able by
- * ProcessLine(). "cruft" kept for historical reasons.
- */
- ELIST_PTR cruft = NULL;
-
- /*
- * The following lists are maintained.
- */
- NODE_PTR hosts = NULL;
- NODE_PTR docs = NULL;
- NODE_PTR dais = NULL; /* Can't be days because of VMS :) */
- NODE_PTR dates = NULL;
- NODE_PTR types = NULL;
- NODE_PTR hours = NULL;
- NODE_PTR domains = NULL;
-
- long int TotalConnects = 0;
-
- char *in_file_name = NULL; /* NULL if stdin */
-
- /* Used to tell the Info routines that you are starting and stoping */
- #define STARTINFO (GOPHER_PTR)0
- #define ENDINFO (GOPHER_PTR)1
-
- /* Width of reports, Width is a major hack, so be careful */
- int Width = 62; /* 79 - WIDTHSUB */
- #define WIDTHSUB 17 /* The width of the standard print stuff */
-
- /* Information */
- /* Internal */
- #define NOINFO 0
- #define DETAILINFO 1
- /* Changing these will change the command line options also */
- /* Error log requested, but not a valid SORT TYPE */
- #define ERRORINFO 'E'
- /* SORT TYPES */
- #define DATAINFO 'D'
- #define HOSTINFO 'H'
- #define WEEKDAYINFO 'W'
- #define MONTHDATEINFO 'M'
- #define TYPEINFO 'T'
- #define TIMEINFO 'I'
- #define DOMAININFO 'O'
-
- byte do_D=0,do_H=0, do_W=0, do_T=0, do_I=0, do_O=0;
-
- char *base = DEFAULTBASE;
-
- /* Start stop dates */
- char start_date[13], stop_date[13];
-
- /* Start stop months */
- byte mbegin = 1, mend = 12;
-
- /* Averages */
- byte AverageStrPos = 0; /* Everything */
- float AverageDiv = 1.0; /* Don't change the value */
-
- /* Sorting */
-
- int SortMult = 1; /*Forward Sort, -1 = Reverse Sort */
- byte SortHits = 1; /*Sort by Hits = 1, Names = 0 */
-
- /* The only forward decleration needed, since I wrote this the pascal way,
- * the way all programs should be written. :) You don't need all the stupid
- * forward declerations, or prototypes.
- */
- void PrintInfo(NODE_PTR tree, void print(GOPHER_PTR), int cmp(GOPHER_PTR a, GOPHER_PTR b), byte DetailType);
-
- /* Simple define that cleans up the code a little */
- #define INFOERROR(str, strparam) {fprintf(stderr, (str), (strparam)); exit(1);}
- #define EXITERROR(str) {fprintf(stderr, (str)); fflush(stderr); exit(1);}
- #define HELPERROR(str) {fprintf(stderr, (str)); PrintHelp(stderr,0);}
-
- #ifndef MIN
- #define MIN(a,b) ((a)<(b)?(a):(b))
- #endif
- /*******************************/
- /* My StrStr, since it is not standard on all unix machines (sun 4.0.3) */
- char *mystrstr(char *s1, char *s2)
- {
- register int len;
-
- if((len = strlen(s2)) == 0)
- return s1;
-
- while (*s1 != '\0')
- {
- if (strncmp(s1, s2, len) == 0)
- return s1;
- s1++;
- }
-
- return NULL;
- }
- /*******************************/
- void mytolower(char *s)
- {
- for(; *s != 0;s++)
- if (isupper(*s))
- *s += 32;
- }
- /*******************************/
- /* Add item to error log */
- ELIST_PTR InsertErrorLog(ELIST_PTR list, char *data)
- {
- ELIST_PTR temp;
- static ELIST_PTR ende;
-
- if (NULL == (temp = (ELIST_PTR)malloc(sizeof(ELIST_REC))))
- EXITERROR("Not enough memory to add to ErrorLog\n");
- if (NULL == (temp->data = (char *)malloc(sizeof(char) * (strlen(data) +1))))
- EXITERROR("Not enough memory to add to ErrorLog\n");
-
- strcpy(temp->data, data);
- temp->next = NULL;
-
- if (list == NULL)
- return (ende = temp);
-
- ende->next = temp;
- ende = ende->next;
-
- return(list);
- }
- #ifndef NODETAIL
- /*******************************/
- LIST_PTR InsertDetail(LIST_PTR list, GOPHER_PTR data)
- {
- LIST_PTR temp;
-
- if (NULL == (temp = (LIST_PTR)malloc(sizeof(LIST_REC))))
- EXITERROR("Not enough memory to add to DetailList\n");
- temp->data = data;
- temp->next = list;
- temp->hits = 1;
- return(temp);
- }
- #endif
- /*******************************/
- /* Insert data into tree, if that element is already in the tree
- * then increment the number of hits. cmp is used to find the location
- * in the tree.
- */
-
- NODE_PTR Insert(NODE_PTR tree, GOPHER_PTR data, int cmp(GOPHER_PTR a, GOPHER_PTR b))
- {
- int i;
-
- if (tree == NULL)
- {
- if (NULL == (tree = (NODE_PTR) malloc(sizeof(NODE_REC))))
- EXITERROR("No memory for InsertHost\n");
- tree->data = data;
- tree->left = tree->right = NULL;
- #ifndef NODETAIL
- tree->llist = InsertDetail(NULL, data);
- #endif
- tree->hits = 1;
- return(tree);
- }
-
- i=cmp(data, tree->data);
-
- if (i > 0)
- tree->right = Insert(tree->right, data, cmp);
- else if (i<0)
- tree->left = Insert(tree->left, data, cmp);
- else
- {
- tree->hits++;
- #ifndef NODETAIL
- tree->llist = InsertDetail(tree->llist, data);
- #endif
- }
-
- return(tree);
- }
- /*******************************/
- /* Insert dates into tree, if that element is already in the tree
- * then increment the number of hits. cmp is used to find the location
- * in the tree.
- */
-
- NODE_PTR InsertDates(NODE_PTR tree, GOPHER_PTR data, int cmp(GOPHER_PTR a, GOPHER_PTR b))
- {
- int i;
- static NODE_PTR last;
- NODE_PTR temp;
-
- if (tree == NULL)
- {
- if (NULL == (tree = (NODE_PTR) malloc(sizeof(NODE_REC))))
- EXITERROR("No memory for InsertHost\n");
- tree->data = data;
- tree->left = tree->right = NULL;
- #ifndef NODETAIL
- tree->llist = InsertDetail(NULL, data);
- #endif
- tree->hits = 1;
- return(last = tree);
- }
-
- i=cmp(data, last->data);
-
- if (i == 0)
- {
- last->hits++;
- #ifndef NODETAIL
- last->llist = InsertDetail(last->llist, data);
- #endif
- }
- else
- {
- temp = last; /* because last is going to be reset */
- temp->right = InsertDates(last->right, data, cmp);
- }
-
- return(tree);
- }
- /*******************************/
- /* Return the node with the data in the tree, using the cmp routine */
- NODE_PTR Find(NODE_PTR tree, GOPHER_PTR data, int cmp(GOPHER_PTR a, GOPHER_PTR b))
- {
- int i;
-
- if (tree == NULL)
- return (NULL);
-
- i=cmp(data, tree->data);
-
- if (i > 0)
- return(Find(tree->right, data, cmp));
- if (i<0)
- return(Find(tree->left, data, cmp));
-
- return(tree);
- }
- /*******************************/
- /* Get a single field from temp, and return the new spot */
- char *getf(char *temp, char *field)
- {
- while(*temp == ' ')
- temp++;
-
- *field = '\0';
- if (*temp == '\n')
- return(temp);
-
- while ((*temp != ' ') && (*temp != '\0'))
- *field++ = *temp++;
-
- *field = '\0';
- return(temp);
- }
- /*******************************/
- int TypesCmp(GOPHER_PTR a, GOPHER_PTR b)
- {
- return(a->type - b->type);
- }
- /*******************************/
- int TimesCmp(GOPHER_PTR a, GOPHER_PTR b)
- {
- return(a->hour - b->hour);
- }
- /*******************************/
- int HostsCmp(GOPHER_PTR a, GOPHER_PTR b)
- {
- return(strcmp(a->hostname, b->hostname));
- }
- /*******************************/
- int DocsCmp(GOPHER_PTR a, GOPHER_PTR b)
- {
- return(strcmp(a->path, b->path));
- }
- /*******************************/
- int DaysCmp(GOPHER_PTR a, GOPHER_PTR b)
- {
- return(a->day - b->day);
- }
- /*******************************/
- int DatesCmp(GOPHER_PTR a, GOPHER_PTR b)
- {
- int i = a->month - b->month;
- if (i == 0)
- return(a->date - b->date);
- else
- return(i);
- }
- /*******************************/
- int DomainCmp(GOPHER_PTR a, GOPHER_PTR b)
- {
- return(strcmp(a->domainname, b->domainname));
- }
- /*******************************/
- byte MonthStr2Num(char *str)
- {
- static int i = 0;
-
- if (strcmp(Months[i], str) == 0)
- return(i+1);
-
- for(i=0;i<12;i++)
- if (strcmp(Months[i], str) == 0)
- return(i+1);
- return(13);
- }
- /*******************************/
- byte DayStr2Num(char *str)
- {
- static int i = 0;
-
- if (strcmp(Days[i], str) == 0)
- return(i+1);
-
- for(i=0;i<7;i++)
- if (strcmp(Days[i], str) == 0)
- return(i+1);
- return(8);
- }
- /*******************************/
- /* This routine adds all the data to all the trees. Now that I have done
- * it this way, I really hate it. What was I thinking? :) It makes no
- * sense to have the dates sort be a tree, since it is always the worst
- * case tree :(. Oh well maybe in 4.0 someone will fix it
- */
- void AddData(GOPHER_PTR data)
- {
- if ((data->month >= mbegin) && (data->month <= mend))
- {
- if (do_H)
- hosts = Insert(hosts, data, HostsCmp);
- if (do_D)
- docs = Insert(docs, data, DocsCmp);
- dates = InsertDates(dates, data, DatesCmp); /* Always do dates */
- if (do_T)
- types = Insert(types, data, TypesCmp);
- if (do_I)
- hours = Insert(hours, data, TimesCmp);
- if (do_W)
- dais = Insert(dais, data, DaysCmp);
- if (do_O)
- domains = Insert(domains, data, DomainCmp);
- /* Small hack to have start and stop dates */
- if (start_date[0] == '\0')
- {
- sprintf(start_date, "%s %s %d", Days[data->day-1], Months[data->month-1],
- data->date);
- }
- sprintf(stop_date, "%s %s %d", Days[data->day-1], Months[data->month-1],
- data->date);
- TotalConnects++;
- }
- }
-
- /*******************************/
- /* What is a more efficent, but CLEAN (non hack) way to do this? */
- void MakeDomain(char *hostname, char *domainname)
- {
- char *temp = strchr(hostname, '.');
-
- if (temp != NULL)
- {
- MakeDomain(temp+1, domainname);
- *temp = 0;
- strcat(domainname, ".");
- strcat(domainname, hostname);
- *temp = '.';
- }
- else
- strcpy(domainname, hostname);
- }
- /*******************************/
- /* Process a single line completely. It checks to make sure it is a
- * Valid line, if not it inserts it into the cruft
- */
- void ProcessLine(char *line)
- {
- GOPHER_PTR data;
- short len;
- char *temp, *temp2; /* Used to save line, incase it is needed for cruft */
- char junk[MAXGLINESIZE];
- char message1[MAXGLINESIZE];
- char message2[MAXGLINESIZE];
-
- if (NULL == (data = (GOPHER_PTR)malloc(sizeof(GOPHER_REC))))
- EXITERROR("Not enough memory to process line. Sorry\n");
-
- temp = line;
-
- temp = getf(temp, junk); /* Day */
- if (8 == (data->day = DayStr2Num(junk)))
- { /* Not a real day of week */
- free(data);
- cruft = InsertErrorLog(cruft, line);
- return;
- }
- temp = getf(temp, junk); /* Month */
- if (13 == (data->month = MonthStr2Num(junk)))
- { /* Not a real month */
- free(data);
- cruft = InsertErrorLog(cruft, line);
- return;
- }
- temp = getf(temp, junk); /* Date */
- data->date = atoi(junk);
- temp = getf(temp, junk); /* Time */
- junk[3] = '\0';
- data->hour = atoi(junk); /* Hour */
- temp = getf(temp, junk); /* Year */
- temp = getf(temp, junk); /* Process ID */
- temp = getf(temp ,junk); /* Hostname */
- if (junk[0] == ':')
- { /* A colon in the hostfield...baaad */
- free(data);
- cruft = InsertErrorLog(cruft, line);
- return;
- }
-
- /* This one is for that annoying 0.0.0.* IP address then gets stuck
- * in the log when someone is trying to access something you ain't got
- */
- if (strncmp(junk,"0.0.0", 5) == 0)
- {
- free(data);
- cruft = InsertErrorLog(cruft, line);
- return;
- }
-
- len = strlen(junk);
- if (NULL == (data->hostname = (char *)malloc(sizeof(char) * (len+1))))
- EXITERROR("Not enough memory. Sorry\n");
- if (NULL == (data->domainname = (char *)malloc(sizeof(char) * (len+1))))
- EXITERROR("Not enough memory. Sorry\n");
- #ifndef HCASEMATTERS
- mytolower(junk); /* Only change to all lower if wanted that way */
- #endif
- strcpy(data->hostname, junk);
-
- /* Figure out Domain stuff */
- if (isdigit(junk[0]))
- {
- strcpy(data->domainname, data->hostname);
- temp2 = strrchr(data->domainname,'.');
- *temp2 = 0;
- }
- else if (NULL == (temp2 = strchr(junk,'.')))
- strcpy(data->domainname, data->hostname);
- else
- MakeDomain(temp2+1, data->domainname);
-
- temp = getf(temp, junk); /* this should make junk[0]=':' */
- if (junk[0] != ':')
- { /* Now we don't have a colon */
- free(data->hostname);
- free(data->domainname);
- free(data);
- cruft = InsertErrorLog(cruft, line);
- return;
- }
-
- temp = getf(temp, message1);
- temp = getf(temp, message2);
- while((*temp == ' ') && (*temp != '\0'))
- temp++;
-
- len = strlen(temp);
- data->path = (char *)malloc(sizeof(char)*(len+1));
- strcpy(data->path, temp);
- data->path[len] = '\0';
-
- if (0 != len)
- {
- if (data->path[len-1] == '\n')
- data->path[len-1] = '\0';
- }
-
- if (strcmp(message1, "Root") == 0)
- {
- data->type = DIRTYPE;
- free(data->path);
- data->path = ROOTNAME;
- AddData(data);
- }
- else if ((strcmp(message1, "retrieved") == 0) && (strcmp(data->path, "/") == 0))
- {
- data->type = DIRTYPE;
- free(data->path);
- data->path = ROOTNAME;
- AddData(data);
- }
- else if (strcmp(message1, "search") == 0)
- {
- strcpy(junk, message2);
- #ifdef NOSEARCHTXT
- /*This finds and removes everything after the " for " in a search line*/
- if (strncmp(data->path, "for ", 4) == 0)
- {
- /* We found it at the beginning of data->path */
- temp = data->path;
- }
- else if (NULL == (temp = mystrstr(data->path, " for ")))
- { /* No " for " in the search */
- free(data->path);
- free(data->hostname);
- free(data->domainname);
- free(data);
- cruft = InsertErrorLog(cruft, line);
- return;
- }
- *temp = '\0';
- #endif
- strcat(junk, " "); /* There is at least one space here */
- strcat(junk, data->path);
- free(data->path);
- data->path = (char *)malloc(sizeof(char)*(strlen(junk)+1));
- strcpy(data->path, junk);
- data->type = SEARCHTYPE;
-
- AddData(data);
- }
- /* changed from "ftp:",4 to "ftp",3 because of NO-PASV patch */
- /* which uses ftp-vms: and ftp-nopasv to denote special ftp types */
- else if (strncmp(message2, "ftp", 3) == 0)
- {
- strcpy(junk, data->path); /* Incase there was a space in the path */
- free(data->path); /* Then we have to save off path, since it contains it*/
- data->path = (char *)malloc(sizeof(char)*(strlen(message2)+strlen(junk)-2));
- strcpy(data->path, message2+4);
- if (strlen(junk) > 0)
- {
- strcat(data->path, " ");
- strcat(data->path, junk);
- }
- data->type = FTPTYPE;
-
- AddData(data);
- }
- else if (strcmp(message1, "retrieved") == 0)
- {
- if (data->path[0] == '\0')
- { /* We some how retrieved nothing */
- free(data->path);
- free(data->hostname);
- free(data->domainname);
- free(data);
- cruft = InsertErrorLog(cruft, line);
- return;
- }
-
- if (strcmp(message2, "directory") == 0)
- data->type = DIRTYPE;
- else if (strcmp(message2, "maildir") == 0)
- data->type = MAILDIRTYPE;
- else if (strcmp(message2, "file") == 0)
- data->type = FILETYPE;
- else if (strcmp(message2, "binary") == 0)
- data->type = BINARYTYPE;
- else if (strcmp(message2, "sound") == 0)
- data->type = SOUNDTYPE;
- else if (strcmp(message2, "range") == 0)
- data->type = RANGETYPE;
- else
- {
- free(data->path);
- free(data->hostname);
- free(data->domainname);
- free(data);
- cruft = InsertErrorLog(cruft, line);
- return;
- }
- AddData(data);
-
- }
- else /* wasn't anything we know about, g+ maybe?*/
- {
- free(data->path);
- free(data->hostname);
- free(data->domainname);
- free(data);
- cruft = InsertErrorLog(cruft, line);
- return;
- }
-
- return;
- }
-
- /*******************************/
- /* The main loop for gathering the data from stdin */
- void GatherInfo(void)
- {
- char line[MAXGLINESIZE];
- FILE *fp;
-
- start_date[0] = '\0';
-
- if (in_file_name == NULL)
- fp = stdin;
- else if (NULL == (fp = fopen(in_file_name, "r")))
- INFOERROR("Error opening input file %s\n", in_file_name);
- while(!feof(fp))
- {
- fgets(line, MAXGLINESIZE, fp);
- if (feof(fp))
- break;
- ProcessLine(line);
- }
- }
- /*******************************/
- /* These vars are only valid right after a call to TreeTo?List. I could have
- * done some fancy var passing, but why bother. :) All the print/plot/graph
- * routines should use the G vars. Which are modified for averages.
- */
- LIST_PTR GByNum;
- long int GByNumMin; /* These two are used for histograms */
- long int GByNumMax;
- long int GNodes;
- long int GTotalConnects;
-
- /*******************************/
- /* Insert the data and number of hits that data got, into a sorted (by hits)
- * link list (GByNum).
- */
- void InsertSByNum(GOPHER_PTR data, long int hits)
- {
- LIST_PTR temp, temp2;
-
- if (NULL == (temp = (LIST_PTR)malloc(sizeof(LIST_REC))))
- EXITERROR("Not enough memory in InsertByNum\n");
- temp->data = data;
- temp->next = NULL;
- temp->hits = hits;
-
- /* Figure out some vars */
- if (hits < GByNumMin)
- GByNumMin = hits;
- if (hits > GByNumMax)
- GByNumMax = hits;
- GNodes++;
-
- if (GByNum == NULL)
- GByNum = temp;
- else if ((GByNum->hits-hits)*SortMult < 0)
- {
- temp->next = GByNum;
- GByNum = temp;
- }
- else
- {
- temp2 = GByNum;
- while (temp2->next != NULL)
- {
- if ((temp2->next->hits-hits)*SortMult < 0)
- {
- temp->next = temp2->next;
- temp2->next = temp;
- return;
- }
- temp2 = temp2->next;
- }
- temp2->next = temp;
- }
- }
-
- /*******************************/
- /* Place data and hits onto the front of the list GByNum */
- void InsertUByNum(GOPHER_PTR data, long int hits)
- {
- LIST_PTR temp;
-
- if (NULL == (temp = (LIST_PTR)malloc(sizeof(LIST_REC))))
- EXITERROR("Not enough memory in InsertUByNum\n");
- temp->data = data;
- temp->next = NULL;
- temp->hits = hits;
-
- /* Figure out some vars */
- if (hits < GByNumMin)
- GByNumMin = hits;
- if (hits > GByNumMax)
- GByNumMax = hits;
- GNodes++;
-
- if (GByNum == NULL)
- GByNum = temp;
- else
- {
- temp->next = GByNum;
- GByNum = temp;
- }
- }
- /*******************************/
- /* I did two different routines so it would be faster :). I know this
- * doesn't follow the logic of the rest of the program, but oh well.
- * Do Inorder so that they remain in order, if two have the same
- * num of hits. S<orted> mean use InsertSByNum. U<nsorted> means use
- * InsertUByNum.
- */
- void TreeToSList(NODE_PTR tree)
- {
- if (tree == NULL)
- return;
-
- TreeToSList(tree->left);
- InsertSByNum(tree->data, tree->hits);
- TreeToSList(tree->right);
- }
-
- /*******************************/
- /* See above :) */
- void TreeToUList(NODE_PTR tree)
- {
- if (tree == NULL)
- return;
-
- TreeToUList(tree->right);
- InsertUByNum(tree->data, tree->hits);
- TreeToUList(tree->left);
- }
- /*******************************/
- /* See above :) R = Reverse */
- void TreeToRUList(NODE_PTR tree)
- {
- if (tree == NULL)
- return;
-
- TreeToRUList(tree->left);
- InsertUByNum(tree->data, tree->hits);
- TreeToRUList(tree->right);
- }
-
- /*******************************/
- NODE_PTR ListToTree(LIST_PTR list, int cmp(GOPHER_PTR, GOPHER_PTR))
- {
- NODE_PTR temptree = NULL;
- for(;list != NULL; list = list->next)
- temptree = Insert(temptree, list->data, cmp);
- return(temptree);
- }
- /*******************************/
- void FreeList(LIST_PTR list)
- {
- LIST_PTR temp;
- while (list != NULL)
- {
- temp = list;
- list = list->next;
- free(temp);
- }
- }
- /*******************************/
- void FreeTree(NODE_PTR tree)
- {
- if (tree == NULL)
- return;
- FreeTree(tree->left);
- FreeTree(tree->right);
- #ifndef NODETAIL
- FreeList(tree->llist);
- #endif
- free(tree);
- return;
- }
- /*******************************/
- int SizeTree(NODE_PTR tree)
- {
- if (tree == NULL)
- return 0;
- return (1 + SizeTree(tree->left) + SizeTree(tree->right));
- }
- /*******************************/
- /* Given a string and and len, left justify and fill with fill */
- void printl(char *str, int len, char fill)
- {
- while (len > 0)
- {
- if (*str == '\n')
- str++;
- if (*str == '\0')
- putc(fill, stdout);
- else
- putc(*str++, stdout);
- len--;
- }
- }
- /*******************************/
- /* Given a string center justify and fill with fill */
- void printc(char *str, char fill)
- {
- int i, len = strlen(str);
- int start = (Width + WIDTHSUB - len)/2;
-
- for(i = 0; i < start; i++)
- putc(fill, stdout);
-
- fputs(str, stdout);
-
- if (fill != ' ')
- for(i = start+len; i < Width + WIDTHSUB ; i++)
- putc(fill, stdout);
- putc('\n', stdout);
- }
- /*******************************/
- char *TypeNames(char type)
- {
- switch(type)
- {
- case FILETYPE:
- return("File");
- case SOUNDTYPE:
- return("Sound");
- case BINARYTYPE:
- return("Binary File");
- case DIRTYPE:
- return("Directory");
- case MAILDIRTYPE:
- return("Mail Directory");
- case FTPTYPE:
- return("FTP");
- case RANGETYPE:
- return("Range");
- case SEARCHTYPE:
- return("Search");
- }
- return("Unknown");
- }
- /*******************************/
- void PrintData(GOPHER_PTR data)
- {
- if (data == STARTINFO)
- printf("Data access%s:\n", AverageStrs[AverageStrPos]);
- else if (data == ENDINFO)
- printf("%ld nodes accessed. Average of %ld connections per node.\n",
- GNodes, GTotalConnects/GNodes);
- else
- {
- printf("%c ",data->type);
- printl(data->path, Width - 2, ' ');
- }
- }
- /*******************************/
- void PrintTime(GOPHER_PTR data)
- {
- if (data == STARTINFO)
- printf("Times%s:\n", AverageStrs[AverageStrPos]);
- else if (data == ENDINFO)
- printf("Average of %ld connections per hour.\n",
- GTotalConnects/GNodes);
- else
- {
- printf("%2d:00",data->hour);
- printl("", Width - 5, ' ');
- }
- }
- /*******************************/
- void PrintType(GOPHER_PTR data)
- {
- if (data == STARTINFO)
- printf("Types%s:\n", AverageStrs[AverageStrPos]);
- else if (data == ENDINFO)
- printf("Average of %ld connections per type.\n",
- GTotalConnects/GNodes);
- else
- printl(TypeNames(data->type), Width, ' ');
- }
- /*******************************/
- void PrintHost(GOPHER_PTR data)
- {
- if (data == STARTINFO)
- printf("Hosts%s:\n", AverageStrs[AverageStrPos]);
- else if (data == ENDINFO)
- printf("%ld hosts connected. Average of %ld connections per host.\n",
- GNodes, GTotalConnects/GNodes);
- else
- printl(data->hostname, Width, ' ');
-
- }
- /*******************************/
- void PrintDomain(GOPHER_PTR data)
- {
- if (data == STARTINFO)
- printf("Domains%s:\n", AverageStrs[AverageStrPos]);
- else if (data == ENDINFO)
- printf("%ld domains connected. Average of %ld connections per domain.\n",
- GNodes, GTotalConnects/GNodes);
- else
- printl(data->domainname, Width, ' ');
-
- }
- /*******************************/
- void PrintDay(GOPHER_PTR data)
- {
- if (data == STARTINFO)
- printf("Days%s:\n", AverageStrs[AverageStrPos]);
- else if (data == ENDINFO)
- printf("Average of %ld connections per day of week.\n",
- GTotalConnects/GNodes);
- else
- printl(Days[data->day-1], Width, ' ');
- }
- /*******************************/
- void PrintDate(GOPHER_PTR data)
- {
- if (data == STARTINFO)
- printf("Dates %s:\n", AverageStrs[AverageStrPos]);
- else if (data == ENDINFO)
- {
- printf("Connections occured on %ld different days.\n", GNodes);
- printf("Average of %ld connections per day.\n", GTotalConnects/GNodes);
- }
- else
- {
-
- printf("%3s %3s %d", Days[data->day-1], Months[data->month-1], data->date);
- if (data->date < 10)
- printl("\0", Width - 9, ' ');
- else
- printl("\0", Width - 10, ' ');
- }
- }
- /*******************************/
- void PlotData(FILE *rfp, long int num, GOPHER_PTR data)
- {
- if (data == STARTINFO)
- INFOERROR("Plot of Data is not currently supported. Mail me ideas: %s\n", EMAIL);
- }
- /*******************************/
- void PlotType(FILE *rfp, long int num, GOPHER_PTR data)
- {
- char *temp = NULL;
- if (data == STARTINFO)
- {
- fprintf(rfp,"set xtics (");
- }
- else if (data == ENDINFO)
- {
- fprintf(rfp,"\"\" %ld)\n", num);
- fprintf(rfp,"set data style linespoints\n");
- fprintf(rfp,"set tics out\n");
- fprintf(rfp,"set grid\n");
- fprintf(rfp,"set title \"Gopher Usage\"\n");
- fprintf(rfp,"plot \"%s.dat\"\n", base);
- }
- else
- {
- temp = TypeNames(data->type);
- fprintf(rfp,"\"%s\" %ld,", temp, num);
- }
-
- }
- /*******************************/
- void PlotHost(FILE *rfp, long int num, GOPHER_PTR data)
- {
- if (data == STARTINFO)
- INFOERROR("Plot of Hosts is not currently supported. Mail me ideas: %s\n", EMAIL);
- }
- /*******************************/
- void PlotDay(FILE *rfp, long int num, GOPHER_PTR data)
- {
- if (data == STARTINFO)
- {
- fprintf(rfp,"set xtics (");
- }
- else if (data == ENDINFO)
- {
- fprintf(rfp,"\"\" %ld)\n", num);
- fprintf(rfp,"set data style linespoints\n");
- fprintf(rfp,"set tics out\n");
- fprintf(rfp,"set grid\n");
- fprintf(rfp,"set title \"Gopher Usage\"\n");
- fprintf(rfp,"plot \"%s.dat\"\n", base);
- }
- else
- {
- fprintf(rfp,"\"%s\" %ld,",Days[data->day-1], num);
- }
- }
- /*******************************/
- void PlotTime(FILE *rfp, long int num, GOPHER_PTR data)
- {
- if (data == STARTINFO)
- {
- fprintf(rfp,"set xtics (");
- }
- else if (data == ENDINFO)
- {
- fprintf(rfp,"\"\" %ld)\n", num);
- fprintf(rfp,"set data style linespoints\n");
- fprintf(rfp,"set tics out\n");
- fprintf(rfp,"set grid\n");
- fprintf(rfp,"set title \"Gopher Usage\"\n");
- fprintf(rfp,"plot \"%s.dat\"\n", base);
- }
- else
- {
- fprintf(rfp,"\"%2d\" %ld,",data->hour, num);
- }
- }
- /*******************************/
- void PlotDate(FILE *rfp, long int num, GOPHER_PTR data)
- {
- if (data == STARTINFO)
- {
- fprintf(rfp,"set xtics (");
- }
- else if (data == ENDINFO)
- {
- fprintf(rfp,"\"\" %ld)\n", num);
- fprintf(rfp,"set data style linespoints\n");
- fprintf(rfp,"set tics out\n");
- fprintf(rfp,"set grid\n");
- fprintf(rfp,"set title \"Gopher Usage\"\n");
- fprintf(rfp,"plot \"%s.dat\"\n", base);
- }
- else
- {
- if ((data->date == 1) || (data->date == 15) || (num == 1))
- fprintf(rfp,"\"%s/%d\" %ld,",Months[data->month-1], data->date, num);
- }
- }
- #ifndef NODETAIL
- /*******************************/
- void DoDetail(NODE_PTR tree, byte DetailType)
- {
- NODE_PTR newtree;
- switch(DetailType)
- {
- case DATAINFO:
- newtree = ListToTree(tree->llist, DocsCmp);
- PrintInfo(newtree, PrintData, DocsCmp, DETAILINFO);
- break;
- case HOSTINFO:
- newtree = ListToTree(tree->llist, HostsCmp);
- PrintInfo(newtree, PrintHost, HostsCmp, DETAILINFO);
- break;
- case WEEKDAYINFO:
- newtree = ListToTree(tree->llist, DaysCmp);
- PrintInfo(newtree, PrintDay, DaysCmp, DETAILINFO);
- break;
- case MONTHDATEINFO:
- newtree = ListToTree(tree->llist, DatesCmp);
- PrintInfo(newtree, PrintDate, DatesCmp, DETAILINFO);
- break;
- case TYPEINFO:
- newtree = ListToTree(tree->llist, TypesCmp);
- PrintInfo(newtree, PrintType, TypesCmp, DETAILINFO);
- break;
- case TIMEINFO:
- newtree = ListToTree(tree->llist, TimesCmp);
- PrintInfo(newtree, PrintTime, TimesCmp, DETAILINFO);
- break;
- case DOMAININFO:
- newtree = ListToTree(tree->llist, DomainCmp);
- PrintInfo(newtree, PrintDomain, DomainCmp, DETAILINFO);
- break;
- default:
- newtree = NULL;
- break;
- }
- FreeTree(newtree);
- }
- #endif
- /*******************************/
- void PrintInfo(NODE_PTR tree, void print(GOPHER_PTR), int cmp(GOPHER_PTR a, GOPHER_PTR b), byte DetailType)
- {
- LIST_PTR temp;
- LIST_PTR ByNum;
- int Nodes;
- long OldTotalConnects = TotalConnects;
-
- GByNum = NULL; /* Init the vars for the TreeToList function */
- GNodes = 0;
- if (SortHits)
- TreeToSList(tree);
- else if (SortMult == 1)
- TreeToUList(tree);
- else
- TreeToRUList(tree);
-
- if (DetailType != DETAILINFO)
- { /* We are not printing Detail info now, so do headers */
- print(STARTINFO);
- printc("", '=');
- }
-
- ByNum = GByNum; /* Save off and clear the globals vars */
- Nodes = GNodes;
- GByNum = NULL;
-
- temp = ByNum;
- while (temp != NULL)
- {
- #ifndef NODETAIL
- if (DetailType == DETAILINFO)
- printf(" ");
- #endif
-
- print(temp->data);
- printf(" %4ld (%2.2f%%)\n", (long int)(temp->hits/AverageDiv), (float)temp->hits*100.0/TotalConnects);
- #ifndef NODETAIL
- if ((DetailType != NOINFO) && (DetailType != DETAILINFO))
- {
- #ifndef DETAIL_TOTAL
- TotalConnects = temp->hits;
- #endif
- DoDetail(Find(tree, temp->data, cmp), DetailType);
- /* Don't generate Detail for NOINFO or if we are already doing detail */
- TotalConnects = OldTotalConnects;
- }
- #endif
- temp = temp->next;
- }
- if (DetailType != DETAILINFO)
- { /* We are not printing Detail info now, so do footers */
- printf("\n");
- GNodes = Nodes; /* Restore, incase detail messed it up */
- GTotalConnects = TotalConnects/AverageDiv;
- print(ENDINFO);
- }
- printf("\n");
- FreeList(ByNum);
- }
- /*******************************/
- void PlotInfo(NODE_PTR tree, void plot(FILE *, long int, GOPHER_PTR))
- {
- LIST_PTR temp;
- FILE *rfp, *dfp;
- char *fn;
- long int points = 1;
-
- fn = (char *)malloc(strlen(base) + 5);
- sprintf(fn,"%s.run", base);
- if (NULL == (rfp = fopen(fn, "w")))
- {
- fprintf(stderr, "Could not open file \"%s\" for plot run\n", fn);
- free(fn);
- return;
- }
- sprintf(fn,"%s.dat", base);
- if (NULL == (dfp = fopen(fn, "w")))
- {
- fprintf(stderr, "Could not open file \"%s\" for plot data\n", fn);
- free(fn);
- return;
- }
- free(fn);
-
- plot(rfp, 0, STARTINFO);
- GByNum = NULL; /* Init the vars for the TreeToList function */
- GByNumMax = 0;
- GByNumMin = 36000;
- TreeToUList(tree);
-
- temp = GByNum;
- while (temp != NULL)
- {
- plot(rfp, points, temp->data);
- fprintf(dfp, "%ld %ld\n", points++, temp->hits);
- temp = temp->next;
- }
- plot(rfp, points, ENDINFO);
- printf("\n");
- FreeList(GByNum);
- fclose(rfp);
- fclose(dfp);
- }
- /*******************************/
- void GraphInfo(NODE_PTR tree, void graph(GOPHER_PTR), int strwidth)
- {
- LIST_PTR temp;
- LIST_PTR ByNum;
- int Nodes;
- int i, max, oldwidth = Width, MyWidth;
-
-
- GByNum = NULL; /* Init the vars for the TreeToList function */
- GNodes = 0;
- GByNumMax = 0;
- GByNumMin = 36000;
- if (SortHits)
- TreeToSList(tree);
- else if (SortMult == 1)
- TreeToUList(tree);
- else
- TreeToRUList(tree);
-
- ByNum = GByNum; /* Save off and clear the globals vars */
- Nodes = GNodes;
- GByNum = NULL;
-
- graph(STARTINFO);
- printc("", '=');
-
- /* Do the width stuff after printc, yes its a major hack. :) */
- MyWidth = Width - strwidth;
- Width = strwidth;
-
- temp = ByNum;
- while (temp != NULL)
- {
- graph(temp->data);
- printf(" %4ld (%5.2f%%) ", (long int)(temp->hits/AverageDiv), (float)temp->hits*100.0/TotalConnects);
- max = (int)((temp->hits/AverageDiv) * (MyWidth/(float)GByNumMax*AverageDiv));
- for(i=0; i < max; i++)
- printf("#");
- printf("\n");
- temp = temp->next;
- }
- GNodes = Nodes; /* Restore */
- GTotalConnects = TotalConnects/AverageDiv;
- printf("\n");
- graph(ENDINFO);
- printf("\n");
- FreeList(ByNum);
- Width=oldwidth;
- }
- /*******************************/
- void PrintErrorInfo(void)
- {
- ELIST_PTR temp = cruft;
-
- printf("Exception/Problem Report\n");
- printf("NOTE: THESE ENTRIES MAY DENOTE A SERVER PROBLEM. THEY SHOULD BE LOOKED OVER!\n");
- printc("", '=');
- while (temp != NULL)
- {
- printf(temp->data);
- temp = temp->next;
- }
- printf("\n");
- }
-
- /*******************************/
-
- void PrintHelp(FILE *fp, int needreturn)
- {
- fprintf(fp,"\nUsage: glog [<REPORTTYPE> | -%c | -h ] ", ERRORINFO);
- #ifdef VMS
- fprintf(fp,"[OPTIONS] -i INFILENAME [-o OUTFILENAME]\n");
- #else
- fprintf(fp,"[OPTIONS] [-i INFILENAME] [-o OUTFILENAME]\n");
- #endif
- fprintf(fp," -h prints this help information\n");
- fprintf(fp," -%c displays an ERROR LOG\n", ERRORINFO);
- fprintf(fp," -i INFILENAME specifies the input file (your gopher logfile)\n");
- #ifndef VMS
- fprintf(fp," stdin is expected to be your gopher logfile, unless -i is used\n");
- #endif
- fprintf(fp," -o OUTFILENAME specifies the output file. If an output file\n");
- fprintf(fp," is not specified, output will be to the screen.\n\n");
-
- fprintf(fp,"REPORTTYPE is:\n");
- fprintf(fp," -g<OUTPUTTYPE> for a histogram\n");
- fprintf(fp," -p<OUTPUTTYPE> to output plot data (gnuplot required to display plot)\n");
- #ifndef NODETAIL
- fprintf(fp," -r<OUTPUTTYPE>[<OUTPUTTYPE>] for a report [with detail]\n\n");
- #else
- fprintf(fp," -r<OUTPUTTYPE> for a report\n\n");
- #endif
-
- #ifdef VMS
- fprintf(fp,"OUTPUTTYPE is: (must be inclosed in quotes)\n");
- #else
- fprintf(fp,"PUTPUTTYPE is:\n");
- #endif
- fprintf(fp," %c = Host Names %c = Day of Week \n",
- HOSTINFO, WEEKDAYINFO);
- fprintf(fp," %c = Document Names %c = Month/Day\n",
- DATAINFO, MONTHDATEINFO);
- fprintf(fp," %c = Type %c = Time\n", TYPEINFO, TIMEINFO);
- fprintf(fp," %c = Domain Name\n\n", DOMAININFO);
- if (needreturn)
- {
- fprintf(stderr, "PRESS [ENTER] TO CONTINUE\n");
- fflush(stderr);
- getc(stdin);
- }
- fprintf(fp,"OPTIONS are\n");
- fprintf(fp," [-b <beginning month #>] [-e <ending month #>]\n");
- fprintf(fp," [-w <width of report>] [-f <base filename for plot>]\n");
- fprintf(fp," [-a<AVERAGETYPE>] [-sSORTTYPE\n\n");
- #ifdef VMS
- fprintf(fp,"AVERAGETYPE is: (must be inclosed in quotes)\n");
- #else
- fprintf(fp,"AVERAGETYPE is:\n");
- #endif
- fprintf(fp," E = Everything Y = Per Year\n");
- fprintf(fp," M = Per Month W = Per Week\n");
- fprintf(fp," D = Per Day H = Per Hour\n\n");
- #ifdef VMS
- fprintf(fp,"SORTTYPE is: (must be inclosed in quotes)\n");
- #else
- fprintf(fp,"SORTTYPE is:\n");
- #endif
- fprintf(fp," h = by hits forward H = by Hits reverse\n");
- fprintf(fp," n = by name forward N = by name reverse\n\n");
-
- fprintf(fp,"WARNING: All arguments are evaluated from left to right,\n");
- fprintf(fp," except for -i, -o, -b, and -e. Which are evaluated only at\n");
- fprintf(fp," the start of execution. This means forexample that the option\n");
- fprintf(fp," -sH has to be in the command line BEFORE a -rO, if you want\n");
- fprintf(fp," the sorting to be changed for the -rO report.\n\n");
-
-
- #ifdef VMS
- fprintf(fp,"Example: glog -s\"n\" -g\"O\" -p\"T\" -a\"Y\" -s\"H\" -r\"D\" -i gopher.log\n");
- fprintf(fp," (Remember to enclose capital letters in double quotes!)\n");
- #else
- fprintf(fp,"Example: glog34 -sn -gO -pT -aY -sH -rD < gopher.log | more\n");
- #endif /* VMS */
- fprintf(fp," '-sn -gO' = Print out a domain graph sorted by the domainname field\n");
- fprintf(fp," '-pT' = Generate a gnuplot file with type information. \n");
- fprintf(fp," '-aY -sH -rD' = Print out a Document Access Report sorted by\n");
- fprintf(fp," reverse number of hits, average the data as if there is a\n");
- fprintf(fp," years worth of data.\n");
-
- #ifdef VMS
- fprintf(fp," Input is from gopher.log, output to the screen except for the plot data.\n");
- #else
- fprintf(fp," Input is from gopher.log output to stdout, except for the plot\n");
- #endif /* VMS */
-
- fflush(fp);
- }
-
- /*******************************/
- void PrintHdr()
- {
- char center[80];
-
- printf("\n");
- printc(GLOG_VERSION,' ');
- fflush(stdout);
-
- sprintf(center, "%s to %s", start_date, stop_date);
- printc(center, ' ');
- if (AverageStrPos == 0)
- {
- sprintf(center, "%ld connections", TotalConnects);
- printc(center, ' ');
- }
- else
- {
- sprintf(center, "%ld real connections", TotalConnects);
- printc(center, ' ');
- printf("\n");
- sprintf(center, "%ld estimated connections%s",
- (long int)(TotalConnects/AverageDiv), AverageStrs[AverageStrPos]);
- printc(center, ' ');
- }
- printf("\n\n");
- fflush(stdout);
- fflush(stderr);
- }
- /*******************************/
- /* Yes I KNOW main is more than 1 page */
- int main(int argc, char **argv)
- {
- int i;
- int NumOfDays;
-
- #ifdef THINK_C
- argc = ccommand(&argv);
- #endif
-
- if (1 == argc || argv[1][1] =='h')
- {
- PrintHelp(stdout,1); /* Clueless */
- exit(-1);
- }
-
- i = 1;
- /* We must go through the arguments twice. Once for the the arguments that
- * can only be set once. I could add argument checking here, but why bother
- */
- while (i<argc)
- {
- if (argv[i][0] == '-')
- switch (argv[i][1])
- {
- case 'b':
- if (i<argc-1)
- mbegin = atoi(argv[++i]);
- else
- HELPERROR("\nexpected beginning month argument for -b\n");
- break;
- case 'e':
- if (i<argc-1)
- mend = atoi(argv[++i]);
- else
- HELPERROR("\nexpected ending month argument for -e\n");
- break;
- case 'i':
- if (i<argc-1)
- in_file_name = argv[++i];
- else
- HELPERROR("\nexpected input file name for -i\n");
- break;
- case 'o':
- if (i<argc-1)
- {
- i++;
- if (freopen(argv[i], "w", stdout) == NULL)
- INFOERROR("Unable to open requested output file %s\n", argv[i]);
- }
- else
- HELPERROR("\nexpected output file name for -o\n");
- break;
- case 'r':
- case 'p':
- case 'g':
- switch(argv[i][2])
- {
- case DATAINFO:
- do_D = 1;
- break;
- case TYPEINFO:
- do_T = 1;
- break;
- case TIMEINFO:
- do_I = 1;
- break;
- case WEEKDAYINFO:
- do_W = 1;
- break;
- case HOSTINFO:
- do_H = 1;
- break;
- case DOMAININFO:
- do_O = 1;
- break;
- }
- break;
- }
- i++;
- }
-
- #ifdef VMS
- /* VMS barfs on stdin as input so FORCE filename */
- if (in_file_name == NULL)
- EXITERROR("No input file name on command line\n");
- #endif /* VMS */
-
- GatherInfo();
-
- if (TotalConnects == 0)
- EXITERROR("\nNo [matching] data to process\n");
-
- NumOfDays = SizeTree(dates);
- fflush(stdout);
- fflush(stderr);
-
- i = 1;
- /* Now go through them again and actually do them, from left to right */
- while (i<argc)
- {
- switch (argv[i][1])
- {
- case 'a': /* average changes */
- switch(argv[i][2])
- {
- case 'E':
- AverageStrPos = 0;
- AverageDiv = 1.0;
- break;
- case 'Y':
- AverageStrPos = 1;
- AverageDiv = NumOfDays/365.0;
- break;
- case 'M':
- AverageStrPos = 2;
- AverageDiv = NumOfDays/(365.0/12.0);
- break;
- case 'W':
- AverageStrPos = 3;
- AverageDiv = NumOfDays/7.0;
- break;
- case 'D':
- AverageStrPos = 4;
- AverageDiv = NumOfDays;
- break;
- case 'H':
- AverageStrPos = 5;
- AverageDiv = NumOfDays*24.0;
- break;
- }
- break;
- case ERRORINFO:
- PrintErrorInfo();
- break;
- case 'r': /*custom reports*/
- PrintHdr();
- switch(argv[i][2])
- {
- case DATAINFO:
- PrintInfo(docs, PrintData, DocsCmp, argv[i][3]);
- break;
- case TYPEINFO:
- PrintInfo(types, PrintType, TypesCmp, argv[i][3]);
- break;
- case TIMEINFO:
- PrintInfo(hours, PrintTime, TimesCmp, argv[i][3]);
- break;
- case WEEKDAYINFO:
- PrintInfo(dais, PrintDay, DaysCmp, argv[i][3]);
- break;
- case MONTHDATEINFO:
- PrintInfo(dates, PrintDate, DatesCmp, argv[i][3]);
- break;
- case HOSTINFO:
- PrintInfo(hosts, PrintHost, HostsCmp, argv[i][3]);
- break;
- case DOMAININFO:
- PrintInfo(domains, PrintDomain, DomainCmp, argv[i][3]);
- break;
- default:
- HELPERROR("expected OUTPUTTYPE argument for -r\n");
- break;
- }
- printf("\n");
- break;
- case 'p': /*custom plots*/
- switch (argv[i][2])
- {
- case DATAINFO:
- PlotInfo(docs, PlotData);
- break;
- case TYPEINFO:
- PlotInfo(types, PlotType);
- break;
- case TIMEINFO:
- PlotInfo(hours, PlotTime);
- break;
- case WEEKDAYINFO:
- PlotInfo(dais, PlotDay);
- break;
- case MONTHDATEINFO:
- PlotInfo(dates, PlotDate);
- break;
- case HOSTINFO:
- PlotInfo(hosts, PlotHost);
- break;
- default:
- HELPERROR("expected SORTTYPE argument for -p\n");
- break;
- }
- break;
- case 'g': /*custom graphs*/
- PrintHdr();
- switch (argv[i][2])
- {
- case DATAINFO:
- GraphInfo(docs, PrintData, 40);
- break;
- case TYPEINFO:
- GraphInfo(types, PrintType, 15);
- break;
- case TIMEINFO:
- GraphInfo(hours, PrintTime,15);
- break;
- case WEEKDAYINFO:
- GraphInfo(dais, PrintDay, 15);
- break;
- case MONTHDATEINFO:
- GraphInfo(dates, PrintDate,15);
- break;
- case HOSTINFO:
- GraphInfo(hosts, PrintHost, 35);
- break;
- case DOMAININFO:
- GraphInfo(domains, PrintDomain, 35);
- break;
- default:
- HELPERROR("expected SORTTYPE argument for -g\n");
- break;
- }
- printf("\n");
- break;
- case 's':
- switch(argv[i][2])
- {
- case 'h':
- SortMult = 1;
- SortHits = 1;
- break;
- case 'H':
- SortMult = -1;
- SortHits = 1;
- break;
- case 'n':
- SortMult = 1;
- SortHits = 0;
- break;
- case 'N':
- SortMult = -1;
- SortHits = 0;
- break;
- default:
- HELPERROR("expected SORTTYPE argument for -g\n");
- break;
- }
- printf("SortMult = %d\n", SortMult);
- break;
- case 'w':
- if (i<argc-1)
- Width = atoi(argv[++i]) - WIDTHSUB;
- else
- HELPERROR("expected width argument for -w\n");
- break;
- case 'f':
- if (i<argc-1)
- base = argv[++i];
- else
- HELPERROR("expected filename argument for -f\n");
- break;
- case 'o':
- case 'i':
- case 'b':
- case 'e':
- i++; /* Skip over their arguments */
- break; /* These are before GatherInfo arguments */
- case '?':
- default:
- fprintf(stderr, "Unknown option \"%c\" Use -h for help\n", argv[i][1]);
- break;
- } /*switch*/
-
- i++; /* next arg...*/
-
- } /*while*/
-
- exit(0);
- }
-
-
-