Sophie

Sophie

distrib > Fedora > 14 > x86_64 > media > updates > by-pkgid > 4edbca00f8879ee12282b01a1c9707ba > files > 35

pnp4nagios-0.4.14-4.fc14.x86_64.rpm

#!/usr/bin/perl -w
#
# (C) 2008-2009 pnp4nagios.org / Wolfgang Nieder
#
# $Id$ 
#
# check Nagios/PNP integration settings
# 2008.09.21: 0.1    initial version
# 2008.09.23: 0.1.1  precheck / logfile
# 2008.09.27: 0.1.2  objects
# 2008.10.07: 0.1.3  check performance data
# 2008.10.21: 0.1.4  logfile changes / dejavu font
# 2008.11.02: 0.1.5  distinguish host name/service description
# 2008.11.08: 0.1.6  redesign
# 2008.11.21: 0.1.7  npcd.cfg, process_perfdata.cfg
# 2008.11.30: 0.1.8  check template syntax
# 2008.12.17: 0.1.9  use installation values / bugfix
# 2009.02.23: 0.1.10 check perfdata directory / bugfixes
# 2009.03.06: 0.1.11 check for multiple entries / bugfixes
# 2009.04.21: 0.1.12 check for Time::HiRes
# 2009.07.08: 0.1.13 Icinga support / bugfix (templates)
# 2009.08.05: 0.1.14 bugfixes (Icinga support / non-standard paths)
# 2009.08.11: 0.1.15 changed Doc-paths
# 2009.08.18: 0.1.16 added layout option / package detection

use strict;
use Getopt::Long;
use File::Find;

my $program = "Check Nagios/Icinga/PNP integration";
my $version = "0.1.16";
my $help = 0;
my $debug = 0;
my $quiet = 0;
my $time = 0;
my $wc = 0;
my $err = 0;
my $warn = 0;
my $crit = 0;
my $product = lc("nagios");
my $pnp_version = '0.4.14';
my $install_opts = '';
my $doc_version = '0.4';
# 
# please remove the hash sign (#) on the following line if you're using Icinga
# or specify "-M icinga"
# $product = lc("icinga");
my $prod_name = ucfirst($product);
my $basedir = '/usr';
my $NagiosBase = "";
my $NagiosBin = "$product" if (-f "$basedir/bin/$product");
my $mode = "";
my $NagiosCfg = "";
my %NagiosCfg = ();
my $rrdtool = '/usr/bin/rrdtool';
$rrdtool = "/usr/bin/rrdtool" unless ((-f "$rrdtool") and (-x "$rrdtool"));
my $PreCheck = 0;
my $LogFile = "";	# PNP config.log
my %LogFile = ();
my $NPCDcfg = "";	# NPCD.cfg
my %NPCDcfg = ();
my $PPcfg = "";	# process_perfdata.cfg
my %PPcfg = ();
my $CPcfg = "";	# config.php
my %CPcfg = ();
my $RFcfg = "";	# resource.cfg
my %RFcfg = ();
my $nFile = "";
my @CfgFiles = ();
my %commands = ();
my $cfg_call = "";
my $StatusLog = "";
my %StatusLog = ();
my $Object = "";
my $RRDpath = "";
my $RRDdir = 0;
my $RRDfile = 0;
my $uid = "";
my $gid = "";
my $user = "";
my $group = "";
my $layout = "";
my $pkg_mgr = "";
my $language = "en";
my $english = "";
if (exists $ENV{LANG}) {
	$language = "de" if ($ENV{LANG} =~ /de/i);
}
my %msg = ();

# process command line parameters
Getopt::Long::Configure('bundling');
GetOptions(
	"h|help" => \$help,
	"d|debug" => \$debug,
	"e|english" => \$english,
	"b|basedir=s" => \$NagiosBase,
	"B|binary=s" => \$NagiosBin,
	"m|mode=s" => \$mode,
	"c|config=s" => \$NagiosCfg,
	"N|npcdcfg=s" => \$NPCDcfg,
	"P|ppcfg=s" => \$PPcfg,
	"p|precheck" => \$PreCheck,
	"q|quiet" => \$quiet,
	"r|rrdtool=s" => \$rrdtool,
	"R|RRDpath=s" => \$RRDpath,
	"U|resource=s" => \$RFcfg,
	"u|user=s" => \$user,
	"g|group=s" => \$group,
	"l|logfile=s" => \$LogFile,
	"o|object=s" => \$Object,
	"M|monitor=s" => \$product,
	"L|layout=s" => \$layout,
	"t|time" => \$time,
);

if ($pnp_version =~ /^(\d+\.\d+)/) {
	$doc_version = "$1";
}
$product = lc($product);
$prod_name = ucfirst($product);
info ("\n\n$program, v$version\n");
if ($english) {
	info ("[I] option -e");
	$language = "en";
}
message();

if (($help) or ((! $mode) and (! $Object))) {
	usage();
	exit 0;
}

if (($debug) and ($quiet)) {
	$quiet = 0;
	info ("qd");
	exit 2
}

# system information
if (-f "/etc/issue") {
	my $line = `cat /etc/issue`;
	$line =~ s/\\.//gs;
	$line =~ s/\n//gs;
	info ("info","OS","$line");
}
info ("info","Perl","$]");
if ($mode) {
	$pkg_mgr = eval "`whereis yum`";
	if ($pkg_mgr =~/:\s+$/) {
		$pkg_mgr = eval "`whereis dpkg`";
		if ($pkg_mgr =~/:\s+$/) {
			$pkg_mgr = eval "`whereis rpm`";
		}
	}
	($pkg_mgr) = $pkg_mgr =~ /:\s*(\S+)/;
	if ($pkg_mgr) {
		info ("info","Package Manager","$pkg_mgr");
		chk_pkg ("nagios",0,1);
		chk_pkg ("icinga",0,1);
		chk_pkg ("pnp4nagios",0,1);
		chk_pkg ("mod-php5,mod_php5",1,0);
		chk_pkg ("php,php5",1,1);
		chk_pkg ("dejavu",1,0);
		if ($crit) {
			info ("LinkReqSW");
			exit 30;
		}
	}
	info ("install_opts","$install_opts") unless ($install_opts =~ /\@INSTALL_OPTS\@/i);
	info ("PNP-version","$pnp_version") unless ($pnp_version =~ /\@PKG_VERSION\@/i);
}	
	
if ($layout) {
	info ("info","Layout","$layout");
	if ($layout =~ /fedora/i) {
		$basedir = "/usr/share" unless ($NagiosBase);
		$NagiosCfg = "/etc/nagios/nagios.cfg" unless ($NagiosCfg);
		$NagiosBin = "/usr/sbin/nagios" unless ($NagiosBin);
		$RRDpath = "/var/lib/pnp4nagios" unless ($RRDpath);
	}	
	elsif ($layout =~ /suse/i) {
		$basedir = "/usr/share" unless ($NagiosBase);
		$NagiosCfg = "/etc/nagios/nagios.cfg" unless ($NagiosCfg);
		$NagiosBin = "/usr/sbin/nagios" unless ($NagiosBin);
		$RRDpath = "/var/spool/nagios-pnp" unless ($RRDpath);
	}	
	elsif ($layout =~ /nagios2/i) {
		$basedir = "/etc/nagios2" unless ($NagiosBase);
		$NagiosCfg = "/etc/nagios2/nagios.cfg" unless ($NagiosCfg);
		$NagiosBin = "/usr/sbin/nagios2" unless ($NagiosBin);
	}	
	elsif ($layout =~ /nagios3/i) {
		$basedir = "/etc/nagios3" unless ($NagiosBase);
		$NagiosCfg = "/etc/nagios3/nagios.cfg" unless ($NagiosCfg);
		$NagiosBin = "/usr/sbin/nagios3" unless ($NagiosBin);
	} else {
		info ("invOption","$layout");
	}	
}	

$basedir = "/usr/local/$product" if ($basedir =~ /^\@prefix\@$/);
$NagiosBase = $basedir unless ($NagiosBase);
if (! defined($NagiosBase)) {
	info ("noBase");
	exit 3
}
if (! -d "$NagiosBase") {
	info ("noBaseDir","$NagiosBase");
	exit 3
}
info ("useBase", "$NagiosBase");
$NagiosCfg = "$NagiosBase/etc/$product.cfg" unless ($NagiosCfg);
if (! defined($NagiosCfg)) {
	if (-f "$NagiosBase/etc/$product.cfg") {
		$NagiosCfg = "$NagiosBase/etc/$product.cfg";
	} else {
		info ("noCfg");
		exit 4
	}
}
if (! -f "$NagiosCfg") {
	info ("noCfgFile","$NagiosCfg");
	exit 5
}
info ("useCfg","$NagiosCfg");
if (! defined($NagiosBin)) {
	if (-f "$NagiosBase/bin/$product") {
		$NagiosBin = "$NagiosBase/bin/$product";
	} else {
		info ("noBinary", "$product") && exit 6;
	}
}
if ($NagiosBin !~ /^\//) {
	$NagiosBin = "$NagiosBase/bin/$NagiosBin";
}
examine ("x;", "${prod_name}-Binary", "$NagiosBin") && exit 6;
info ("useBinary","$NagiosBin");

if ($mode) {
	if ($mode !~ /^default$|^sync$|^Bulk$|^NPCD$/i) {
		info ("invPNPmode");
		info ("LinkPNPconfig");
		exit 7
	}
	if ($mode =~ /^default$/) {
		$mode = "sync";
		if (($pnp_version =~ /^(\d+\.\d+)/) and ($1 >= 0.6)) {
			$mode = "NPCD";
		}
	}
	info ("PNPmode","$mode");
}
if (($LogFile ne "") and (! -f $LogFile)) {
	info ("invFile","$LogFile");
	exit 8
}

info ("useLog","$LogFile") if ($LogFile);

# get Nagios version 
my $NagiosVer = `$NagiosBin -V | grep "$prod_name " | head -1`;
chomp $NagiosVer;
info ("[I] $prod_name info: $NagiosVer");
($NagiosVer) = $NagiosVer =~ /$prod_name .*?(\d+)\./;

# check Nagios Config
info ("verifyCfg");
my $NagiosMsg = `$NagiosBin -v $NagiosCfg | grep "Error:"`;
if ($NagiosMsg) {
	print "===\n$NagiosMsg===\n";
	info ("NagiosChkErr");
	info ("LinkNagiosChk");
	exit 9;
}
process_nagios_cfg();

# check rrdtool
if ($mode) {
	info ("verifyRRD","$rrdtool");
	if (! -f "$rrdtool") {
		info ("invFile","$rrdtool");
		info ("LinkReqSW");
		info ("LinkRRDtool");
		exit 10;
	}
	examine ("x;", "rrdtool", "$rrdtool") && exit 11;
	my $rrdtoolVer = `$rrdtool | grep "RRDtool [1-9]"`;
	chomp ($rrdtoolVer);
	$rrdtoolVer =~ s/ Copy.*//;
	info ("[I] RRDtool: $rrdtoolVer");
	
# check rrdtool fonts
	my $erg = system ("which rpm >/dev/null");
	if ($erg == 0) {
		$erg = system("rpm -qa | grep dejavu >/dev/null 2>&1");
		if ($erg) {
			info ("noFonts");
			info ("LinkReqSW");
		}
	}	

# check RRDs perl module
	$erg = eval "use RRDs;1";
	if ($erg) {
		info ("useRRDs");
	} else {
		info ("noRRDs");
	}

# check Time::Hires perl module
	$erg = eval "use Time::HiRes;1";
	if (! $erg) {
		info ("noHiRes");
	}

	if ($RFcfg eq "") {
#		($RFcfg) = $NagiosCfg =~ m#(^.*/)#;
#		$RFcfg .= "resource.cfg";
		$RFcfg = $NagiosCfg{"resource_file"};
	}
	info ("procFile","$RFcfg");
	open (RFILE, "$RFcfg") || abort (29, "errOpen", "$RFcfg", "$!");
	while (<RFILE>) {
		chomp;
		s/#.*//;
		s/\s*$//;
		next if (/^$/);
		my ($par, $val) = /^(.*?)=(.*)/;	# shortest string (broker module contains multiple equal signs)
		if (($par eq "") or ($val eq "")) {
			info ("oddLine", "$_");
			next;
		}
		$RFcfg{"$par"} .= $val;
	}
	close (RFILE);
}

status_log();
process_cfg_log();

# objects.cache / cfg-files
if ($PreCheck) {
	info ("useEntry");
	process_cfg_entries();
} else {
	if ($err) {
		$wc++;
		$err = 0;
	}
	if (! exists $NagiosCfg{"object_cache_file"}) {
		$NagiosCfg{"object_cache_file"} = "$NagiosBase/var/objects.cache";
	}
	examine ("f;","object_cache_file", $NagiosCfg{"object_cache_file"}) && exit 12;
	info ("useCache","$NagiosCfg{\"object_cache_file\"}");
	process_file($NagiosCfg{"object_cache_file"});
}		

# check common settings in nagios.cfg
if (exists $NagiosCfg{"process_performance_data"}) {
	if ($NagiosCfg{"process_performance_data"} !~ /^1$/) {
		info ("noPerfEna");
		info ("LinkEnaPerf");
		if ($mode =~ /sync/i) {
			info ("PNPsync");
		} elsif ($mode =~ /NPCD/i) {
			info ("PNPnpcd");
		} else {	
			info ("PNPbulk");
		}
	}
} else {
	info ("noPerfEna");
	info ("LinkEnaPerf");
}

# check sync mode
if (($NagiosVer >= 3) and (uc($mode) =~ /sync/i)) {
	if ((exists $NagiosCfg{"enable_environment_macros"}) and ($NagiosCfg{"enable_environment_macros"} !~ /^1$/)) {
		info ("envMacrosDis");
		info ("LinkEnaEnv");
	}
}
chk_param ("service_perfdata_command", "sync");
chk_param ("host_perfdata_command", "sync");

# check Bulk modes
chk_param ("service_perfdata_file", "Bulk|NPCD");
chk_param ("service_perfdata_file_template", "Bulk|NPCD");
chk_param ("service_perfdata_file_mode", "Bulk|NPCD");
chk_param ("service_perfdata_file_processing_interval", "Bulk|NPCD", '\d+');
chk_param ("service_perfdata_file_processing_command", "Bulk|NPCD");
chk_param ("host_perfdata_file", "Bulk|NPCD");
chk_param ("host_perfdata_file_template", "Bulk|NPCD");
chk_param ("host_perfdata_file_mode", "Bulk|NPCD");
chk_param ("host_perfdata_file_processing_interval", "Bulk|NPCD", '\d+');
chk_param ("host_perfdata_file_processing_command", "Bulk|NPCD");

chk_npcdcfg ();
chk_ppcfg ();
chk_cpcfg ();

# set/check perfdata directory
if (exists ($PPcfg{rrdpath})) {
	$RRDpath = "$PPcfg{rrdpath}" unless ($RRDpath);
}
$RRDpath = "$NagiosBase/share/perfdata" unless ($RRDpath);
if ("$RRDpath" eq "no") {
	info ("noRRDchk");
	$RRDpath = "";
}
if ($RRDpath) {
	if (! -d "$RRDpath") {
		info ("invDir", "$RRDpath");
	} else {
		info ("RRDpath", "$RRDpath");
		my $erg = eval "open (TST, \">$RRDpath/testfile\")";
		if (! $erg) {
			info ("noWrite","$RRDpath","$NagiosCfg{\"${product}_user\"}");
		} else {
			unlink ("$RRDpath/testfile");
		}
		find(\&chk_perfdata, "$RRDpath");
		if ($RRDfile) {
			info ("RRDcount", $RRDdir, $RRDfile);
		} else {
			info ("noRRDfiles", $RRDdir);
		}
	}
}

if ($wc == 0) {
	info ("noErrors");
	print "OK | Errors=0\n" if ($quiet);
	exit 0
} elsif ($crit == 0) {
	info ("Warnings");
	print "WARNING | Warnings=$warn; Errors=$crit\n" if ($quiet);
	exit 1
} else {	
	info ("Errors");
	print "CRITICAL | Warnings=$warn; Errors=$crit\n" if ($quiet);
	exit 2
}
exit 3;

#
# subroutines
#
# show usage
sub usage {
	return if ($quiet);
	if ($language =~ /de/i) {
	print <<EOF1;
Dieses Script prueft verschiedene Einstellungen/Eintraege in Ihrer $prod_name-
bzw. PNP-Umgebung, um Ihnen beim Finden von Problemen zu helfen.
Es kann vor und waehrend der Laufzeit von PNP benutzt werden.

Die Ausgaben beginnen mit einem Buchstaben mit folgender Bedeutung:
[I] Informationen zu Einstellungen, ...
[A] durchzufuehrende Aktionen
[W] Warnung: beeintraechtigt nicht die Arbeitsweise von PNP
[E] Fehlermeldung: PNP wird nicht korrekt arbeiten, solange das Problem
    besteht
[H] Hinweis: es ist ratsam, die angegebene Dokumentation zu lesen
[D] Debugging-Meldung, die hoffentlich zur Fehlerbehebung fuehrt
EOF1
} else {
print <<EOF2;
This script will check certain settings/entries of your $prod_name/PNP environ-
ment to assist you in finding problems when you are using PNP.
It may be used prior and during operation of PNP.

Output starts with a letter with the following meaning:
[I] informational message about settings, ...
[A] actions to be taken
[W] warning message, will not affect the operation of PNP
[E] error message: PNP will not work without resolving the problem(s)
[H] hint: it might be worth reading the appropriate documentation
[D] debugging message, hopefully showing the source of your problem
EOF2
}
print <<EOF3;

$0 [-h]
	-m <mode> [ -l <logfile>] [ -p ] | -o <object>
	[ -b <basedir> ]
	[ -B <binary> ]
	[ -c <config file> ]
	[ -N <npcd config file> ]
	[ -P <process_perfdata config file> ]
	[ -r <rrdtool binary> ]
	[ -R <perfdata directory>|no ]
	[ -U <resource config file> ]
	[ -u <user> ]
	[ -g <group> ]
	[ -M <monitoring product> ]
	[ -L <layout> ]
	[ -t ]
	[ -e ]
	[ -d | -q ]
	   
parameters:
	-h, --help        print these lines
	-b, --basedir=s   $prod_name Base directory (default: $basedir)
	-B, --binary=s    $prod_name binary (default: $product)
	-c, --config=s    $prod_name main config file (default: $basedir/etc/product.cfg)
	-m, --mode=s      PNP mode ("default", "sync", "bulk", "NPCD")
	-l, --logfile=s   check configure log file 
	-N, --npcdcfg=s   PNP config file for NPCD mode (default: $basedir/etc/pnp/npcd.cfg)
	-P, --ppcfg=s     process_perfdata config file (default: $basedir/etc/pnp/process_perfdata.cfg)
	-p, --precheck    use config files instead of objects cache
	-r, --rrdtool=s   specify the location of the RRDtool binary
	-R, --RRDpath=s   specify the perfdata directory (default: $basedir/share/perfdata) or "no" for no check
	-U, --resource=s  specify the location of the resource.cfg (default: $basedir/etc/resource.cfg)
	-M, --monitor=s   specify the monitoring product (default: nagios)
	-L, --layout=s    specify a layout (Nagios2, Nagios3, SuSE, Fedora)
	-u, --user=s      user of the perfdata directory
	-g, --group=s     group of the perfdata directory
	-q, --quiet       quiet mode, non-zero return code will indicate errors
	-o, --object=s    $prod_name object (host name/service description)
	                  "Name" : search for matching host name or service desc
	                  "Name;": search for matching host name
	                  ";Name": search for service description
	-t, --time        show warnings if RRDfiles are too old
	-e, --english     show english messages/links
	-d, --debug       some debugging output
EOF3
}

# process nagios.cfg
sub process_nagios_cfg {
	info ("procFile","$NagiosCfg");
	open (NFILE, "$NagiosCfg") || abort (21, "errOpen", "$NagiosCfg", "$!");
	while (<NFILE>) {
		chomp;
		s/#.*//;
		s/\s*$//;
		next if (/^$/);
		my ($par, $val) = /^(.*?)=(.*)/;	# shortest string (broker module contains multiple equal signs)
		if (($par eq "") or ($val eq "")) {
			info ("oddLine", "$_");
			next;
		}
		$val .= ";";	# multiple cfg_dir/cfg_file entries might occur
		$NagiosCfg{"$par"} .= $val;
	}
	close (NFILE);
	# remove trailing semicolon
	foreach my $key (keys %NagiosCfg) {
		chop $NagiosCfg{"$key"};
		next if ($key =~ /^cfg_/);
		if ($NagiosCfg{"$key"} =~ /;/) {
			info ("dupEntry","$key");
		}
	}
	info ("[I] ${product}_user=$NagiosCfg{\"${product}_user\"}");
	if ($user) {
		$uid = getpwnam ($user);
		if (! $uid) {
			info ("noUser","RRDpath","$user");
			return 31;
		}
		info ("[I] perfdata_user=$user");
	} else {
		$uid = getpwnam ($NagiosCfg{"${product}_user"});
		$user = $NagiosCfg{"${product}_user"};
	}
	info ("[I] ${product}_group=$NagiosCfg{\"${product}_group\"}");
	if ($group) {
		$gid = getgrnam ($group);
		if (! $gid) {
			info ("noGroup","RRDpath","$group");
			return 32;
		}
		info ("[I] perfdata_group=$group");
	} else {
		$gid = getgrnam ($NagiosCfg{"${product}_group"});
		$group = $NagiosCfg{"${product}_group"};
	}
}

# process status log file
sub status_log {
	return if ($Object eq "");
	my $hint = 0;
	
	# check if status log file is present
	$StatusLog = $NagiosCfg{"status_file"};
	if (($StatusLog eq "") or (! -f $StatusLog)) {
		info ("invFile","$StatusLog");
		return 20;
	}
	
	# process status log file
	info ("procFile","$StatusLog");
	info ("searchObj","$Object");
	my $zeile = "";
	my $name = "";
	my ($hostname,$srvdesc) = $Object =~ /(.*);(.*)/;
	$hostname = "" unless (defined($hostname));
	$srvdesc = "" unless (defined($srvdesc));
	
	open (SFILE, "$StatusLog") || abort (22, "errOpen", $StatusLog, $!);
	while (<SFILE>) {
		chomp;
		s/^\s+//;
		s/\s+$//;
		s/#.*//;
		s/\\$//;
		next if (/^$/);
		my ($host) = /host_name=(.*)/;
		my ($service) = /service_description=(.*)/;
		my ($type) = /(\S+)\s+\{/;
		$name = "$type" if (defined($type));		
		$name .= ";$host" if (defined $host);		
		$name .= ";$service" if (defined $service);		
		$zeile .= "$_";
		$zeile .= "#" if ($_ =~ /=/);
		if ($zeile =~ /\}/) {			
			$StatusLog{"$name"} = $zeile;
			info ("[D] $zeile") if ($debug);
			if ($hostname ne "") {
				if ($zeile !~ /host_name=$hostname/i) {
					$zeile = "";
					next;
				}	
			}
			if ($srvdesc ne "") {
				if ($zeile !~ /service_description=$srvdesc/i) {
					$zeile = "";
					next;
				}	
			}
			if (uc($name) =~ /$Object/i) {
				$name =~ s/.*?;//;
				my ($perf_data) = $zeile =~ /#performance_data\s*=\s*(.*?)#/;
				if ($perf_data ne "") {
					info ("[I] Performance data ($name): $perf_data");
					$_= $perf_data." ";
					# try to check for valid performance data according to
					# http://nagiosplug.sourceforge.net/developer-guidelines.html#AEN203
					while ($_) {
						my $label = "";
						if (/^'/) {
							s/^'(.*?)'=//;
							$label = $1;
						} else {
							s/(.*?)=//;
							$label = $1;
						}
						if (! defined($label)) {
							info ("noLabel");
							$hint = 1;
						} else {
							info ("[D] Label:>$label<") if ($debug);
						}
						s/,/./g;	# change decimal comma 
						s/^(.*?)[; ]//;
						my ($value,$uom) = $1 =~ /([-]?[0-9.]+)(.*)/;
						if (! defined($value)) {
							info ("invValue");
							$hint = 1;
						} else {
							info ("[D] value:>$value<") if ($debug);
						}
						if (($uom) and ($uom !~ /^(c|%|[um]?s|[KMGT]?B)$/)) {
							info ("invUOM","$uom");
							$hint = 1;
						}
						info ("[D] UOM:>$uom<:\n") if (($debug) and (defined($uom)));
						chk_fmt ("Warning",  '^[@~]?[-]?[0-9.:]+$');
						chk_fmt ("Critical", '^[@~]?[-]?[0-9.:]+$');
						chk_fmt ("Minimum",  '^[-]?[0-9.]+$');
						chk_fmt ("Maximum",  '^[-]?[0-9.]+$');
						s/^\s+//;
					}
				} else {
					info ("noPerf","$name");
					info ("LinkPNPreq");
					$hint = 1;
				}
			}
			$zeile = "";
			$name = "";
		}
	}
	close (SFILE);
	info ("LinkDevInfo") if ($hint);
	exit 0;
}

# process config.log
sub process_cfg_log {
	return if ($LogFile eq "");

	info ("procFile","$LogFile");
	open (LFILE, "$LogFile") || abort (23, "errOpen", $LogFile, $!);
	while (<LFILE>) {
		chomp;
		s/="(.*)"/=$1/;
		s/='(.*)'/=$1/;
		if (/\/configure\s/) {
			$cfg_call = $_;
		}
		if (/(.*)\s*?=\s*?(.*)/) {
			$LogFile{"$1"} = $2;
		}
	}
	close (LFILE);
	foreach my $key (keys %LogFile) {
		while ($LogFile{"$key"} =~ /{(.*?)}/) {
			my ($val) = $1;
			if (exists ($LogFile{$val})) {
				$LogFile{"$key"} =~ s/\${$val}/$LogFile{$val}/;
			}
		}
	}
	examine ("d;","CFG_DIR",$LogFile{"CFG_DIR"});	
	examine ("d;","PERFDATA_DIR",$LogFile{"PERFDATA_DIR"});	
	examine ("d;","PERFDATA_SPOOL_DIR",$LogFile{"PERFDATA_SPOOL_DIR"});	
	examine ("d;","HTML_DIR",$LogFile{"HTML_DIR"});	

	examine ("f;","PERFDATA_LOG",$LogFile{"PERFDATA_LOG"});	
	examine ("f;","RRDTOOL",$LogFile{"RRDTOOL"});	
	examine ("f;","NPCD_LOG",$LogFile{"NPCD_LOG"});	

	examine ("u;","${product}_user",$LogFile{"${product}_user"});	
	examine ("g;","${product}_grp",$LogFile{"${product}_grp"});	
}

# check parameter from nagios.cfg
sub chk_param {
	my ($param,$valid,$val) = @_;
	info ("chkPar","$param") if ($debug);
	if (exists $NagiosCfg{"$param"}) {
		info ("keyValue","$param","$NagiosCfg{\"$param\"}") if ($debug);
		if (uc($mode) !~ /$valid/i) {
			info ("parModeInv","$param","$mode");
			info ("LinkPNPconfig","$param");
			return;
		}
		if (defined($val)) {
			info ("ParValue","$val") if ($debug);
			if ($NagiosCfg{"$param"} !~ /$val/) {
				info ("invValue2","$NagiosCfg{\"$param\"}","$param");
				info ("LinkNagiosCfg","$param");
			}
		}
		if ($param =~ /.*_perfdata_command/) {
			my $cmd = "$commands{$NagiosCfg{\"$param\"}}";
			my $chk = '/process_perfdata.pl';
			$chk .= " -d HOSTPERFDATA" if ($param =~ /^host/);
			if ( $cmd !~ /$chk$/i) {
				info ("invValue2","$cmd","$param");
				info ("PNPsync");
			}
		}
		if ($param =~ /perfdata_file_template/) {
			chk_template ("$param");
		}
		if ($param =~ /perfdata_.*_command/) {
			if (! exists($commands{"$NagiosCfg{\"$param\"}"})) {
				info ("noCmd","$NagiosCfg{\"$param\"}");
				info ("LinkNagiosCfg2");
			}
		}
		return;
	}
	# param not found in nagios.cfg
	if (uc($mode) =~ /$valid/i) {
		if ($param =~ /^service/) {
			info ("noParCfg","$param");
			info ("LinkNagiosCfg","$param");
			return;
		}
		if ($prod_name eq "Icinga") {
			if ($NagiosVer >= 3) {
				info ("noParCfgH","$param");
			} else {
				info ("notAdv","$param");
			}
			info ("LinkNagiosCfg","$param");
		}
	}
}

# read config file
sub process_file {
	my ($file) = @_;
	my $cmd = "";
	my $line = "";
	open (CFILE, "$file") || abort (24, "errOpen", $file, $!);
	while (<CFILE>) {
		s/#.*//;
		next if (/^$/);
		chomp;	
		next unless (/command_[name|line]/);
		if (/command_name/) {
			($cmd) = /command_name\s*(.*)/;	
			next;	
		}
		($line) = /command_line\s*(.*)/ ;	
		$commands{"$cmd"} = "$line";
		next unless (/process_perfdata.pl/);
		my @cmd = split (/\s+/,$line);
		for my $i (0..$#cmd) {
			if ($cmd[$i] =~ /(\$USER\d+\$)/) {
				if (exists $RFcfg{"$1"}) {		
					my $val = $RFcfg{"$1"};
					$cmd[$i] =~ s/\$USER\d+\$/$val/;
				} else {
					info ("noRes", "$1");	
				}
			}
			info ("noFile", "$cmd", "$cmd[$i]") unless (-f "$cmd[$i]");
			last if ($cmd[$i] =~ /perfdata.pl/);
		}
	}
	close (CFILE);
	if ($debug) {
		for my $key (sort keys %commands) {
			info ("keyValue","$key","$commands{$key}") if ($key =~ /process/);
		}
	}
}

# resolve config dir/file entries
sub process_cfg_entries {
	# process cfg_dir entries
	if (exists $NagiosCfg{"cfg_dir"}) {
		my @dirs = split (/;/,$NagiosCfg{cfg_dir});
		for my $idx (0..$#dirs) {
			info ("[D] cfg_dir : $dirs[$idx]") if ($debug);
			my @files = glob("$dirs[$idx]/*.cfg");
			push @CfgFiles, @files;
		}
	}
	# process cfg_file entries
	if (exists $NagiosCfg{"cfg_file"}) {
		my @files = split (/;/,$NagiosCfg{cfg_file});
		for my $idx (0..$#files) {
			info ("[D] cfg_file: $files[$idx]") if ($debug);
			push @CfgFiles, $files[$idx];
		}
	}
	# process config file(s) to get command_name entries
	for my $idx (0..$#CfgFiles) {
		process_file ("$CfgFiles[$idx]");
	}
}

# check performance data format
sub chk_fmt {
	my ($var,$pattern) = @_;
	my $zeile = "";
	info ("[D] var:>$var<") if ($debug);
	return if (/^$/);
	s/^(.*?)([; ])//;
	my $value = $1 || "";
	if (($value ne "") and ($2 eq " ")) {
		$_ = " ".$_;
		return;
	}
	$zeile .= "value:>$value< ";
	if ($value) {
		if ($value !~ /$pattern/) {
			info ("invChar","$var","$value");
		}
		if ($value =~ /[~@]?([-]?[0-9.]*):([-]?[0-9.]*)/) {
			my $v1 = $1;
			my $v2 = $2;
			if ($value =~ /~/) {
				$zeile .= "alert if value > $v2";
			} else {
				if (! $v1) {
					info ("undefVal","$var");
					return;
				}
				if ($v2) {	
					info ("startEnd", "$v1", "$v2") if ($v1 > $v2);
					if ($value =~ /@/) {
			 			$zeile .= "alert if $v1 <= value <= $v2";
					} else {
						$zeile .= "alert if value < $v1 or value > $v2";
					}
				} else {
					if ($value =~ /:/) {
						$zeile .= "alert if value < $v1";
					} else {
						$zeile .= "alert if value < 0 or value > $v1";
					}
				}
			}
		} else {	
			$value =~ /([-]?[0-9.]+)/;
			$zeile .= "alert if value > $1";
		}		
	}
	info ("[D] $zeile") if (($debug) and ($zeile)); 
}

sub chk_template {
	my ($param) = @_;
	my ($type) = $param =~ /^(.*)_perfdata/;
	$type = uc($type);
	my %template = ();
	$err = 0;
	$template{"DATATYPE"} = 0;
	$template{"TIMET"} = 0;
	$template{"HOSTNAME"} = 0;
	$template{"${type}CHECKCOMMAND"} = 0;
	$template{"${type}PERFDATA"} = 0;
#	$template{"${type}STATE"} = 0;
	$template{"HOSTSTATE"} = 0;
	$template{"HOSTSTATETYPE"} = 0;
	if ($type eq "SERVICE") {
		$template{"SERVICEDESC"} = 0;
		$template{"SERVICESTATE"} = 0;
		$template{"SERVICESTATETYPE"} = 0;
	}
	info ("chkTemplate","$param");
	my $val = $NagiosCfg{"$param"};
	if ($val !~ /([A-Z]+?::[A-Z\$]+?.?)+/) {
		info ("invTemplate");
	}
	$val .= "\\t";
	while ($val =~ s/([A-Z]+?)::(.+?)([^A-Z\$].)//) {
		my $p1 = $1; my $p2 = $2; my $p3 = $3;
		if ($val ne "") {
			info ("invDelim","$p3") if ($p3 ne "\\t");
			info ("missDelim") if (! defined ($p3));
		}
		if (defined ($p1)) {
			if (exists ($template{$p1})) {
				$template{$p1}++;
			} else {
				info ("invTempVar","$p1");
			}	
			if (defined ($p2)) {
				info ("keyValue","$p1","$p2") if ($debug);
				if ($p1 eq "DATATYPE") {
					info ("invDatatype","$p2") if ($p2 ne "${type}PERFDATA");
				} else {
					info ("invTempVal","$p2","\$$p1\$") if ($p2 ne "\$$p1\$");
				}
			} else {
				info ("missTempVal");
			}	
		} else {
			info ("missTempVar");
		}
	} 
	for my $key (sort keys %template) {
		info ("missTempVar","$key") unless ($template{$key} > 0);
	}
	info ("PNPbulk") if ($err);
}

# check npcd.cfg
sub chk_npcdcfg {
# create hash with options and valid values	
	%NPCDcfg = ();
	$NPCDcfg{user} = "u;";
	$NPCDcfg{group} = "g;";
	$NPCDcfg{log_type} = "v;syslog|file";
	$NPCDcfg{log_file} = "f;[H]";
	$NPCDcfg{max_logfile_size} = 'n;^\d+$;341';
	$NPCDcfg{log_level} = "v;-1|0|1|2";
	$NPCDcfg{perfdata_spool_dir} = "d;;344";
	$NPCDcfg{perfdata_file_run_cmd} = "x;;336";
	$NPCDcfg{perfdata_file_run_cmd_args} = "o;";
	$NPCDcfg{npcd_max_threads} = 'n;^\d+$';
	$NPCDcfg{use_load_threshold} = "v;0|1;341-494";	# deprecated since 0.4.11
	$NPCDcfg{load_threshold} = 'n;^\d+\.\d+$;341';
	$NPCDcfg{pid_file} = "f;[H];386";
	$NPCDcfg{sleep_time} = 'n;^\d+$;439';	# new since 0.4.8
	$NPCDcfg{identify_npcd} = "v;0|1;497";	# new since 0.4.11
	$NPCDcfg{perfdata_file} = "d;;558";
	$NPCDcfg{perfdata_spool_filename} = "f;;643";
	$err = 0;

# try to set a file name if variable is unset
	if (($mode =~ /^NPCD/i) and ($NPCDcfg eq "")) {
		if (-f "$NagiosBase/etc/pnp/npcd.cfg-sample") {
			$NPCDcfg = "$NagiosBase/etc/pnp/npcd.cfg-sample";
		}
		if (-f "$NagiosBase/etc/pnp/npcd.cfg") {
			$NPCDcfg = "$NagiosBase/etc/pnp/npcd.cfg";
		}
	}

# config file name set?
	if ($NPCDcfg eq "") {
		if ($mode =~ /NPCD/i) {
			info ("NPCDcfgReq");
			info ("PNPnpcd");
			$wc++;
		}
		return;
	}

# only needed in npcd mode	
	if ($mode !~ /NPCD/i) {
		info ("noNPCDreq");
		return;
	}

# process file
	procFile ("npcd.cfg","$NPCDcfg",\%NPCDcfg,25);

# show doc link if needed	
	info ("PNPnpcd") if ($err);
}

# check process_perfdata.cfg
sub chk_ppcfg {
# create hash with options and valid values	
	%PPcfg = ();
	$PPcfg{timeout} = 'n;^\d+$;209';
	$PPcfg{use_rrds} = 'n;^\d+$;'; 
	$PPcfg{rrdpath} = 'd;;';
	$PPcfg{rrdtool} = 'x;;';
	$PPcfg{cfg_dir} = 'd;;';
	$PPcfg{rrd_heartbeat} = 'n;^\d+$;423'; 
	$PPcfg{rra_cfg} = 'f;;';
	$PPcfg{rra_step} = 'n;^\d+$;';
	$PPcfg{log_file} = 'f;[H];';
	$PPcfg{log_level} = 'v;0|1|2;';
	$PPcfg{xml_enc} = 'v;UTF-8|ISO-8859-1|US-ASCII;414';
	$PPcfg{rrd_daemon_opts} = 'S;.*;520'; 
	$err = 0;

# try to set a file name if variable is unset
	if ($PPcfg eq "") {
		if (-f "$NagiosBase/etc/pnp/process_perfdata.cfg-sample") {
			$PPcfg = "$NagiosBase/etc/pnp/process_perfdata.cfg-sample";
		}
		if (-f "$NagiosBase/etc/pnp/process_perfdata.cfg") {
			$PPcfg = "$NagiosBase/etc/pnp/process_perfdata.cfg";
		}
	}
# config file name set?
	if ($PPcfg eq "") {
		%PPcfg = ();
		return;
	}

# process file
	procFile ("process_perfdata.cfg","$PPcfg",\%PPcfg,26);

# show doc link if needed	
	info ("LinkPPcfg") if ($err);
}

# check config.php
sub chk_cpcfg {
	%CPcfg = ();
	$CPcfg{'$conf[\'rrdtool\']'} = "x;$rrdtool;";
	$CPcfg{'$conf[\'graph_width\']'} = 'n;^\d+$;243';
	$CPcfg{'$conf[\'graph_height\']'} = 'n;^\d+$;243';
	$CPcfg{'$conf[\'graph_opt\']'} = 'S;.*;'; 
	$CPcfg{'$conf[\'rrdbase\']'} = 'd;;';
	$CPcfg{'$conf[\'page_dir\']'} = 'd;;279';
	$CPcfg{'$conf[\'refresh\']'} = 'n;^\d+$;';
	$CPcfg{'$conf[\'max_age\']'} = 'n;^\(?[\d\* ]+\)?$';   
	$CPcfg{'$conf[\'temp\']'} = 'd;;';
	$CPcfg{'$conf[\'nagios_base\']'} = "S;.+;";
	$CPcfg{'$conf[\'allowed_for_service_links\']'} = 'S;[\S,]+;';
	$CPcfg{'$conf[\'allowed_for_host_search\']'} = 'S;[\S,]+;';
	$CPcfg{'$conf[\'allowed_for_host_overview\']'} = 'S;[\S,]+;';
	$CPcfg{'$conf[\'allowed_for_pages\']'} = 'S;[\S,]+;381';
	$CPcfg{'$conf[\'overview-range\']'} = 'v;0|1;';
	$CPcfg{'$conf[\'lang\']'} = 'v;en|de|fr|se|nl|es;';
	$CPcfg{'$conf[\'date_fmt\']'} = "S;.*;279";
	$CPcfg{'$conf[\'rrd_daemon_opts\']'} = 'S;.*;520';
	$CPcfg{'$conf[\'enable_recursive_template_search\']'} = 'v;0|1;595';
	$CPcfg{'$conf[\'use_fpdf\']'} = 'v;0|1;';	
	$CPcfg{'$conf[\'background_pdf\']'} = 'f;;321';
	$CPcfg{'$conf[\'use_calendar\']'} = 'v;0|1;';
	$CPcfg{'$conf[\'show_xml_icon\']'} = 'v;0|1;607';
	$CPcfg{'$conf[\'multigraph-links\']'} = 'v;0|1;-279';	
	$CPcfg{'$conf[\'html_dir-links\']'} = 'd;;235-237';	
	$CPcfg{'$views[0]["title"]'} = 'S;[\S,]+;173';
	$CPcfg{'$views[0]["start"]'} = 'n;^\(?[\d\* ]+\)?$;173';
	$CPcfg{'$views[1]["title"]'} = 'S;[\S,]+;173';
	$CPcfg{'$views[1]["start"]'} = 'n;^\(?[\d\* ]+\)?$;173';
	$CPcfg{'$views[2]["title"]'} = 'S;[\S,]+;173';
	$CPcfg{'$views[2]["start"]'} = 'n;^\(?[\d\* ]+\)?$;173';
	$CPcfg{'$views[3]["title"]'} = 'S;[\S,]+;173';
	$CPcfg{'$views[3]["start"]'} = 'n;^\(?[\d\* ]+\)?$;173';
	$CPcfg{'$views[4]["title"]'} = 'S;[\S,]+;173';
	$CPcfg{'$views[4]["start"]'} = 'n;^\(?[\d\* ]+\)?$;173';
	$err = 0;

# try to set a file name if variable is unset
	if ($CPcfg eq "") {
		if (-f "$NagiosBase/etc/pnp/config.php") {
			$CPcfg = "$NagiosBase/etc/pnp/config.php";
		}
	}

# config file name set?
	if ($CPcfg eq "") {
		%CPcfg = ();
		return;
	}

# process file
	procFile ("config.php","$CPcfg",\%CPcfg,27);
# show doc link if needed	
	info ("LinkCPcfg") if ($err);
}

# read file and examine if options are valid
sub procFile {
	my ($desc,$fname,$ptr,$errno) = @_;
	my $rev = "";
	
# not a (regular) file?
	examine ("f;", "$desc","$fname") && return;
	my $php = $fname =~ /php$/;

# check contents	
	info ("procFile","$fname");
	open (PFILE,"$fname") || abort ($errno, "errOpen", $fname, $!);
	while (<PFILE>) {
		chomp;
		if (/\$Id:/) {
			($rev) = /\S\s+(\d+)\s+\d{4}-\d{2}-\d{2}/;
			info ("info","$_");
		}
		s/#.*//;
		s/\s*$//;
		next if (/^$/);
		next if (/^\<\?php|\?\>/);
		my ($par, $val) = /(.*?)\s*=\s*(.*)/;
		if ($php and ($val !~ /.*;$/)) {
			info ("invEOL","$_");
			next;
		}
		$val =~ s/;$//;
		$val =~ s/\s*$//;
		if ((($val =~ /^\"/) and ($val !~ /\"$/)) or
			(($val =~ /^\'/) and ($val !~ /\'$/)) or
			(($val !~ /^\"/) and ($val =~ /\"$/)) or
			(($val !~ /^\'/) and ($val =~ /\'$/))) {
			info ("invQuote","$val");
		}
		$val =~ s/^["']//;
		$val =~ s/["']$//;
		$par = $_ if (! defined ($par));
		$par = lc($par);
		if (examine ($ptr,$par,$val)) {
			delete $ptr->{$par};
		} else {
			$ptr->{$par} = $val;
		}
	}
	close (PFILE);
}

# examine option and value
sub examine {
	my ($var,$par,$val,$curr_rev) = @_;
	my $hint = "";
	my $rev = "";

	if (ref($var)) {
		if (exists($var->{$par})) {
			$var = $var->{$par};
		} else {
			info ("invOption",$par);
			return
		}
		($hint) = $var =~ /\w;(.*)/;
	}
			
	info ("keyValue","$par","$val") if ($debug);
	my ($act,$patt) = $var =~ /(.*?);(.*)/;
	($patt,$rev) = $patt =~ /(.*);(\d*?-?\d*?)$/ if ($patt =~ /;/);
	if (defined $curr_rev) {
		my ($min_rev,$max_rev) = $rev =~ /(\d*)[-]?(\d*)/;
		$min_rev = 0 unless (defined($min_rev) and ($min_rev ne ""));
		$max_rev = 9999 unless (defined($max_rev) and ($max_rev ne ""));
		info ("minRev","$par","$min_rev") if ($curr_rev < $min_rev);
		info ("maxRev","$par","$max_rev") if ($curr_rev >= $max_rev);
	}
	if (($act eq "u") and (! getpwnam($val))) {
		info ("noUser",$par, "$val");
	} elsif (($act eq "g") and (! getgrnam($val))) {
		info ("noGroup",$par, "$val");
	} elsif ($act eq "x") {
			if (! -f $val) { 
				info ("noFile",$par,$val); 
			} elsif (! -x $val) { 
				info ("binExec",$val);
			}
	} elsif (($act eq "f") and (! -f $val)) {
		if ($hint) {
			info ("noFileYet",$par,$val);
		} else {
			info ("noFile",$par,$val);
		}
	} elsif (($act eq "d") and (! -d $val)) {
		info ("noDir",$par,$val);
	} elsif (($act eq "s") and (! -s $val)) {
		info ("noSock",$val);
	} elsif (($act eq "n") and ($val !~ /$patt/)) {
		info ("noNumber",$val);
	} elsif (($act eq "v") and ($val !~ /$patt/)) {
		info ("invValue2",$val,$par);
	} elsif (($act eq "S") and ($val !~ /$patt/)) {
		info ("invValue2",$val,$par);
	}
	return $err;
}

# show additional info if desired
sub info {
	my @par = @_;
	my $line = "";
	
	if (exists ($msg{"$par[0]"})) {
		$line = $msg{"$par[0]"};
	} else {
		$line = $par[0];
	}
	for (1..$#par) {
		$line =~ s/%s/$par[$_]/;
	}
	if ($line =~ /\[E\]/) {
		$wc++;
		$crit++;
	}
	if ($line =~ /\[W\]/) {
		$wc++;
		$warn++;
	}
	print "$line\n" unless ($quiet);
}

# abort script
sub abort {
	my ($rc, @par) = @_;
	info (@par);
	exit $rc;
}

# check perfdata dir
sub chk_perfdata {
	-d && $_ ne "." && $RRDdir++;
	my $f = "$File::Find::name";
	return unless (($f =~ /\/$/) or ($f =~ /rrd$|xml$/));
	if ($uid) {
		my $fuid = (stat("$f"))[4];
		my $fname = getpwuid($fuid);
		info ("RRDuser","$f", "$fname", "$user") if ($fuid != $uid);
	}
	if ($gid) {
		my $fgid = (stat("$f"))[5];
		my $fgroup = getpwuid($fgid);
		info ("RRDgroup","$f", "$fgroup", "$group") if ($fgid != $gid);
	}
	-d && return;
	$RRDfile++ if ($f =~ /rrd$/);
	return unless ($f =~ /xml$/);
	my $rc = 99;
	my $txt = "no RC found in file";
	if ($time) {
		my $max_age = $CPcfg{'$conf[\'max_age\']'};
		while ($max_age =~ /(\d+)\*(\d+)(\D.*)?/) {
			if (defined($3)) {	
				$max_age = $1 * $2."$3";
			} else {
				$max_age = $1 * $2;
			}
		}	
		my $old = time() - $max_age;
		my $age = (stat ($f))[9];
		info ("RRDold","$f","$max_age") if ($age < $old);
	}
	open (F, "$f");
	while (<F>) {
		if (/<RC>(\d)<\/RC>/) {
			$rc = $1;
		}
		if (/<TXT>(.*)<\/TXT>/) {
			$txt = $1;
			last;
		}
	}	
	info ("RRDrc","$f",$rc, "$txt") if ($rc);
}
	
sub chk_pkg {
	my ($pkg_names,$req,$exactly) = @_;
	my @pkg_names = split (/,/,$pkg_names);
	my $pkg_name = "";
	my $pkg = "";

	for my $idx (0..$#pkg_names) {
		next if ($pkg);
		$pkg_name = $pkg_names[$idx];
		if ($pkg_mgr =~ /yum/) {
			if ($exactly) {
				$pkg = `yum list installed $pkg_name 2>/dev/null | grep "installed"`;
			} else {
				$pkg = `yum list installed 2>/dev/null | grep "$pkg_name" | grep "installed"`;
			}
			$pkg =~ s/\s+/ /g;
			$pkg =~ s/ installed//g;
		} elsif ($pkg_mgr =~ /dpkg/) {
			if ($exactly) {
				$pkg = `dpkg -l "$pkg_name" 2>/dev/null | grep "ii"`;
			} else {
				$pkg = `dpkg -l 2>/dev/null | grep "$pkg_name" | grep "ii"`;
			}
			$pkg =~ s/ii\s+//gs;
			$pkg =~ s/\s+/ /gs;
			$pkg =~ s/(\S+ \S+).*/$1/gs;
		} elsif ($pkg_mgr =~ /rpm/) {
			if ($exactly) {
				$pkg = `rpm -qa $pkg_name`;
			} else {
				$pkg = `rpm -qa | grep $pkg_name`;
			}
		}
	}
	$pkg =~ s/\s$//gs;
	if ($pkg) {
		info ("Package","$pkg");
		return 1
	} else {
		info ("noPkg","$pkg_names") if ($req);
		return 0
	}
}

# set different messages according to the language
sub message {
	$msg{"qd"} = "[E] --quiet and --debug are mutually exclusive";
	$msg{"noBase"} = "[E] $prod_name basedir not found/not specified";
	$msg{"noBaseDir"} = "[E] $prod_name basedir \"%s\" does not exist";
	$msg{"useBase"} = "[I] using $prod_name basedir \"%s\"";
	$msg{"noBinary"} = "[E] binary \"%s\" not found/defined";
	$msg{"useBinary"} = "[I] using $prod_name binary \"%s\"";
	$msg{"noCfg"} = "[E] $product.cfg not specified";
	$msg{"noCfgFile"} = "[E] config file \"%s\" not found";
	$msg{"useCfg"} = "[I] using $prod_name config \"%s\"";
	$msg{"binExec"} = "[E] File \"%s\" is not executable";
	$msg{"verifyCfg"} = "[A] verifying $prod_name config";
	$msg{"invPNPmode"} = "[E] no valid mode specified (sync, Bulk, NPCD, default)";
	$msg{"PNPmode"} = "[I] PNP mode: \"%s\"";
	$msg{"Package"} = "[I] Package: \"%s\"";
	$msg{"noPkg"} = "[E] Package \"%s\" not found";
	$msg{"useLog"} = "[I] LogFile \"%s\" specified";
	$msg{"NagiosChkErr"} = "[E] $prod_name check found errors";
	$msg{"NagiosCfgErr"} = "[E] $prod_name config contains errors";
	$msg{"verifyRRD"} = "[A] checking RRDtool (%s)";
	$msg{"info"} = "[I] %s: %s";
	$msg{"invFile"} = "[E] \"%s\" is not a (regular) file";
	$msg{"invDir"} = "[E] directory \"%s\" does not exist";
	$msg{"useEntry"} = "[I] using cfg_dir/cfg_file entries";
	$msg{"useCache"} = "[I] using \"%s\" entries";
	$msg{"dupEntry"} = "[E] directive \"%s\" is duplicate";
	$msg{"noPerfEna"} = "[E] no performance data enabled (process_performance_data=1 in $product.cfg)";
	$msg{"envMacrosDis"} = "[E] environment macros disabled (enable_environment_macros=0)";
	$msg{"noFonts"} = "[H] dejavu fonts may be missing";
	$msg{"noErrors"} = "\nNo (obvious) errors found. Happy graphing with PNP";
	$msg{"Warnings"} = "\nWarnings found. Please check the settings.";
	$msg{"Errors"} = "\nErrors found. Please check the settings and have a look at the documentation.";
	$msg{"procFile"} = "[A] processing \"%s\"";
	$msg{"searchObj"} = "[A] searching for \"%s\"";
	$msg{"noLabel"} = "[E] no label defined";
	$msg{"invValue"} = "[E] no valid value";
	$msg{"invOption"} = "[E] \"%s\" is not a valid option";
	$msg{"invUOM"} = "[E] \"%s\" doesn't seem to be a valid UOM";
	$msg{"minRev"} = "[W] option \"%s\" is valid starting with revision %s";
	$msg{"maxRev"} = "[W] option \"%s\" is only valid until revision %s";
	$msg{"noUser"} = "[E] (%s) user \"%s\" does not exist";
	$msg{"noGroup"} = "[E] (%s) group \"%s\" does not exist";
	$msg{"noPerf"} = "[E] There is NO performance data for \"%s\" !";
	$msg{"noRRDchk"} = "[I] perfdata directory will NOT be checked";
	$msg{"RRDpath"} = "[A] checking of RRDpath \"%s\"";
	$msg{"RRDuser"} = "[E] \"%s\": owner is \"%s\" instead of %s";
	$msg{"RRDgroup"} = "[E] \"%s\": group is \"%s\" instead of %s";
	$msg{"RRDrc"} = "[E] \"%s\"\n\tRRDtool RC: %s, %s";
	$msg{"RRDold"} = "[W] \"%s\" is older than %s seconds";
	$msg{"RRDcount"} = "[I] %s dir(s) with a total of %s rrd file(s)";
	$msg{"noRRDfiles"} = "[E] %s dir(s) but NO rrd files => NO graphs!";
	$msg{"useRRDs"} = "[I] RRDs perl module installed";
	$msg{"noRRDs"} = "[I] RRDs perl module not installed";
	$msg{"noHiRes"} = "[E] Time::HiRes perl module not installed";
	$msg{"chkPar"} = "[D] checking parameter \"%s\"";
	$msg{"ParValue"} = "[I] parameter value \"%s\"";
	$msg{"parModeInv"} = "[E] \"%s\" not valid in \"%s\" mode";
	$msg{"invValue2"} = "[E] value \"%s\" for \"%s\" is invalid";
	$msg{"chkTemplate"} = "[A] checking template \"%s\"";
	$msg{"invTemplate"} = "[E] syntax of template is invalid";
	$msg{"invDelim"} = "[E] invalid delimiter (%s) in template";
	$msg{"missDelim"} = "[E] missing delimiter in template";
	$msg{"invDatatype"} = "[E] datatype \"%s\" in template is invalid";
	$msg{"invTempVar"} = "[E] variable \"%s\" in template is (probably) invalid";
	$msg{"invTempVal"} = "[E] value \"%s\" in template is invalid, should be \"%s\"";
	$msg{"invEOL"} = "[E] \"%s\" should end with a semicolon";
	$msg{"invQuote"} = "[E] \"%s\" quotes are not matching";
	$msg{"missTempVar"} = "[E] variable \"%s\" in template is missing";
	$msg{"missinvTempVal"} = "[E] value \"%s\" in template is missing";
	$msg{"noCmd"} = "[E] command_name \"%s\" not found";
	$msg{"noParCfg"} = "[E] \"%s\" not found in $product.cfg";
	$msg{"noParCfgH"} = "[H] \"%s\" not found in $product.cfg";
	$msg{"notAdv"} = "[H] \"%s\" not advisable in Nagios < 3.x";
	$msg{"invChar"} = "[E] \"%s\" (\"%s\") has invalid format/contains invalid characters";
	$msg{"undefVal"} = "[E] no (valid) value for \"%s\" defined";
	$msg{"noNumber"} = "[E] %s not a valid number";
	$msg{"startEnd"} = "[E] start (%s) is greater than end (%s)";
	$msg{"noFile"} = "[E] (%s) file \"%s\" is missing";
	$msg{"noRes"} = "[E] resource \"%s\" is not defined";
	$msg{"noFileYet"} = "[I] (%s) file \"%s\" doesn't exist (yet)";
	$msg{"noDir"} = "[E] (%s) directory \"%s\" is missing";
	$msg{"noSock"} = "[E] \"%s\" is not a socket";
	$msg{"noWrite"} = "[E] \"%s\": no write permissions for \"%s\"";
	$msg{"key"} = "[D] key:\"%s\"";
	$msg{"keyValue"} = "[D] directive:\"%s\", value:\"%s\"";
	$msg{"oddLine"} = "[W] \"%s\" looks odd";
	$msg{"errOpen"} = "[E] open of %s failed, RC=%s";

	$msg{"LinkNagiosChk"} = "[H] http://nagios.sourceforge.net/docs/3_0/verify_config.html";
	$msg{"LinkReqSW"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/about#required_software";
	$msg{"LinkRRDtool"} = "[H] http://www.rrdtool.org";
	$msg{"LinkPNPreq"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/about#requirements";
	$msg{"PNPsync"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/config#default_mode";
	$msg{"PNPbulk"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/config#bulk_mode";
	$msg{"PNPnpcd"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/config#npcd";
	$msg{"NPCDcfgReq"} = "[E] NPCD config file required";
	$msg{"noNPCDreq"} = "[H] NPCD config file is not required";
	$msg{"LinkEnaEnv"} = "[H] http://nagios.sourceforge.net/docs/3_0/configmain.html#enable_environment_macros";
	$msg{"LinkEnaPerf"} = "[H] http://nagios.sourceforge.net/docs/3_0/configmain.html#process_performance_data";
	$msg{"LinkDevInfo"} = "[H] http://nagiosplug.sourceforge.net/developer-guidelines.html#AEN203";
	$msg{"LinkPNPconfig"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/config";
	$msg{"LinkPPcfg"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/config";
	$msg{"LinkCPcfg"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/webfe";
	$msg{"LinkNagiosCfg"} = "[H] http://nagios.sourceforge.net/docs/3_0/configmain.html#%s";
	$msg{"LinkNagiosCfg2"} = "[H] http://nagios.sourceforge.net/docs/3_0/configmain.html#process_performance_data\n    (and following options)";
	
	if ($language =~ /de/i) {
		$msg{"qd"} = "[E] --quiet und --debug schliessen sich gegenseitig aus";
		$msg{"noBase"} = "[E] ${prod_name}-Basisverzeichnis nicht gefunden/angegeben";
		$msg{"noBaseDir"} = "[E] ${prod_name}-Basisverzeichnis \"%s\" existiert nicht";
		$msg{"useBase"} = "[I] benutze ${prod_name}-Basisverzeichnis \"%s\"";
		$msg{"noBinary"} = "[E] Binary \"%s\" nicht gefunden/definiert";
		$msg{"useBinary"} = "[I] benutze ${prod_name}-Binary \"%s\"";
		$msg{"noCfg"} = "[E] $product.cfg nicht angegeben";
		$msg{"noCfgFile"} = "[E] Konfigurationsdatei \"%s\" nicht gefunden";
		$msg{"useCfg"} = "[I] benutze ${prod_name}-config \"%s\"";
		$msg{"binExec"} = "[E] Datei \"%s\" ist nicht ausfuehrbar";
		$msg{"verifyCfg"} = "[A] verifiziere ${prod_name}-Konfiguration";
		$msg{"invPNPmode"} = "[E] kein gueltiger PNP-Modus angegeben (sync, Bulk, NPCD, default)";
		$msg{"PNPmode"} = "[I] PNP-Modus: \"%s\"";
		$msg{"Package"} = "[I] Paket: \"%s\"";
		$msg{"noPkg"} = "[E] Paket \"%s\" nicht gefunden";
		$msg{"NPCDcfgReq"} = "[E] NPCD-Konfigurationsdatei erforderlich";
		$msg{"noNPCDreq"} = "[H] NPCD-Konfigurationsdatei nicht erforderlich";
		$msg{"useLog"} = "[I] LogFile \"%s\" angegeben";
		$msg{"NagiosChkErr"} = "[E] ${prod_name}-Konfigurationspruefung findet Fehler";
		$msg{"NagiosCfgErr"} = "[E] ${prod_name}-Konfigurationsdatei enthaelt Fehler";
		$msg{"verifyRRD"} = "[A] pruefe RRDtool (%s)";
		$msg{"invFile"} = "[E]: \"%s\" ist keine (regulaere) Datei";
		$msg{"invDir"} = "[E] Verzeichnis \"%s\" existiert nicht";
		$msg{"useEntry"} = "[I] benutze cfg_dir/cfg_file-Eintraege";
		$msg{"useCache"} = "[I] benutze \"%s\"-Eintraege";
		$msg{"dupEntry"} = "[E] Direktive \"%s\" ist doppelt";
		$msg{"noPerfEna"} = "[E] keine Performance-Daten aktiviert (process_performance_data=1 in $product.cfg)";
		$msg{"envMacrosDis"} = "[E] Environment-Makros deaktiviert (enable_environment_macros=0)";
		$msg{"noFonts"} = "[H] dejavu-Fonts sind ggf. nicht installiert";
		$msg{"noErrors"} = "\nKeine (offensichtlichen) Fehler gefunden. Viel Spass mit PNP";
		$msg{"Warnings"} = "\nWarnungen gefunden.\nBitte ueberpruefen Sie die Einstellungen.";
		$msg{"Errors"} = "\nFehler gefunden.\nBitte ueberpruefen Sie die Einstellungen und lesen Sie die Dokumentation.";
		$msg{"procFile"} = "[A] verarbeite \"%s\"";
		$msg{"searchObj"} = "[A] suche nach \"%s\"";
		$msg{"noLabel"} = "[E] kein Label definiert";
		$msg{"invValue"} = "[E] kein gueltiger Wert";
		$msg{"invOption"} = "[E] \"%s\" ist keine gueltige Option";
		$msg{"invUOM"} = "[E] \"%s\" scheint keine gueltige Masseinheit zu sein";
		$msg{"minRev"} = "[W] Option \"%s\" ist erst gueltig ab Revision %s";
		$msg{"maxRev"} = "[W] Option \"%s\" ist nur gueltig bis Revision %s";
		$msg{"noUser"} = "[E] (%s) Benutzer \"%s\" existiert nicht";
		$msg{"noGroup"} = "[E] (%s) Gruppe \"%s\" existiert nicht";
		$msg{"noPerf"} = "[E] es gibt KEINE Performance-Daten fuer \"%s\"";
		$msg{"noRRDchk"} = "[I] perfdata-Verzeichnis wird NICHT geprueft";
		$msg{"RRDpath"} = "[A] pruefen von RRDpath \"%s\"";
		$msg{"RRDuser"} = "[E] \"%s\": Owner ist \"%s\" anstatt %s";
		$msg{"RRDgroup"} = "[E] \"%s\": Group ist \"%s\" anstatt %s";
		$msg{"RRDold"} = "[W] \"%s\" ist aelter als %s Sekunden";
		$msg{"RRDcount"} = "[I] %s Verzeichnis(se) mit insgesamt %s rrd-Datei(en)";
		$msg{"noRRDfiles"} = "[E] %s Verzeichnis(se) aber KEINE rrd-Dateien => KEINE Graphen!";
		$msg{"useRRDs"} = "[I] RRDs Perl-Modul installiert";
		$msg{"noRRDs"} = "[I] RRDs Perl-Modul nicht installiert";
		$msg{"noHiRes"} = "[E] Time::HiRes Perl-Modul nicht installiert";
		$msg{"chkPar"} = "[D] pruefe Parameter \"%s\"";
		$msg{"ParValue"} = "[I] Parameterwert \"%s\"";
		$msg{"parModeInv"} = "[E] \"%s\" ist im \"%s\"-Modus nicht gueltig";
		$msg{"invValue2"} = "[E] Wert \"%s\" fuer \"%s\" ist ungueltig";
		$msg{"chkTemplate"} = "[A] pruefe Template \"%s\"";
		$msg{"invTemplate"} = "[E] Syntax des Templates ist ungueltig";
		$msg{"invDelim"} = "[E] ungueltiger Delimiter (%s) im Template";
		$msg{"missDelim"} = "[E] fehlender Delimiter im Template";
		$msg{"invDatatype"} = "[E] Datentyp \"%s\" im Template ist ungueltig";
		$msg{"invTempVar"} = "[E] Variable \"%s\" im Template ist (wahrscheinlich) ungueltig";
		$msg{"invTempVal"} = "[E] Wert \"%s\" im Template ist ungueltig, sollte \"%s\" lauten";
		$msg{"invEOL"} = "[E] \"%s\" sollte mit einem Semikolon enden";
		$msg{"invQuote"} = "[E] \"%s\" Anfuehrungszeichen nicht paarig";
		$msg{"missTempVar"} = "[E] Variable \"%s\" im Template fehlt";
		$msg{"missinvTempVal"} = "[E] Wert \"%s\" im Template fehlt";
		$msg{"noCmd"} = "[E] command_name \"%s\" nicht gefunden";
		$msg{"noParCfg"} = "[E] \"%s\" nicht in $product.cfg gefunden";
		$msg{"noParCfgH"} = "[H] \"%s\" nicht in $product.cfg gefunden";
		$msg{"notAdv"} = "[H] \"%s\" wird fuer Nagios < 3.x nicht empfohlen";
		$msg{"invChar"} = "[E] \"%s\" (%s) hat ein ungueltiges Format/enthaelt ungueltige Zeichen";
		$msg{"undefVal"} = "[E] kein (gueltiger) Wert fuer \"%s\" definiert";
		$msg{"noNumber"} = "[E] %s ist keine gueltige Zahl";
		$msg{"startEnd"} = "[E] Startwert (%s) ist groesser als Endwert (%s)";
		$msg{"noFile"} = "[E] (%s) Datei \"%s\" fehlt";
		$msg{"noRes"} = "[E] Ressource \"%s\" ist nicht definiert";
		$msg{"noFileYet"} = "[I] (%s) Datei \"%s\" existiert (noch) nicht";
		$msg{"noDir"} = "[E] (%s) Verzeichnis \"%s\" fehlt";
		$msg{"noSock"} = "[E] \"%s\" ist kein Socket";
		$msg{"noWrite"} = "[E] \"%s\": keine Schreibberechtigung fuer \"%s\"";
		$msg{"key"} = "[D] key:\"%s\"";
		$msg{"keyValue"} = "[D] Direktive:\"%s\", Wert:\"%s\"";
		$msg{"oddLine"} = "[W] \"%s\" sieht komisch aus";
		$msg{"errOpen"} = "[E] oeffnen von %s fehlgeschlagen, RC=%s";

		$msg{"LinkNagiosChk"} = "[H] http://www.nagios-wiki.de/nagios/doku3/verify_config";
		$msg{"LinkReqSW"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/about#benoetigte_software";
		$msg{"LinkPNPreq"} = "[H] http://docs.pnp4nagios.org/$language/pnp-${doc_version}/about#anforderungen_an_plugins";
		$msg{"LinkEnaEnv"} = "[H] http://www.nagios-wiki.de/nagios/doku3/#enable_environment_macros";
		$msg{"LinkEnaPerf"} = "[H] http://www.nagios-wiki.de/nagios/doku3/configmain#process_performance_data";
		$msg{"LinkNagiosCfg"} = "[H] http://www.nagios-wiki.de/nagios/doku3/configmain#%s";
		$msg{"LinkNagiosCfg2"} = "[H] http://www.nagios-wiki.de/nagios/doku3/configmain#process_performance_data\n    (und folgende Optionen)";
	}
}