#!/usr/athena/bin/perl -w

use POSIX qw(isatty);

$my_zlogdir = "/var/tmp/noctzlog";

$file  = "";
$zephyrs = 4 ;
$no_more = isatty(STDOUT)?0:1;
$file_on_stdin = isatty(STDIN)?0:1;
$no_tail = 0 ;
$no_spam = 1 ;
$simple  = 0;
$tail = &find_tail();
%umap = ();
$lastdate = "";

while(@ARGV) {
    $arg = shift @ARGV;

    if ($arg eq "-f") {
	$file = shift @ARGV;
    } elsif ($file eq "") {
	$file  = "${my_zlogdir}/zlog.${arg}";
    } elsif ($arg =~ /^\d+$/) {
	$zephyrs = $arg;
    } elsif ($arg =~ /^--?(nomore|raw)$/) {
	$no_more = 1;
    } elsif ($arg =~ /^--?spam/) {
	$no_spam = 0;
    } elsif ($arg =~ /^--?simple/) {
	$simple = 1;
    } elsif ($arg =~ /^--?nick/) {
	my $map = shift @ARGV;
	if ($map =~ /^([^=]+)=([^=]+)$/) {
	    $umap{"$1\@athena.mit.edu"} = $2;
	    $umap{"$1\@ATHENA.MIT.EDU"} = $2;
	    $umap{$1} = $2;
	} else {
	    die "Cannot parse map \"$map\"\n";
	}
    } else {
	print("Hm, unrecognized arg \"$arg\". Aborting.\n");
	exit(1);
    }
}

if ($zephyrs == 0) {
    $no_tail = 1;
}

&main($file, $zephyrs);

sub main {
    local($file, $zephyrs) = @_;
    
    if (!$no_more) {
	open(OUT, "|more");
    } else {
	open(OUT, ">&STDOUT");
    }

    if ($file_on_stdin) {
	open(LOG, "<&STDIN");
    } elsif (!$no_tail) {
	open(LOG, "${tail} -${zephyrs} ${file} |");
    } else {
	open(LOG, "<${file}");
    }
    while (<LOG>) {
	&print_zephyr($_);
    }
    close(LOG);

    close(OUT);

    exit(0);
}

sub print_zephyr {
    chop;         # remove newline which separates zephyrs in log
    s/\\\\/\\b/g; # to avoid problems with, say, "\\\\not a newline"
    s/\\n/\n/g;
    s/\\w/\cw/g;  # \cw is control-w
    s/\\b/\\/g;   # to grab the backslashes after all
#    s/\ct\ct/\n/g;


    ($sender, $recipient, $class, $instance, $opcode, $body,
     $auth, $sig, $ztime, $zdate, $fromhost) = split('\t');

    if ($class =~ /^syslog$/i) {
	return;
    }

    if (($class =~ /^mail$/i) && $no_spam &&
	($body =~ /new mail in INBOX.Spamscreen/)) {
	# Unless --spam flag is given, don't look at spam notification
	return;
    }

    $auth = &authparse($auth);

    if ($simple) {
	return if ($opcode =~ /^ping$/i);

	if ($lastdate ne "" && $lastdate ne $zdate) {
	    print OUT "\n", ("=" x 60), "\n\n";
	}
	my $nick = nickname($sender);

	print OUT ("$nick ($ztime $zdate):\n  ",
		   join("\n  ", split("\n", $body)),
		   "\n\n");

	$lastdate = $zdate;
	return;
    }

    if ($opcode =~ /^ping$/i) {
	print OUT ("    ZPING! ($ztime)\n");
	print OUT ("$sender\@$fromhost\n");
    } elsif (($class =~ /^login$/i) && ($opcode =~ /^USER_LOG(IN|OUT)$/)) {
	&leftcprint(((($opcode =~ /LOGIN/)?"LOGIN":"LOGOUT") . ", $sender"),
		    "on $fromhost",
		    "$ztime $zdate");
    } elsif (($class eq "Mail") && ($sender eq "") &&
	     ($body =~ s/You have new mail.*\n\n//)) {
	$body =~ s/From Post Office \S+.mit.edu:\n//;
	print OUT "New Mail:\n";
	foreach (split(/\n/, $body)) {print OUT " $_\n" ;}
	print OUT "\n";
    } else {
	($opcode ne "") && &cprint("Opcode: $opcode");

	&cprint("$auth   To: $recipient");
	if ($class =~ /^message$/i) {
	    if ($instance !~ /^personal$/i) {
		&cprint("Instance: $instance");
	    }
	} else {
	    &cprint("Class: $class, Instance: $instance");
	}
	&cprint("$ztime $zdate");
	&cprint(split(/\n/, "$sig <$sender>\n"));
	
	&cprint("\@$fromhost");
	print OUT ("\n$body\n\n");
    }
}

sub nickname {
    my($full) = @_;

    if (!exists $umap{$full}) {
	$umap{$full} = $full;
    }
    return($umap{$full});
}

sub padToSize {
    local($width, $str) = @_;
    my $pad = $width - length($str);
    if ($pad < 0) {
	$pad = 0;
    }
    return $pad;
}

sub leftcprint {
    local(@s) = @_;
    local($max, $len) = (0, 0);

    # print a set of lines, centered, but left-shifted
    for $line (@s) {
	($max < ($len = length($line))) && ($max = $len);
    }

    foreach $l (@s) {
	# fake it for now
	print OUT (" " x (padToSize($max, $l)/2), $l, "\n");
    }
}

sub cprint {
    # print a line, centered on screen
    local(@s) = @_;

    foreach $l (@s) {
	# fake it for now
	print OUT (" " x (padToSize(80, $l)/2), $l, "\n");
    }
}

sub authparse {
    # return string corresponding to auth
    local($a) = @_;
    ($a eq "+ ") && return "Authentic";
    ($a eq "- ") && return "Unauthentic";
    ($a eq "? ") && return "Forged";
    return "badauth-$a";
}


sub find_tail {
    local($tail) = "/mit/gnu/bin/gtail";
    if ( ! -f $tail ) {
	$tail = "tail";
    }
    if (! open(FTEST, ("</mit/gnu/bin"))) {
	$tail = "tail";
	print STDERR "Error in checking for gnu locker was $?\n";
	print STDERR "No gnu tail available. Using system version.\n";
    }
    close(FTEST);
    return($tail);
}

