#!/usr/bin/perl

use strict;
use Net::Nsca;

# The only documentation for this.
sub usage {
	my $id = '$Id: smart_send_nsca.pl,v 1.1 2006/03/28 11:51:24 bc Exp $';
	print "NSCA Client Perl $id\n";
	print "Nagios/NSCA Copyright (c) 2000-2006 Ethan Galstad (www.nagios.org)\n";
	print "Nagios Perl Client/Library Copyright (c) 2001 P Kent, 2006 B Campbell\n";
	print "License: GPL 2\n";
	print "Encryption Routines: unknown\n";
	print "\n";
	print "Usage: $0 -H <host_address> [-p port] [-to to_sec] [-d delim] [-c config_file] [-s sitename,hostname,hostname] [-t trace] [-o sitename]\n";
	print "\n";
	print "Options:\n";
	print " <host_address> = The host name or IP address of a remote host running\n";
	print "                  the NSCA daemon.  Note that the -H may be specificed\n";
	print "                  multiple times.\n";
	print " [port]         = The port on which the daemon is running on all hosts\n";
	print "                  specified.  Default is 5667\n";
	print " [to_sec]       = Number of seconds before a network activity times out.\n";
	print "                  (Default is 10 seconds, applied to connect, read and write)\n";
	print " [delim]        = Delimiter to use when parsing input (defaults to a tab)\n";
	print " [config_file]  = Name of config file to use.\n";
	print " [sitename]     = Name of a site.  Enables distributed Path Tracing.  When\n";
	print "                  used with the '-o' option, will send to just one responding\n";
	print "                  host within that site, picked at random each time.\n";
	print " [hostname]     = Name of a host within a site.\n";
	print " [trace]        = A boolean (0/1) whether to use path tracing.\n";
	print "\n";
	print "Note:\n";
	print "This utility is used to send passive check results to the NSCA daemon. Host\n";
	print "and Service check data that is to be sent to the NSCA daemon is read from\n";
	print "standard input. Input should be provided in the following format\n";
	print "(tab-delimited unless overriden with -d command line argument, one entry per\n";
	print "line):\n";
	print "\n";
	print "Service Checks:\n";
	print "<host_name>[delim]<svc_desc>[delim]<return_code>[delim]<plugin_output>[newline]\n";
	print "\n";
	print "Host Checks:\n";
	print "<host_name>[delim]<return_code>[delim]<plugin_output>[newline]\n";
	print "\n";
	exit(1);
}

my $configfile = undef;
my %hosts = undef;
my %sites = undef;
my $delim = "\t";
my $timeout = 10;
my $port = 5667;
my $do_trace = 0;
my $have_sites = 0;
my $use_config = 0;
my $found = 0;
my $oneinsite = undef;

my $curloop = 0;
while( $curloop < scalar @ARGV ){
	if( $ARGV[$curloop] =~ /^\-(\S+)$/ ){
		my $what = $1;
		my $nextloop = $curloop+1;
		if( ! defined( $ARGV[$nextloop] ) ){
			$ARGV[$nextloop] = "";
		}

		if( $what eq "to" && $ARGV[$nextloop] =~ /^\s*\d+\s*$/ ){
			$timeout = $ARGV[$nextloop];
		}elsif( $what eq "H" ){
			$found++;
			$hosts{$ARGV[$nextloop]}++;
		}elsif( $what eq "s" ){
			my @tsplit = split( /,/, $ARGV[$nextloop] );
			my $maxscal = ( scalar @tsplit ) - 1;
			$sites{$tsplit[0]} = join( ',', @tsplit[1..$maxscal] );
			print STDERR "Found site $tsplit[0] \n";
			$have_sites++;
			$do_trace++;
		}elsif( $what eq "c" ){
			$configfile = $ARGV[$nextloop];
			$use_config++;
		}elsif( $what eq "d" ){
			$delim = $ARGV[$nextloop];
		}elsif( $what eq "p" ){
			$port = $ARGV[$nextloop];
		}elsif( $what eq "t" ){
			$do_trace = $ARGV[$nextloop];
			if( $do_trace =~ /^\s*$/ ){
				$do_trace = 0;
			}
		}elsif( $what eq "o" ){
			$oneinsite = $ARGV[$nextloop];
		}elsif( $what eq "h" ){
			&usage();
			exit(2);
		}
		$curloop++;
	}
	$curloop++;
}

# If tracing was requested, and a configuration file was supplied, there
# may be hosts within the config file that we can use, instead of 
# inisting on a host supplied via the command line.
if( $do_trace && $use_config ){
	$found++;
}

if( ! $found ){
	&usage();
}

# If we didn't have a configuration file supplied, see if there is known
# one that we can use.
if( ! $use_config ){
	foreach my $tconfig( "/etc/nsca/smart_send_nsca.cfg", "/etc/nsca/send_nsca.cfg" ){
		next if( $use_config );
		next unless( -f $tconfig && -r $tconfig );
		$use_config++;
		$configfile = $tconfig;
	}
}

# Start looping on lines.
my $retval = 0;
while( my $line = <STDIN> ){
	chomp( $line );
	my @tsplit = split( /$delim/, $line );
	my %message = ( "host_name" => $tsplit[0] );
	if( scalar @tsplit == 3 ){
		$message{"return_code"} = $tsplit[1],
		$message{"plugin_output"} = $tsplit[2],
	}elsif( scalar @tsplit == 4 ){
		$message{"svc_description"} = $tsplit[1],
		$message{"return_code"} = $tsplit[2],
		$message{"plugin_output"} = $tsplit[3],
		# print "Plugin output of $tsplit[3]\n";
	}else{
		print STDERR "Incorrect number of fields in line\n";
		next;
	}

	my %args = (
			message => \%message,
			hosts => \%hosts,
			remote_port => $port,
			use_config_hosts => $use_config,
			use_trace => $do_trace,
			timeout => $timeout,
			);

	if( defined( $configfile ) ){
		$args{"config_file"} = $configfile;
	}

	if( $have_sites ){
		$args{"sites"} = \%sites;
	}

	if( defined( $oneinsite ) ){
		$args{"send_to_one_in_site"} = $oneinsite;
	}

	
	if( ! Net::Nsca->broadcast_message( %args ) ){
		print STDERR "Broadcast failed - path odd?\n";
		$retval++;
	}
}

# And exit.
exit( $retval );
