#!/usr/pkg/bin/perl
#
# @(#)proc-cron.pl,v 1.4 2004/04/23 06:14:31 kim Exp
#
# Look through /var/log/cron for things which might be errors (sorted
# by machine) and put them on stdout.
#
# 2000-08-08  Kimmo Suominen
#

%HOST	= ();			# Hash of arrays
@ODD	= ();			# Oddly formatted messages
$COUNT	= 0;
$DIV	= '=' x 72 . "\n";

# Log line exaple:
#
#	Aug  8 00:05:00 hrothgar CRON[24970]: (root) CMD (/usr/libexec/atrun) 
#
# If the word 'last' (as in 'last message repeated') appears in the facility
# position than the message is treated as an independent message associated
# with the previous message.
#
while( <> ) {

    # Take apart the front of the line
    ( $mon, $dom, $time, $rest ) = split( ' ', $_, 4 );

    # Is the first whitespace after the hostname a tab?
    if ( $rest =~ /(\s)/ && $1 eq "\t" ) {
	( $host, $facility, $msg ) = ( $`, '', "\t$'" );
    } else {
	( $host, $facility, $msg ) = split( / /, $rest, 3 );
	if ( $facility eq "last" ) {
	    ( $facility, $msg ) = ( "", "$facility $msg" );
	} elsif ( $facility !~ /:$/ ) {
	    ( $facility, $msg ) = ( "", "\t$facility $msg" );
	}
    }

    # Grab corrupted lines early...
    if ( !defined($msg) || $msg eq '' || $facility =~ /^ / ) {
	push( @ODD, $_ );
	next;
    }

    #
    # Treat continuations of the previous message in the same way we
    # treated the previous message.  This handles "last message 
    # repeated..." and also things like the multi-line named startup
    # message.
    #
    if ( $facility eq '' || $msg =~ /^\s/ ) {
	push( @$origin, "$mon $dom $time $facility$msg" ) if defined($origin);
	next;
    }
    undef $origin;

    # Some messages are known to be innocuous...
    &skipcron($msg) && next;

    # Origin is the array reference within %HOST which we are to use
    $origin = ($HOST{$host} ||= []);

    # Put the message in the appropriate list...
    push( @$origin, "$mon $dom $time $facility $msg" );

}

Report("STDOUT");

exit 0;

sub Report
{
    my( $fd ) = @_;

    &Dump($fd,"Badly Formatted Lines",\@ODD);

    foreach $host ( sort(keys(%HOST)) ) {
	&Dump($fd,$host,$HOST{$host});
    }
}

sub Dump
{
    my( $fd, $title, $msgs ) = @_;

    # Skip hosts with no messages
    return unless @$msgs;

    # Add some whitespace unless this is the first host
    print $fd "\n\n" if $COUNT++;

    # Dump output (@$msgs has newlines already)
    print $fd $DIV, "$title\n", $DIV, "\n", @$msgs ;
}

sub skipcron
{
    my( $msg ) = @_;

    return 1 if $msg =~ /^\(\S+\) CMD (FINISH|START) \(/;
    return 1 if $msg =~ /^\(\S+\) (CMD|RELOAD) \(/;
    return 1 if $msg =~ /^\(\S+\) (DELETE|LIST|REPLACE) \(\S+\)\s*$/;
    return 1 if $msg =~ /^\(\S+\) (BEGIN|END) EDIT \(\S+\)\s*$/;

    return 0;
}
