blob: a7ad2ab68e5a396a4047b93a8fc21791d937cbc5 [file] [log] [blame]
apw3812c032006-12-07 21:01:14 +00001#!/usr/bin/perl
2#
3# console <host>/<machine> -- interactive client interface
4#
5# The main interactive client interace to conmux. Allows direct
6# interaction with the payload, as well as allowing break out
7# to the conmux menu to envoke defined commands; for example
8# hardreset.
9#
10# (C) Copyright IBM Corp. 2004, 2005, 2006
11# Author: Andy Whitcroft <andyw@uk.ibm.com>
12#
13# The Console Multiplexor is released under the GNU Public License V2
14#
15$| = 1;
16
17our $P = 'console';
18
19use IO::Socket;
20use IO::Multiplex;
21use Getopt::Long qw(:config no_auto_abbrev);
22
23my $CONMUX = '/usr/local/conmux';
24my $CONMUX = $ENV{'CONMUX_ROOT'} if ($ENV{'CONMUX_ROOT'});
25
26# Find our internal libraries.
27###my $lib = $0; $lib =~ s@/[^/]+$@@;
28###push(@INC, $lib);
29###require Conmux;
30##use lib ".";
31##use Conmux;
32use lib "/usr/local/conmux/lib";
33use Conmux;
34
35# Basic terminal handling.
36sub termRaw {
37 $termSettings = `stty -g`;
38 system "stty raw -echo opost onlret";
39}
40sub termRestore {
41 system "stty $termSettings";
42}
43
44my $bot;
45my $list;
46my $status;
47GetOptions(
48 'b|bot=s' => \$bot,
49 'l|list' => \$list,
50 's|status' => \$status,
51);
52sub usage {
53 warn "Usage: $P <service>\n";
54 warn " $P <registry>/<service>\n";
55 warn " $P <host>:<port>\n";
56 warn " $P --status <service>\n";
57 die " $P --list [<registry>]\n";
58}
59
60my $id;
61if ($bot) {
62 $id = 'bot:' . $bot;
63} else {
64 $id = 'user:' . $ENV{'LOGNAME'};
65}
66
67#
68# MODE: registry list.
69#
70if ($list) {
71 if ($#ARGV == -1) {
72 print Conmux::Registry::list('-');
73
74 } elsif ($#ARGV == 0) {
75 print Conmux::Registry::list($ARGV[0]);
76
77 } else {
78 usage();
79 }
80 exit 0
81}
82
83#
84# COMMAND: payload status command
85#
86if ($status) {
87 usage() if ($#ARGV != 0);
88
89 my $sock;
90 eval {
91 $sock = Conmux::connect($ARGV[0]);
92 };
93 if ($@) {
94 print "unavailable\n";
95 exit 0
96 }
97 my %r = Conmux::sendCmd($sock, 'CONNECT', { 'id' => $id,
98 'to' => 'console', 'hide' => 1 });
99 if ($r{'status'} ne 'OK') {
100 print "unavailable\n";
101
102 } elsif ($r{'state'}) {
103 print "$r{'state'}\n";
104
105 } else {
106 print "unknown\n";
107 }
108 exit 0;
109}
110
111
112#
113# COMMAND: general payload connect.
114#
115if ($#ARGV != 0) {
116 usage();
117}
118
119# Create a multiplex object
120my $mux = new IO::Multiplex;
121
122# Connect to the host/port specified on the command line,
123# or localhost:23
124my $sock = Conmux::connect($ARGV[0]);
125
126my %r = Conmux::sendCmd($sock, 'CONNECT', { 'id' => $id, 'to' => 'console' });
127die "$P: $ARGV[0]: connect failed - $r{'status'}\n" if ($r{'status'} ne 'OK');
128
129print "Connected to $r{'title'} (~\$quit to exit)\n";
130
131# OK, we are now connected ... add the relevant file handles to the mux
132$mux->add($sock);
133$mux->add(\*STDIN);
134# We want to buffer output to the terminal. This prevents the program
135# from blocking if the user hits CTRL-S for example.
136$mux->add(\*STDOUT);
137
138# We're not object oriented, so just request callbacks to the
139# current package
140$mux->set_callback_object(__PACKAGE__);
141
142termRaw();
143
144# Enter the main mux loop.
145$mux->loop;
146
147# mux_input is called when input is available on one of
148# the descriptors.
149sub mux_input {
150 my $package = shift;
151 my $mux = shift;
152 my $fh = shift;
153 my $input = shift;
154
155 # Figure out whence the input came, and send it on to the
156 # other place.
157 if ($fh == $sock) {
158 print STDOUT $$input;
159
160 # Remove the input from the input buffer.
161 $$input = '';
162 } else {
163 print $sock $$input;
164
165 # Remove the input from the input buffer.
166 $$input = '';
167## while ($$input ne "") {
168## # Check for an incomplete escape ... wait for more.
169## if ($$input =~ /^~$/s) {
170## return;
171## }
172## if ($$input =~ s/^~\$//s) {
173## $mux->shutdown($sock, 1);
174## }
175## # Its not an escape ... pass it on.
176## # Ship anything before that cannot be the escape.
177## if ($$input =~ s/^(.[^~]*)(~|$)/\2/s) {
178## print $sock $1;
179## }
180## }
181 }
182}
183
184# This gets called if the other end closes the connection.
185sub mux_eof {
186 print STDERR "Connection Closed\n";
187 termRestore();
188 exit;
189}
190sub mux_close {
191 print "CLOSE\n";
192}