#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
#define MAXLINE	80
#define MAXPREG 80

/*
	6/28/2000 RPD:  broke Linux into its own separate category rather
			than a subcategory of X11
*/

typedef struct _grepentry {
	char *name;
	char *grepfor;
	int count;
	regex_t *preg;
} grepentry;

grepentry majorclientosfamily[]= {
	"Windows 95           ", 		"Windows 95|Win95|Win32", 	0, NULL,
	"Windows NT           ", 		"Windows NT|WinNT", 	0, NULL,
	"Windows 98           ", 		"Windows 98|Win98", 	0, NULL,
	"Windows 3.1          ", 		"Windows|Windows 3.1|Win3.1|Win16", 	0, NULL,
	"Linux                ",		"Linux",	0, NULL,
	"Macintosh            ", 		"Macintosh|Mac", 	0, NULL,
	"Other X11 (see below)", 		"X11", 		0, NULL,
	"Search Engine        ",		"Spider|LinkBot|Lycos|Architex|Scooter|InfoSeek|WiseWire|Slurp|EmailSiphon|LinkWalker",	0, NULL,
	"WebTV                ",		"WebTV", 	0, NULL,
	"LibWWW               ",		"libwww", 	0, NULL,
	"OS/2                 ",		"OS/2", 	0, NULL,
	"Java                 ", 		"Java",		0, NULL,
	"Prodigy              ", 		"PRODIGY",		0, NULL,
	"Amiga                ", 		"Amiga",	0, NULL,
	"Solaris (not X11?)   ", 		"olaris",	0, NULL,
//	"Linux (not X11?)     ", 		"Linux",	0, NULL,
	"OSF                  ", 		"OSF",	0, NULL,
	"Other Mozilla (OS?)  ",        "Mozilla", 0, NULL,
	"MSProxy              ",        "MSProxy", 0, NULL,
//	"RedBaron             ", 		"Redbaron",	0, NULL,
	NULL, 					NULL, 		0, NULL,
};

// define this to be array position of X11 in above (lame)
#define X11ENTRY	6

grepentry x11ostype[]= {
	"SunOS", 	"SunOS",	0, NULL,
//	"Linux", "Linux", 0, NULL,
	"HP", "HP", 0, NULL,
	"IRIX", "IRIX", 0, NULL,
	"OSF", "OSF", 0, NULL,
	"AIX", "AIX", 0, NULL,
	"Solaris", 	"Solaris",	0, NULL,
	"FreeBSD", "FreeBSD", 0, NULL,
	"NetBSD", "NetBSD", 0, NULL,
	"BSDI", "BSDI", 0, NULL,
	"BSD/OS", "BSD/OS", 0, NULL,
	"VMS", "VMS", 0, NULL,
	"SCO", " SCO", 0, NULL,			// CISCO was showing up . . . leading space prevents that
	NULL, 					NULL, 		0, NULL,
};

int totalx11os;
int eflags=0;

main()
{
	char inbuf[MAXLINE];
	regex_t preg1[MAXPREG];	// how big does this need to be?  not in man page
	int cflags=0;
	int moff, i, totalmajclios=0;
	int foundmajoscli=0;

	i=0;
	while(majorclientosfamily[i].name != NULL) {
		majorclientosfamily[i].preg=(regex_t *) malloc(MAXPREG);
		regcomp(majorclientosfamily[i].preg, majorclientosfamily[i].grepfor, REG_NOSUB|REG_EXTENDED);
		i++;
	}

	i=0;
	while(x11ostype[i].name != NULL) {
		x11ostype[i].preg=(regex_t *) malloc(MAXPREG);
		regcomp(x11ostype[i].preg, x11ostype[i].grepfor, REG_NOSUB|REG_EXTENDED);
		i++;
	}

	printf("all regexps compiled\n");

	while(fgets(inbuf, MAXLINE, stdin) != NULL) {
		foundmajoscli=0;
		i=0;
		while(majorclientosfamily[i].name != NULL) {
			//printf("matching %d\n", i);
			if(!regexec(majorclientosfamily[i].preg, inbuf, 0, NULL, eflags)) {
				majorclientosfamily[i].count++;
				foundmajoscli=1;
				totalmajclios++;
				if(i==X11ENTRY) MatchX11(inbuf);
				break;
			}
			i++;
		}
		if(!foundmajoscli) {
			printf("failed to classify major client OS type:  %s", inbuf);
		}
	}

	printf("\nMajor Client OS Type (%d total entries)\n", totalmajclios);
	i=0;
    while(majorclientosfamily[i].name != NULL) {
		printf("%s\t\t%d\t%2.2f%%\n", majorclientosfamily[i].name, majorclientosfamily[i].count, ((float) majorclientosfamily[i].count*100.0) / (float) totalmajclios);
        i++;
    }

	printf("\nBreakdown of X11 OS Type (%d total entries were classified)\n", totalx11os);
	i=0;
    while(x11ostype[i].name != NULL) {
		printf("%s\t\t%d\t%2.2f%%\n", x11ostype[i].name, x11ostype[i].count, ((float) x11ostype[i].count*100.0) / (float) totalx11os);
        i++;
    }
}

MatchX11(char *inbuf)
{
	int i;
	int foundx11ostype;	
	
	foundx11ostype=0;
	i=0;
	while(x11ostype[i].name != NULL) {
		//printf("matching %d\n", i);
		if(!regexec(x11ostype[i].preg, inbuf, 0, NULL, eflags)) {
			x11ostype[i].count++;
			foundx11ostype=1;
			totalx11os++;
			break;
		}
		i++;
    }

	if(!foundx11ostype) {
		printf("failed to classify X11 OS type:  %s", inbuf);
	}

}
