#!/usr/bin/perl
#
#  Copyright 2006 by Jim Brown
#  Author:  Jim Brown, ThruPoint Inc. 
#  email :  jbrown@thrupoint.net 
#  Date  :  May 14, 2006 
#
#  Tue Nov 27 21:09:51 UTC 2018:  This software is now
#  placed in the public domain.
#  #include <std_disclaimer.h> i.e. use at your own risk.
# 
########################################################################################
#
#
# NAME: 
#     file2syslog.pl - script to send files to the Log Collection host at a defined speed.
#
#
# SYNOPSIS:
#     perl file2syslog.pl num [file_list]
#
# DESCRIPTION:
#     This script reads through the input files and sends
#     entries to the syslog server at a defined speed.
#     Pattern matching is supported by changing the logpatterns array. (see below).
#
# INPUT FORMATS:
#     Any text based input, limited to 250 bytes.
#
# OUTPUT FORMATS:
#     Output is syslog entries formatted for syslog.
#
#
# MODIFICATION HISTORY:
#     Created: 07/31/03  - Jim Brown, ThruPoint Inc.  (jbrown@thrupoint.net)
#     Re-Created: 05/14/2006  - Jim Brown, ThruPoint Inc.  (jbrown@thrupoint.net)
#
#      This script now uses IO::Socket to format and send a UDP message to the remote
#      Log Collection server.  We can't use Sys::Syslog because it only writes to the local
#      syslogd process, depending on that process forward the message.
#
#      This version formats the message per RFC 3164 directly, with the exception that
#      we send the entire FQDN in the message like Solaris does.
#
###########################################################################################################

# Set for unbuffered IO.
$| = 1;

sub usage()
{
  print "\nUsage:  file2syslog.pl num  [file_list]\n";
  print "           where  num       is a decimal throttle in seconds\n";
  print "                  file_list is a list of files to print\n\n";
  print "                A thottle value must be specified.  There is no default value.\n";
  print "                Use 0 to print with no delay, .25 to print with 1/4 second delay, etc.\n";
  print "                An empty file_list prints from STDIN\n\n";
  exit 1;
} 


$throttle = shift (@ARGV);

if (!($throttle =~ /\d+/))
{
  &usage;
}


# Use logpatterns for pattern matching.  Default is no.
$use_logpatterns = 1;

# Patterns for the messages we care about.
# Note: to add a new pattern, create a regex as below with NO spaces.  Use \s+ for spaces.
# Last entry is a test pattern, and can be removed.
#

@logpatterns = qw(
(.*?)\%SYS-SP-STDBY-\d+-RESTART:\s+System\s+restarted(.*)
(.*?)\%SYS-\d+-RESTART:\s+System\s+restarted(.*)
(.*?)\%SYS-\d+-RELOAD:\s+Reload\s+requested\s+by(.*)
(.*?)\%SYS-\d+-CONFIG_I:\s+Configured\s+from\s+\S+\s+by\s+\S+\s+on\s+\S+(.*)
(.*?)\%SYS-\d+-CONFIG_I:\s+Configured\s+from\s+\S+\s+by\s+\S+
\s*foobar(.*)
);


# The remote Log Collection Server.
$remote_host = "127.0.0.1";     # Change to a remote hostname if needed.
$remote_port = "514";


# The facility and level.
$facility_and_level = "<150>";  #local2.info  HARDCODED for now.



use POSIX qw(strftime);
use IO::Socket;

# Next the hostname.  
$myhostname = `hostname`;
chop $myhostname;

# Next we need our name and pid.
$procname = "file2syslog";
$mypid = $$;

# Bring up the socket
#
$socket = IO::Socket::INET->new(PeerAddr  => $remote_host,
                                PeerPort  => $remote_port,
                                Proto     => "udp")

   or die "Couldn't open UDP socket to syslog for $remote_host : $remote_port :$@\n";


# Our own banner
$msgtext = "file2syslog STARTED";

# OK, let's fire it up...
&sendit($msgtext);


#
# Scan through the input file and send to syslog.
# If $use_logpatterns is set, attempt to match the 
# input to an entry in logpatterns array.  If found
# send to syslog, if not, just skip the line.
# If $use_logpatterns is not set, log every line
# to syslog.
#

while(<>)
{

  $inputline = $_;
  chop $inputline;

    # If $use_logpatterns is set, look
    # through the logpattern array for a match.

    if($use_logpatterns)
    {
      foreach $pat (@logpatterns)
      {
        if ($inputline =~ /^$pat$/)
        {
          # We have a line from the file.
#         print STDERR "*** Found pattern [$pat],[$inputline]\n";

          &sendit($inputline);

          # Continue on to the next pattern line.
          last;  
        }
      }
     }
     else
     {
        &sendit ($inputline);
     }

  # Don't (or do) be a speed-demon.
  select undef, undef, undef, $throttle;


}



#
# Last call...
#

$msgtext = "file2syslog ENDED";

&sendit($msgtext);



#
# End of program.
#



sub sendit()
{  my $in_line = shift(@_);

#   print "[$in_line]\n";

#
# Send a line to syslog.
#

# Correctly formatted date and time for this message.
$now_string = strftime "%b %e %H:%M:%S", localtime;  

# If any scrubbing must be done, do it here.
# The line we found.
$msgtext = $in_line;

# Putting it all together...
$syslog_message = "$facility_and_level${now_string} ${procname}[$mypid]: $msgtext";

# Send it on its merry way...
print $socket $syslog_message;

}





