#!/usr/bin/ruby
#
# Copyright (c) 2006,2007 Peter Palfrader
#
# 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.

require 'optparse'

NAGIOS_STATUS = { :OK => 0, :WARNING => 1, :CRITICAL => 2, :UNKNOWN => -1 };

$owfs_path = '/var/lib/owfs'
$owfs_path = ENV['OWFSPATH'] if ENV['OWFSPATH']

def bail_out(m)
	STDERR.puts "#{$0}: #{m}"
	exit 1
end

def runcmd(command, input)
	rdin , wrin  = IO.pipe
	rdout, wrout = IO.pipe
	rderr, wrerr = IO.pipe

	pid = fork
	unless pid
		# child
		wrin.close
		rdout.close
		rderr.close
		STDIN.reopen rdin
		STDOUT.reopen wrout
		STDERR.reopen wrerr
		exec(*command)
		throw("fell through exec(). WTF.")
	end
	rdin.close
	wrout.close
	wrerr.close

	out = []
	err = []
	tin  = Thread.new { wrin.print input; wrin.close }
	tout = Thread.new { out = rdout.readlines }
	terr = Thread.new { err = rderr.readlines }
	tin.join
	tout.join
	terr.join
	Process.wait pid

	exitstatus = $?.exitstatus

	[exitstatus, out, err]
end

def report(device)
	Process.gid=0
	Process.egid=0

	# fuse does weird checks.  this fails:
	# File.new($owfs_path+'/'+device+'/temperature', "r") ---> FAILS: in `initialize': Permission denied - /var/lib/owfs/10.D234EE000800/temperature (Errno::EACCES)

	# Sometimes the directory in OWFS does not exist, and cat will say
	# cat: /var/lib/owfs/10.D234EE000800/temperature: Invalid argument
	# so retry it a few times, since ls'ing the directory helps on the command line at least
	5.times do
		exitstatus, out, err = runcmd(['cat', $owfs_path+'/'+device+'/temperature'], '')
		if exitstatus != 0
			STDERR.puts "Child exited with non-zero exit code(%d): %s"%[exitstatus >> 8, err.join]
			runcmd(['ls', $owfs_path], '')
			sleep 1
		else
			STDERR.puts "command succeeded but returned something on stderr: #{err.join}" if err.size > 0
			return out.join.to_f
		end
	end
	puts "Could not get data for #{device}."
	exit NAGIOS_STATUS[:UNKNOWN];
end


@lowcrit = 10;
@lowwarn = 15;
@highwarn = 25;
@highcrit = 30;

def show_help(parser, code=0, io=STDOUT)
  program_name = File.basename($0, '.*')
  io.puts "Usage: #{program_name} [options]"
  io.puts parser.summarize
  exit(code)
end
ARGV.options do |opts|
	opts.on_tail("-h", "--help" , "Display this help screen")                { show_help(opts) }
	opts.on("-d", "--device=<ow device>"  , String, "Device ID")   { |x| @device = x }
	opts.on("-n", "--name=<name>"         , String, "Human readable device specifier")   { |x| @name = x }
	opts.on("-w", "--high-warn=integer"  , Integer, "Upper warning limit")   { |x| @highwarn = x }
	opts.on("-c", "--high-crit=integer"  , Integer, "Upper critical limit")  { |x| @highcrit = x }
	opts.on("-W", "--low-warn=integer"  , Integer, "Lower warning limit")    { |x| @lowwarn = x }
	opts.on("-C", "--low-crit=integer"  , Integer, "Lower critical limit")   { |x| @lowcrit = x }
	opts.parse!
end
show_help(ARGV.options, 1, STDERR) if ARGV.length != 0
show_help(ARGV.options, 1, STDERR) unless @device

@name = @device unless @name;

temp = report @device


if temp > @highcrit  or   temp < @lowcrit
	puts "CRITICAL: device #{@name} is at #{temp}"
	exit NAGIOS_STATUS[:CRITICAL]
elsif temp > @highwarn  or  temp < @lowwarn
	puts "WARN: device #{@name} is at #{temp}"
	exit NAGIOS_STATUS[:WARNING]
else
	puts "OK: device #{@name} is at #{temp}"
	exit NAGIOS_STATUS[:OK]
end