#!/usr/bin/perl # # console / -- interactive client interface # # The main interactive client interace to conmux. Allows direct # interaction with the payload, as well as allowing break out # to the conmux menu to envoke defined commands; for example # hardreset. # # (C) Copyright IBM Corp. 2004, 2005, 2006 # Author: Andy Whitcroft # # The Console Multiplexor is released under the GNU Public License V2 # $| = 1; our $P = 'console'; use FindBin; use POSIX qw(errno_h BUFSIZ); use IO::Socket; use Getopt::Long qw(:config no_auto_abbrev); my $CONMUX = $FindBin::Bin; my $CONMUX = $ENV{'CONMUX_ROOT'} if ($ENV{'CONMUX_ROOT'}); # Find our internal libraries. use lib $FindBin::Bin; use lib "$FindBin::Bin/../lib/"; use lib "$FindBin::Bin/lib/"; use Conmux; # Basic terminal handling. sub termRaw { $termSettings = `stty -g`; system "stty raw -echo opost onlret"; } sub termRestore { system "stty $termSettings"; } my $bot; my $list; my $status; GetOptions( 'b|bot=s' => \$bot, 'l|list' => \$list, 's|status' => \$status, ); sub usage { warn "Usage: $P \n"; warn " $P /\n"; warn " $P :\n"; warn " $P --status \n"; die " $P --list []\n"; } my $id; if ($bot) { $id = 'bot:' . $bot; } else { $id = 'user:' . $ENV{'LOGNAME'}; } # # MODE: registry list. # if ($list) { if ($#ARGV == -1) { print Conmux::Registry::list('-'); } elsif ($#ARGV == 0) { print Conmux::Registry::list($ARGV[0]); } else { usage(); } exit 0 } # # COMMAND: payload status command # if ($status) { usage() if ($#ARGV != 0); my $sock; eval { $sock = Conmux::connect($ARGV[0]); }; if ($@) { print "unavailable\n"; exit 0 } my %r = Conmux::sendCmd($sock, 'CONNECT', { 'id' => $id, 'to' => 'console', 'hide' => 1 }); if ($r{'status'} ne 'OK') { print "unavailable\n"; } elsif ($r{'state'}) { print "$r{'state'}\n"; } else { print "unknown\n"; } exit 0; } # # COMMAND: general payload connect. # if ($#ARGV != 0) { usage(); } # Connect to the host/port specified on the command line, # or localhost:23 my $sock = Conmux::connect($ARGV[0]); my %r = Conmux::sendCmd($sock, 'CONNECT', { 'id' => $id, 'to' => 'console' }); die "$P: $ARGV[0]: connect failed - $r{'status'}\n" if ($r{'status'} ne 'OK'); print "Connected to $r{'title'} (~\$quit to exit)\n"; #display message of the day passed by the server e.g. who is already connected print "$r{'motd'}"; my $rin = $win = $ein = ''; vec($rin, fileno(STDIN), 1) = 1; vec($rin, fileno($sock), 1) = 1; my $ein = $rin | $win; # We want to buffer output to the terminal. This prevents the program # from blocking if the user hits CTRL-S for example. # XXX ^^^ termRaw(); # Loop waiting for input from the user, or from the server. while (1) { $nfound = select($rout=$rin, $wout=$win, $eout=$ein, undef); if ($nfound < 0) { if ($! == EINTR || $! == EAGAIN) { next; } die "$P: select failed - $!\n"; } if (vec($rout, fileno(STDIN), 1)) { $len = sysread(STDIN, $data, 4096); if ($len <= 0) { if ($len < 0) { if ($! == EINTR || $! == EAGAIN) { next; } die "$P: STDIN: read failed - $!\n"; } print STDERR "Connection Closed (client)\n"; last; } print $sock $data; } if (vec($rout, fileno($sock), 1)) { $len = sysread($sock, $data, 4096); if ($len <= 0) { if ($len < 0) { if ($! == EINTR || $! == EAGAIN) { next; } die "$P: server: read failed - $!\n"; } print STDERR "Connection Closed (server)\n"; last; } print $data; } } termRestore();