| #!/usr/bin/perl |
| # |
| # console <host>/<machine> -- 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 <andyw@uk.ibm.com> |
| # |
| # 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 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 <service>\n"; |
| warn " $P <registry>/<service>\n"; |
| warn " $P <host>:<port>\n"; |
| warn " $P --status <service>\n"; |
| die " $P --list [<registry>]\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(); |