package Parse::Syslog;

# $Id: Syslog.pm,v 0.90 2000/07/24 04:20:47 sweth Exp $
# Copyright 2000 Sweth Chandramouli

# Parse::Syslog is really simple: the new() method creates an object to
# reference a Syslog message object, while the message() object method
# takes a string containing a syslog message, which it parses and whose
# relevant values are put into the hash of the Syslog object it was
# passed.  All succesful parsings will populate the hash keys "month",
# "day", "time", and "host".  If the string is a syslog-coalesced "last
# message repeated N times" message, the hash key "count" will be set to
# N, and the "tag" and "text" keys are unset.  Otherwise, the "text" key
# will be populated with the actual syslog message itself, and the "tag"
# key # will be populated with the syslog tag, without the trailing colon;
# if the tag contains a PID in [brackets] at its end, then that will also
# be stripped, and the PID will be put in "pid".  If the string passed to
# message() is not a valid syslog message, the method will return false.

# That wasn't very clear.  Here's an example that will parse
# /var/adm/messages:

#use Parse::Syslog;
#$syslog = Parse::Syslog->new();
#open (SYSLOG, '/var/adm/messages');
#while (my $line = <SYSLOG>) {
#   $syslog->message($line);
#   print $syslog->{tag};
#   if ($syslog->{pid}) {
#      print "(" , $syslog->{pid}, ")";
#   };
#   print ":", $syslog->{text}, "\n";
#};

# If that doesn't clear things up, just read the code; I tried to make
# it easy to read.

my @REVISION = qw($Revision: 0.90 $);
my $VERSION = $REVISION[1];

use Exporter;

@ISA       = qw( Exporter );
@EXPORT    = qw( message );
@EXPORT_OK = qw( new );

sub new {
   my $self  = {
      month => undef,
      day   => undef,
      time  => undef,
      host  => undef,
      count => undef,
      tag   => undef,
      pid   => undef,
      text  => undef
   };
   bless ($self, shift);
}

sub message {
   my $self = shift; # Get the object reference
   if (@_) {
      my $line = shift;
      chomp ($line);
      if ($line =~ /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+last message repeated (\d+) times?$/) {
         $self->{month} = $1;
         $self->{day}   = $2;
         $self->{time}  = $3;
         $self->{host}  = $4;
         $self->{count} = $5;
         $self->{tag}   = undef;
         $self->{pid}   = undef;
         $self->{text}  = undef;
      } elsif ($line =~ /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
         $self->{month} = $1;
         $self->{day}   = $2;
         $self->{time}  = $3;
         $self->{host}  = $4;
         $self->{count} = undef;
         $self->{tag}   = $5;
         $self->{text}  = $6;
         $self->{tag} =~ s/:$//;
         if ($self->{tag} =~ s/\[([^]]+)\]//) {
            $self->{pid} = $1;
         } else {
            $self->{pid} = undef
         };
         # I wanted to have this return $self->{text}, but it's technically
         # possible for a syslog message to not have any text, in which case
         # it would appear that this method had failed.
         return 1;
      } else {
         $self->{month} = undef;
         $self->{day}   = undef;
         $self->{time}  = undef;
         $self->{host}  = undef;
         $self->{tag}   = undef;
         $self->{pid }  = undef;
         $self->{text}  = undef;
         return 0;
      };
   } else {
      return 0;
   };
};