/*
// httplog.c
//
// (c) Armin Obersteiner
//
// Parsing ncsa/cern httpd logfile
//
// USAGE: httplog [-s <keyword>] [-l] <logfile>
//
// <logfile>      -  httpd <logfile>
// -l             -  long: country statistics
// -lt            -  long: time statistics
// -s <keyword>   -  search for <keyword>
//
// compiles on:   MaxonC++ (amiga)
//                gcc (amiga)
//                gcc (bsd)
// (it should actually compile on any platform then :)
//
//  ->>>  gcc -o httplog httplog.c -lm
//
// itīs made to work on logfiles with american date format and austrian/german time format (24h)
//
//
//    to include new countries:
//
//          -   add lines to structure "struct dummy c"
//       -  donīt forget to increase "country_anz"
//
//    to adapt time and date for other logfile formats:
//
//          -   do the same with "struct dummy d" / "struct dummy t"
//       -  donīt forget to increase/decrease "day_anz" :)  / "time_anz"
//
//    the second entry in these stuctures (dummy) is the string to search for
//       (use spaces or brackets, because itīs more reliable then)
//    the third entry is the string for output
//
//
// CU Armin :)
//
//    ( Armin.Obersteiner@giga.or.at )
*/
/* Armin Obersteiner wrote a nice httpd log parser.
 * I played with it, to suit my fancy.
 * First of all, I found that there were many numeric addresses in
 * my logfiles.  That made for a large number of unidentified domains
 * when run with the -l flag.  I didn't like that, so I invoked AmiTCP
 * to find the name that goes with the missing address.  It doesn't always
 * work, if the local DNS server cannot find a name to go with an IP
 * number, but when the server is helpful, it does work.
 * Next, I added all of the countries to be found in the ISO 3166
 * document.  Then, I made the output for -l sorted by increasing
 * number of hits.
 * Added getadd(), site_ext  26 Nov 95 TCW
 * Added ISO 3166 countries 28 Nov 95 TCW
 * Compiles under SAS/C 6.56
 * Requires AmiTCP >=4.0
 * TCW:= tomas willis <tomas@cae.wisc.edu>
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include "httplog_rev.h"
/*TCW*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

FILE *f;

static char *revstag = VERSTAG;	/* TCW 16 Nov 95 */

  struct dummy {
      int count;
      char *ext;
      char *name;
  };

/* 27 Nov 95: TCW:
* Added _all_ of the ISO 3166 country codes.
* Now, you should hardly every encounter unknown networks.
* Sorted to help most likely hits occur at the top of the list
* for _my_ site.  If in Europe, you milage (kilometrage?) may vary.
* Kept old (e.g. .uk, .gov) stuff.
*/
/*int country_anz=26;*/
struct dummy c[] =
{
/* localhost --- many hits from testing, perhaps */
    {0, "localhost", "localhost"},

/* north america --- many hits from many computers */
    {0, ".edu", "usa education"},
    {0, ".com", "usa commercial"},
    {0, ".gov", "usa goverment"},
    {0, ".mil", "usa military"},
    {0, ".org", "usa organization"},
    {0, ".us", "united states"},
    {0, ".ca", "canada"},

/* this is new and official, but not busy yet.  still, that will change. */
    {0, ".int", "international organization"},

/* the network */
    {0, ".net", "network"},

/* europe --- many hits from many computers. sorted, a little */
    {0, ".de", "germany"},
    {0, ".uk", "united kingdom (.uk)"},
    {0, ".fi", "finland"},
    {0, ".nl", "netherlands"},
    {0, ".se", "sweden"},
    {0, ".no", "norway"},
    {0, ".at", "austria"},
    {0, ".be", "belgium"},
    {0, ".ch", "switzerland"},
    {0, ".dk", "denmark"},
    {0, ".es", "spain"},
    {0, ".fr", "france"},
    {0, ".fx", "france, metropolitan"},
    {0, ".gb", "united kingdom (.gb)"},
    {0, ".gr", "greece"},
    {0, ".ie", "ireland"},
    {0, ".is", "iceland"},
    {0, ".it", "italy"},
    {0, ".pt", "portugal"},

/* places with computers */
    {0, ".au", "australia"},
    {0, ".il", "israel"},
    {0, ".jp", "japan"},
    {0, ".kr", "korea, south"},
    {0, ".mx", "mexico"},
    {0, ".nz", "new zealand"},
    {0, ".sg", "singapore"},
    {0, ".za", "south africa"},
    {0, ".tw", "taiwan"},

/* more europe --- fewer hits, sorted a bit */
    {0, ".pl", "poland"},
    {0, ".ru", "russian federation"},
    {0, ".si", "slovenia"},
    {0, ".sk", "slovakia"},
    {0, ".tr", "turkey"},
    {0, ".ua", "ukraine"},
    {0, ".al", "albania"},
    {0, ".am", "armenia"},
    {0, ".ba", "bosnia and herzegowina"},
    {0, ".bg", "bulgaria"},
    {0, ".cy", "cyprus"},
    {0, ".cz", "czech republic"},
    {0, ".ee", "estonia"},
    {0, ".ge", "georgia"},
    {0, ".hr", "croatia"},
    {0, ".hu", "hungary"},
    {0, ".li", "liechtenstein"},
    {0, ".lt", "lithuania"},
    {0, ".lu", "luxembourg"},
    {0, ".lv", "latvia"},
    {0, ".md", "moldovia"},
    {0, ".ro", "romania"},
    {0, ".yu", "yugoslavia"},

/* may have computers */
    {0, ".cn", "china"},
    {0, ".in", "india"},
    {0, ".eg", "egypt"},
    {0, ".ph", "philippines"},


/* americas and carribean */
    {0, ".br", "brazil"},
    {0, ".ar", "argentina"},
    {0, ".bo", "bolivia"},
    {0, ".bz", "belize"},
    {0, ".cl", "chile"},
    {0, ".cu", "cuba"},
    {0, ".do", "dominican republic"},
    {0, ".ec", "ecuador"},
    {0, ".gt", "guatemala"},
    {0, ".ht", "haiti"},
    {0, ".jm", "jamaica"},
    {0, ".ng", "nigeria"},
    {0, ".pe", "peru"},
    {0, ".pr", "puerto rico"},
    {0, ".sv", "el salvador"},
    {0, ".uy", "uruguay"},


/* not so likely to have computers, just alphabetized */
    {0, ".af", "afghanistan"},
    {0, ".dz", "algeria"},
    {0, ".as", "american samoa"},
    {0, ".ad", "andorra"},
    {0, ".ao", "angola"},
    {0, ".ai", "anguilla"},
    {0, ".aq", "antarctica"},
    {0, ".ag", "antigua and barbuda"},
    {0, ".aw", "aruba"},
    {0, ".az", "azerbaijan"},
    {0, ".bs", "bahamas"},
    {0, ".bh", "bahrain"},
    {0, ".bd", "bangladesh"},
    {0, ".bb", "barbados"},
    {0, ".by", "belarus"},
    {0, ".bj", "benin"},
    {0, ".bm", "bermuda"},
    {0, ".bt", "bhutan"},
    {0, ".bo", "bolivia"},
    {0, ".bw", "botswana"},
    {0, ".bv", "bouvet island"},
    {0, ".io", "british indian ocean territory"},
    {0, ".bn", "brunei darussalam"},
    {0, ".bf", "burkina faso"},
    {0, ".bi", "burundi"},
    {0, ".kh", "cambodia"},
    {0, ".cm", "cameroon"},
    {0, ".cv", "cape verde"},
    {0, ".ky", "cayman islands"},
    {0, ".cf", "central african republic"},
    {0, ".td", "chad"},
    {0, ".cx", "christmas island"},
    {0, ".cc", "cocos islands"},
    {0, ".co", "colombia"},
    {0, ".km", "comoros"},
    {0, ".cg", "congo"},
    {0, ".ck", "cook islands"},
    {0, ".cr", "costa rica"},
    {0, ".ci", "cote d'ivoire"},
    {0, ".dj", "djibouti"},
    {0, ".dm", "dominica"},
    {0, ".tp", "east timor"},
    {0, ".gq", "equatorial guinea"},
    {0, ".er", "eritrea"},
    {0, ".et", "ethiopia"},
    {0, ".fk", "falkland islands"},
    {0, ".fo", "faroe islands"},
    {0, ".fj", "fiji"},
    {0, ".gf", "french guiana"},
    {0, ".pf", "french polynesia"},
    {0, ".tf", "french southern territories"},
    {0, ".ga", "gabon"},
    {0, ".gm", "gambia"},
    {0, ".gh", "ghana"},
    {0, ".gi", "gibraltar"},
    {0, ".gl", "greenland"},
    {0, ".gd", "grenada"},
    {0, ".gp", "guadeloupe"},
    {0, ".gu", "guam"},
    {0, ".gn", "guinea"},
    {0, ".gw", "guinea-bissau"},
    {0, ".gy", "guyana"},
    {0, ".hm", "heard and mcdonald islands"},
    {0, ".hn", "honduras"},
    {0, ".hk", "hong kong"},
    {0, ".id", "indonesia"},
    {0, ".ir", "iran"},
    {0, ".iq", "iraq"},
    {0, ".jo", "jordan"},
    {0, ".kz", "kazakhstan"},
    {0, ".ke", "kenya"},
    {0, ".ki", "kiribati"},
    {0, ".kp", "korea, north"},
    {0, ".kw", "kuwait"},
    {0, ".kg", "kyrgyzstan"},
    {0, ".la", "laos"},
    {0, ".lb", "lebanon"},
    {0, ".ls", "lesotho"},
    {0, ".lr", "liberia"},
    {0, ".ly", "libya"},
    {0, ".mo", "macau"},
    {0, ".mk", "macedonia"},
    {0, ".mg", "madagascar"},
    {0, ".mw", "malawi"},
    {0, ".my", "malaysia"},
    {0, ".mv", "maldives"},
    {0, ".ml", "mali"},
    {0, ".mt", "malta"},
    {0, ".mh", "marshall islands"},
    {0, ".mq", "martinique"},
    {0, ".mr", "mauritania"},
    {0, ".mu", "mauritius"},
    {0, ".yt", "mayotte"},
    {0, ".fm", "micronesia"},
    {0, ".mc", "monaco"},
    {0, ".mn", "mongolia"},
    {0, ".ms", "montserrat"},
    {0, ".ma", "morocco"},
    {0, ".mz", "mozambique"},
    {0, ".mm", "myanmar"},
    {0, ".na", "namibia"},
    {0, ".nr", "nauru"},
    {0, ".np", "nepal"},
    {0, ".an", "netherlands antilles"},
    {0, ".nc", "new caledonia"},
    {0, ".ni", "nicaragua"},
    {0, ".ne", "niger"},
    {0, ".nu", "niue"},
    {0, ".nf", "norfolk island"},
    {0, ".mp", "northern mariana islands"},
    {0, ".om", "oman"},
    {0, ".pk", "pakistan"},
    {0, ".pw", "palau"},
    {0, ".pa", "panama"},
    {0, ".pg", "papua new guinea"},
    {0, ".py", "paraguay"},
    {0, ".pn", "pitcairn"},
    {0, ".qa", "qatar"},
    {0, ".re", "reunion"},
    {0, ".rw", "rwanda"},
    {0, ".kn", "saint kitts and nevis"},
    {0, ".lc", "saint lucia"},
    {0, ".vc", "saint vincent and the grenadines"},
    {0, ".ws", "samoa"},
    {0, ".sm", "san marino"},
    {0, ".st", "sao tome and principe"},
    {0, ".sa", "saudi arabia"},
    {0, ".sn", "senegal"},
    {0, ".sc", "seychelles"},
    {0, ".sl", "sierra leone"},
    {0, ".sb", "solomon islands"},
    {0, ".so", "somalia"},
    {0, ".gs", "south georgia and the south sandwich islands"},
    {0, ".lk", "sri lanka"},
    {0, ".sh", "st. helena"},
    {0, ".pm", "st. pierre and miquelon"},
    {0, ".sd", "sudan"},
    {0, ".sr", "suriname"},
    {0, ".sj", "svalbard and jan mayen islands"},
    {0, ".sz", "swaziland"},
    {0, ".sy", "syria"},
    {0, ".tj", "tajikistan"},
    {0, ".tz", "tanzania"},
    {0, ".th", "thailand"},
    {0, ".tg", "togo"},
    {0, ".tk", "tokelau"},
    {0, ".to", "tonga"},
    {0, ".tt", "trinidad and tobago"},
    {0, ".tn", "tunisia"},
    {0, ".tm", "turkmenistan"},
    {0, ".tc", "turks and caicos islands"},
    {0, ".tv", "tuvalu"},
    {0, ".ug", "uganda"},
    {0, ".ae", "united arab emirates"},
    {0, ".um", "united states minor outlying islands"},
    {0, ".uz", "uzbekistan"},
    {0, ".vu", "vanuatu"},
    {0, ".va", "vatican city"},
    {0, ".ve", "venezuela"},
    {0, ".vn", "viet nam"},
    {0, ".vg", "virgin islands (british)"},
    {0, ".vi", "virgin islands (u.s.)"},
    {0, ".wf", "wallis and futuna islands"},
    {0, ".eh", "western sahara"},
    {0, ".ye", "yemen"},
    {0, ".zr", "zaire"},
    {0, ".zm", "zambia"},
    {0, ".zw", "zimbabwe"},
};

int day_anz = 7;
struct dummy d[7] =
{
    {0, "Mon ", "mon"},
    {0, "Tue ", "tue"},
    {0, "Wed ", "wed"},
    {0, "Thu ", "thu"},
    {0, "Fri ", "fri"},
    {0, "Sat ", "sat"},
    {0, "Sun ", "sun"},
};

int time_anz = 24;
struct dummy t[24] =
{
    {0, " 00:", "00"},
    {0, " 01:", "01"},
    {0, " 02:", "02"},
    {0, " 03:", "03"},
    {0, " 04:", "04"},
    {0, " 05:", "05"},
    {0, " 06:", "06"},
    {0, " 07:", "07"},
    {0, " 08:", "08"},
    {0, " 09:", "09"},
    {0, " 10:", "10"},
    {0, " 11:", "11"},
    {0, " 12:", "12"},
    {0, " 13:", "13"},
    {0, " 14:", "14"},
    {0, " 15:", "15"},
    {0, " 16:", "16"},
    {0, " 17:", "17"},
    {0, " 18:", "18"},
    {0, " 19:", "19"},
    {0, " 20:", "20"},
    {0, " 21:", "21"},
    {0, " 22:", "22"},
    {0, " 23:", "23"},
};

char prg[256];

  struct cache {
      int year;
      int value;
  };

struct cache ca =
{0, 0};

/* prototypes */
void main(int, char **);
void ende(int, char *);
void parse_cern(char *);
int date2day(int, int, int);
int sjahr(int);
char *from_address(char *);
int dummy_count_compare(void *, void *);
int dummy_name_compare(void *, void *);
int dummy_ext_compare(void *, void *);
void sort_dummy_count(struct dummy *, int);
void sort_dummy_ext(struct dummy *, int);
void sort_dummy_name(struct dummy *, int);



void
main(int argc, char *argv[])
{
    int anz = 0, i = 0, x;
    double sonst = 0;
    int minus_l = 0;
    int minus_lt = 0;
    int minus_s = 0;
    double prozent;
    char file[256];
    char such[256];
    char line[1024], site[1024], back[1024], date[1024], back1[1024];
    /* char method[1024],file[1024],protocol[1024]; */
    int country_anz = sizeof(c) / sizeof(struct dummy);
    /* TCW */
    char site_ext[32];		/* I doubt more than 6 are needed */
    int ii;
    char *cp;
    int improved_count = 0, not_improved_count = 0;
    int try_ext_matching;
    int unknown_ext_found = 0;

    if (argc < 2) {
	printf("USAGE: %s [-s <keyword>] [-l[t]] <logfile> \n", argv[0]);
    }
    else {
	strcpy(prg, argv[0]);

	if (!strcmp(argv[1], "-s")) {
	    if (argc == 4) {
		strcpy(such, argv[2]);
		if (!strcmp(argv[2], "-l") || !strcmp(argv[2], "-lt"))
		    ende(1, "wrong arguments");
		if (!strcmp(argv[3], "-l") || !strcmp(argv[3], "-lt"))
		    ende(1, "wrong arguments");
		strcpy(file, argv[3]);
		minus_s = 1;
	    }
	    else if (argc == 5) {
		strcpy(such, argv[2]);
		if (!strcmp(argv[2], "-l") || !strcmp(argv[2], "-lt"))
		    ende(1, "wrong arguments");
		if (strcmp(argv[3], "-l") && strcmp(argv[3], "-lt"))
		    ende(1, "wrong arguments");
		strcpy(file, argv[4]);
		minus_s = 1;
		if (!strcmp(argv[3], "-l")) {
		    minus_l = 1;
		}
		else
		    minus_lt = 1;

	    }
	    else
		ende(1, "wrong arguments");
	}
	else if (!strcmp(argv[1], "-l")) {
	    if (argc != 3)
		ende(1, "wrong arguments");

	    minus_l = 1;
	    strcpy(file, argv[2]);
	}
	else if (!strcmp(argv[1], "-lt")) {
	    if (argc != 3)
		ende(1, "wrong arguments");

	    minus_lt = 1;
	    strcpy(file, argv[2]);
	}
	else
	    strcpy(file, argv[1]);


	if ((f = fopen(file, "r")) != NULL) {
	    char site_old[1024] = "";

	    int first = 1;
	    int cern = 0;

	    while (((fgets(line, 1024, f)) != NULL)) {
		if (first) {
		    first = 0;
		    strcpy(back1, line);
		    if (strstr(back1, "- -") != NULL)
			cern = 1;
		}

		if (minus_s)
		    strcpy(back, line);

		i++;
		/*fprintf(stderr,"%d\r",i);*/
		strcpy(site, strtok(line, "["));
		strcpy(date, strtok(NULL, "]"));
		/*strcpy(method,strtok(NULL," "));
               strcpy(file,strtok(NULL," "));
               strcpy(protocol,strtok(NULL," \0\n")); */
		/*TCW*/
		/* strip trailing whitespace from site[] */
		for (ii = (strlen(site) - 1); ii >= 0; --ii) {
		    if (isspace(site[ii]))
			site[ii] = (char) 0;
		    else
			break;
		}
		try_ext_matching = 1;
		if (isdigit(site[strlen(site) - 1])) {	/* we are numberic */
		    /*printf("The old site is `%s'\t",site);*/
		    cp = from_address(site);
		    if (strcmp(cp, site)) {	/* ie, they are different */
			strncpy(site, cp, 1024);
			++improved_count;
		    }
		    else {
			++not_improved_count;
			try_ext_matching = 0;
		    }
		    /*printf("The new site is `%s'\n",site);*/
		}

		if (try_ext_matching) {
		    /* find the extension of site, that is, the last .bit */
		    /* work backwords to find a '.' if not localhost*/
		    if (0 == strcmp(site, "localhost"))
			strcpy(site_ext, "localhost");
		    else {
			for (ii = (strlen(site) - 1); ii >= 0; --ii) {
			    if ('.' == site[ii]) {
				cp = site + ii;
				break;
			    }
			}
			strncpy(site_ext, cp, 32);
		    }
		    /*printf("The extension is `%s'\n",site_ext);*/
		}

		if (minus_s) {
		    if (strstr(back, such) != NULL) {
			if (minus_l) {
			    int ext_found;

			    if (try_ext_matching) {
				ext_found = 0;
				for (x = 0; x < country_anz; x++) {
				    if (0 == strcmp(site_ext, c[x].ext)) {
					(c[x].count)++;
					ext_found = 1;
					break;
				    }
				}
				if (0 == ext_found)
				    ++unknown_ext_found;
				/*fprintf(stderr, "New extension found: `%s'\n", site_ext);*/
			    }
			}
			if (minus_lt) {
			    if (cern == 0) {
				for (x = 0; x < day_anz; x++)
				    if (strstr(date, d[x].ext) != NULL)
					(d[x].count)++;
				for (x = 0; x < time_anz; x++)
				    if (strstr(date, t[x].ext) != NULL)
					(t[x].count)++;
			    }
			    else
				parse_cern(date);
			}
			anz++;
		    }
		}
		else {
		    if (minus_l) {
			int ext_found;

			if (try_ext_matching) {
			    ext_found = 0;
			    for (x = 0; x < country_anz; x++) {
				if (0 == strcmp(site_ext, c[x].ext)) {
				    (c[x].count)++;
				    ext_found = 1;
				    break;
				}
			    }
			    if (0 == ext_found)
				++unknown_ext_found;
			    /*fprintf(stderr, "New extension found: `%s'\n", site_ext);*/
			}
		    }

		    if (minus_lt) {
			if (cern == 0) {
			    for (x = 0; x < day_anz; x++)
				if (strstr(date, d[x].ext) != NULL)
				    (d[x].count)++;
			    for (x = 0; x < time_anz; x++)
				if (strstr(date, t[x].ext) != NULL)
				    (t[x].count)++;
			}
			else
			    parse_cern(date);
		    }
		    if (strcmp(site, site_old) != 0)
			anz++;
		}

		if (!minus_s)
		    strcpy(site_old, site);
	    }

	    fclose(f);

	    if (minus_s) {
		printf("searching for: %s\n\n", such);
		printf("access: %d/%d  %8.4f %%\n", anz, i, (double) anz * (double) 100 / (double) i);
	    }
	    else
		printf("access: %d/%d\n", anz, i);
	    if (minus_l) {
		if (i == 0)
		    ende(2, "logfile wrong");

		printf("\n");
		sort_dummy_count(c, country_anz);
		for (x = 0; x < country_anz; x++)
		    if (c[x].count) {
			if (!minus_s) {
			    prozent = (double) c[x].count * (double) 100 / (double) i;
			}
			else {
			    prozent = (double) c[x].count * (double) 100 / (double) anz;
			}

			if (prozent > 0.001)
			    printf("%6.2f %% : %s\n", prozent, c[x].name);
			sonst = sonst + prozent;
		    }
		prozent = (double) 100 - sonst;

		if (prozent > 0.001)
		    printf("\n%6.2f %% : others\n", prozent);
		printf("%d of %d numeric IP addresses improved.\n",
		  improved_count, (improved_count + not_improved_count));
		if (unknown_ext_found > 0)
		    printf("Found unknown non-numeric extensions %d times.\n",
			   unknown_ext_found);

	    }
	    if (minus_lt) {
		if (i == 0)
		    ende(2, "logfile wrong");

		printf("\n");

		for (x = 0; x < day_anz; x++)
		    if (d[x].count) {
			if (!minus_s) {
			    prozent = (double) d[x].count * (double) 100 / (double) i;
			}
			else {
			    prozent = (double) d[x].count * (double) 100 / (double) anz;
			}

			if (prozent > 0.009)
			    printf("%s: %6.2f %%\n", d[x].name, prozent);
		    }
		printf("\n");
		for (x = 0; x < time_anz; x++)
		    if (t[x].count) {
			if (!minus_s) {
			    prozent = (double) t[x].count * (double) 100 / (double) i;
			}
			else {
			    prozent = (double) t[x].count * (double) 100 / (double) anz;
			}

			if (prozent > 0.009)
			    printf("%s: %6.2f %%\n", t[x].name, prozent);
		    }
	    }
	}
	else
	    ende(5, "canīt open logfile");

	ende(0, "");
    }
}

void
ende(int n, char *end)
{
    if (f)
	fclose(f);

    if (strcmp(end, "") != 0)
	printf("%s: %s !\n", &prg, end);
    exit(n);
}

void
parse_cern(char *dd)
{
    char date[1024], hour[10];
    char da[3], mo[4], yea[5];

    int h, x;
    int day, mon, year;

    strcpy(date, strtok(dd, ":"));
    strcpy(hour, strtok(NULL, ":"));

    h = atoi(hour);

    for (x = 0; x < time_anz; x++)
	if (h == x)
	    (t[x].count)++;

    strcpy(da, strtok(date, "/"));
    strcpy(mo, strtok(NULL, "/"));
    strcpy(yea, strtok(NULL, "\0"));

    day = atoi(da);

    if (!strcmp(mo, "Jan"))
	mon = 1;
    if (!strcmp(mo, "Feb"))
	mon = 2;
    if (!strcmp(mo, "Mar"))
	mon = 3;
    if (!strcmp(mo, "Apr"))
	mon = 4;
    if (!strcmp(mo, "May"))
	mon = 5;
    if (!strcmp(mo, "Jun"))
	mon = 6;
    if (!strcmp(mo, "Jul"))
	mon = 7;
    if (!strcmp(mo, "Aug"))
	mon = 8;
    if (!strcmp(mo, "Sep"))
	mon = 9;
    if (!strcmp(mo, "Oct"))
	mon = 10;
    if (!strcmp(mo, "Nov"))
	mon = 11;
    if (!strcmp(mo, "Dec"))
	mon = 12;

    year = atoi(yea);

    h = date2day(day, mon, year);

    if (h != 0)
	for (x = 0; x < day_anz; x++)
	    if (h == (x + 1))
		(d[x].count)++;
}

/* Updated routine */
/*  date2day
    (c) Armin.Obersteiner@giga.or.at

    input: <int> day,month,year
    output:<int> 0,1-7

    0: error (before 1.1.1500 - this should be enough)

    1-7: Monday-Sunday
*/

int 
date2day(int day, int month, int year)
{
    int md[12] =
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    int i;
    int tag = 0;
    int s;

    if (year < 1500)
	return 0;
    if ((month < 1) || (month > 12))
	return 0;
    if (day < 1)
	return 0;

    s = sjahr(year);

    if ((day > md[month - 1])) {
	if (!s)
	    return 0;
	if ((s) && (month = 2) && (day > 29))
	    return 0;
    }

    for (i = 1; i < month; i++)
	tag = tag + md[i - 1];
    if (s && (month > 2))
	tag = tag + 1;

    tag = tag + day + year + (year / 4) - (year / 100) + (year / 400);
    if (s)
	tag--;

    return (((tag - 2) % 7) + 1);
}

/* Updated routine */
/*  sjahr
    (c) Armin.Obersteiner@giga.or.at

    input:  <int> year
    output: <int> 0,1

    0: normal year
    1: leap-year
*/

int 
sjahr(int year)
{
    int schalt = 0;

    if ((year % 4) == 0)
	schalt = 1;
    if ((year % 100) == 0)
	if ((year % 400) != 0)
	    schalt = 0;

    return schalt;
}

extern struct hostent *gethostbyaddr();

char *
from_address(char *astring)
{
    unsigned long addr;		/* address in host order */
    struct hostent *host;	/* structure returned by gethostbyaddr() */

    /* parse string into address */
    if ((addr = inet_addr(astring)) == -1) {
	/*fprintf(stderr, "%s is not a valid address\n", astring) ;*/
	return astring;
    }

    /* try to find hostentry, caddr_t defined in sys/types.h */
    if ((host = (struct hostent *) gethostbyaddr((caddr_t) & addr, sizeof(addr), AF_INET)) == NULL) {
	return astring;
    }
    else {
	return (host->h_name);
    }
}

int
dummy_count_compare(void *d1, void *d2)
{
    int v1 = ((struct dummy *) d1)->count;
    int v2 = ((struct dummy *) d2)->count;

    return ((v1 < v2) ? -1 : ((v1 > v2) ? 1 : 0));
}

int
dummy_name_compare(void *d1, void *d2)
{
    char *v1 = ((struct dummy *) d1)->name;
    char *v2 = ((struct dummy *) d2)->name;
    int retval;

    retval = strcmp(v1, v2);
    if (retval < 0) {
	return -1;
    }
    else {
	if (retval > 0) {
	    return 1;
	}
	else {
	    return 0;
	}
    }
}

int
dummy_ext_compare(void *d1, void *d2)
{
    char *v1 = ((struct dummy *) d1)->ext;
    char *v2 = ((struct dummy *) d2)->ext;
    int retval;

    retval = strcmp(v1, v2);
    if (retval < 0) {
	return -1;
    }
    else {
	if (retval > 0) {
	    return 1;
	}
	else {
	    return 0;
	}
    }
}



void
sort_dummy_count(struct dummy *d, int size)
{
    qsort((void *) d, (size_t) size, sizeof(struct dummy), dummy_count_compare);
}

#if ACTUALLY_USED

void
sort_dummy_ext(struct dummy *d, int size)
{
    qsort((void *) d, (size_t) size, sizeof(struct dummy),
	  dummy_ext_compare);
}

void
sort_dummy_name(struct dummy *d, int size)
{
    qsort((void *) d, (size_t) size, sizeof(struct dummy),
	  dummy_name_compare);
}

#endif				/* ACTUALLY_USED */
