BazB has asked for the wisdom of the Perl Monks concerning the following question:

I've been tidying up a Perl CGI script I kludged together a while ago, and one of the issues I'm having is moving config info (particularly passwords) out of of the script and into a config file outside of the web directory.

The most obvious solution to this would be App::Config, however I'm still interested why the method I attempted to use does not work.

Super Search didn't dig up what I was looking for.

I was reading Tom Christiansen's Perl Style talk and came across his suggestion to use

do "/path/to/config/file.conf";
in the main script to read configuration information from another file of the form
# Config file for a perl script. $user = 'BazB' $pass = 'yaright'; $server = 'foo.bar.com';

Unfortunately, this does not seem to work under strict.

My test script is

#! /usr/bin/perl -w use strict; my ($server, $user, $pass); do "/home/baz/testconfig.conf"; print $server, "\n", $user, "\n", $pass, "\n";
However it fails with
Use of uninitialized value in print at ./readconfig.pl line 8.

I've tried playing around with the script, but the only way I can get it to 'work' is to comment out

use strict; my ($server, $user, $pass);
which is bad, bad, bad. Even then, there are warnings:
Name "main::user" used only once: possible typo at ./readconfig.pl lin +e 8.
(and similar for the other variables).

I certainly do not want to write a parser to read config files.

Why does using do in this manner fail?
Is there another simple way of reading configuration information without resorting to something like App::Config?

Cheers.

BazB

Edit: chipmunk 2002-02-10

Replies are listed 'Best First'.
Re: Using do to read config
by chromatic (Archbishop) on Feb 10, 2002 at 20:48 UTC
    As documented in perlfunc for do: code evaluated with "do FILENAME" cannot see lexicals in the enclosing scope; "eval STRING" does.

    This is widely considered to be a feature.

    If you make your variables package globals, you will have better luck.

    You might also look at Data::Dumper or Data::Denter to perform this more effectively.

    Edit: chipmunk 2002-02-10

Re: Using do to read config
by gellyfish (Monsignor) on Feb 10, 2002 at 20:46 UTC

    You want to put a package main; in your config file and then instead of my ( $server, $user, $pass) put  use vars qw($server $user $pass) and everything will be fine ;-} (you don't actually need to declare the package in your config file but it will help if you add any other packages)

    /J\

Re: Using do to read config
by Zaxo (Archbishop) on Feb 11, 2002 at 00:12 UTC

    do FILE; returns the value of the last statement in FILE, so globalizing things isn't really necessary. That property can be used to restrict visibility of the configuration:

    $ cat foo.conf my %conf = ( passwd => 'joe', uname => 'joe', foo => 1, ); \%conf; $ perl -w -Mstrict -e 'BEGIN{my $conf = do "foo.conf";sub whisper {pri +nt $conf->{passwd},$/}} whisper()' joe
    Attempts to make use of $conf outside the BEGIN block will fail.

    After Compline,
    Zaxo

Re: Using do to read config
by merlyn (Sage) on Feb 11, 2002 at 03:38 UTC
Re: Using do to read config
by mull (Monk) on Feb 10, 2002 at 23:28 UTC

    Regarding not wanting to write your own parser, it's actually not that bad. I have a little one that I've been using for small config files for awhile; nothing fancy but it works:

    sub readConfigFile($){ my $cfgfile = shift; my %cfg; open(CONFIG, $cfgfile) or die " Error opening $cfgfile: $!\n"; while (<CONFIG>) { next if /^\s*$/; next if /^\#/; chomp; next unless /=/; my ($key, $variable) = split(/=/,$_,2); $variable =~ s/(\$(\w+))/$cfg{$2}/g; $cfg{$key} = $variable; } return %cfg; }

    In my opinion, this is a nifty and simple little config file parser.