From hasant@trabas.com Tue Feb 27 20:08:03 2001 Date: Thu, 24 Aug 2000 05:54:29 +0700 (JAVT) From: Hasanuddin Tamir To: bandung-pm-list@happyfunball.pm.org Subject: Re: [Bandung.pm] Modifying @INC: my problem and solution (any comment?) Organization: TRABAS >> No wonder Steven Haryanto on Aug 24 said that, SH] hi hasan, SH] SH] for this kind of problem i've come up with a slightly SH] different approach: use the environment variable. SH] there are two choices: SH] SH] a) use the default PERL5LIB/PERLLIB SH] pros: no script modification needed SH] SH] b) invent something like PROJROOTDIR or PROJLIBDIR SH] pros: works with other non-Perl scripts (Python, SH] shell, etc.) I used this kind of approaches, but I never felt satisfied with environment variables, partly the same reason as you mentioned nearly at the end of your email: security. Besides, the implementor must always set the ENV each time the path changes, either in the system (e.g. profile) or in httpd.conf (assuming Apache), and then we still need to restart/reload the server. I don't set my scripts setuid either, but for important application I always use -T switch, so PERL5LIB/PERLLIB certainly don't work for me. Ok, let's see some comparisons, let's assumme that we don't use setuid nor -T. We have this application: Mail2SMS with the following structure, mail2sms/ -> the base dir lib/ -> the modules path perl/ -> perl modules python/ -> python modules web/ -> the document root (and all scripts lie here) 1. It's intalled under /usr/local. a. using PERL5LIB (or similiar approach) What needs to be done: 1. Some where in the system or web server conf export PERL5LIB=/usr/local/mail2sms/lib/perl or SetEnv PERL5LIB /usr/local/mail2sms/lib/perl 2. In the scripts: nothing b. using ordinary lib module What needs to be done: 1. Some where in the system or web server conf: nothing 2. In the scripts: use lib '/usr/local/mail2sms/lib/perl'; c. using BaseLib; What needs to be done: 1. Some where in the system or web server conf: nothing 2. In the scripts: use BaseLib qw(mail2sms lib/perl); 2. Now we move the application to /home/hasant/public_html. a. using PERL5LIB (or similiar approach) What needs to be changed: 1. Some where in the system or web server conf export PERL5LIB=/home/hasant/publich_html/mail2sms/lib/perl or export PERL5LIB=/usr/local/mail2sms/lib/perl:\ /home/hasant/publich_html/mail2sms/lib/perl or SetEnv PERL5LIB /usr/local/mail2sms/lib/perl 2. In the scripts: nothing b. using ordinary lib module What needs to be changed: 1. Some where in the system or web server conf: nothing 2. In the scripts: use lib '/home/hasant/public_html/mail2sms/lib/perl'; c. using BaseLib; What needs to be changed: 1. Some where in the system or web server conf: nothing 2. In the scripts: nothing (automatically refers to the new path) 3. We want to develop three development versions, each in different directory, say a. v2.0-beta-01, /usr/local/mail2sms/beta-01 b. v2.1-pre, /usr/local/mail2sms/pre-release c. v3.0-alpha, /usr/local/mail2sms/alpha So which one PERL5LIB should contains? All with colon separated? Then all versions will refer to the same lib which is not supposed to be. When using lib module, all scripts in beta version will say, use lib '/usr/local/mail2sms/beta-01/mail2sms/lib/perl'; and scripts in alpha version will say, use lib '/usr/local/mail2sms/alpha/mail2sms/lib/perl'; With BaseLib? All scripts in all versions just still need to say, use BaseLib qw(mail2sms lib/perl); and they all refer to their respective private Perl module paths. And when I'm ready to turn the pre-release version into production version, I might need to move/copy the application set to, for example: /vhost/www/hasant.com. The environment variables, the web server conf, and the scripts remain untouched. The use() statement above will switch referring to: /vhost/www/hasant.com/mail2sms/lib/perl SH] in the b) case, you will need something like this SH] in the beginning of your Perl script: SH] SH] use lib $ENV{PROJLIBDIR}; SH] SH] or (if your lib dir name is fixed): SH] SH] use lib "$ENV{PROJROOTDIR}/priv_modules"; SH] SH] and then you can use PROJROOTDIR as a base to search SH] for other directories, without defining many other SH] environment variables (PROJBINDIR, PROJLOGDIR, etc.) SH] SH] if you need to include other directories under SH] PROJLIBDIR -- like i usually do because i install SH] other CPAN modules under PROJLIBDIR -- you can do SH] something like this: SH] SH] use lib $ENV{PROJLIBDIR}; SH] use Includer; SH] SH] where Includer.pm is located under PROJLIBDIR and SH] pulls other directories into the search path: SH] SH] # contente of Includer SH] use lib "$ENV{PROJLIBDIR}/lib/perl5/site_perl/5.005"; SH] use lib "$ENV{PROJLIBDIR}/lib/perl5/site_perl/5.005/i386-linux"; This will be handled by BaseLib to include the standard hierarchy like lib module does. SH] SH] or, you can use colon-separated path (like Unix's SH] PATH) to let you include several directories: SH] SH] BEGIN { SH] for(split/:/,$ENV{PROJLIBDIR}) { use lib $_; } SH] } SH] SH] your scripts can also refuse to run if PROJLIBDIR SH] is not defined or looks suspicious. SH] SH] BEGIN { SH] for($ENV{PROJLIBDIR}){ SH] croak "PROJLIBDIR is not defined!" unless defined; SH] ($_)=/(.*)/; # untaint like crazy SH] use lib $_; SH] } Well, that's too much for the script. Besides, you missed one bracket :-) SH] and lastly, you can check to prevent the same SH] directory included more than once if you want (as SH] lib.pm doesn't do this currently). SH] SH] the last two/three pieces of code can be put in the SH] Includer module. the part checking the definedness SH] of PROJLIBDIR can also be put in Includer should we SH] decide to install Includer in the standard search SH] path. and then all that is needed in the projects' SH] scripts is this single line: SH] SH] use Includer; SH] SH] you can also, of course, change the name 'Includer' SH] if you hate it. :-) SH] SH] among the cons for using environment variables is SH] security (esp. for setuid scripts which are to be SH] run under other people's environment). but so far SH] i've managed to not need setuid scripts in my SH] projects. SH] SH] this approach is not perfect either, i believe, but SH] so far it works for me. Yes, I can see that. We have different requirement and situation :-) SH] as to your last question, i can't give an answer. SH] but, sure, i'd say: go for it. (oops, i gave one SH] :-) Thank you very much for the input, for the discussion, and for the support. I really enjoy discussing this :-) Regards, san --