#!/usr/bin/perl -w
#
# Author: Christian Timmerer <timse@itec.uni-klu.ac.at>
# Date  : 05.11.2001
#
# Desription: Uses SNMP to check printer status
#
# ----------------------------------------------------------------------
#
#
#
#
# Copyright Notice: GPL
#

BEGIN {
        if ($0 =~ m/^(.*?)[\/\\]([^\/\\]+)$/) {
                $runtimedir = $1;
                $PROGNAME = $2;
        }
}

use strict;
use lib $main::runtimedir;
use Getopt::Long;
use vars qw($VERSION $PROGNAME);
use utils qw($TIMEOUT %ERRORS &print_revision &support);
use Getopt::Long;
Getopt::Long::Configure('bundling', 'no_ignore_case');
use SNMP::Util;

$VERSION = "0.0.1";

sub print_help ();
sub print_usage ();
sub help ();
sub version ();
sub hex2ascii;

delete @ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

#-- Just in case of problems, let's not hang NetSaint
$SIG{'ALRM'} = sub {
     print "ERROR: plugin timed out!\n";
     exit $ERRORS{"UNKNOWN"};
};
alarm($TIMEOUT);

#-- get command line options
my %options = ();
my $err = GetOptions(
	"V|version"		=> \$options{version},
	"h|help"		=> \$options{help},
	"H|hostname=s"		=> \$options{hostname},
	"v|snmp-version=s"	=> \$options{snmp_ver},
	"C|community=s"		=> \$options{snmp_community},
	);

#-- check command line options
if ($err != 1) { print_usage(); exit $ERRORS{'UNKNOWN'}; }
if ($options{version}) { version(); }
if ($options{help})    { help(); }


if (! defined($options{hostname})) {
   print "\nERROR\n";
   print "\tHostname not exists\n\n";
   help();
}

if (! defined($options{snmp_ver})) { $options{snmp_ver} = '1'; }
if (! defined($options{snmp_community})) { $options{snmp_community} = 'public'; }

#-- define SNMP::Util object 
my $snmp = new SNMP::Util(-device    => $options{hostname},
                          -community => $options{community},
                          -timeout   => 5,
                          -retry     => 3,
                          -poll      => 'off',
                          -version   => $options{snmp_ver},
                         );

#-- fetch uptime from network device
my $UPTIME = $snmp->get('n', 'sysUpTime.0');

if ($snmp->error) {
   print $snmp->errmsg, "\n";
   exit $ERRORS{'CRITICAL'};
}

#-- fetch printer alert entries
my $prtAlertEntry = $snmp->walk_hash('v', 'prtAlertSeverityLevel', 'prtAlertDescription');

if ($snmp->error) {
   print $snmp->errmsg, "\n";
   exit $ERRORS{'CRITICAL'};
}

my $prtAlertGroup = $snmp->walk_hash('e', 'prtAlertGroup');

if ($snmp->error) {
   print $snmp->errmsg, "\n";
   exit $ERRORS{'WARNING'};
}


#-- if nothing is returned, everthing might be ok and the printer is working
#   e.g. processing a job
my $data_exists = 0;
foreach (keys %$prtAlertEntry) {
  if (exists($prtAlertEntry->{$_})) { $data_exists++; }
}
if (! $data_exists) {
   print "OK - Printer $options{hostname} is up and running ...\n";
   exit $ERRORS{'OK'};
}


#-- prtAlertSeverityLevel determines the printer status critical, warning or other
#   other also means, that the print is in power save mode!
my %crit_err  = ();
my %warn_err  = ();
my %other_err = ();
foreach (sort keys %{$prtAlertEntry->{'prtAlertSeverityLevel'}}) {
  if ($prtAlertEntry->{'prtAlertSeverityLevel'}{$_} == 3) { #-- critical
     $crit_err{$_} = 1;
  }
  elsif ($prtAlertEntry->{'prtAlertSeverityLevel'}{$_} == 1) { #-- other
     $other_err{$_} = 1;
  }
  elsif ($prtAlertEntry->{'prtAlertSeverityLevel'}{$_} > 3) { #-- warning
     $warn_err{$_} = 1;
  }
}

#-- generate output message and return state
#   retrieve number of critical, warning or other errors
my $nb_crit = scalar keys %crit_err;
my $nb_warn = scalar keys %warn_err;
my $nb_other = scalar keys %other_err;
my $msg = '';

#-- CRITICAL ERRORS
if ($nb_crit) {
   $msg = "CRITICAL ";
   if ($nb_crit > 1) {
      $msg .= "($nb_crit) ";
   }
   foreach (keys %crit_err) {
      $msg .= '- Unit: ' . $prtAlertGroup->{'prtAlertGroup'}{$_} . ' Msg: ' . hex2ascii($prtAlertEntry->{'prtAlertDescription'}{$_});
      last;
   }
   print "$msg\n";
   exit $ERRORS{'CRITICAL'};
}

#-- WARNING ERRORS
if ($nb_warn) {
   $msg = "WARNING ";
   if ($nb_warn > 1) {
      $msg .= "($nb_warn) ";
   }
   foreach (keys %warn_err) {
      $msg .= '- Unit: ' . $prtAlertGroup->{'prtAlertGroup'}{$_} . ' Msg: ' . hex2ascii($prtAlertEntry->{'prtAlertDescription'}{$_});
      last;
   }
   print "$msg\n";
   exit $ERRORS{'WARNING'};
}

#-- OTHER ERRORS
#   e.g. POWERSAVE ON => Printer is OK!!!
if ($nb_other) {
   $msg = "OTHER ";
   if ($nb_other> 1) {
      $msg .= "($nb_other) ";
   }
   foreach (keys %other_err) {
      $msg .= '- Unit: ' . $prtAlertGroup->{'prtAlertGroup'}{$_} . ' Msg: ' . hex2ascii($prtAlertEntry->{'prtAlertDescription'}{$_});
      last;
   }
   print "$msg\n";
   exit $ERRORS{'OK'};
}

#--------------------------------------------------------------------------------
#--  Converts HEX into ASCII
#--
sub hex2ascii {
  my $string = shift;

  $string =~ s/ //g;			#-- eliminate spaces
  
  my $ascii = pack("H*", $string);      #-- pack string by using HEX-Template
  $ascii =~ s/\n/ /g;			#-- remove <cr>
  return $ascii;
}


#--------------------------------------------------------------------------------
#-- HELP MESSAGE when using -h or --help option
#--
sub print_help() {
        print_revision($PROGNAME,'$Revision: 1.2 $VERSION . ' $ ');
        print <<HELP;

Perl Netsaint Plugin for checking Printer Status

Copyright (c) 2001 Christian Timmerer <timse\@itec.uni-klu.ac.a.t>

Usage: $PROGNAME -H <hostname> [options]

Options:
  -H | --hostname	<hostname> 	Hostname or IP address of the printer
  -v | --snmp-version	<version>	SNMP Version. Default: 1
  -C | --community	<community>	SNMP Community

  -h | --help		this message
  -V | --version	Version information

HELP
        support();
}

#--------------------------------------------------------------------------------
#-- USAGE in case of wron arguments supplied
#--
sub print_usage () {
        print "$PROGNAME -H host [-v snmp-version -c community]\n";
        print "$PROGNAME [-h | --help]\n";
        print "$PROGNAME [-V | --version]\n";
}

#--------------------------------------------------------------------------------
#-- VERSION information
#--
sub version () {
        print_revision($PROGNAME,'$Revision: 1.2 $VERSION . ' $ ');
        exit $ERRORS{'OK'};
}

#--------------------------------------------------------------------------------
#-- Alias on print_help :)
#--
sub help () {
        print_help();
        exit $ERRORS{'OK'};
}
