KVM test: introduce VM exceptions
[autotest-zwu.git] / conmux / Conmux.pm
blob343d3e04fdf402213ad9af1e2c0b054b81f49fbf
2 # Conmux.pm -- core console multiplexor package
4 # Implements the core multiplexor functionality such as resolution of
5 # names and connecting to the conmux server.
7 # (C) Copyright IBM Corp. 2004, 2005, 2006
8 # Author: Andy Whitcroft <andyw@uk.ibm.com>
10 # The Console Multiplexor is released under the GNU Public License V2
12 package Conmux;
13 use URI::Escape;
14 use File::Basename;
15 use Cwd 'abs_path';
17 our $Config;
19 BEGIN {
20 my $abs_path = abs_path($0);
21 my $dir_path = dirname($abs_path);
23 my $cf = '/usr/local/conmux/etc/config';
24 if (-e "$dir_path/etc/config") {
25 $cf = "$dir_path/etc/config";
26 } elsif (-e "$dir_path/../etc/config") {
27 $cf = "$dir_path/../etc/config";
30 if (-f $cf) {
31 open(CFG, "<$cf") || die "Conmux: $cf: open failed - $!\n";
32 while(<CFG>) {
33 chomp;
34 next if (/^#/ || /^\s*$/ || !/=/);
36 my ($name, $value) = split(/=/, $_, 2);
37 $value =~ s/^"//;
38 $value =~ s/"$//;
40 # Substitute variables.
41 while ($value =~ /\$([A-Za-z0-9_]+)/) {
42 my $v = $Config->{$1};
43 $value =~ s/\$$1/$v/;
45 $Config->{$name} = $value;
47 close(CFG);
51 sub encodeArgs {
52 my (%a) = @_;
53 my ($a, $n, $s);
55 ##print "0<$_[0]> ref<" . ref($_[0]) . ">\n";
57 # Handle being passed references to hashes too ...
58 $a = \%a;
59 $a = $_[0] if (ref($_[0]) eq "HASH");
61 for $n (sort keys %{$a}) {
62 $s .= uri_escape($n) . '=' . uri_escape($a->{$n}) .
63 ' ';
65 chop($s);
66 $s;
69 sub decodeArgs {
70 my ($s) = @_;
71 my (%a, $nv, $n, $v);
73 # Decode the standard argument stream.
74 for $nv (split(' ', $s)) {
75 ($n, $v) = split('=', $nv, 2);
76 $a{uri_unescape($n)} = uri_unescape($v);
79 %a;
82 sub sendCmd {
83 my ($fh, $c, $a) = @_;
84 my ($rs);
86 # Send the encoded command ...
87 print $fh $c . " " . encodeArgs($a) . "\n";
89 # Read the reply.
90 $rs = <$fh>;
91 chomp($rs);
93 decodeArgs($rs);
96 sub sendRequest {
97 my ($fh, $c, $a) = @_;
98 my %a = { 'result' => 'more' };
100 # Send the encoded command ...
101 print $fh $c . " " . encodeArgs($a) . "\n";
105 sub revcResult {
106 my ($fh) = @_;
107 my ($rs);
109 # Read the reply.
110 $rs = <$fh>;
111 chomp($rs);
113 decodeArgs($rs);
117 # Configuration.
119 sub configRegistry {
120 my $reg = $Config->{'registry'};
122 $reg = "localhost" if (!$reg);
123 $reg;
126 # Connect to the host/port specified on the command line,
127 # or localhost:23
128 sub connect {
129 my ($to) = @_;
130 my ($reg, $sock);
132 # host:port
133 if ($to =~ /:/) {
134 # Already in the right form.
136 # registry/service
137 } elsif ($to =~ m@(.*)/(.*)@) {
138 my ($host, $service) = ($1, $2);
140 $to = Conmux::Registry::lookup($host, $service);
142 # service
143 } else {
144 $to = Conmux::Registry::lookup('-', $to);
147 $sock = new IO::Socket::INET(Proto => 'tcp', PeerAddr => $to)
148 or die "Conmux::connect $to: connect failed - $@\n";
150 # Turn on keep alives by default.
151 $sock->sockopt(SO_KEEPALIVE, 1);
153 $sock;
156 package Conmux::Registry;
157 sub lookup {
158 my ($host, $service) = @_;
160 $host = Conmux::configRegistry() if ($host eq '-');
162 # Connect to the registry service and lookup the requested service.
163 my $reg = new IO::Socket::INET(Proto => 'tcp',
164 PeerAddr => "$host", PeerPort => 63000)
165 or die "Conmux::connect: registry not available - $@\n";
167 my %r = Conmux::sendCmd($reg, 'LOOKUP', { 'service' => $service });
168 die "Conmux::Registry::lookup: $service: error - $r{'status'}\n"
169 if ($r{status} ne "OK");
171 close($reg);
173 $r{'result'};
176 sub add {
177 my ($host, $service, $location) = @_;
179 $host = Conmux::configRegistry() if ($host eq '-');
181 # Connect to the registry service and lookup the requested service.
182 my $reg = new IO::Socket::INET(Proto => 'tcp',
183 PeerAddr => "$host", PeerPort => 63000)
184 or die "Conmux::connect: registry not available - $@\n";
186 my %r = Conmux::sendCmd($reg, 'ADD', { 'service' => $service,
187 'location' => $location });
188 die "Conmux::Registry::add: $service: error - $r{'status'}\n"
189 if ($r{status} ne "OK");
191 close($reg);
196 sub list {
197 my ($host, $service, $location) = @_;
198 my (@results, %r);
200 $host = Conmux::configRegistry() if ($host eq '-');
202 # Connect to the registry service and ask for a list.
203 my $reg = new IO::Socket::INET(Proto => 'tcp',
204 PeerAddr => "$host", PeerPort => 63000)
205 or die "Conmux::connect: registry not available - $@\n";
207 %r = Conmux::sendCmd($reg, 'LIST', { });
208 ## while ($r{'status'} eq 'more') {
209 ## %r = receiveResult($reg);
210 ## push(@results, $r{'result'});
211 ## }
212 die "Conmux::Registry::list: error - $r{'status'}\n"
213 if ($r{'status'} ne "OK");
215 close($reg);
217 $r{'result'};