[Date Prev] [Date Index] [Date Next] [Thread Prev] [Thread Index] [Thread Next]
Christopher Fowler cfowler@outpostsentinel.com
Fri, 25 Apr 2003 13:01:36 -0700 (PDT)
Don't say I don't give anything back :) Someone mod this to support all command line options. And clean it up a bit.
#!/usr/bin/perl sub cpanMirrorSpeak { my $mod = $_[0]; die <<EOT; You don't have $mod installed. Please install a copy from your favourite CPAN mirror. perl -MCPAN -e 'install( "$mod" )' EOT } eval { require POSIX; }; if( $@ ) { cpanMirrorSpeak("POSIX"); } eval { require IO::Socket; }; if( $@ ) { cpanMirrorSpeak("IO::Socket"); } eval { require Getopt::Std; }; if( $@ ) { cpanMirrorSpeak("Getopt::Std"); } eval { require IO::Select; }; if( $@ ) { cpanMirrorSpeak("IO::Select"); } use Getopt::Std; use POSIX; use IO::Socket; use IO::Select; use strict; # Static variables my $USER; my $SERVER; my $CONSOLE; # Commands my $CMD_LOGIN = "c;"; sub console_syntax { die "$0 [-h] -s <server> -u <user> <console>\n"; } sub console_pArgs { console_syntax() unless (getopts("s:u:h")); console_syntax() if not $Getopt::Std::opt_s; console_syntax() if not $Getopt::Std::opt_u; console_syntax() if $Getopt::Std::opt_h; console_syntax() if not @ARGV; $USER = $Getopt::Std::opt_u; $SERVER = $Getopt::Std::opt_s; $CONSOLE = $ARGV[0]; return; } # # Implement enough of the portcommander protocol # to attach to the required console (or die trying), # return the live socket. # sub connect_console { my $SERVER = $_[0]; my $CONSOLE = $_[1]; my $USER = $_[2]; my $PASS = $_[3]; # # Create the socket to the main server # We'll recoeve a port number then connect to secondary # server for console data # my $sock = new IO::Socket::INET (PeerAddr => $SERVER, PeerPort => 782, Proto => 'tcp',) or return -1; # We do not want buffered output to socket $sock->autoflush(); ($_ = <$sock>) ; return -1 unless /ok/ ; # Specify console name print $sock "call:$CONSOLE\n"; # Only valid reply is a port number, # stick that in $1. ($_ = <$sock>); return -1 unless /^(\d+)/ ; close($sock); $sock = new IO::Socket::INET (PeerAddr => $SERVER, PeerPort => $1, Proto => 'tcp',) or return -1; $sock->autoflush(); setsockopt($sock, SOL_SOCKET, SO_KEEPALIVE, 1); ($_ = <$sock>) ; return unless /ok/ ; # tell server we wish to log in print $sock $CMD_LOGIN; # TODO: test reply. ($_ = <$sock>) ; # specify user name print $sock "$USER\n"; ($_ = <$sock>) ; if (/^host:/) { print $sock "$CONSOLE\n"; #TODO #validate we are connected #to the console ($_ = <$sock>) ; } if (/^passwd:/) { print "Enter $USER\@$SERVER\'s password: "; $PASS = getPassword(); print $sock "$PASS\n"; ($_ = <$sock>) ; return -1 if (/Sorry/) ; } return $sock ; } sub getPassword { \*STDOUT->flush(); \*STDIN->autoflush(); my $t1 = POSIX::Termios->new; my $t2 = POSIX::Termios->new; $t1->getattr(); $t2->getattr(); my $c_lflag = $t1->getlflag(); $t1->setlflag($c_lflag &= ~&POSIX::ECHO); $t1->setattr( 0, &POSIX::TCSANOW ); my $pass; $pass = <STDIN>; chomp($pass); $t2->setattr( 0, &POSIX::TCSANOW ); print "\n"; return $pass; } # Main # my $cCon; console_pArgs(); if(( $cCon = connect_console($SERVER, $CONSOLE, $USER, "password")) == -1) { die "Could not connect to console!\n"; } print "[Enter `^Ec?' for help]\n"; \*STDOUT->flush(); sub cfmakeraw { my $tty = $_[0]; $tty->getattr(); my $c_iflag = $tty->getiflag(); my $c_oflag = $tty->getoflag(); my $c_lflag = $tty->getlflag(); my $c_cflag = $tty->getcflag(); $tty->setiflag($c_iflag &= ~&POSIX::IGNBRK); $tty->setiflag($c_iflag &= ~&POSIX::BRKINT); $tty->setiflag($c_iflag &= ~&POSIX::PARMRK); $tty->setiflag($c_iflag &= ~&POSIX::ISTRIP); $tty->setiflag($c_iflag &= ~&POSIX::INLCR); $tty->setiflag($c_iflag &= ~&POSIX::IGNCR); $tty->setiflag($c_iflag &= ~&POSIX::ICRNL); $tty->setiflag($c_iflag &= ~&POSIX::IXON); $tty->setoflag($c_oflag &= ~&POSIX::OPOST); $tty->setlflag($c_lflag &= ~&POSIX::ECHO); $tty->setlflag($c_lflag &= ~&POSIX::ECHONL); $tty->setlflag($c_lflag &= ~&POSIX::ICANON); $tty->setlflag($c_lflag &= ~&POSIX::ISIG); $tty->setlflag($c_lflag &= ~&POSIX::IEXTEN); $tty->setcflag($c_cflag &= ~&POSIX::CSIZE); $tty->setcflag($c_cflag &= ~&POSIX::PARENB); $tty->setcflag($c_cflag | &POSIX::CS8); } my $termios = POSIX::Termios->new; my $old = POSIX::Termios->new; $termios->getattr(); $old->getattr(); cfmakeraw($termios); $termios->setattr( 0, &POSIX::TCSANOW ); #cfmakeraw sets the terminal attributes as follows: #termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP #|INLCR|IGNCR|ICRNL|IXON); #termios_p->c_oflag &= ~OPOST; #termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); #termios_p->c_cflag &= ~(CSIZE|PARENB); #termios_p->c_cflag |= CS8; my $fdset = new IO::Select; my $wfdset = new IO::Select; my $r_ready; my $w_ready; my $error; my $timeout = 30; my $err; $fdset->add($cCon); $fdset->add(\*STDIN); while (1) { SELECT: ($r_ready, $w_ready, $error) = IO::Select->select($fdset, $wfdset, $err, $timeout); # If nothing has occured, we have timedout if($r_ready eq "") { goto SELECT; } foreach my $ready (@$r_ready) { my $data; if($ready == \*STDIN) { sysread($ready, $data, 1); print $cCon $data; } if($ready == $cCon) { if(sysread($ready, $data, 1) == 0) { $old->setattr( 1, &POSIX::TCSANOW ); exit(0); } print $data; \*STDOUT->flush(); } } }