FS:Conf patches

David Morton freeside at petra.osprey.net
Fri Apr 7 10:00:03 PDT 2000


Attached are two patches for UID.pm and Conf.pm files.   These
patches allow for configuration to be set in a more limited
area.   This seems to work for me so far... I'm sure it could use a
little cleanup.  

Here's a brief description of what it does/expects:

Upon the first use of FS:Conf, it loads system wide
values from /usr/local/etc/freeside/freeside.conf.

UID.pm looks in the mapsecrets file for the username/directory pair,
and then loads the Conf module with that new directory, for example,
/usr/local/etc/freeside/osprey/freeside.conf
This file has the datasource names, and most of the configuration.

(The only reason for having two files, is if this is supposed to support
two different companies on the same setup.  I wouldn't mind dropping
this expectation for a while)

IniConf needs to be installed from CPAN...  I may change this part, but
the
configuration file format won't need to change.


the freeside.conf file has the format:


#comments start with '#'
[default]   #section names in []'s   
key=value
array=<<EOT
value1
value2
value3
EOT

bool=true
anotherbool=1
yetanother=something rediculous.

#this next line doesn't work.

badbool=          

badbool=                    #although this does; value is spaces.  It's
a bug.
                            #the comment makes it read the spaces.
[other]
foo=bar

______________________


For exists() to work, the  value must have a value, although it doesn't
matter what.

exists("yetanother")  is true
exists("badbool=") is not true for the first entry, although the second
entry would overwrite the first.
-------------- next part --------------
--- /home/freeside/dist/freeside_current/FS/FS/UID.pm	Thu Apr  6 11:57:00 2000
+++ FS/UID.pm	Thu Apr  6 11:19:21 2000
@@ -215,15 +215,27 @@
   my($setuser) = shift;
   $user = $setuser if $setuser;
   die "No user!" unless $user;
-  my($conf) = new FS::Conf $conf_dir;
-  my($line) = grep /^\s*$user\s/, $conf->config('mapsecrets');
-  die "User not found in mapsecrets!" unless $line;
-  $line =~ /^\s*$user\s+(.*)$/;
-  $secrets = $1;
+  
+  open MAPSECRETS, $conf_dir . "/mapsecrets";
+  
+  while (<MAPSECRETS>) {
+  	if (/^\s*$user\s+(.*)$/) {
+		$secrets = $1;
+		last;
+	}
+  }
   die "Illegal mapsecrets line for user?!" unless $secrets;
-  ($datasrc, $db_user, $db_pass) = $conf->config($secrets)
+  
+  
+  my($conf) = new FS::Conf "$conf_dir$secrets" ;
+  ($datasrc, $db_user, $db_pass) = $conf->config("datasource")
     or die "Can't get secrets: $!";
-  $FS::Conf::default_dir = $conf_dir. "/conf.$datasrc";
   ($datasrc, $db_user, $db_pass);
 }
 
-------------- next part --------------
--- /home/freeside/dist/freeside_current/FS/FS/Conf.pm	Thu Apr  6 11:57:00 2000
+++ FS/Conf.pm	Fri Apr  7 11:37:14 2000
@@ -1,7 +1,9 @@
 package FS::Conf;
 
-use vars qw($default_dir);
+use vars qw(%configs $config_main);
 use IO::File;
+use IniConf;
+use Carp;
 
 =head1 NAME
 
@@ -19,38 +21,83 @@
   $dir = $conf->dir;
 
   $value = $conf->config('key');
+  $value = $conf->config('key','section');
   @list  = $conf->config('key');
   $bool  = $conf->exists('key');
 
 =head1 DESCRIPTION
 
-Read access to Freeside configuration values.  Keys currently map to filenames,
-but this may change in the future.
+Read access to Freeside configuration values.  Freeside looks for a file named 
+F<freeside.conf> in the directory named, or F</usr/local/etc/freeside> as default.
+FS::Conf stores the configuration in a class variable %configs, so that it won't
+have to be reloaded if new is called again.  The freeside.conf file is formatted
+like an .ini  file;  see the manpage for IniConf 
 
 =head1 METHODS
 
 =over 4
 
+=cut
+
+BEGIN {
+	$default_dir = "/usr/local/etc/freeside";	#if this could be set be a command
+											#line argument, that would be nifty
+
+
+    if ($config_main = IniConf->new( -file => $default_dir .
+	                                          "/freeside.conf"))  {
+			my $mainself={ 'dir' => $default_dir,
+				   'config' =>  $config_main} ;
+		bless $mainself, "FS::Conf";
+		$configs{$default_dir} = $mainself;
+	} else {
+		print STDERR "Could not open config file: $default_dir/freeside.conf\n"
+		. "There were problems on the following lines:\n" . 
+		join "\n", @IniConf::errors;
+		print "\n";
+		exit();
+	}
+}
+
+
 =item new [ DIRECTORY ]
 
-Create a new configuration object.  A directory arguement is required if
-$FS::Conf::default_dir has not been set.
+Create a new configuration object.  Defaults to F</usr/local/etc/freeside/> if 
+no parameter is passed; otherwise it looks for the F<freeside.conf> file in the
+directory indicated.
 
 =cut
 
 sub new {
-  my($proto,$dir) = @_;
-  my($class) = ref($proto) || $proto;
-  my($self) = { 'dir' => $dir || $default_dir } ;
-  bless ($self, $class);
+	my($proto,$dir) = @_;
+	my($class) = ref($proto) || $proto;
+	
+	$dir = $default_dir if !defined($dir);
+	$dir =~ s/(.*)\/$/$1/;
+	
+	if (exists $configs{$dir}) {
+		return  $configs{$dir};
+	} 
+	
+	#print "loading more config values from $dir/freeside.conf\n";
+	
+	
+	my $config = IniConf->new( -file => $dir . "/freeside.conf");
+	my($self) = { 'dir' => $dir,
+				 'config' => $config} ;
+
+	bless $self, $class;
+	$configs{$dir} = $self;
+	
 }
 
 =item dir
 
-Returns the directory.
+Returns the directory.  (Not sure if this is needed anymore - DGM)
 
 =cut
 
+
 sub dir {
   my($self) = @_;
   my $dir = $self->{dir};
@@ -64,49 +111,56 @@
 =item config 
 
 Returns the configuration value or values (depending on context) for key.
+Optional section parameter specifies which section to look in for the key;
+defaults to "default".   A temporary hack allows for the key to include
+a directory path - this will be interpreted as a section, ie.
+C<config("/foo/bar/file")> translates to C<config("file", "/foo/bar")>
 
 =cut
 
 sub config {
-  my($self,$file)=@_;
-  my($dir)=$self->dir;
-  my $fh = new IO::File "<$dir/$file" or return;
-  if ( wantarray ) {
-    map {
-      /^(.*)$/
-        or die "Illegal line (array context) in $dir/$file:\n$_\n";
-      $1;
-    } <$fh>;
-  } else {
-    <$fh> =~ /^(.*)$/
-      or die "Illegal line (scalar context) in $dir/$file:\n$_\n";
-    $1;
-  }
+	my($self,$file, $section)=@_;
+	my($dir)=$self->{dir};
+	
+	$section = "default" if !defined $section;
+	
+	if ($file =~ /(.*)\/(.*)/) {  #subdirectories translate to sections?
+		$section = $1;            #backwards compatability hack
+		$file = $2;
+	}
+
+	my $result = eval '$configs{$dir}->{config}->val($section, $file)';
+
+	
+
 }
 
 =item exists
 
-Returns true if the specified key exists, even if the corresponding value
-is undefined.
+Returns true if the specified key exists, no matter what the value. (A value
+must exist in the configuration file, though.)  Parameters are the same as
+C<config>
 
 =cut
 
 sub exists {
-  my($self,$file)=@_;
-  my($dir) = $self->dir;
-  -e "$dir/$file";
+  my($self,$file, $section)=@_;
+  my($dir) = $self->{dir};
+  $section = "default" if !defined $section;
+  
+  if ($file =~ /(.*)\/(.*)/) {  #subdirectories translate to sections...
+		$section = $1;          #backwards compatability hack
+		$file = $2;
+  }
+  
+  my $result = eval '$configs{$dir}->{config}->val("default",$file)';
+  
+  if ($@) {
+  	croak "FATAL:  Problem in FS::Conf::exists!";
+  } else {
+  	return $result;
+  }
 }
 
-=back
-
-=head1 BUGS
-
-Write access (with locking) should be implemented.
-
-=head1 SEE ALSO
-
-config.html from the base documentation contains a list of configuration files.
-
-=cut
 
 1;


More information about the freeside-devel mailing list