##---------------------------------------------------------------------------## ## File: ## $Id: Config.pm,v 1.8 2002/09/20 02:58:38 ehood Exp $ ## Description: ## POD at end of file. ##---------------------------------------------------------------------------## ## Copyright (C) 2002 Earl Hood ## ## 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 ##---------------------------------------------------------------------------## package MHArc::Config; BEGIN { $Debug = 0; $Cache = 1; } sub load { my $self = { }; my $mod = shift; # Name of module my $fname = shift; # Filename to read configuration from my $class = ref($mod) || $mod; bless $self, $class; $self->read_filename($fname); } sub read_filename { my $self = shift; my $in_file = shift; READ_FILE: { if ($in_file eq '-') { $fh = \*STDIN; $self->parse_config_sh($fh); last READ_FILE; } my $filename = $in_file; my $cache_file = $in_file . '.cache.pl'; if ($Cache) { my $cache_mtime; if (-e $cache_file) { $cache_mtime = (stat(_))[9]; print 'Cache mtime: ', $cache_mtime, "\n" if $Debug; } if (!(-e $filename)) { $filename .= '.dist'; if (-e $filename) { warn qq/Warning: Using "$filename"\n/; } else { die qq/ERROR: "$in_file" does not exist\n/; } } my $file_mtime = (stat(_))[9]; print 'Config mtime: ', $file_mtime, "\n" if $Debug; if (defined($cache_mtime) && ($cache_mtime >= $file_mtime)) { print "Using cache\n" if $Debug; delete $INC{$cache_file}; my $vars; eval { $vars = require $cache_file; }; if ($@) { warn qq/Warning: Problem requiring "$cache_file": $@\n/; } else { $self = $vars; last READ_FILE; } } } local(*FILE); open(FILE, $filename) || die qq/ERROR: Unable to open "$filename": $!\n/; print "Using $filename\n" if $Debug; $self->parse_config_sh(\*FILE); close(FILE); if ($Cache) { eval { require Data::Dumper; local $Data::Dumper::Terse = 1; local $Data::Dumper::Indent = 0; print 'Create cache ', $cache_file, "\n" if $Debug; open(FILE, '>'.$cache_file) || die qq/Unable to create "$cache_file": $!\n/; print FILE '# DO NOT EDIT THIS FILE!', "\n", Data::Dumper::Dumper($self), ';'; close(FILE); }; if ($@) { warn qq/Warning: Problem writing "$cache_file": $@\n/; unlink($cache_file); }; } } # Check for MHONARC_LIB, and if defined, add to perl's @INC if ($self->{'MHONARC_LIB'}) { print 'Adding ', $self->{'MHONARC_LIB'}, "to \@INC\n" if $Debug; unshift(@INC, $self->{'MHONARC_LIB'}); } $self; } sub parse_config_sh { my $self = shift; my $fh = shift; my($line, $key, $value); while (defined($line = <$fh>)) { next unless $line =~ /\S/; next if $line =~ /^\s*#/; chomp $line; ($key, $value) = split(/=/, $line, 2); if ($value =~ s/^'//) { $value =~ s/'$//; } else { $value =~ s/^"//; $value =~ s/"$//; $value = _expand_vars($self, $value); } $self->{$key} = $value; } } sub dump_config { my $self = shift; my $fh = shift; foreach my $key (sort keys %$self) { print $fh $key, '=', $self->{$key}, "\n"; } } sub _expand_vars { my $map = shift; my $str = shift; $str =~ s/(^|[^\$])\$(\{[^}]+\}|[\w]+)/$1 . _var_lookup($map, $2);/ge; $str; } sub _var_lookup { my $map = shift; my $key = shift; $key =~ s/[{}]//g; defined($map->{$key}) ? $map->{$key} : defined($ENV{$key}) ? $ENV{$key} : ""; } #my $config = MHArc::Config->load('-'); #foreach (sort keys %$config) { # print "$_=", $config->{$_}, "\n"; #} #========================================================================== 1; __END__ =head1 NAME MHArc::Config - Load mail archive configuration file =head1 SYNOPSIS $conf = MHArc::Config->load($filename); print $conf->{'HTML_DIR'}; =head1 DESCRIPTION This module will load in the archive configuration file. The archive configuration file defines variables in Bourne shell syntax format. B Only a subset of the Bourne shell syntax is supported, so do not get fancy with the file. The C static method will create a new configuration instance that is a bless hash reference. The variables defined in the file will be the hash keys. B If the filename specified does not exist, then the C method will check for the filename with a C<.dist> extension. It is recommended to not rely on the C<.dist> version since it will get overwritten on software updates. =head1 CACHING This module will create a cached version of the file loaded to make subsequent loadings quicker. The cached file will be called CfilenameE.cache.pl> and will contain the configuration data in a Perl format. When loading the configuration of a file, the timestamps of the cache file and the regular file are compared. If the cache is newer, it is used. Else, the regular file will be loaded and a new cache file created. =head1 VARIABLES =over =item C<$MHArc::Config::Cache> If set to C<0>, no cache processing will be done. Configuration will be loaded directly from specified file. =item C<$MHArc::Config::Debug> If set to C<1>, diagnostic information will be printed. This variable should only be used for debugging and not in production. =back =head1 VERSION C<$Id: Config.pm,v 1.8 2002/09/20 02:58:38 ehood Exp $> =head1 AUTHOR Earl Hood, earl@earlhood.com This module is part of the mharc archiving system and comes with ABSOLUTELY NO WARRANTY and may be copied only under the terms of the GNU General Public License, which may be found in the MHArc distribution. =cut