--- nfo/perl/scripts/sshwrap/Shell/SSH.pm 2003/01/20 19:01:06 1.1 +++ nfo/perl/scripts/sshwrap/Shell/SSH.pm 2003/01/20 19:05:07 1.2 @@ -1,7 +1,7 @@ package Shell::SSH; use strict; use warnings; -use base qw( Shell ); +#use base qw( Shell ); our($VERSION, $AUTOLOAD); $VERSION = '0.01'; @@ -11,19 +11,26 @@ # we try to imitate "use base qw( Shell 0.4 );" which of course will never work since it "arrays" all values inside qw() # but it also calls 'require' under the hood - rendering a "use base ('Shell 0.4');" useless, too, hmmm..... # question: can this already be done in a more formal way? -BEGIN { my $requires = 0.4; die "Shell version $requires required--this is only version $Shell::VERSION" if ($Shell::VERSION lt $requires); } +#BEGIN { my $requires = 0.4; die "Shell version $requires required--this is only version $Shell::VERSION" if ($Shell::VERSION lt $requires); } +BEGIN { + sub RUNNING_IN_HELL () { $^O eq 'MSWin32' } +} use Data::Dumper; -use IPC::Run qw( start pump finish timeout ); +use IPC::Run qw( start pump finish timeout timer ); +#use IPC::Run::Win32Helper; # debugging for IPC::Run -# $ENV{IPCRUNDEBUG} = 2; +#$ENV{IPCRUNDEBUG} = 10; +#$ENV{IPCRUNDEBUG} = 2; +$ENV{IPCRUNDEBUG} = 32; local *IN; local *OUT; local *ERR; -$Shell::hasHandler = 1; +my $in; my $out; my $err; my $handle; +my $t; sub new { my $class = shift; @@ -37,19 +44,23 @@ sub DESTROY { } sub AUTOLOAD { - my $self = shift if ref $_[0] && $_[0]->isa( 'Shell' ); + #my $self = shift if ref $_[0] && $_[0]->isa( 'Shell' ); + #my $self = shift if ref $_[0] && $_[0]->isa( 'Shell' ); + my $self = shift; my $cmd = $AUTOLOAD; $cmd =~ s/^.*:://; - #print Dumper(@_); - #exit; - if ($self) { + #if ($self) { # TODO: handle asynchronizity(?) here! return $self->_run_command($cmd, @_); - } + #} } sub _init { my $self = shift; + $self->{in} = ''; + $self->{out} = ''; + $self->{err} = ''; + $in = $out = $err = ''; $self->{method} ||= 'ssh'; } @@ -68,50 +79,163 @@ my $cmd = join(" ", @cmd); #print "command: ", $cmd, "\n"; - $self->{handle} = start - \@cmd, - 'pipe', \*OUT, - '2>pipe', \*ERR, - timeout( 5 ) - or die "could not open IPC::Run - handle: $?" ; +# $self->{handle} = start +# \@cmd, +# 'pipe', \*OUT, +# '2>pipe', \*ERR, +# timeout( 20 ) +# or die "could not open IPC::Run - handle: $?" ; + #$self->{handle} = start \@cat, \$in, \$out + #$self->{handle} = + + #print "command: ", join(' ', @cmd), "\n"; + + if (!RUNNING_IN_HELL) { + #$t = timeout(15); + $t = timer(10); + $handle = + start(\@cmd, \$in, \$out, \$err, $t) + or print "NO HANDLE: $?\n"; + #or die "could not open IPC::Run - handle: $?" ; + } else { + $handle = start + \@cmd, + 'pipe', \*OUT, + '2>pipe', \*ERR, + timeout( 20 ) + or print "NO HANDLE: $?\n"; + #or die "could not open IPC::Run - handle: $?" ; + + # make filehandles hot + IN->autoflush(1); + OUT->autoflush(1); + ERR->autoflush(1); + } + + print "STARTUP FINISHED\n"; + #sleep 10; } sub _stop { my $self = shift; - finish $self->{handle}; + #finish $self->{handle}; + #finish $self->{handle}; + finish $handle; } sub _run_command { my $self = shift; my $rcommand = shift; +#print "rcmd: $rcommand\n"; my $rargs = join(' ', @_); $rargs ||= ''; my $rcommandstring = join(' ', $rcommand, $rargs); + $rcommandstring =~ s/\s//g; + #print "cmd: '", $rcommandstring, "'\n"; #open IN, ''; - print IN $rcommandstring; - close IN; - $self->_read_output(); + #$self->_read_output(); + #print IN $rcommandstring; + #close IN; + #pump $self->{handle}; + #$self->{in} = $rcommandstring; + + print "COMMAND SENT: $rcommandstring\n"; + + if (!RUNNING_IN_HELL) { + $in = $rcommandstring . "\n"; + } else { + print IN $rcommandstring, "\n"; + #close IN; + } + #$in = $rcommandstring; + #pump $self->{handle}; + #$out = ''; + #pump $handle while length $in; + pump $handle; + #pump $handle; + + #print "first pumping ready", "\n"; + + #$self->_read_output(); + return ''; } sub _read_output { + #print "_read_output\n"; my $self = shift; $self->{buffer} = []; my $buffer = ''; #print "=read\n"; + #print Dumper($self->{handle}); - while () { - #print "line: ", $_, "\n"; - chomp(); - push @{$self->{buffer}}, $_; - $buffer .= $_ . "\n"; + #while () { + #pump $self->{handle}; + #sleep 1; pump $self->{handle}; + #sleep 1; pump $self->{handle}; + #pump $self->{handle}; + #pump $handle; + + #pump $handle while length $out; + #pump $handle; + #pump $handle; + #pump $handle; + #pump $handle until length $out; + #$self->{response}->($out) if $out; + #return; + +#print Dumper($self->{handle}); + + # the command-response-roundtrip should + # take a smaller amount of time than the initial connection + my $tcmd = timer(5); + + until ($tcmd->is_expired) { + + if (!RUNNING_IN_HELL) { + + pump $handle; + #while (!$t->is_expired) { + while ($out && !$tcmd->is_expired) { + print ".\n"; + chomp($out); + print "line: ", $out, "\n"; + $self->{response}($out) if $out; + #push @{$self->{buffer}}, $_; + $buffer .= $out . "\n"; + #pump $self->{handle}; + pump $handle; + } + + } else { + + print "=========WIN32\n"; + + #pump $handle; + #until (my $line = || $tcmd->is_expired) { + my $line = ; + chomp($line); + print "line: ", $line, "\n"; + $buffer .= $out . "\n"; + #pump $self->{handle}; + pump $handle; + + } + } - #print "=read okay\n"; + + print "=read okay\n"; + + if ($tcmd->is_expired) { + print "command expired", "\n"; + } + # TODO: async! #return $buffer; - $self->{response}->($buffer); + $self->{response}->($buffer) if $buffer; } sub get_output {