#! /usr/bin/perl -w
#
# check_eventdb.pl - nagios plugin
#
# Copyright (C) 2009 Martin Fuerstenau <mf_at_maerber.de>
# Based on the script of Gerd Mueller
# Copyright (C) 2006 Gerd Mueller / Netways GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#

# Changes:
# 
# 2009-06-11: Martin Fuerstenau <mf_at_maerber.de>
#             - Added the ability to check program filed from the database. It can be
#               be delivered by all agents but wasn't used yet 
#             - Added $opt_dbuser and $opt_dbpasswd in "default values".
#               So there is no need to add a lot of users/password in the Nagios command
#               definition file
#
# 2009-09-25: Martin Fuerstenau <mf_at_maerber.de>
#             Version 2
#             Corrections:
#             - Code reformatting for better readability. Mainly it means putting corresponding
#               braces and brackets in the same column
#
#             - use subs qw(add_part myexit print_usage); removed from code. It was obsolete here 
#               due to the fact that all subroutines a called in a distinct manner i.e. 
#               print_usage() and NOT print_usage. print_usage would be interprated as a bareword
#               due to use of strict.
#
#             - Removed declaration of global variables because declaration of local variables (my...)
#               works in the same way when placed at the beginning of the program and you have the 
#               benefit do place declaration, default preset ans comment in one line
#
#             - $update removed because it was unused
#
#             - @sql and @params replaced by $sql for some reasons:
#               - easier and more effective to store statement in a variable than
#                 in a array and join all elements together to get a string.
#               - easier to use a string directly in a variable than to use a sprintf and variable
#                 values seperatly
#
#             - Reformatted print_usage to have help output better to read 
#
#             - in add_part my ($field, $value, $op, $agg) = @_; was shortened to
#               my ($field, $value) = @_; due to the fact that $op and $agg were never passed via
#               function call
#
#             - $op and $agg now defined "presets and declarations" instead of add_part
#
#             - use Config::IniFiles; removed from code because it was not used.
#
#             - Replaced the myexit call in print_usage with a simple exit in the if statement at
#               the beginning of the code because the output of myexit could be a little bit
#               confusing to the user.
#
#             - The only used SQL statement "SELECT COUNT(uid) as count from $opt_dbtable where 1"
#               was replaced.
#               - "as count" was absolutely not necessary because "count" as column name was used
#                  nowhere
#               - the statement would not work in the case it should give back ID (database uid)
#                 or messagestrings. Instead of this $rowcnt (Row counter) was used to determine
#                 the number of rows in an array.
#
#             - Replaced in myexit() $out .= chr(10) with $out .= "\n" for better readability.
#               Who knows today which ASCII is what. And as a second reason \n (new line) is safer.
#               On a Unix/Linux system it means chr(10) which is a linefeed, on a Windows system it
#               means chr(10)/Linefeed  and chr(13)/Carriage return.
#
#             - $agg stored only the scalar AND for the select statement and was only used in one
#               place. Therefore the variable was removed and the scalar was used directly in the
#               statement. This make the statement easier to read and to maintain.
#
#             - A return code of -1 in myexit() for UNKNOWN was not correct (It results in a 255 on the shell).
#               According to the Nagios manual UNKNOWN should cause in a 3. Corrected. 
#
#
#             New functions and options:
#
#             - -r|--regexp will treat messagestrings as regular expressions
#
#             - -s|--show shows the found messages in Nagios. Lenght of string can be set
#               in $message_lenght and multilineoutput can be HTML style or Nagios 3 style.
#               See $ml_show_msg.
#
#             - --acknowledged  will include acknowledged entries in the select statement
#
#             - --version added to print program version
#
#             - Values for priority can be added as single scalar (for example emerg) or as a comma
#               separated list (for example emerg,alert,crit)
#
#             - variable §matches removed. It was replaced by $rowcnt because we let not count
#               the database. We count the rows received from the database.  
#
#             - --maxage  Maximum age for records use for alerts
#
#             - Acting as eventhandler:
#               In case of using check_eventdb as a event handler all three variables (--servicestate,
#               --servicestatetype and --serviceoutput) nust be used together. Records found
#                 will be acknowledged.
#               --servicestate Contains $SERVICESTATE$ from Nagios if started as eventhandler
#                 for acknowledging or deleting records/entries
#               --servicestatetype Contains $SERVICESTATETYPE$ from Nagios if started as eventhandler
#                 for acknowledging records/entries
#               --serviceoutput Contains $SERVICEOUTPUT$ from Nagios if started as eventhandler
#                 for acknowledging or deleting records/entries.  $SERVICESTATE$ MUST be OK or UP,
#                 $SERVICESTATETYPE$ MUST be hard and $SERVICEOUTPUT$ should contain the output of
#                 your "submit passive check result" together with the name of the operator
#                 (for example "problem fixed - D.Duck")
#
# Noch einbauen
#             - --recover  The messagestring following this will cause a recovery. Wildcards are
#               allowed. If -r is set the string will be interpreted as a regular expression. -H
#               must been set. And the message containing the recovery string must be the latest.
#               If there are alerts newer than the recovery string only this alerts are used.
#
#               --recover_regexp Interpret recoverstring as regular expression (awk/sed style).
#               Works only with --recover set.
#
#               --recover_prio  The messagestring following this will contain the priority for
#               recovery -H must been set.
#
#               --recover_prog This will contain a name of a program causing the recovery in case
#               the recovery message is not sent by the program causing the error. -H must been set.


use strict;
use Getopt::Long;
use File::Basename;
use DBI;

#--- Start presets and declarations ----------------------------------------------------------------

my $PROGNAME = basename($0);
my $VERSION  = '2.0';
my $opt_db       = "eventdb";               # Database name
my $opt_dbtable  = "events";                # Table for query
my $opt_dbhost   = "localhost";             # Database host
my $opt_dbuser   = "eventdb";               # Connecting user
my $opt_dbpasswd = "ereichniss";            # As it says ....
my $opt_host     = "";                      # Host to look for when searching
my $opt_msg      = "";                      # Messages searched

my @uid;                                    # Here we have arrays for all fields from the database
my @type;                                   # we select. Using this we can access every line of the
my @host;                                   # result in a simple manner. We use this for example 
my @facility;                               # for assembling the message line send to Nagios if the 
my @priority;                               # messages from the database are wanted. By default
my @program;                                # Nagios 3.x can display 4 KB of text. Messagelines will
my @datetime;                               # be cut to $message_lenght. Adjust it for your needs
my @message;                                # 

my $message_lenght = 20;                    # As mentioned above cut messages to number
                                            # of characters

my $opt_show_message;                       # Display messages found 
my $msg2show;                               # Messages to be displayed 

my $ml_show_msg = '0';                      # Multilinestyle of displayed messages
                                            # 0 = Nagios 3 mulitlinestype
                                            # 1 = HTML style (adds <BR> to output

my $opt_priority = "";                      # The message priority either in Nagios or syslog format
                                            #
                                            # Syslog format:
                                            # emerg   - A panic condition was reported to all processes.
                                            # alert   - A condition that should be corrected immediately.
                                            # crit    - A critical condition.
                                            # err     - An error message.
                                            # warning - A warning message. 
                                            # notice  - A condition requiring special handling.
                                            # info    - A general information message.
                                            # debug   - A message useful for debugging programs.
                                            #
                                            # Nagios format:
                                            # down 
                                            # critical
                                            # warning
                                            # unreachable
                                            # unknown
                                            #
                                            # Opposite to Syslog format there can be positive events
                                            # in Nagios format:
                                            # up
                                            # ok 


my $opt_label    = "";                      # You can place an optional label between OK/WARNING/CRITICAL
                                            # and the returned message string. maybe helpfull in command
                                            # definitions
my $opt_type     = "";                      # With this you can search for the type (syslog,mail,snmptrap...) 
my $opt_facility = "";                      # If the messages are caused by syslog it contains the service-
                                            # name or component causing the message. In all other cases 
                                            # look at the documentation of the relevant agent.
my $opt_program = "";                       # Program (or something like that) causing the error.
my $opt_help;                               # Needed for displaying the help message
my $opt_critical;                           # As it says ...
my $opt_warning;                            # As it says ...
my $opt_ack;                                # Acknowledged or not? 0 means don't look for acknowledged 
                                            # problems
my $opt_ack_default = '0';                  # Default for $opt_ack
my $opt_regexp;                             # Interpret input as regular expression (awk/sed style)
                                            # Will only work if -m is given

my $opt_recover;                            # If this is set it contains the recovery string. 
my $opt_recover_priority;                   # If this is set it contains the priority code for recovery. 
my $opt_recover_program;                    # This can to be set if the recovering is not caused by the
                                            # program causing the error
my $opt_recover_regexp;                     # Interpret recoverstring as regular expression (awk/sed style)

my $nag_servicestate;                       # Contains $SERVICESTATE$ from Nagios if started as
                                            # eventhandler for acknowledging or deleting records/entries
my $nag_servicestatetype;                   # Contains $SERVICESTATETYPE$ from Nagios if started as
                                            # eventhandler for acknowledging or deleting records/entries
my $nag_serviceoutput;                      # Contains $SERVICOUTPUT$ from Nagios if started as
                                            # eventhandler for acknowledging or deleting records/entries
my $eventhandler = '0';                     # Do we act as eventhandler?
                                            # 0 = Normal check plugin
                                            # 1 = Eventhandler

my $opt_maxage;                             # Maximum age for records
my $opt_show_version;                       # Only as a switch to show the version number
my $dbh;                                    # The database handle
my $sth;                                    # The statement handle
my $result;
my @row;                                    # Contains alla rows returned from SQL statement
my $rowcnt = 0;                             # Number of rows returned from the SQL statement
my $reco_rowcnt = 0;                        # Needed for additional lines containing the recovery lines
my $tmp_rowcnt = 0;                         # Only needed for temporary storage of counters
my $sql;                                    # Contains the SQL statement
my $sql_part;                               # Contains the part SQL statement built in add_part()
my $op;                                     # It is the operand for selects like AND,OR,LIKE...
my $counter;                                # So if we need a counter (for loops or so) we now
                                            # have one for general purpose

#--- End presets and declarations ------------------------------------------------------------------

#GetOptions
Getopt::Long::Configure('bundling');
GetOptions(
          "a"                   => \$opt_ack,
          "acknowledged"        => \$opt_ack,
          "c=i"                 => \$opt_critical,
          "critical=i"          => \$opt_critical,
          "db=s"                => \$opt_db,
          "dbtable=s"           => \$opt_dbtable,
          "dbuser=s"            => \$opt_dbuser,
          "dbpassword=s"        => \$opt_dbpasswd,
          "dbhost=s"            => \$opt_dbhost,
          "f=s"                 => \$opt_facility,
          "facility=s"          => \$opt_facility,
          "h"                   => \$opt_help,
          "help"                => \$opt_help,
          "H=s"                 => \$opt_host,
          "host=s"              => \$opt_host,
          "l=s"                 => \$opt_label,
          "label=s"             => \$opt_label,
          "maxage=s"            => \$opt_maxage,
          "m=s"                 => \$opt_msg,
          "msg=s"               => \$opt_msg,
          "p=s"                 => \$opt_priority,
          "priority=s"          => \$opt_priority,
          "P=s"                 => \$opt_program,
          "program=s"           => \$opt_program,
          "r"                   => \$opt_regexp,
          "regexp"              => \$opt_regexp,
          "recover=s"           => \$opt_recover,
          "recover_regexp"      => \$opt_recover_regexp,
          "recover_prio=s"      => \$opt_recover_priority,
          "recover_prog=s"      => \$opt_recover_program,
          "s"                   => \$opt_show_message,
          "show"                => \$opt_show_message,
          "servicestate=s"      => \$nag_servicestate,
          "servicestatetype=s"  => \$nag_servicestatetype,
          "serviceoutput=s"     => \$nag_serviceoutput,
          "t=s"                 => \$opt_type,
          "type=s"              => \$opt_type,
          "version"             => \$opt_show_version,
          "w=i"                 => \$opt_warning,
          "warning=i"           => \$opt_warning,
          ) || die "\n";

# Just print the help - nothing else
if ($opt_help)
   {
   print_usage();
   exit;
   }

# Just print the version number - nothing else
if ($opt_show_version)
   {
   print "$PROGNAME Version $VERSION\n";
   exit;
   }

# Do some general checks to be sure that parameters were entered correctly

# The first thing is to check wether teh srcipt acts as an eventhandler or not
# If it acts as an event handler we have to check that all three parameters has been 
# set in a correct manner.

if ($nag_servicestate || $nag_servicestatetype || $nag_serviceoutput)
   {
   if ($nag_servicestate && ($nag_servicestate =~ m/^-.*/))
      {
      print "Error! --servicestate contains no valid argument!\n";
      exit 1;
      }
   if ($nag_servicestatetype && ($nag_servicestatetype =~ m/^-.*/))
      {
      print "Error! --servicestatetype contains no valid argument!\n";
      exit 1;
      }
   if ($nag_serviceoutput && ($nag_serviceoutput =~ m/^-.*/))
      {
      print "Error! --serviceoutput contains no valid argument!\n";
      exit 1;
      }

   if (!($nag_servicestate && $nag_servicestatetype && $nag_serviceoutput))
      {
      print "Error! If using the progam as eventhandler you have to set all three options:\n";
      print "--servicestate, --servicestatetype and --serviceoutput \n";
      exit 1;
      }
      
   # Well now we have done all to be sure that all arguments for acting as event handler has
   # been set in an approriate manner. Now we can process. First we have to check for correct
   # parameters in --servicestate and --servicestatetype.
   
   if ($nag_servicestate ne 'OK' )
      {
      exit;
      }

   if (!($nag_servicestatetype eq 'HARD' || $nag_servicestatetype eq 'SOFT'))
      {
      exit;
      }
   $eventhandler=1;
   }

# So now we look if acknowledged records should be processed too. If $ops_ack is set to 1
# the add_part subroutine later on will not be processed for ackknowledged

if ($opt_ack)
   {
   $opt_ack = '1';
   }
else
   {
   $opt_ack = $opt_ack_default;
   }
  
# --recover needs the host to be set and it need a valid content
if ($opt_recover)
   {
   if ($opt_recover =~ m/^-.*/)
      {
      print "\nError! --recover needs a recoverstring!\n\n";
      print_usage();
      exit 1;
      }
   if (!$opt_host)
      {
      print "\nError! --recover needs a host to been set!\n\n";
      print_usage();
      exit 1;
      }
   }

# ----recover_prio needs the host to be set and it need a valid content
if ($opt_recover_priority)
   {
   if ($opt_recover_priority =~ m/^-.*/)
      {
      print "\nError! --recover_prio needs a priority!\n\n";
      print_usage();
      exit 1;
      }
   if (!$opt_host)
      {
      print "\nError! --recover_prio needs a host to been set!\n\n";
      print_usage();
      exit 1;
      }
   }

# --recover_prog needs the host to be set and it need a valid content and
# either a valid priority and/or a valid messagestring
if ($opt_recover_program)
   {
   if ($opt_recover_program =~ m/^-.*/)
      {
      print "\nError! --recover_prog needs a program name!\n\n";
      print_usage();
      exit 1;
      }
   if (!$opt_host)
      {
      print "\nError! --recover_prog needs a host to been set!\n\n";
      print_usage();
      exit 1;
      }
   if (!$opt_recover)
      {
      if (!$opt_recover_priority)
         {
         print "\nError! --recover_prog needs a valid priority or a messagestring to been set!\n\n";
         print_usage();
         exit 1;
         }
      }
   }

# Values for critical and warning are absolutely necessary
if (!$opt_critical)
   {
   print "\nError! No values given for critical!\n\n";
   print_usage();
   exit 1;
   }

# If --maxage is set lets check for the correct date format
if ($opt_maxage && !($opt_maxage =~ m/....-..-.. ..:..:../))
   {
   print "\nError! --maxage not in correct format! Must be \"YYYY-MM-DD HH:MM:SS\".\n\n";
   exit 1;   
   }

# Connecting to Database
$dbh = DBI->connect( "DBI:mysql:database=$opt_db;host=$opt_dbhost",
	           $opt_dbuser, $opt_dbpasswd, { PrintError => 0 } )
                   || myexit( 'UNKNOWN', "can't connect to database!" );

# Now lest's build some part of the SQL statement
add_part('host', $opt_host)
        if ($opt_host ne '');

add_part('message', $opt_msg)
        if ($opt_msg ne '');

add_part('priority', $opt_priority)
        if ($opt_priority ne '');

add_part('type', $opt_type)
        if ($opt_type ne '');

add_part('facility', $opt_facility)
        if ($opt_facility ne '');

add_part('program', $opt_program)
        if ($opt_program ne '');

add_part('datetime', $opt_maxage)
        if ($opt_maxage && ($opt_maxage ne ''));

add_part('acknowledged', $opt_ack)
        if ($opt_ack eq '0');


# We have no longer a simple "Count matches" here. We start constructing the
# SQL-Statement using 

$sql = "SELECT uid,type,host,facility,priority,program,UNIX_TIMESTAMP(datetime),message";
$sql .= " from $opt_dbtable where $sql_part order by datetime";

prepare_sql();
execute_sql();

if ($result)
   {
   get_the_row_jack();
   }

# So now we look for a recovery cause by message or program or prio or a mix of that
if ($opt_recover || $opt_recover_priority || $opt_recover_program)
   {
   
   # Reset $sql_part
   $sql_part = "";
     
   
   # Well if $opt_regexp was set it has been processed and we need it no longer
   # So know we have to determine if the recover message should be handled as
   # a regular expression
   
   $opt_regexp = $opt_recover_regexp;
  
   
   add_part('host', $opt_host)
           if ($opt_host ne '');

   add_part('message', $opt_recover)
           if ($opt_recover && ($opt_recover ne ''));

   add_part('priority', $opt_recover_priority)
           if ($opt_recover_priority && ($opt_recover_priority ne ''));

   add_part('type', $opt_type)
           if ($opt_type ne '');

   add_part('facility', $opt_facility)
           if ($opt_facility ne '');

   add_part('program', $opt_recover_program)
           if ($opt_recover_program && ($opt_recover_program ne ''));

   $sql = "SELECT uid,type,host,facility,priority,program,UNIX_TIMESTAMP(datetime),message";
   $sql .= " from $opt_dbtable where $sql_part order by datetime";

   prepare_sql();
   execute_sql();

   # We must store the old rowcounter. We need it later

   $tmp_rowcnt = $rowcnt;

   if ($result)
      {
      get_the_row_jack();
      }

   $reco_rowcnt = $rowcnt;
   $rowcnt = $tmp_rowcnt;
   
   if ($reco_rowcnt > $rowcnt)
      {
      # Now $rowcnt contains the index of the last record +1 for alerts
      # and $reco_rowcnt contains the index of the last record +1 for recovery messages
      # We now have to look if the data for the record indicated by $reco_rowcnt
      # is newer than the record indicated by $rowcnt
   
      if ($datetime[$reco_rowcnt-1] > $datetime[$rowcnt-1])
         {
         set_acknowledge('Event',"Records has been reset by $facility[$reco_rowcnt-1] with record id: $uid[$reco_rowcnt-1] - priority: $priority[$reco_rowcnt-1] - program: $program[$reco_rowcnt-1] - message: $message[$reco_rowcnt-1]");

         $rowcnt=0;
         }
      }
   }

# Following mesages to Nagios only if acting as plugin
if ($eventhandler == 0)
   {
   
   # First disconnect from the database
   dbh_disconnect();
   
   if ($rowcnt >= $opt_critical)
      {
      myexit( 'CRITICAL', $rowcnt . " matches found!", "matches=$rowcnt" );
      }
   else
      {
      if ($opt_warning && $rowcnt >= $opt_warning)
         {
         myexit( 'WARNING', $rowcnt . " matches found.", "matches=$rowcnt" );
         }
      else
         {
         myexit( 'OK', $rowcnt . " matches found.", "matches=$rowcnt" );
         }
      }
   }

# And now the code for the event handler. Remember - we are still connected to the database 
if ($eventhandler == 1)
   {
   set_acknowledge('Nagios',"$nag_serviceoutput");
   
   # And disconnect from database   
   dbh_disconnect();
   exit;
   }

myexit( 'Default exit', 'Unknown results - using default exit' );


# Begin subroutines ------------------------------------------------------------------------

sub set_acknowledge
    {
    my $ack_author = $_[0];
    my $ack_msg = $_[1];

   # Now we set "acknowledged" to 1 in all relevant records 
   for ($counter=0;$counter<$rowcnt;$counter++)
       {
       $sql = "update events set acknowledged = '1' where uid = $uid[$counter] limit 1";
       prepare_sql();
       execute_sql();
       $sql = "insert into comments (uid,event_fk,author,type,comment,crdate) ";
       $sql .= "values (NULL,$uid[$counter],'.$ack_author.','ack','".$ack_msg."',now())";
       prepare_sql();
       execute_sql();
       } 
    }


sub myexit
    {
    my $time;
    my $date;

    my $status = $_[0];
    my $text = $_[1];
    my $perfdata = $_[2];

    my %STATUS_CODE = ( 'Default exit' => '3', 'OK' => '0', 'WARNING' => '1', 'CRITICAL' => '2' );
    my $out = undef;

   if ($opt_show_message)
      {
      # First we prepare the message string
      for ($counter=0;$counter<$rowcnt;$counter++)
          {
          $msg2show .= "$message[$counter]\n";
          }
      }


    # Hint for the people not so fit in perl: $var .= " foo" is the same as $var = $var." foo" 
    # is the same as  $var = "$var foo" . It is only shorter.
 
    # Nagios 3.x multiline output
    if ($ml_show_msg == 0)
       {
       $out .= "$status: $opt_label $text";
       $out .= " - Additional info in Service State Information" if ($opt_show_message && $msg2show && !($status =~ m/^Default exit.*/));
       $out .= "|$perfdata" if ($perfdata);
       $out .= "\n";
       $out .= $msg2show if ($opt_show_message && $msg2show && !($status =~ m/^Default exit.*/));
       }

    # For older versions multiline output with HTML code
    if ($ml_show_msg == 1)
       {
       $out .= "$status: $opt_label $text";
       if ($opt_show_message && $msg2show && !($status =~ m/^Default exit.*/))
          {
          chomp $msg2show;
          $msg2show =~ s/\n/<br>/g;
          $msg2show =~ s/^/<br>/g;
          $out .= $msg2show;
          }
       $out .= "|$perfdata" if ($perfdata);
       $out .= "\n";
       }

    print $out;
    exit $STATUS_CODE{$status};
    }

sub add_part
    {
    my ($field, $value) = @_;
    
    # Now lets determine if the messagestring submitted should be interpreted as
    # regular expression or not
    if ($opt_regexp && $field eq 'message')
       {
       $op = 'regexp';
       }
    else
       {
       $op = '=';
       }

    # This is a little bit dirty, but it should work. Using a split to make a array out
    # of the comma seperated list would be cleaner - but who cares? We have to make an OR
    # from the comma.
    if ($field eq 'priority')
       {
       $value =~ s/,/" OR priority = "/g;
       }

    if ($value =~ m/^(\*|\?|\+|\{)/ && lc($op) eq 'regexp')
       {
       print "\nError! According to the options entered messages should be interpreted as regular expression. ";
       print "But the message starts with \"*\" which is a repetition-operator in regular expressions ";
       print "and not a wildcard. Correct expression or remove -r|--regexp to enable wildcard syntax.\n\n";
       exit 1;
       }

    if ($value =~ m/\*|\%/ && lc($op) ne 'regexp')
       {
       $op = 'LIKE';
       $value =~ s/\*/\%/g;
       }

    # Due to the fact that the OR must be interpreted first before all other AND
    # we habe do but some braces around the expression with priority
    if ($field eq 'priority')
       {
       $sql_part .= " AND ($field $op \"$value\")";
       }
    else
       {
       if ($field eq 'datetime')
          {
          $sql_part .= " AND $field > \"$value\"";
          }
       else
          {
          $sql_part .= " AND $field $op \"$value\"";
          }
       }

    # Remove the first AND. Why? If we have an AND first we must have
    # a construct like "where 1 AND..." as it was was in the past. Removing the first AND
    # makes the 1 obsolete an results in a SQL statement which is cleaner (- I think).
    $sql_part =~ s/^ AND //;

    return 1;
    }

sub prepare_sql
    {
    # Preparing the query
    $sth = $dbh->prepare($sql) || myexit( 'UNKNOWN', "Can't preare the query: ". $dbh->errstr );
    }    

sub execute_sql
    {
    # Executing the query
    $result = $sth->execute() || myexit( 'UNKNOWN', "Can't execute the query: ". $sth->errstr );
    }

sub dbh_disconnect
    {
    #Disconnect from the database
    $dbh->disconnect() || myexit( 'UNKNOWN', "Can't disconnect: ". $dbh->errstr );;
    }

sub get_the_row_jack
    {
   while (@row = $sth->fetchrow_array())
         {
         $uid[$rowcnt] = $row[0];
         $type[$rowcnt] = $row[1];
         $host[$rowcnt] = $row[2];
         $facility[$rowcnt] = $row[3];
         $priority[$rowcnt] = $row[4];
         $program[$rowcnt] = $row[5];
         $datetime[$rowcnt] = $row[6];
         $message[$rowcnt] = $row[7];
         
         # And we cut the message as described above
         $message[$rowcnt] = substr($message[$rowcnt],0,$message_lenght);
         $rowcnt++;
         }
    $sth->finish();
    }
    
sub print_usage
    {
    print <<EOU;
Usage: $PROGNAME [ -H|--host <hostname>] [-p|--priority <priority>] [-m|--msg <message>] [--maxage <date>] [-r|--regexp] [-s|--show] [-t|--type <logtype>] [-a|--acknowledged] [-P|--program <program>] [-l|--label <label>] [--version] [--recover <message>] [--recover_regexp] [--recover_prio <prio>] [--recover_prog <program>] [--servicestate <state>] [--servicestatetype <statetype>] [--serviceoutput <output>] [--db <db>] [--dbtabe <dbtable>] [--dbuser <dbuser>] [--dbpassword <dbpassword>] [--dbhost <dbhost>]  -c|--critical <integer> [-w|--warning <integer>]

Options:

-H --host                      Hostname as logged by agent (optional).
-p --priority <priority>       Priority as logged by agent either in Nagios or
                               syslog format. Must be entered either as a single
                               scalar (like emerg) or as a comma seperated
                               list (emerg,alert,crit) (optional).
                            
                               Syslog format:
                               emerg   - A panic condition was reported to
                                         all processes.
                               alert   - A condition that should be corrected
                                         immediately.
                               crit    - A critical condition.
                               err     - An error message.
                               warning - A warning message. 
                               notice  - A condition requiring special handling.
                               info    - A general information message.
                               debug   - A message useful for debugging programs.

                               Nagios format:
                               down 
                               critical
                               warning
                               unreachable
                               unknown

                               Opposite to Syslog format there can be positive
                               events in Nagios format:
                               up
                               ok 

-m --msg <message>             Message as logged by agent (optional).

--maxage <date>                Select only records not older than maxage. maxage
                               has to ben entered in the form "YYYY-MM-DD HH:MM:SS".
                               Don't forget quotes around the date (optional).

-r --regexp                    Treat message as regular expression (sed/awk sytax)
                               (optional).

-s --show                      Show stored messages (optional).

-t --type <logtype>            The logtype (e.g. syslog, snmptrap, mail) (optional).

-P --program <program>         Program as logged by agent (optional).

-l --label <label>             label for plugin output (optional).

-w --warning <integer>         number matches to result in warning status
                               (optional).

-c --critical <integer>        number of matches to result in critical status
                               (mandatory).

-a --acknowledged              Include acknowledged problems (optional).

--recover <message>            The messagestring following this will cause a
                               recovery. Wildcards are allowed. If -r is set
                               the string will be interpreted as a regular
                               expression -H must been set. And the message
                               containing the recovery string must be the latest.
                               If there are alerts newer than the recovery string
                               only this alerts are used. (optional).

--recover_regexp               Interpret recoverstring as regular expression
                               (awk/sed style). Works only with --recover set.
                               (optional) 

--recover_prio <prio>          The messagestring following this will contain 
                               the priority for recovery -H must been set (optional).

--recover_prog <program>       This will contain a name of a program causing the
                               recovery in case the recovery message is not sent by the
                               program causing the error. -H must been set (optional).

--servicestate <state>         Contains \$SERVICESTATE\$ from Nagios if started
                               as eventhandler for acknowledging records/entries.

--servicestatetype <statetype> Contains \$SERVICESTATETYPE\$ from Nagios if started
                               as eventhandler for acknowledging records/entries.

--serviceoutput <output>       Contains \$SERVICEOUTPUT\$ from Nagios if started
                               as eventhandler for acknowledging records/entries.
                            
                               In case of using check_eventdb as a event handler
                               all 3 (--servicestate, --servicestatetype and
                                --serviceoutput) must be used together.
                               \$SERVICESTATE\$ MUST be OK or UP,
                               \$SERVICESTATETYPE\$ MUST be HARD and \$SERVICEOUTPUT\$
                               should contain the output of your "submit passive
                               check result" together with the name of the operator
                               (for example "problem fixed - D.Duck")
                            
--db <database>                Database (default: eventdb)

--dbtable <tablename>          Tablename (default: events)

--dbuser <dbuser>              Databaseuser (default: none)

--dbpassword <dbpassword>      Databasepassword (default: none)

--dbhost <dbhost>              Databaseserver (default: localhost)

--version                      Print program verion
    
EOU
    }

