[pm-h] Overriding package subroutines (the hard way)
Todd Rinaldo
toddr at null.net
Fri Jul 6 06:19:43 PDT 2007
I went a little crazy yesterday (I was already partially there) trying to
figure this out. I thought I'd throw this out on the list and see if there
are other ways to do it.
We want to log a user's session to a priveliged account from start to stop.
We also need to do some pre-qual and some post processing once they're done.
We want to use Net::SSH::Perl to do this. Here's my problem: Net::SSH::Perl
has an interactive mode that would meet this need, except it does not
provide any obvious hooks to do additional logging.
The bad way: Go re-write the appropriate pm file (Net::SSH::Pel::SSH2). I
refuse to use this option.
The evil way: Use Sub::Override to re-write the subroutine I want to hack.
The problem is it looks like this below. Search for ### in the override
code.
The problem with this code is it's not very adaptable to change if the CPAN
module changes. It'd be better if I could insert a hook and then have it
resume the original subroutine. I don't think I can with the Sub::Override
module. I've also got a problem with my use of main::LOG, but see no more
elegant way pull this off.
Is there a better way?
---------------------------------------------------------------------
#!perl
use strict;
use warnings;
use Net::SSH::Perl
package Net::SSH::Perl::SSH2;
use Sub::Override;
my $override = Sub::Override->new()
$override->replace (shell => sub {
my $ssh = shift;
my $cmgr = $ssh->channel_mgr;
my $channel = $ssh->_session_channel;
$channel->open;
$channel->register_handler(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, sub {
my($channel, $packet) = @_;
my $r_packet = $channel->request_start('pty-req', 0);
my($term) = $ENV{TERM} =~ /(\w+)/;
$r_packet->put_str($term);
$r_packet->put_int32(0) for 1..4;
$r_packet->put_str("");
$r_packet->send;
$channel->{ssh}->debug("Requesting shell.");
$channel->request("shell", 0);
});
my($exit);
$channel->register_handler(SSH2_MSG_CHANNEL_REQUEST,
_make_input_channel_req(\$exit));
$channel->register_handler("_output_buffer", sub {
syswrite STDOUT, $_[1]->bytes;
############# Inserting custom TODD code.
my $output = $_[1]->bytes;
print main::LOG $output;
});
$channel->register_handler("_extended_buffer", sub {
syswrite STDERR, $_[1]->bytes;
});
$ssh->debug("Entering interactive session.");
$ssh->client_loop;
});
1;
# Must use package main to be able to write code after a package definition?
package main;
open (LOG, ">", "ssh.$$.log") or die;
use Net::SSH::Perl;
my $host = "host";
my $user = "username";
my $password = "passhere";
my $ssh = Net::SSH::Perl->new($host);
$ssh->login($user, $pass);
use Term::ReadKey;
ReadMode('raw');
$ssh->shell;
ReadMode('restore');
exit;
More information about the Houston
mailing list