Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Installing modules without root and shell

by tinita (Parson)
on Dec 30, 2004 at 21:02 UTC ( [id://418403]=CUFP: print w/replies, xml ) Need Help??

for updates see http://cgipan.sf.net/

hi monks, this question is asked quite often, at least in the forums i read often. people have a webserver, but only ftp access, and of course no root.

while it is relatively easy to provide the answer if it's a pure perl module (create directory and put .pm file into it) it gets more complicated if the module is not pure perl.

still, i think, many people might have make and a compiler available through system() in a CGI-script.
however, to do all the Makefile.PL stuff with a CGI-script is messy. so i wrote a little script (namely cgipan) which does that. it's probably far from being able to install all kinds of modules, but i could install Config::IniFiles and CPAN.pm with it (yes, there's no CPAN.pm on my webhoster's machine...)

also my script does no sanity checks at all (yet), but it shouldn't be be publicly accessible at all anyway.
note that the script should only be accessible for you (use .htaccess or just use it temporarily), and note that the created library is writeable for the webserver. this might or might not be a security risk in your shared environment. when in doubt, copy the created lib to another directory with your user/ftpuser permissions.

i would be glad if someone could look over it and try it out, or just comment if this is a good idea. update: It's also availabe at my module archive

it's ready for running, and you probably only have to change the $root-variable and/or $build_dir and $lib. these directories have to be writeable by the webserver. put your Module-3.13.tgz in $build_dir and start. to use the installed module, you have to do use lib $lib, where $lib is that directory you set in the cgipan script.

so if you think it's a good idea i would continue to work on it.

and, in advance, i wish you all a happy new year!

update: yes, probably 'Cool uses' is a better place for it

update: okay, i'll move the script from my scratchpad here in readmore tags (or is it too much code?):

update 2.1.2005: extended security tipps

please look here for updates. I added taint mode now in version 0.05
#!/usr/bin/perl -w # --------------------------- # Cgipan # CGI-Script for installing modules on a server where you don't # have root access and no shell access. You have to have # tools like make and tar, though. # Tina Mueller, Dec 29th 2004 # --------------------------- use strict; use vars qw($VERSION); $VERSION = 0.04; # --------------------------- # Change variables to your needs (you probably just need # to change $root) # own root dir on server (not / though) # or leave blank, then $ENV{DOCUMENT_ROOT} will be used, # which might not be a good thing my $root = '/homepages/bla/blubb/cgipan' || $ENV{DOCUMENT_ROOT} || ''; # create before starting; must have write permissions # for webserver my $build_dir = "$root/build"; my $lib = "$root/mylib"; # path to make my $make = '/usr/bin/make'; # path to tar my $tar = '/bin/tar'; # or /usr/bin/gtar ... # url to cgi-script. $ENV{SCRIPT_NAME} should be sufficient my $self = '' || $ENV{SCRIPT_NAME}; # or you can define all these variables in your own cgipan.conf # ($self, $make, $tar, $build_dir, $lib) if (-f "cgipan.conf") { open D, "cgipan.conf" or die $!; local $/; my $conf = <D>; close D; eval $conf; } # --------------------------- #use Data::Dumper; use CGI; use CGI::Carp qw(fatalsToBrowser); my $cgi = CGI->new; my $w = $cgi->param('w') || $cgi->path_info || 'start'; $w =~ s#^/##; print head($w); #print "$_ = $ENV{$_}<br>" for sort keys %ENV; my %map = ( start => \&start, ut => \&unpack_tar, sd => \&show_dist, pmf => \&makefile, make => \&mmake, maket => \&make_test, makei => \&make_install, tm => \&test_module, ); my $sub = $map{$w}; $sub->(); print foot($w); sub test_module { my $module = $cgi->param('mod'); unless ($module) { print <<EOM; <br>Test if Module is installed: <form action="$self/tm"> <input type="text" name="mod"> <input type="submit" value="go"> </form> EOM return; } my $version; my $path; my $inc_mod = $module; $inc_mod =~ s#::#/#g; $inc_mod .= ".pm"; eval qq#use lib qw($lib); use $module; \$version = \$${module} +::VERSION; \$path = \$INC{"$inc_mod"};#; print <<EOM; Errors: (<tt>$@</tt>)<br> \$${module}::VERSION = $version<br> \$INC{$inc_mod} = $path<br> EOM } sub makefile { my $dist = $cgi->param('dist'); chdir $build_dir; chdir $dist; my $cmd = qq#perl -I$lib Makefile.PL PREFIX=$lib LIB=$lib 2>&1 +#; my $out = command($cmd); print $out; print qq#if everything looks okay, you may now build the modul +e: <a href="$self/make?dist=$dist">make</a>#; } sub mmake { my $dist = $cgi->param('dist'); chdir $build_dir; chdir $dist; my $cmd = qq#$make 2>&1#; my $out = command($cmd); print $out; print qq#if everything looks okay, you may now make the tests: <a href="$self/maket?dist=$dist">test</a>#; } sub make_test { my $dist = $cgi->param('dist'); chdir $build_dir; chdir $dist; my $cmd = qq#$make test 2>&1#; my $out = command($cmd); print $out; print qq#if everything looks okay, you may now install: <a href="$self/makei?dist=$dist">install</a>#; } sub make_install { my $dist = $cgi->param('dist'); chdir $build_dir; chdir $dist; my $cmd = qq#$make install 2>&1#; my $out = command($cmd); print $out; print qq#Ok, if everything looks fine, you are done! You can verify if the module is <a href="$self/tm">installed</a>.#; } sub command { my $cmd = shift; my $output = qx#$cmd#; return qq#<pre>$cmd:\n$output</pre>#; } sub unpack_tar { my $tarf = $cgi->param('tar'); chdir $build_dir; print q#Trying to unpack $tarf...<br>#; my $cmd = qq#$tar -xvzf $tarf 2>&1#; my $output = command($cmd); print <<EOM; $output if everything looks okay, you should see the unpacked directory: <a href="$self">start</a> EOM } sub show_dist { my $dist = $cgi->param('dist'); chdir $build_dir; opendir my $dir, $dist or die "Could not open '$dist': $!"; my @files = grep { !m/^\.\.?$/ } readdir $dir; closedir $dir; print <<EOM; 1. <a href="$self/pmf?dist=$dist"><tt>perl -I$lib Makefile.PL PREFIX=$ +lib LIB=$lib</tt></a><br> 2. <a href="$self/make?dist=$dist"><tt>make</tt></a><br> 3. <a href="$self/maket?dist=$dist"><tt>make test</tt></a><br> 4.<a href="$self/makei?dist=$dist"><tt>make install</tt></a><br> <p> EOM print qq#<pre>#; print qq#$_\n# for @files; print qq#</pre>#; } sub start { my %list = list_build(); print qq#Directories:<br><ul>#; foreach my $file (@{$list{dir}}) { print qq#<li><a href="$self/sd?dist=$file">$file</a></ +li>#; } print qq#</ul>Files:<br><ul>#; foreach my $file (@{$list{file}}) { print qq#<li>$file <a href="$self/ut?tar=$file">unpack</a></li>#; } print qq#</ul>#; } sub list_build { chdir $build_dir; opendir my $dir, "." or die "Could not open '$build_dir': $!"; my @files = grep { !m/^\.\.?$/ } readdir $dir; closedir $dir; my %hash; for my $f (sort @files) { next if -l $f; if (-d $f) { push @{$hash{dir}}, $f; } elsif (-f $f) { push @{$hash{file}}, $f; } } return %hash; } sub foot { $cgi->end_html; } sub head { # do some checking my $bd_ok = 'ok'; my $l_ok = 'ok'; my $errors = ""; my $user = getpwuid($<); if (!-d $build_dir) { $errors .= qq#Your build_dir '$build_dir' does not exi +st. Please create it, with the correct permissions.<br>#; $bd_ok = 'not there'; } elsif (!-w $build_dir) { $errors .= qq#Your build_dir '$build_dir exists, but i +s not writeable for me (I am $user, uid $<).#; $bd_ok = 'not writeable'; } if (!-d $lib) { $errors .= qq#Your lib '$lib' does not exist. Please c +reate it, with the correct permissions.<br>#; $l_ok = 'not there'; } elsif (!-w $lib) { $errors .= qq#Your lib '$lib exists, but is not writea +ble for me (I am $user, uid $<).#; $l_ok = 'not writeable'; } my $err = $errors ? qq#<font color="red"><b>Errors:</b><br>$er +rors</font># : ""; my $st = $cgi->header; $st .= $cgi->start_html(-title => 'CGIPAN'); $st .= <<EOM; <h3 align="center">Welcome to Cgipan</h3> <b>Config:</b><br> <table border="1"> <tr><td>perl version:</td><td>$]</td></tr> <tr><td>\$root:</td><td>$root</td></tr> <tr><td>\$build_dir:</td><td>$build_dir ($bd_ok)</td></tr> <tr><td>\$lib:</td><td>$lib ($l_ok)</td></tr> <tr><td>document root:</td><td>$ENV{DOCUMENT_ROOT}</td></tr> </table> $err<br> <a href="$self">Start</a> | <a href="$self/tm">Test Module</a> <p> EOM } =pod =head1 NAME cgipan =head1 README CGI-Script for installing modules on a server where you don't have root access and no shell access. You have to have tools like make and tar, though. =head1 DESCRIPTION To use cgipan, put it in your cgi-bin directory on your server and make it executable. Then it will run. It will most likely show you the message that /homepages/bla/blubb/cgipan/build|lib don't exist. These are the directories you need for cgipan. Create them where you need them and change the variables $build_dir and $lib. They have to be writeable by the webserver, so if they aren't, cgipan will show te appropriate error messge. Note: Don't make this script accessible for others!! (yes, two exclamation marks) While this script shouldn't be public anyway, at the moment it does no sanity checks at all. Ok, I warned you. Now have fun =) =head1 OSNAMES C<Linux> =head1 PREREQUISITES CGI CGI::Carp tar or gnutar make =head1 LICENSE L<cgipan> may be distributed under the same terms as Perl itself. =head1 SCRIPT CATEGORIES CPAN CGI =head1 BUGS No sanity checks; not enough HTML-entities-replacing etc. =head1 AUTHOR Tina Mueller, Dec 30th 2004 (http://search.cpan.org/~tinita/) =cut

Replies are listed 'Best First'.
Re: Installing modules without root and shell
by BUU (Prior) on Dec 30, 2004 at 22:40 UTC
    Just a note, please don't include references from SOPW and similar type nodes to stuff on your scratch pad, as the node will always be here but your scratch pad may change.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://418403]
Approved by Arunbear
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (4)
As of 2024-03-29 12:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found