blob: f031e5b2c594ce1eb88ad31355a11fc9dfdcc6b2 [file] [log] [blame] [edit]
#!/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 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 <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();