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

Hello monks, I have a module I am trying to package for deployment. This module reads the contents of a configuration file which is in the module's directory.

Let's say the module name is acme.pm and the config file is acme.config. Both files are installed under <module_dir>/acme.

My problem is that I can't seem to figure out how to specify a path to that config file that the module will use once deployed. This works from the command line but does not work when the module is imported. (complains that it can't find "acme.config"):
#!/usr/local/lib/perl sub get_config { my $CONFIGPATH = 'acme.config'; open (CONFIG,$CONFIGPATH) or die "$0: File '$CONFIGPATH': $!\n"; undef $/; my $c=<CONFIG>; close CONFIG; return chomp($c); }
I have also tried ./acme.config. I do not want to put a hard path in because this will surely break under various module installation schemas. The file is read-only and static, and I would prefer it live in the module directory.

I'm sure this is yet another answer that will make me feel like a primitive hack once it is patiently explained to me. Help?

Replies are listed 'Best First'.
Re: Read a static file from module directory
by Fletch (Bishop) on Nov 29, 2001 at 21:27 UTC

    If you know that it'll always be in the same directory as the Foo module you could look in $INC{Foo.pm} and use File::Basename to extract a directory name.

Re: Read a static file from module directory
by DrManhattan (Chaplain) on Nov 29, 2001 at 21:51 UTC
    If you know the location of the config file relative to the script which uses your module, you can use FindBin:
    # Parent script resides in /usr/local/myproject/bin # Module and config file reside in /usr/local/myproject/lib use FindBin qw($Bin); sub get_config { my $CONFIGPATH = "$Bin/../lib/acme.config"; open (CONFIG, "<$CONFIGPATH") or die "$0: File '$CONFIGPATH': $!"; undef $/; my $c=<CONFIG>; close CONFIG; return $c; }
    A couple of other notes: <list>
  • You should get in the habit of explicitly directing your open() calls. E.g. use "<$CONFIGFILE" instead of "$CONFIGFILE". In this particular case it isn't a big deal, but if $CONFIGFILE was supplied by a user, that user could set it to something bad like "|rm -rf /*".
  • chomp() operates directly on the variable you give it as an argument, so returning chomp($c) won't do what you think it does.
  • chomp() doesn't do anything at all in slurp mode ($/ = undef) anyway. :)
  • </list>

    -Matt

      My bad, perils of gut-and-paste. I already found out about chomp being an in-place method and not a result. Point taken on directing open, I will use that.

      Problem I have is that the calling script does not reside in /usr/local. It's in the httpd docs directory as a cgi script using CGI.pm. I do a 'require acme;' and then when I try to invoke get_config is when the sadness starts.

      I will look into FindBin, that seems promising.

      Thanks for the help, I will go forth and attempt to sin no more.

Re: Read a static file from module directory
by mpeppler (Vicar) on Nov 30, 2001 at 00:46 UTC
    Unless I misunderstand the question you could use the %INC hash to find out where acme.pm was loaded from.

    For example

    use lib "lib/products"; use CTtools; print "$INC{'CTtools.pm'}\n";
    prints "lib/products/CTtools.pm".

    This should let you find the directory where "acme.pm" is found, and thus the config file.

    Michael

Re: Read a static file from module directory
by Fastolfe (Vicar) on Nov 30, 2001 at 00:38 UTC
    As another poster mentioned, you can use %INC and File::Basename to identify the filesystem path where acme.pm was found:
    use File::Basename 'dirname'; sub get_config { my $filename = dirname($INC{'acme.pm'}) . "/$_[0]"; croak "Can't find $filename" unless -f $filename; ... }
    Another option is to simply walk @INC, or some other "config file path" of your choice and find this file:
    sub find_config { my $filename = shift; foreach (@_) { return "$_/$filename" if -f "$_/$filename"; } return; } my $filename = find_config("acme.conf", @INC, "/also/search/here", "/a +nd/here") or die "Couldn't find acme.conf!";