Question

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;
}
Was it helpful?

Solution

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); 
}

OTHER TIPS

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top