From 83a7ab4c1080c407fe9c225c96d30e3456c94c2f Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Mon, 11 Jun 2018 11:30:38 +0200 Subject: [PATCH] lxc enter: improve escape key handling The escape key should not be passed through, this now only happens when pressing the escape key twice (as it is with tmux, screen, ssh, etc.). Also prepared the code to handle a configurable escape key, and restructured the handling to more easily allow adding more keys. For instance we could add shortcuts for some `pct` commands. Most of them are marginally useful, but snapshot, migrate, shutdown or stop might still be nice-to-have things. The idea is also that if we reuse the code for serial terminals for VMs we can add shortcuts to eg. paste the current terminal size (probably the most useful one), or to send sys-rqs or agent commands. Signed-off-by: Wolfgang Bumiller --- PVE/APIClient/Commands/lxc.pm | 41 ++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/PVE/APIClient/Commands/lxc.pm b/PVE/APIClient/Commands/lxc.pm index c60017b..b30e09f 100644 --- a/PVE/APIClient/Commands/lxc.pm +++ b/PVE/APIClient/Commands/lxc.pm @@ -149,6 +149,16 @@ my $full_write = sub { return $len; }; +# Takes an escape character with an optional '^' prefix and returns an escape +# character code. +my $escapekey_to_char = sub { + my ($def) = @_; + if ($def =~ /^\^?([a-zA-Z])$/) { + return 1 + ord(lc($1)) - ord('a'); + } + die "bad escape key definition: $def\n"; +}; + __PACKAGE__->register_method ({ name => 'enter', path => 'enter', @@ -171,6 +181,9 @@ __PACKAGE__->register_method ({ my $config = PVE::APIClient::Config->load(); my $conn = PVE::APIClient::Config->remote_conn($config, $param->{remote}); + # FIXME: This should come from $config + my $escape_char = $escapekey_to_char->('a'); + # Get the real node from the resources endpoint my $resource_list = $conn->get("api2/json/cluster/resources", { type => 'vm'}); my ($resource) = grep { $_->{type} eq "lxc" && $_->{vmid} eq $param->{vmid}} @$resource_list; @@ -268,7 +281,7 @@ __PACKAGE__->register_method ({ my $output_fh = \*STDOUT; - my $ctrl_a_pressed_before = 0; + my $in_escape_sequence; my $winch_received = 0; $SIG{WINCH} = sub { $winch_received = 1; }; @@ -292,7 +305,7 @@ __PACKAGE__->register_method ({ my $len = length($$buffer_ref); my $nr = syswrite($fh, $$buffer_ref); if (!defined($nr)) { - next if $! == EINTR || $! == EAGAIN; + return if $! == EINTR || $! == EAGAIN; die "drain buffer - write error - $!\n"; } return $nr if !$nr; @@ -344,11 +357,27 @@ __PACKAGE__->register_method ({ my $char = ord($buff); - # check for CTRL-a-q - return if $ctrl_a_pressed_before == 1 && $char == hex("0x71"); - - $ctrl_a_pressed_before = ($char == hex("0x01") && $ctrl_a_pressed_before == 0) ? 1 : 0; + # Handle escape sequences: + if ($in_escape_sequence) { + $in_escape_sequence = 0; + if ($char == 0x71) { + # (escape, 'q') + return; + } elsif ($char == $escape_char) { + # (escape, escape) + # Pass this one through as a single escapekey + } else { + # Unknown escape sequence + # We could generate a bell or something... + # but for now just skip it + next; + } + } elsif ($char == $escape_char) { + $in_escape_sequence = 1; + next; + } + # Pass the key through: $websock_buffer .= $create_websockt_frame->("0:" . $nr . ":" . $buff); $write_select->add($web_socket); } -- 2.39.2