#!/usr/bin/perl -w

# check_digitemp.pl Copyright (C) 2002 by Brian C. Lane <bcl@brianlane.com>
#
# This is a NetSaint plugin script to check the temperature on a local 
# machine. Remote usage may be possible with SSH
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
# ===========================================================================
# Howto Install in NetSaint (tested with v0.0.7)
#
# 1. Copy this script to /usr/local/netsaint/libexec/ or wherever you have
#    placed your NetSaint plugins
#
# 2. Create a digitemp config file in /usr/local/netsaint/etc/
#    eg. digitemp -i -s/dev/ttyS0 -c /usr/local/netsaint/etc/digitemp.conf
#
# 3. Make sure that the webserver user has permission to access the serial
#    port being used.
#
# 4. Add a command to /usr/local/netsaint/etc/commands.cfg like this:
#    command[check-temp]=$USER1$/check_digitemp.pl -w $ARG1$ -c $ARG2$ \
#    -t $ARG3$ -f $ARG4$
#    (fold into one line)
#
# 5. Tell NetSaint to monitor the temperature by adding a service line like
#    this to your hosts.cfg file:
#    service[kermit]=Temperature;0;24x7;3;5;1;home-admins;120;24x7;1;1;1;; \
#    check-temp!65!75!1!/usr/local/netsaint/etc/digitemp.conf
#    (fold into one line)
#    65 is the warning temperature
#    75 is the critical temperature
#    1 is the sensor # (as reported by digitemp -a) to monitor
#    digitemp.conf is the path to the config file
#
# 6. If you use Centigrade instead of Fahrenheit, change the commands.cfg
#    line to include the -C argument. You can then pass temperature limits in
#    Centigrade in the service line.
#
# ===========================================================================
# Howto Install in Nagios (tested with v1.0b4)
#
# 1. Copy this script to /usr/local/nagios/libexec/ or wherever you have
#    placed your Nagios plugins
#
# 2. Create a digitemp config file in /usr/local/nagios/etc/
#    eg. digitemp -i -s/dev/ttyS0 -c /usr/local/nagios/etc/digitemp.conf
#
# 3. Make sure that the webserver user has permission to access the serial
#    port being used.
#
# 4. Add a command to /usr/local/nagios/etc/checkcommands.cfg like this:
#
#    #DigiTemp temperature check command
#    define command{
#        command_name    check_temperature
#        command_line    $USER1$/check_digitemp.pl -w $ARG1$ -c $ARG2$ \
#        -t $ARG3$ -f $ARG4$
#    (fold above into one line)
#        }
#
# 5. Tell NetSaint to monitor the temperature by adding a service line like
#    this to your service.cfg file:
#
#    #DigiTemp Temperature check Service definition
#    define service{
#        use                         generic-service
#        host_name                       kermit
#        service_description             Temperature
#        is_volatile                     0
#        check_period                    24x7
#        max_check_attempts              3
#        normal_check_interval           5
#        retry_check_interval            2
#        contact_groups                  home-admins
#        notification_interval           240
#        notification_period             24x7
#        notification_options            w,u,c,r
#        check_command                   check_temperature!65!75!1!  \
#        /usr/local/nagios/etc/digitemp.conf
#        (fold into one line)
#        }
#
#    65 is the warning temperature
#    75 is the critical temperature
#    1 is the sensor # (as reported by digitemp -a) to monitor
#    digitemp.conf is the path to the config file
#
# 6. If you use Centigrade instead of Fahrenheit, change the checkcommands.cfg
#    line to include the -C argument. You can then pass temperature limits in
#    Centigrade in the service line.
#
# ===========================================================================

# Modules to use

require 5.004;
use strict;
use lib utils.pm ;
use Plugin;
use Plugin::Parameter qw($helpparameterlist $versionparameterlist $configfileparameter
			 $warningparameter $criticalparameter $timeoutparameter
			 $verboseparameter);

# Define all our variable usage
use vars qw($opt_c $opt_f $opt_s $opt_t $opt_w $opt_F $opt_C $xml $opt_V $opt_h
	    $temperature $conf_file $temp_fmt
	    $crit_level $warn_level $null
            $percent $fmt_pct 
            $verb_err $command_line $PROGNAME);
use utils qw(%ERRORS &usage);

$configfileparameter->default("/etc/digitemp.conf");
$configfileparameter->description("Digitemp Config File");
my $sensorparameter = new Plugin::Parameter(-name => "sensor", -flags => [ 's', 'sensor' ],
					    -optional => "yes", -valueoptional => 0, -type => "INTEGER",
					    -default => 0,
					    -description => "Digitemp sensor number");
my $fahrenheitparameter = new Plugin::Parameter(-name => "fahrenheit", -flags => [ 'F', 'fahrenheit' ],
						-optional => "yes", -valueoptional => "yes",
						-description => "Temperatures in Fahrenheit");
my $centigradeparameter = new Plugin::Parameter(-name => "centigrade", -flags => [ 'C', 'centigrade' ],
						-optional => "yes", -valueoptional => "yes",
						-description => "Temperatures in Centigrade");
$warningparameter->type("TEMPERATURE");
$warningparameter->optional("no");
$warningparameter->checker(\&Plugin::Parameter::_check_temperature);
$warningparameter->description("warning temperature threshold");
$criticalparameter->type("TEMPERATURE");
$criticalparameter->optional("no");
$criticalparameter->checker(\&Plugin::Parameter::_check_temperature);
$criticalparameter->description("critical temperature threshold");

my @commandparameterlist = ( $configfileparameter,
			     $sensorparameter,
			     $fahrenheitparameter,
			     $centigradeparameter,
			     $warningparameter,
			     $criticalparameter,
			     $verboseparameter );

my $plugin = new Plugin(-revision => '$Revision: 1.1 $',
			-copyright => "2002 Brian C. Lane <bcl\@brianlane.com>, Howard Wilkinson <howard\@cohtech.com>",
			-shortcomment => "This plugin checks the temperature information returned by a digitemp sensor.",
			-parameterlists => [ \@commandparameterlist, $helpparameterlist, $versionparameterlist ],
		        -checker => sub { my ($plugin) = @_;
					  if ($opt_w >= $opt_c) {
					    $plugin->usage();
					    &utils::usage("$PROGNAME UNKNOWN: *** WARN level must not be greater than CRITICAL when checking temperature!\n");
					  }
					  if (!-f $opt_f) {
					    $plugin->usage();
					    &utils::usage("$PROGNAME UNKNOWN: *** You must have a digitemp.conf file\n");
					  }
					  if ($opt_C && $opt_F) {
					    $plugin->usage();
					    &utils::usage("$PROGNAME UNKNOWN: Cannot specify both centrigrade and fahrenheit\n");
					  } });

$plugin->init();

# Default to Fahrenheit input and result (use -C to change this)
$temp_fmt = 3;

if($opt_C) {
  $temp_fmt = 2;
}

$plugin->start_timeout($opt_t, "No response from digitemp (alarm)");

# Read the output from digitemp
# Output in form 0\troom\tattic\tdrink
open( DIGITEMP, "/usr/local/bin/digitemp -c $opt_f -t $opt_s -q -o $temp_fmt |" );

my $status = 'UNKNOWN';
my $message = "";
# Process the output from the command
while( <DIGITEMP> ) {
  chomp;

  if( $_ =~ /^nanosleep/i ) {
    $message = "Error reading sensor #$opt_s";
    last;
  } else {
    # Check for an error from digitemp, and report it instead
    if( $_ =~ /^Error.*/i ) {
      $message = $_;
    } else {
      ($null,$temperature) = split(/\t/); # Last record only???
    }
  }
}
close( DIGITEMP );

$plugin->stop_timeout();

if (!$message && !$temperature) {
  $message = "Error parsing result for sensor #$opt_s";
} elsif( $temperature && $temperature >= $opt_c ) {
  $message = "Temperature CRITICAL - Sensor #$opt_s = $temperature"
  . ( $temp_fmt == 3 )?"F":"C";
  $status = 'CRITICAL';
} elsif ($temperature && $temperature >= $opt_w ) {
  $message = "Temperature WARNING - Sensor #$opt_s = $temperature"
    .( $temp_fmt == 3 )?"F":"C";
  $status = 'WARNING';
} elsif( $temperature ) {
  $message = "Temperature OK - Sensor #$opt_s = $temperature"
    . ( $temp_fmt == 3 )?"F":"C";
  $status = 'OK';
}

print "$PROGNAME $status: $message\n";
exit $ERRORS{$status};

