From a0d3719b52a55c7c1961b6692e53a4b3b6b4ca98 Mon Sep 17 00:00:00 2001 From: Leo Simons Date: Thu, 28 Aug 2014 18:02:27 +0200 Subject: [PATCH] Scrub SSH PTY output to filter out command echo-ing. --- plugins/communicators/ssh/communicator.rb | 41 +++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index beab115e1..4921ce53e 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -401,6 +401,9 @@ module VagrantPlugins return yield connection if block_given? end + DELIM_START = 'UniqueStartStringPTY' + DELIM_END = 'UniqueEndStringPTY' + # Executes the command on an SSH connection within a login shell. def shell_execute(connection, command, **opts) opts = { @@ -421,10 +424,14 @@ module VagrantPlugins shell_cmd = shell if shell shell_cmd = "sudo -E -H #{shell_cmd}" if sudo + use_tty = false + stdout = '' + # Open the channel so we can execute or command channel = connection.open_channel do |ch| if @machine.config.ssh.pty ch.request_pty do |ch2, success| + use_tty = success and command != '' if success @logger.debug("pty obtained for connection") else @@ -439,7 +446,11 @@ module VagrantPlugins # Filter out the clear screen command data = remove_ansi_escape_codes(data) @logger.debug("stdout: #{data}") - yield :stdout, data if block_given? + if use_tty + stdout << data + else + yield :stdout, data if block_given? + end end ch2.on_extended_data do |ch3, type, data| @@ -487,14 +498,29 @@ module VagrantPlugins end # Output the command - ch2.send_data "#{command}\n".force_encoding('ASCII-8BIT') + if use_tty + ch2.send_data "stty raw -echo\n" + ch2.send_data "export PS1=\n" + ch2.send_data "export PS2=\n" + ch2.send_data "export PROMPT_COMMAND=\n" + sleep(0.1) + data = "printf #{DELIM_START}\n" + data += "#{command}\n" + data += "printf #{DELIM_END}\n" + data = data.force_encoding('ASCII-8BIT') + ch2.send_data data + else + ch2.send_data "#{command}\n".force_encoding('ASCII-8BIT') + end # Remember to exit or this channel will hang open ch2.send_data "exit\n" # Send eof to let server know we're done ch2.eof! + ch2.wait end + ch.wait end begin @@ -530,6 +556,17 @@ module VagrantPlugins keep_alive.kill if keep_alive end + if use_tty + @logger.debug("stdout: #{stdout}") + if not stdout.include? DELIM_START or not stdout.include? DELIM_END + @logger.error("Error parsing TTY output") + raise Vagrant::Errors::SSHInvalidShell.new + end + data = stdout[/.*#{DELIM_START}(.*?)#{DELIM_END}/m, 1] + @logger.debug("selected stdout: #{data}") + yield :stdout, data if block_given? + end + # Return the final exit status return exit_status end