From f124829c9b35377de2a8316b7e23aa7a8c5d7b23 Mon Sep 17 00:00:00 2001 From: John Starks Date: Fri, 20 May 2016 19:04:20 -0700 Subject: [PATCH] Windows: Work around Windows BS/DEL behavior In Windows containers in TP5, DEL is interpreted as the delete key, but Linux generally interprets it as backspace. This prevents backspace from working when using a Linux terminal or the native console terminal emulation in Windows. To work around this, translate DEL to BS in Windows containers stdin when TTY is enabled. Do this only for builds that do not have the fix in Windows itself. Signed-off-by: John Starks --- libcontainerd/client_windows.go | 3 +++ libcontainerd/container_windows.go | 3 +++ libcontainerd/process_windows.go | 32 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/libcontainerd/client_windows.go b/libcontainerd/client_windows.go index fac9a35683..ddf8543e33 100644 --- a/libcontainerd/client_windows.go +++ b/libcontainerd/client_windows.go @@ -291,6 +291,9 @@ func (clnt *client) AddProcess(containerID, processFriendlyName string, procToAd return err } + // TEMP: Work around Windows BS/DEL behavior. + iopipe.Stdin = fixStdinBackspaceBehavior(iopipe.Stdin, procToAdd.Terminal) + // Convert io.ReadClosers to io.Readers if stdout != nil { iopipe.Stdout = openReaderFromPipe(stdout) diff --git a/libcontainerd/container_windows.go b/libcontainerd/container_windows.go index ec35746b5c..e1f64a1704 100644 --- a/libcontainerd/container_windows.go +++ b/libcontainerd/container_windows.go @@ -102,6 +102,9 @@ func (ctr *container) start() error { } ctr.startedAt = time.Now() + // TEMP: Work around Windows BS/DEL behavior. + iopipe.Stdin = fixStdinBackspaceBehavior(iopipe.Stdin, ctr.ociSpec.Process.Terminal) + // Convert io.ReadClosers to io.Readers if stdout != nil { iopipe.Stdout = openReaderFromPipe(stdout) diff --git a/libcontainerd/process_windows.go b/libcontainerd/process_windows.go index 0371aec91f..12593bba67 100644 --- a/libcontainerd/process_windows.go +++ b/libcontainerd/process_windows.go @@ -2,6 +2,8 @@ package libcontainerd import ( "io" + + "github.com/docker/docker/pkg/system" ) // process keeps the state for both main container process and exec process. @@ -25,3 +27,33 @@ func openReaderFromPipe(p io.ReadCloser) io.Reader { }() return r } + +// fixStdinBackspaceBehavior works around a bug in Windows before build 14350 +// where it interpreted DEL as VK_DELETE instead of as VK_BACK. This replaces +// DEL with BS to work around this. +func fixStdinBackspaceBehavior(w io.WriteCloser, tty bool) io.WriteCloser { + if !tty || system.GetOSVersion().Build >= 14350 { + return w + } + return &delToBsWriter{w} +} + +type delToBsWriter struct { + io.WriteCloser +} + +func (w *delToBsWriter) Write(b []byte) (int, error) { + const ( + backspace = 0x8 + del = 0x7f + ) + bc := make([]byte, len(b)) + for i, c := range b { + if c == del { + bc[i] = backspace + } else { + bc[i] = c + } + } + return w.WriteCloser.Write(bc) +}