#!/usr/bin/perl -ws
#
# Compressed ppsw logs
#
# Capital letters are rejections, lower-case letters are temporary
# rejections or bad messages that we have accepted. Punctuation is good.
#
# $Cambridge: hermes/src/stats/scripts/logsurf,v 1.31 2005/04/26 14:30:12 fanf2 Exp $

use strict;

use vars '$v', '$r', '$h';

my $columns = defined $ENV{COLUMNS} ? $ENV{COLUMNS} : 80;

my $nl;
my $lt;
my $gt;
my $space;
my %colour;
if ($h) {
	$nl = "<br>\n";
	$lt = "&lt;";
	$gt = "&gt;";
	$space = "&nbsp;";
	%colour = (
		'off' => "",
		'ppsw-0' => "color=maroon",
		'ppsw-1' => "color=coral",
		'ppsw-2' => "",
		'ppsw-3' => "color=purple",
		'ppsw-4' => "color=green",
		'ppsw-5' => "color=olive",
		'ppsw-6' => "color=navy",
		'ppsw-7' => "",
		'ppsw-8' => "color=teal",
		'ppsw-9' => ""
	);
} elsif ($ENV{TERM} =~ /xterm/) {
	print "\e]0;email activity on ppsw\a";
	$nl = "\n";
	$lt = "<";
	$gt = ">";
	$space = " ";
	%colour = (
		'off' => "\e[m",
		'ppsw-0' => "\e[31m",
		'ppsw-1' => "\e[32m",
		'ppsw-2' => "\e[m",
		'ppsw-3' => "\e[m",
		'ppsw-4' => "\e[m",
		'ppsw-5' => "\e[m",
		'ppsw-6' => "\e[m",
		'ppsw-7' => "\e[33m",
		'ppsw-8' => "\e[m",
		'ppsw-9' => "\e[34m"
	);
} else {
	$nl = "\n";
	$lt = "<";
	$gt = ">";
	$space = " ";
	%colour = (
		'off' => "",
		'ppsw-0' => "",
		'ppsw-1' => "",
		'ppsw-2' => "",
		'ppsw-3' => "",
		'ppsw-4' => "",
		'ppsw-5' => "",
		'ppsw-6' => "",
		'ppsw-7' => "",
		'ppsw-8' => "",
		'ppsw-9' => ""
	);
}

sub colprint ($) {
	my $string = shift;
	if (/(ppsw-[0-9])/) {
		if ($h) {
			print "<font $colour{$1}>$string</font>";
		} else {
			print "$colour{$1}$string";
		}
	} else {
		print "$colour{off}$string";
	}
}

$| = 1;

my @pat = (
	[ $lt, qr/ <= / ],
	[ $gt, qr/ => / ],
	[ "-", qr/ -> / ],
	[ "b", qr/ [*][*] / ],
	[ "c", qr/temporarily refused connection|too many connections from that IP address/ ],
	[ "D", qr/listed at [^;]*/ ], # dns
	[ "v", qr/\\S* FOUND  / ], # ClamAV
	[ "V", qr/Found .* !!! / ], # McAfee
	[ "O", qr/Relaying is not permitted/ ], # not open
	[ "H", qr/Please use your name when saying HELO/ ],
	[ "A", qr/No SMTP service for unauthorized users/ ],
	[ "P", qr/SMTP protocol violation: synchronization error/ ],
	[ "s", qr/Could not complete sender verify/ ],
	[ "S", qr/Sender verify failed/ ],
	[ "r", qr/temporarily rejected RCPT/ ],
	[ "R", qr/rejected RCPT/ ],
	[ "j", qr/SpamAssassin [(]score=([56789]|[1-9][0-9]+)[.][0-9]+/ ],
	[ "!", qr/SIGHUP received: re-exec daemon|exim [0-9.]+ daemon started|(Start|End) queue run:/ ],
);

my $datetime = "";
my $time = "";
my $bad = 0;
my $junk = 0;
my $count = 0;
my $ingood = 0;
my $outgood = 0;
my $s_bad = 0;
my $s_junk = 0;
my $s_count = 0;
my $s_ingood = 0;
my $s_outgood = 0;

sub smooth (\$$) {
	my $var = shift;
	my $add = shift;
	$$var = $$var * 59/60 + $add * 1/60;
}

sub percent ($$) {
	my $a = shift;
	my $b = shift;
	return $b ? $a * 100 / $b : 100;
}

while (<>) {
NL:	until ($v) {
		/^(.{7}(.{9}))/;
		last NL if $1 eq $datetime;
		if (not $datetime) {
			$datetime = $1;
			$time = $2;
			print $r ? $datetime : $time;
			last NL;
		}
		$datetime = $1;
		$time = $2;
		smooth $s_bad, $bad;
		smooth $s_junk, $junk;
		smooth $s_count, $count;
		smooth $s_ingood, $ingood;
		smooth $s_outgood, $outgood;
		if ($r) {
			printf $space x ($columns - 60 - $count) .
			    "$colour{off} %3d %2d  %2d %2d  %2d %1d %3d %-2d %2d %3.1f  %2d %2d$nl$datetime",
			    $count, $s_count,
			    $bad, $s_bad,
			    $ingood, $s_ingood,
			    $outgood, $s_outgood,
			    $junk, $s_junk,
			    percent($s_bad, $s_bad + $s_outgood),
			    percent($s_junk, $s_ingood);
		} else {
			printf $space x ($columns - 20 - $count) .
			    "$colour{off} %2d %2d %2d$nl$time",
			    $s_count,
			    percent($s_bad, $s_bad + $s_outgood),
			    percent($s_junk, $s_ingood);
		}
		$bad = 0;
		$junk = 0;
		$count = 0;
		$ingood = 0;
		$outgood = 0;
		last NL;
	}
	for my $ref (@pat) {
		my ($sym,$pat) = @$ref;
		if(/($pat)/) {
			if ($v) {
				colprint "$1\n";
			} else {
				colprint $sym;
				$count++;
				$bad++ if $sym =~ /\w/;
				$junk++ if $sym eq "j";
				$ingood++ if $sym eq $lt;
				$outgood++ if $sym eq $gt or $sym eq "-";
			}
			last;
		}
	}
}
