#!/usr/bin/perl
use Getopt::Long;

#
# README FIRST
# 
# This script was tested with success agains following printers:
#  - Lexmark X644e version NC2.NPS.N211 kernel 2.6.10 All-N-1
#  - Lexmark T644 version NC2.NPS.N211 kernel 2.6.10 All-N-1
#
#
# WARNING
# For printers like OKI OkiLAN 8300e try to use check_oki_printer.pl
#

$snmpget = "/usr/bin/snmpget";
$snmpwalk = "/usr/bin/snmpwalk";

sub init {
	$status = GetOptions(
                "p=s" => \$community,"community=s" => \$community,
                "h=s" => \$hostname, "hostname=s" => \$hostname,
                "i=s" => \$item, "item" => \$item,
                "w=i" => \$w, "warning" => \$w,
                "c=i" => \$c, "critical" => \$c,
                );

	usage() if (!defined($community) || !defined($hostname) || !defined($item));
	main();
}

sub usage {
	print "Usage:\n";
	print "\t$0 -h <hostname> -p <community>  -i <item> [-w X] [-c Y]\n";
	print "\tItem can be: ";
	print "'paper', 'toner', 'miscalerts', 'tray', 'supply', 'output', 'load', 'uptime', 'status', 'storage'\n";
	print "\t-w Warning for load\n";
	print "\t-c Critical for load (must be major than -w)\n\n";
	exit(3);
}

sub hexToBin() {

	($num)=@_;

	# get an decimal
	$num = oct($num) if $num =~ /^0/;
	sprintf($num,"%d", $num);
	
	# get the binary
	my $num = unpack("B32", pack("N", $num));
	$num =~ s/^0+(?=\d)//;
	
	# fill with zeros our byte
	$missing=8-length($num);
	$temp="";
	for ($i=0; $i<$missing; $i++ ) {
		$temp=$temp."0";
   	}
	$num = $temp.$num;

	return $num;
}

sub verifyErrors {

	$binary = shift;
	@bits;

	while ($binary =~ /(.)/g) { # . is never a newline here
		push(@bits,$1);
    	}

	# Error vector positions
        # bit map
        #
        # PAPER
        # lowPaper              0
        # noPaper               1
        #
        # TONER
        # lowToner              2
        # noToner               3
        #
        # MISCALERTS
        # doorOpen              4
        # jammed                5
        # offline               6
        # serviceRequested      7
        # overduePreventMaint  14
        #
        # TRAY
        # inputTrayMissing      8
        # outputTrayMissing     9
        # inputTrayEmpty       13
        #
        # SUPPLY
        # markerSupplyMissing  10
        #
        # OUTPUT
        # outputNearFull       11
        # outputFull           12
	
 	@trError = (    'lowPaper',
                        'noPaper',
                        'lowToner',
                        'noToner',
                        'doorOpen',
                        'jammed',
                        'offline',
                        'serviceRequested',
                        'inputTrayMissing',
                        'outputTrayMissing',
                        'markerSupplyMissing',
                        'outputNearFull',
                        'outputFull',
                        'inputTrayEmpty',
                        'overduePreventMaint');


	if ($item eq "paper") {
		@e = (0,1);
	} elsif ($item eq "toner") {
		@e = (2,3);
	} elsif ($item eq "miscalerts") {
		@e = (4,5,6,7,14);
	} elsif ($item eq "tray") {
		@e = (8,9,13);
	} elsif ($item eq "supply") {
		@e = (10);
	} elsif ($item eq "output") {
		@e = (11,12);
	} else {
		&usage();
	}

	$critical = 0;
	$cMsg = "";
	$oMsg = "";
	foreach (@e) {
		if ($bits[$_] == 1) {
			$critical = 1;
			$cMsg .= $trError[$_]."(CRITICAL) ";
		} else {
			$oMsg .= $trError[$_]."(OK) ";
		}
	}

	if ($critical) {
		print "CRITICAL - $cMsg\n";
		exit(2); 
	}

	print "OK - $oMsg\n";
	exit(0);	

}

sub load {

	&usage() if (!defined($c) || !defined($w) || $c < $w);

	$run = `$snmpget -Oq -On -v 1 -c $community $hostname .1.3.6.1.2.1.25.3.3.1.2.3 2>/dev/null`;
	$run =~ /^\.1\.3\.6\.1\.2\.1\.25\.3\.3\.1\.2\.3\s(\d+)$/;
	$load = $1;

	if ($load > $c) {
		print "CRITICAL - load $load |load=$load;$w;$c;0;\n";
		exit(2);
	}

	if ($load > $w) {
		print "WARNING - load $load |load=$load;$w;$c;0;\n";
		exit(1);
	}

	print "OK - load $load |load=$load;$w;$c;0;\n";
	exit(0);


}


sub uptime {
	$run = `$snmpwalk -On -c $community -v1 $hostname .1.3.6.1.2.1.1.3.0 2>/dev/null`;
	$run =~ /^\.1\.3\.6\.1\.2\.1\.1\.3\.0\s(.+)$/;
	$uptime = $1;

	print "OK - Uptime $uptime\n";
	exit(0);

}

sub printStatus {

	$run = `$snmpget -Oq -On -v 1 -c $community $hostname .1.3.6.1.2.1.25.3.5.1.1.1 2>/dev/null`;
	$run =~ /^\.1\.3\.6\.1\.2\.1\.25\.3\.5\.1\.1\.1\s(.+)$/;
	$status = $1;

	if ($status ne "printing" && $status ne "idle") {
		print "CRITICAL - Print status $status\n";
		exit(2);
	}

	print "OK - Print status $status\n";
	exit(0);

}

sub verifyHexa {
        # verify printer errors
        $run = `$snmpget -Oq -On -v 1 -c $community $hostname .1.3.6.1.2.1.25.3.5.1.2.1 2>/dev/null`;
        $run =~ m/^\.1\.3\.6\.1\.2\.1\.25\.3\.5\.1\.2\.1\s(.*)$/;
	$values = $1;
	$values =~ m/^\"*(\d*)\s(\d*)\s*\"*$/;

        # prevent diferent inplmentations
	if ($1 eq "") {
		$hex1 = "0x00";
	} else {
		$hex1 = "0x".$1;
	}

	if ($2 eq "") {
		$hex2 = "0x00";
	} else {
		$hex2 = "0x".$2;
	}

        $bin1 = &hexToBin($hex1);
        $bin2 = &hexToBin($hex2);

        &verifyErrors($bin1.$bin2);
}

sub storage {

        &usage() if (!defined($c) || !defined($w));
        # hrStorageSize
        $run = `$snmpget -On -Oq -c $community -v1 $hostname .1.3.6.1.2.1.25.2.3.1.5.1 2>/dev/null`;
        $run =~ m/\.1\.3\.6\.1\.2\.1\.25\.2\.3\.1\.5\.1\s(\d+)$/;
        $total = $1;

        # hrStorageUsed
        $run = `$snmpget -On -Oq -c $community -v1 $hostname .1.3.6.1.2.1.25.2.3.1.6.1 2>/dev/null`;
        $run =~ m/\.1\.3\.6\.1\.2\.1\.25\.2\.3\.1\.6\.1\s(\d+)$/;
        $used = $1;

        $pct = (100 * $used)/$total;

        $pct = sprintf("%.2f",$pct);

        if ($pct > $c) {
                print "CRITICAL - Ocupacao espaco de armazenamento interno $pct% |usage=$pct%;$w;$c;0;100\n";
                exit(2);
        }
        if ($pct > $w) {
                print "WARNING - Ocupacao espaco de armazenamento interno $pct% |usage=$pct%;$w;$c;0;100\n";
                exit(1);
        }

        print "OK - Ocupacao espaco de armazenamento interno $pct% |usage=$pct%;$w;$c;0;100\n";
        exit(0);
}

sub main {

	# veriry printer snmp
	system("$snmpget -Oq -v 1 -c $community $hostname .1.3.6.1.2.1.1.1.0 2>/dev/null 1>&2");
	if ($? != 0) {
		print "CRITICAL - Erro conectando snmp impressora remota $hostname\n";
		exit(2);
	}


	&load() if ($item eq "load");
	&uptime() if ($item eq "uptime");
	&storage() if ($item eq "storage");
	&printStatus() if ($item eq "status");

	$run = `$snmpget -Oq -On -v 1 -c $community $hostname .1.3.6.1.2.1.1.1.0 2>/dev/null`;
	$run =~ m/\.1\.3\.6\.1\.2\.1\.1\.1\.0 (.*)$/;

	&verifyHexa();
	exit;
}

init();
