views:

169

answers:

3

In cPanel, they tell you to insert this code into the beginning of Perl files. I'm not sure what it does. I've tried code with and without this in the beginning of the file and it seems to all work the same. I haven't tested that out with cron running the code, but only as myself. By "tested it out", I mean using print lines, database connections & returns, subs, vars, etc...

BEGIN 
{
    my $base_module_dir = (-d '/home/root/perl' ? '/home/root/perl' : ( getpwuid($>) )[7] . '/perl/');
    unshift @INC, map { $base_module_dir . $_ } @INC;
}
+3  A: 

This code sets up Perl to prefer modules in either /home/root/perl--if it exists and is a directory--or ~/perl when looking for modules to load. It basically takes every path that the Perl would normally use and bases them in that chosen directory.

Likely, this allows the user to have a debugging or bugfix version of a system module and for Perl to prefer that instead.

It does this in a BEGIN block because it's the only way to make sure that a block of logic can be run to modify @INC to affect the behavior of use statements.

Axeman
It doesn't prepend a directory, but actually prepends that directory to the names of all members of @INC and adds that larger list to the front of @INC, hence the map.
HerbN
+10  A: 

It is designed to set your module search path. Specifically, it sets the default location (first location checked) the user's local perl/ directory. It not only adds that directory but makes it a new root for @INC. It does this for every entry in @INC. In a limited access environment such as those that use CPanel this insures you scripts (general cgi) user your modules over any other.

BEGIN means it occurs before any code not in the block.

The first line determines if /home/root/perl exists and is a directory. If both are true it assigns that to $base_module_dir, otherwise it assigns <user home>/perl/ to the variable. Remember, in perl you can index a function call directly if it returns a list.

It finds the user's home directory with getpwuid($>). getpwuid() gets user account information for a given user (generally from passwd on a Unix system) and returns it as a list. $> is the effective user id of the script. The reason for the index of 7 is that is the location of the home directory in the list (and it is the 8th field in passwd if memory serves).

It then prepends ALL entries in @INC with $base_module_dir and inserts those modified entries at the front of @INC. So it's not just adding $base_module_dir as a directory but is adding that as a new root for all entries in @INC. That's why it uses map instead of just adding a single entry.

HerbN
Ah, right. I've deleted my response since I missed the effects of the map. Thanks for pointing that out. +1 to HerbN
T.Rob
what about this piece? "( getpwuid($>) )[7]" I don't understand the $> and the array ref (?) to [7]
CheeseConQueso
@CheeseConQueso: Added details on the getpwuid call to the answer.
HerbN
+8  A: 

Maybe a bit easier to read:

# The BEGIN block is explained in perldoc perlmod

BEGIN {
    # Prefix all dirs already in the include path, with root's perl path if it exists, or the
    # current user's perl path if not and make perl look for modules in those paths first:
    # Example: 
    #     "/usr/lib/perl" => "/home/root/perl/usr/lib/perl, /usr/lib/perl"

    my $root_user_perl_dir = '/home/root/perl';

    # Fetch user home dir in a non-intuitive way:
    # my $user_perl_dir = ( getpwuid($>) )[7] . '/perl/');

    # Fetch user home dir slightly more intuitive:
    my $current_userid        = $>; # EFFECTIVE_USER_ID see perldoc perlvar
    # See perldoc perlfunc / perldoc -f getpwuid
    my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) 
        = getpwuid($current_userid); 
    my $current_user_home_dir = $dir; 
    my $user_perl_dir         = $current_user_home_dir . '/perl/';

    my $base_module_dir = '';

    if (-d $root_user_perl_dir ) { 
        # Use this if the path exists
        $base_module_dir = $root_user_perl_dir;
    }
    else { 
        # or fallback to current user's path
        $base_module_dir = $user_perl_dir;
    }

    # Generate the new paths
    my @prefixed_INC = map { $base_module_dir . $_ } @INC;

    # Add the generated paths in front of the existing ones.
    @INC = (@prefixed_INC, @INC); 
}
nicomen
what about this piece? "( getpwuid($>) )[7]" I don't understand the $> and the array ref (?) to [7]
CheeseConQueso
http://p3rl.org/getpwuid - but I'll edit my answer slightly
nicomen
+1 for showing me again why I love the Perl.
Dummy00001
Dummy00001: What part? That it can be written for humans too? :-)
nicomen