IPfind: analyze webalizer access logs

In the Mocka section I describe the IPfind program which scans the acess log files, generated by Webalizer, for 404's. In Linux the program runs stable, so I wanted to port it to Minix. After some small modifications the program runs fine with Minix as well.

Minix M2 compiler does not know the InOut.EOF function. So I had to go through the DEF files of the Minix system to discover that in Minix, for the InOut.Read function, the 'Done' variable is defined as follows:

   Done := NOT "End of file"
   
So the Linuxline (1) was replaced by the Minixline (2):
   (1)	Exhausted := InOut.EOF ();
   (2)	Exhausted := InOut.Done;
   

IPfind.mod

      
MODULE IPfind;

(*  Scanner for finding error codes from Webalizer log files	*)

IMPORT	InOut;

TYPE	Identifier			= ARRAY [0..255] OF CHAR;

VAR	IP, Date, URL, Dum		: Identifier;
	Code				: CARDINAL;
	Exhausted			: BOOLEAN;


PROCEDURE SkipItem;

VAR	ch	: CHAR;

BEGIN
   REPEAT  
      InOut.Read (ch);
      Exhausted := InOut.Done;
      IF  Exhausted  THEN  RETURN  END
   UNTIL  ch > ' ';
   REPEAT  
      InOut.Read (ch);
      Exhausted := InOut.Done;
      IF  Exhausted  THEN  RETURN  END
   UNTIL  ch <= ' ';
END SkipItem;


PROCEDURE ReadName (VAR str : ARRAY OF CHAR);

VAR	n		: CARDINAL;
	ch, endch	: CHAR;

BEGIN
   REPEAT  
      InOut.Read (ch);
      Exhausted := InOut.Done;
      IF  Exhausted  THEN  RETURN  END
   UNTIL  ch > ' ';		(* Eliminate whitespace		*)
   IF  ch = '['  THEN  endch := ']'  ELSE  endch := ch  END;
   n := 0;
   REPEAT
      InOut.Read (ch);
      Exhausted := InOut.Done;
      IF  Exhausted  THEN  RETURN  END;
      IF  n <= HIGH (str)  THEN  str [n] := ch  ELSE  ch := endch  END;
      INC (n)
   UNTIL ch = endch;
   IF  n <= HIGH (str)  THEN  str [n-1] := 0C  END;
END ReadName;


PROCEDURE ReadString (VAR str : ARRAY OF CHAR);

VAR	n		: CARDINAL;
	ch, endch	: CHAR;

BEGIN
   REPEAT  
      InOut.Read (ch);
      Exhausted := InOut.Done;
      IF  Exhausted  THEN  RETURN  END
   UNTIL  ch > ' ';		(* Eliminate whitespace		*)
   n := 0;
   REPEAT
      InOut.Read (ch);
      Exhausted := InOut.Done;
      IF  Exhausted  THEN  RETURN  END;
      IF  n <= HIGH (str)  THEN  str [n] := ch  END;
      INC (n)
   UNTIL ch <= ' ';
   IF  n <= HIGH (str)  THEN  str [n-1] := 0C  END;
END ReadString;


BEGIN
   REPEAT
      ReadString (IP);		SkipItem;		SkipItem;
      ReadName (Date);
      ReadName (URL);		InOut.ReadCard (Code);	SkipItem;
      ReadName (Dum);		ReadName (Dum);
      IF  Code = 404  THEN
         InOut.WriteString (Date);	InOut.Write (11C);
         InOut.WriteString (URL);
	 InOut.WriteLn
      END
   UNTIL  Exhausted;
END IPfind.
   
Compile the file with the command:
   $ m2 IPfind.mod -o IPf
   $ strip IPf
   $ ls -l IP*
   -rwxr-xr-x 1 jan  operator  17484 Sep 29 10:08 IPf
   -rw-r--r-- 1 jan  operator   2006 Sep 29 10:07 IPfind.mod
   
Compare the executables with Mocka:
      
   jan@beryllium:~/modula/div$ ls -l
   -rwxr-xr-x  1 jan users 23336 2007-09-28 21:42 IPfind
   -rw-r--r--  1 jan users  2092 2007-09-28 22:14 IPfind.mod
   jan@beryllium:~/modula/div$
   
And this is the value after stripping! Apparently the ACK is a rather lean compiler! Too bad it isn't available for Linux. Do I hear any volunteers?

Page created on 30 September 2007 and

Page equipped with FroogleBuster technology