package CS::Config; use Carp; use strict; use vars qw(@ISA @EXPORT $VERSION); require Exporter; $VERSION = '0.1'; @ISA = qw(Exporter); @EXPORT = qw(getpluginc gethostc checkpluginc checkhostc); =head1 NAME CS::Config - Checkservice config parsing =head1 SYNOPSIS use CS::Config; my $error; return print STDERR "$error\n" if $error = checkpluginc('warning', 'sms'); my $beepconfig = getpluginc('warning', 'sms'); return print STDERR "$error\n" if $error = checkhostc('groupA/subgroupB', 'host1'); my $hostconfig = gethostc('groupA/subgroupB', 'host1'); =head1 DESCRIPTION I provides two kinds of config parsers for two types of configfiles. =head1 FUNCTIONS The following functions are provided. The functions uses '/etc/checkservice' as default configroot unless $CS::Config::root is set to a valid directory. =cut our ($root); $root = '/etc/checkservice' unless (defined $root and -d $root); =over 4 =item getpluginc(TYPE, PLUGIN) Hashes a config file with format 'key=value' so information can be retrieved from the hash returned using $ref->{key}. my $config = getpluginc('warning', 'test'); print "Value of key: ", $config->{key}, "\n"; =cut sub getpluginc { my %conf; my ($type, $plugin) = @_; my ($key, $value); (! -d "$root/plugins/$type") and croak "Couldn\'t find config dir \'$root/plugins/$type\', moduletype may not exist\n"; (! -r "$root/plugins/$type/$plugin.conf") and croak "Configfile \'$root/plugins/$type/$plugin.conf\' not found or not readable\n"; open CONF, "$root/plugins/$type/$plugin.conf" or croak "Couldn't open configfile \'$root/plugins/$type/$plugin.conf\' for reading!\n"; while () { chomp; s/#.*//; if (($key, $value) = /^\s*(\S+)\s*=\s*(\S.*)/) { $conf{$key} = $value; } } close CONF; return \%conf; } =item checkpluginc(TYPE, PLUGIN) Checks the validaty, readability and accessibility of PLUGIN of type TYPE. Returns 0 if config is valid, or a string if an (parse)error occurs. The string can be a notification of the fact that the configfile isn't readable/accessible or that a parse error occured on a given line. if ($error = checkpluginc('warning', 'beep') { print STDERR "beeplugin: $error\n"; # Error reporting if ran manual return 3; # Returncode 3: plugin error! } else { my $config = getpluginc('warning', 'beep'); } =cut sub checkpluginc { my ($type, $plugin) = @_; return "Unable to read/find $root/plugins/$type/$plugin.conf: $!" unless ( -r "$root/plugins/$type/$plugin.conf"); return parseconf("$root/plugins/$type/$plugin.conf"); } =item gethostc([GROUPPATH], HOST) Returns a hash with three keys: url, mailto, and services Where url is a string, mailto a reference to an array and services a reference to an hash, where the keys are the (first of the) portnumber(s) to check and the values a reference to another hash, representing a service, which is an hash with it's own 5 keys: ports, shortname, longname, checktype and action. Visualization: \%hash (url) --> "http://www.linvision.com/checkservice" (mailto) --> \(paul@linvision.com, root@linvision.com) (services) --> \%services (21) --> \%service (ports) --> \(21) (shortname) --> "ftp" (longname) --> "WuFTPd" (checktype) --> "x" (action) --> "" (137) --> \%service (ports) --> \(137,139) (shortname) --> "samba" ...etc ...etc Example: my $hostc = gethostc('groupA', 'host1'); print "URL:\t $hostc->{url}\n"; print "Mailto:\t ", join(',', @($host->{'mailto'})), "\n"; print "Services to check: "; foreach (keys %{$hostc->{'services'}}) { print $hostc->{'services'}->{$_}->{'shortname'}, " "; } print "\n"; =cut sub gethostc { my $host = pop; my $path = shift; my ($url, @mailto, %services); $path .= '/' unless !$path or $path =~ /\/$/; (! -r "$root/hosts/$path$host") and croak "Hostfile \'$root/hosts/$path$host\' not found or not readable!\n"; open CONF, "$root/hosts/$path$host" or croak "Couldn't open configfile \'$root/hosts/$path$host\' for reading!\n"; my %conf = (url => \$url, mailto => \@mailto, services => \%services); while () { chomp; s/#.*//; if (/^\s*service\s*=\s*([\d,]+):(\w+):([sxn]):([^:]*):?(.*)$/) { my @ports = split ',', $1; my %service = (ports => \@ports, shortname => $2, checktype => $3, longname => $4, action => $5); $services{$ports[0]} = \%service; } elsif (/^\s*mailto\s*=\s*(([\w._-]+@[\w_.-]+:)*[\w._-]+@[\w_.-]+)$/) { @mailto = split ':', $1; } elsif (/^\s*url\s*=\s*((\w+):\/\/[\w_.?&]+)$/) { $url = $1; } } close CONF; return \%conf; } =item checkhostc([GROUPPATH], HOST) Checks the validity, readability and accessability of configfile for HOST, grouped in optional GROUPPATH.. Returns 0 if config is valid, return string with failed-reason if something went wrong. (see also checkpluginc() above). =cut sub checkhostc { my $host = pop; my $path = shift; $path .= '/' unless !$path or $path =~ /\/$/; return "Unable to read/find $root/hosts/$path$host: $!" unless ( -r "$root/hosts/$path$host"); return parseconf("$root/hosts/$path$host"); } sub parseconf { my $cfile = shift; open CONF, $cfile or return "Couldn't open configfile $cfile: $!"; while () { chomp; s/#.*//; return "Parse error on line $. of $cfile: $_" unless $_ =~ /^\s*(\S+)\s*=\s*(\S.*)/ or $_ =~ /^\s*$/; } return 0; } =head1 BUGS checkpluginc() and checkhostc() returns parse errors on configfiles that ARE parsable by getpluginc() and gethostc(). =head1 COPYRIGHT Copyright (c) 2001 Paul van Tilburg. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Checkservice itself. =head1 AUTHOR INFORMATION Paul van Tilburg , Checkservice homepage: http://www.linvision.com/checkservice/ =head1 SEE ALSO L, L. =cut 1;