The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl

=head1 NAME

nrpe-server - A Nagios NRPE Server

=head1 SYNOPSIS

 ./nrpe-server --conf ./nrpe-server.conf --pid /var/run/pid --listen 127.0.0.1 --port 5666

=head1 DESCRIPTION

This is a simple perl implementation of the nagios-nrpe server you can see SYNOPSIS for how to start it.

After it is started it will listen on a given port (either by config or on the commandline) and run checks
as defined in your config.

NOTE: Options set on the commandline can overwrite options defined in the config file.

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2013 by Andreas Marschke <andreas.marschke@googlemail.com>.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut

use 5.010_000;

use strict;
use warnings;

use Data::Dumper;
use Getopt::Long;
use IO::File;
use Pod::Usage;
use Config::File;
use IPC::Cmd qw(run);
use Nagios::NRPE::Daemon;
use Nagios::NRPE::Packet;
use threads;

use constant {
  NRPE_CONF_DIR => '/etc/nagios'
};
my($listen_cmd,$port_cmd,$config_cmd,$pid_cmd,$ssl_cmd);

my $result = GetOptions (
  "l|listen=s" =>\$listen_cmd,
  "p|port=s"   => \$port_cmd,
  "c|config=s" => \$config_cmd,
  "P|pid=s"    => \$pid_cmd,
  "s|ssl"      => \$ssl_cmd,
  "h|help"     => sub { pod2usage(-exitval   => 0,
				  -verbose   => 99,
				  -noperldoc => 1) });

my($listen,
   $port,
   $log_facillity,
   $pid,
   $user,
   $ssl,
   $nrpe_group,
   $allowed_hosts,
   $debug,
   $command_timeout,
   $connection_timeout,
   $commandlist);

my $config_hash;

if (defined $config_cmd) {
  $config_hash = Config::File::read_config_file($config_cmd) or die "ERROR: Can't open config. Reason: $!";
} elsif ( -e NRPE_CONF_DIR."/nrpe.cfg" ) {
  $config_hash = Config::File::read_config_file(NRPE_CONF_DIR."/nrpe.cfg") 
    or die "ERROR: Can't open config. Reason: $!";
}

$commandlist = $config_hash->{command};

$listen = $listen_cmd || $config_hash->{server_address} || "127.0.0.1";
$port = $port_cmd || $config_hash->{server_port} || "5666";
$pid = $pid_cmd || $config_hash->{pid_file} || "/var/run/nagios/nrpe.pid";
$ssl = 1 if defined $ssl_cmd;
$allowed_hosts = $config_hash->{allowed_hosts} || "0.0.0.0";
$command_timeout = $config_hash->{command_timeout} || "60";
$connection_timeout = $config_hash->{connection_timeout} || 300;

die "No Commands to execute given." if (not defined $commandlist);

foreach (keys %$commandlist) {
  my @args = split /\ /,$commandlist->{$_};
  my $hashref = {};
  $hashref->{bin} = $args[0];
  my $length = scalar @args;
  my $argstr = "";
  for (my $i = 1; $i < $length ; $i++) {
    $argstr .= " ".$args[$i];
  }

  $hashref->{args} = $argstr;
  $commandlist->{$_} = $hashref;
}

my $daemon = Nagios::NRPE::Daemon->new(listen => $listen,
				       port   => $port,
				       pid_dir => $pid,
				       ssl => $ssl,
				       commandlist => $commandlist,
				       callback => sub {
					 my ($self,$check,@options) = @_;
					 my $commandlist = $self->commandlist();
					 if ($commandlist->{$check}) {
					   my $args = $commandlist->{$check}->{args};
					   my $i = 0;
					   foreach (@options) {
					     $i++;
					     $args =~ "s/\$ARG$i\$/$_/";
					   }
					   my $buffer;
					   if (scalar run(command => $commandlist->{$check}->{bin} . " " . $args,
							  verbose => 0,
							  buffer => \$buffer,
							  timeout => 20)) {
					     chomp $buffer;
					     return $buffer;
					   }
					 }
				       }
				      );


threads->new($daemon->start());