Add "Config" module.
authorStefan Schantl <stefan.schantl@ipfire.org>
Fri, 20 Nov 2015 20:56:49 +0000 (21:56 +0100)
committerStefan Schantl <stefan.schantl@ipfire.org>
Fri, 20 Nov 2015 20:56:49 +0000 (21:56 +0100)
This module contains functions to read, validate and set various
configure options which are used in guardian.

The main functions called "UseConfig" allows to pass which config file
should be read and validates the input by calling a subfunction. The
validated settings will be returend as a hash.

The "CheckConfig" function directly can be called with a hash, which
contains the various config options and values and will return an
error message if there are any problems.

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
modules/Config.pm [new file with mode: 0644]

diff --git a/modules/Config.pm b/modules/Config.pm
new file mode 100644 (file)
index 0000000..9f2fc55
--- /dev/null
@@ -0,0 +1,186 @@
+package Guardian::Config;
+use strict;
+use warnings;
+
+use Exporter qw(import);
+
+our @EXPORT_OK = qw(CheckConfig UseConfig);
+
+# The default config file which is used, if no one has been specified.
+my $configfile = "/etc/guardian/guardian.conf";
+
+# The maximum amount of chars, which a line in the configfile is allowed to contain.
+my $maxlength = "64";
+
+# Hash with default settings. They may be overwritten by settings of the config file.
+my %defaults = (
+       "LogLevel" => "info",
+       "LogFacility" => "syslog",
+       "BlockCount" => "3",
+       "BlockTime" => "86400",
+);
+
+#
+## UseConfig configuration function.
+#
+## This function does the main work. It is responsible for calling the subfunction
+## to read the given config file (or use the default one if none has been specified),
+## and push the returned object to the validate subfunction. Finally the validated
+## settings will be merged with the default ones (existing defaults will be overwritten).
+#
+sub UseConfig ($) {
+       my $file = $_[0];
+
+       # If not file has been specified, use the default one.
+       unless ($file) {
+               $file = $configfile;
+       }
+
+       # Call subfunction to get the settings from config file.
+       # Store the options and values in a temporary hash.
+       my %temp = &ReadConfig($file);
+
+       # Validate config settings.
+       my $error = &CheckConfig(\%temp);
+
+       # As long, as no error message is returned, the config is valid.
+       unless ($error) {
+               # Merge hash with contains the default
+               # and temporary config hash. If both hashes contains
+               # the same keys, the keys+values of the first one (%defaults)
+               # will be overwritten.
+               my %config = (%defaults, %temp);
+
+               # Return the final configuration hash.
+               return %config;
+
+       # If an error message is returned, exit and print the error message.
+       } else {
+               die "Invalid configuration: $error\n";
+       }
+}
+
+#
+## ReadConfig (configfile) function.
+#
+## This function is used to read a given configuration file and store the
+## values into a hash which will be returned.
+#
+sub ReadConfig ($) {
+       my $file = $_[0];
+
+       # Hash to store the read-in configuration options and values.
+       my %config = ();
+
+       # Check if the configfile exists and is read-able.
+       unless (-r "$file") {
+                       die "The given configfile ($file) does not exist, or is not read-able: $!\n";
+       }
+
+       # Open the config file and read-in all configuration options and values.
+       open(CONF, "$file") or die "Could not open $file: $!\n";
+
+       # Process line by line.
+       while (my $line = <CONF>) {
+               # Skip comments.
+               next if ($line =~ /\#/);
+
+               # Skip blank  lines.
+               next if ($line =~ /^\s*$/);
+
+               # Remove any newlines.
+               chomp($line);
+
+               # Remove any spaces at the start and end of the line.
+               $line =~ s/^\s*//;
+               $line =~ s/\s*$//;
+
+               # Check line lenght, skip it, if it is longer than, the
+               # allowed maximum.
+               my $length = length("$line");
+               next if ($length gt $maxlength);
+
+               # Splitt line into two parts.
+               my ($option, $value) = split (/=/, $line);
+
+               # Add config option and value to the config hash.
+               $config{$option} = $value;
+       }
+
+       # Close the config file.
+       close(CONF);
+
+       # Return the configuration hash.
+       return %config;
+}
+
+#
+## The CheckConfig function.
+#
+## This function is responsible to validate configure options which has
+## to be passed as a hash. It will return an error message which provides some
+## deeper details, if any problems have been detected.
+#
+sub CheckConfig (\%) {
+       # Dereference the given hash-ref and store
+       # them into a new temporary hash.
+       my %config = %{ $_[0] };
+
+       # If a BlockTime has been configured, check if the value is a natural number.
+       if (exists($config{BlockTime})) {
+               # Get the configured value for "BlockTime".
+               my $value = $config{BlockTime};
+
+               # Call subroutine for validation.
+               my $error = &check_number("$value");
+
+               # If the check fails, immediately return an error message.
+               if ($error) {
+                       return "Invalid BlockTime: $error";
+               }
+       }
+
+       # If a BlockCount has been configured, check if the value is a natural number.
+       if (exists($config{BlockCount})) {
+               # Get the configured value for "BlockCount".
+               my $value = $config{BlockCount};
+
+               # Call subroutine for validation.
+               my $error = &check_number("$value");
+
+               # If the check fails, immediately return an error message.
+               if ($error) {
+                       return "Invalid BlockCount: $error";
+               }
+       }
+
+       # XXX - add check for validating the configured loglevel.
+
+       # The config looks good, so return nothing (no error message).
+       return undef
+}
+
+#
+## The check_number subroutine.
+#
+## This simple subroutine is used to check if a given string is numeric
+## and contains a natural number which has to be greater than zero.
+#
+sub check_number ($) {
+       my $input = $_[0];
+
+       # Check if the input is a natural number.
+       unless ($input =~ /^\d+$/) {
+               return "$input is not a natural number";
+       }
+
+       # Check if the number is greater than zero.
+       unless ($input gt "0") {
+               return "$input has to be greater than zero";
+       }
+
+       # Input is okay, return no error message (nothing).
+       return undef;
+}
+
+1;