#! /usr/bin/perl -w
#
# check_rsync  -  Check Rsync and modules availability
# Version: 1.01
#
# Copyright (C) 2006-2007 Thomas Guyot-Sionnest <tguyot@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#

use POSIX;
use strict;
use Getopt::Long;

use vars qw($opt_H $opt_p $opt_m);
use vars qw($PROGNAME);
use lib "/usr/local/nagios/libexec";
use utils qw($TIMEOUT %ERRORS);

$PROGNAME = "check_rsync";
$ENV{'PATH'}='';
$ENV{'BASH_ENV'}='';
$ENV{'ENV'}='';

Getopt::Long::Configure('bundling');
GetOptions (
	"H=s" => \$opt_H, "hostname=s" => \$opt_H,
	"p=s" => \$opt_p, "port=s" => \$opt_p,
	"m=s@" => \$opt_m, "module=s@" => \$opt_m );

unless (defined($opt_H)){
  print "Usage: $PROGNAME -H <host> [-p <port>] [-m <module>[,<user>,<password>] [-m <module>[,<user>,<password>]...]]\n";
  exit $ERRORS{'UNKNOWN'};
}

my $host = $opt_H;
my $port = defined($opt_p) ? $opt_p : 873;

# Create an array for each -m arguments and store them in @modules
my @modules;
if (defined($opt_m)) {
  for(@$opt_m) {
    push @modules, [ split(/,/) ];
  }
}

# Just in case of problems, let's not hang Nagios
$SIG{'ALRM'} = sub {
        print "CRITICAL: Rsync timed out\n";
        exit $ERRORS{"CRITICAL"};
};

# Rsync arguments
my $source = "rsync://$host";

alarm($TIMEOUT);

# Get a list of modules to see if rsync is up
my $command = "/usr/bin/rsync --port=$port $source";
my $result = `$command`;
my $error_code = $?;

#Turn off alarm
alarm(0);

my $realerr = $error_code >> 8;
report_error("Rsync command $command failed with error " . $realerr) if ($realerr != 0);

# If one or more -m, check if these modules exists first...
if (@modules) {

  my @result = split(/\n/, $result);

  foreach my $mod (@modules) {
    my $match = 0;
    for (@result) {
      $match = 1 if (/^$$mod[0]\s/);
    }
    report_error("Module $$mod[0] not found") if ($match == 0);
  }
} else { # else just return OK
  print "OK: Rsync is up\n";
  exit $ERRORS{'OK'};
}

# Check each -m aruments...
for my $arg (@modules) {
  if (defined($$arg[1]) and defined($$arg[2])) {
    $source = "rsync://$$arg[1]" . '@' . "$host/$$arg[0]";
    $ENV{'RSYNC_PASSWORD'} = $$arg[2];
  } else {
    $source = "rsync://$host/$$arg[0]";
  }

  alarm($TIMEOUT);

  # Better safe than sorry...
  undef $error_code;
  undef $result;
  # Get a file listing of the root of the module
  $command = "/usr/bin/rsync --port=$port $source";
  $result = `$command`;
  $error_code = $?;

  #Turn off alarm
  alarm(0);

  $realerr = $error_code >> 8;
  report_error("Rsync command failed on module $$arg[0] with error " . $realerr) if ($realerr != 0);
}

if (@modules > 0) {
  print "OK: Rsync is up with ", scalar(@modules), " module tested\n" if (@modules == 1);
  print "OK: Rsync is up with ", scalar(@modules), " modules tested\n" if (@modules > 1);
  exit $ERRORS{'OK'};
} else { # We hould never end up here :)
  print "UNKNOWN: The unexpected occured (bug?)\n";
  exit $ERRORS{'UNKNOWN'};
}

# Report error passed as one string, print rsync messages to STDERR
sub report_error {
  my $report = shift;
  print "CRITICAL: $report\n";
  exit $ERRORS{'CRITICAL'};
}

