CPANPLUS::Daemon - Remote CPANPLUS access


CPANPLUS-Daemon documentation Contained in the CPANPLUS-Daemon distribution.

Index


Code Index:

NAME

Top

CPANPLUS::Daemon -- Remote CPANPLUS access

SYNOPSIS

Top

    ### from the command line
    cpanpd -p secret                        # using defaults
    cpanpd -P 666 -u my_user -p secret      # options provided, recommended

    ### using the API
    use CPANPLUS::Daemon;
    $daemon = CPANPLUS::Daemon->new(
                            username    => 'my_user',
                            password    => 'secret',
                            port        => 666,
                        );
    $daemon->run;

    ### (dis)connecting to the daemon, from the default shell
    CPAN Terminal> /connect --user=my_user --pass=secret localhost 666
    ...
    CPAN Terminal> /disconnect

DESCRIPTION

Top

CPANPLUS::Daemon let's you run a daemon that listens on a specified port and can act as a remote backend to your CPANPLUS::Shell::Default.

You can use the CPANPLUS::Shell::Default shell to connect to the daemon. Note that both sides (ie, both the server and the client) ideally should run the same version of the CPANPLUS::Shell::Default, to ensure maximum compatibillity

See the CPANPLUS::Shell::Default documentation on how to connect to a remote daemon.

METHODS

Top

$daemon = CPANPLUS::Daemon->new(password => $pass, [username => $user, port => $port]);

Creates a new CPANPLUS::Daemon object, based on the following paremeters:

password (required)

The password needed to connect to this server instance

username (optional)

The user needed to connect to this server instance. Defaults to cpanpd.

port

The port number this server instance will listen on. Defaults to 1337.

$daemon->run( [stdout => \*OUT, stderr => \*ERR] );

This actually makes the daemon active. Note that from here on, you lose control of the program, and it is handed to the daemon. You can now only exit the program via a SIGINT or another way that terminates the process.

You can override where the daemon sends its output by supplying the an alternate filehandle via the stdout and stderr parameter

AUTHOR

Top

This module by Jos Boumans <kane@cpan.org>.

COPYRIGHT

Top


CPANPLUS-Daemon documentation Contained in the CPANPLUS-Daemon distribution.
package CPANPLUS::Daemon;

use strict;
use vars qw[$VERSION];

use IO::String;
use Params::Check               qw[check];
use POE                         qw[Component::Server::TCP];
use CPANPLUS::Shell             qw[Default];
use Locale::Maketext::Simple    Class => 'CPANPLUS', Style => 'gettext';

use base 'Object::Accessor';

local $Params::Check::VERBOSE = 1;

$VERSION = '0.02';

sub new {
    my $class = shift;
    my %hash  = @_;
    my $self  = bless {}, $class;

    my $tmpl = {
        password    => { required   => 1 },
        username    => { default    => 'cpanpd' },
        port        => { default    => 1337 },
    };        

    $self->mk_accessors( qw[conf shell], keys %$tmpl );

    $self->shell( CPANPLUS::Shell->new() );
    $self->conf(  $self->shell->backend->configure_object );


    my $args = check( $tmpl, \%hash ) or return;

    ### make sure to disable the pager ###
    $self->conf->set_program( pager => '' );

    ### store all provided opts as accessors
    $self->$_( $args->{$_} ) for keys %$tmpl;

    return $self;
}

sub run {
    my $self = shift;
    my %hash = @_;

    $|++;
    ### redirect STDOUT and STDERR ###
    local *STDOUT_SAVE;
    local *STDERR_SAVE;

    open( STDOUT_SAVE, ">&STDOUT" ) or warn loc("Couldn't dup STDOUT: %1");
    open( STDERR_SAVE, ">&STDERR" ) or warn loc("Couldn't dup STDERR: %1");

    my($stdout_fh, $stderr_fh);
    my $tmpl = {
        stdout  => { default => \*STDOUT_SAVE, store => \$stdout_fh },
        stderr  => { default => \*STDERR_SAVE, store => \$stderr_fh },
    };
    
    check( $tmpl, \%hash ) or return;

    #close *STDOUT; close *STDERR;
    *STDERR = *STDOUT;

    POE::Component::Server::TCP->new(
        Alias       => "cpanpd",
        Port        => $self->port,
        ClientInput => sub {
            my ($session, $heap, $input) = @_[SESSION, HEAP, ARG0];

            my $remote_host          =  $heap->{remote_ip} .':'.
                                        $heap->{remote_port};
            my($user,$pass,$command) =  split "\0", $input;

            my $status;     # the status value to return 0 || 1
            my $msg;        # the message we'll send back
            my $locmsg;     # the message we'll print locally

            unless( $user eq $self->username and $pass eq $self->password ) {

                $status = 0;
                $msg    = loc(  "Remote command failed: Invalid password ".
                                "for user '%1'\n", $user). "\n";
                $locmsg = "[$remote_host] ". $msg;

            } else {

                ### print it now anyway, so we can see what the daemon
                ### is currently doing
                print $stdout_fh loc("[%1] Running '%2'\n",
                                        $remote_host, $command );

                $status = 1;

                ### VERSION verification for compatibility ###
                if( $command =~ /^VERSION=(.+)$/ ) {
                    my $local_ver   = $CPANPLUS::Shell::Default::VERSION;
                    my $remote_ver  = $1 || 0;

                    if( $local_ver != $remote_ver) {
                        $msg = loc("Differing shell versions detected:\n".
                                    "Local:     %1\n".
                                    "Remote:    %2\n".
                                    "Continuing is not advised, do so at your ".
                                    "own risk", $local_ver, $remote_ver);

                        $locmsg =  loc( '[%1] Differing version detected'.
                                        '. remote: %1 local %2',
                                        $remote_host, $remote_ver,
                                        $local_ver ). "\n";
                    } else {
                        $msg =      loc("Connection accepted" );
                        $locmsg =   loc('[%1] Connection accepted',
                                        $remote_host ). "\n";
                    }

                ### normal command ###
                } else {
                    tie *STDOUT, 'IO::String';
                    $self->shell->dispatch_on_input( input => $command );

                    seek( STDOUT, 0, 0 );

                    $msg .= join "", <STDOUT>;
                }
            }

            ### print the local message, send back and answer + status
            print $stdout_fh $locmsg;
            $heap->{client}->put( $status ."\0". $msg);
        }
    );

    print $stdout_fh loc("Starting '%1' on port %2...", 'cpanpd', $self->port ).$/;

    $poe_kernel->run;

    print $stdout_fh loc("Exiting '%1'...", 'cpanpd').$/;
    exit 0;
}

1;

# Local variables:
# c-indentation-style: bsd
# c-basic-offset: 4
# indent-tabs-mode: nil
# End:
# vim: expandtab shiftwidth=4: