Update console dep to c12b1e7919c14469339a5d38f2f8

This fixes interactive consoles in windows

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2018-08-22 13:33:01 -04:00
parent 53a8c946f5
commit d6cd1e5379
2 changed files with 74 additions and 38 deletions

View File

@ -1,5 +1,5 @@
github.com/containerd/go-runc 808e8444ac4633a8e5eb7314fc6b5d27051727dd github.com/containerd/go-runc 808e8444ac4633a8e5eb7314fc6b5d27051727dd
github.com/containerd/console 4d8a41f4ce5b9bae77c41786ea2458330f43f081 github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2 github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40 github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c

View File

@ -17,6 +17,7 @@
package console package console
import ( import (
"fmt"
"os" "os"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -28,55 +29,90 @@ var (
ErrNotImplemented = errors.New("not implemented") ErrNotImplemented = errors.New("not implemented")
) )
func (m *master) init() { func (m *master) initStdios() {
m.h = windows.Handle(m.f.Fd()) m.in = windows.Handle(os.Stdin.Fd())
if err := windows.GetConsoleMode(m.h, &m.mode); err == nil { if err := windows.GetConsoleMode(m.in, &m.inMode); err == nil {
if m.f == os.Stdin {
// Validate that windows.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it. // Validate that windows.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it.
if err = windows.SetConsoleMode(m.h, m.mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err == nil { if err = windows.SetConsoleMode(m.in, m.inMode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err == nil {
vtInputSupported = true vtInputSupported = true
} }
// Unconditionally set the console mode back even on failure because SetConsoleMode // Unconditionally set the console mode back even on failure because SetConsoleMode
// remembers invalid bits on input handles. // remembers invalid bits on input handles.
windows.SetConsoleMode(m.h, m.mode) windows.SetConsoleMode(m.in, m.inMode)
} else if err := windows.SetConsoleMode(m.h, m.mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err == nil {
m.mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
} else { } else {
windows.SetConsoleMode(m.h, m.mode) fmt.Printf("failed to get console mode for stdin: %v\n", err)
} }
m.out = windows.Handle(os.Stdout.Fd())
if err := windows.GetConsoleMode(m.out, &m.outMode); err == nil {
if err := windows.SetConsoleMode(m.out, m.outMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err == nil {
m.outMode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
} else {
windows.SetConsoleMode(m.out, m.outMode)
}
} else {
fmt.Printf("failed to get console mode for stdout: %v\n", err)
}
m.err = windows.Handle(os.Stderr.Fd())
if err := windows.GetConsoleMode(m.err, &m.errMode); err == nil {
if err := windows.SetConsoleMode(m.err, m.errMode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err == nil {
m.errMode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
} else {
windows.SetConsoleMode(m.err, m.errMode)
}
} else {
fmt.Printf("failed to get console mode for stderr: %v\n", err)
} }
} }
type master struct { type master struct {
h windows.Handle in windows.Handle
mode uint32 inMode uint32
f *os.File
out windows.Handle
outMode uint32
err windows.Handle
errMode uint32
} }
func (m *master) SetRaw() error { func (m *master) SetRaw() error {
if m.f == os.Stdin { if err := makeInputRaw(m.in, m.inMode); err != nil {
if err := makeInputRaw(m.h, m.mode); err != nil {
return err return err
} }
} else {
// Set StdOut and StdErr to raw mode, we ignore failures since // Set StdOut and StdErr to raw mode, we ignore failures since
// windows.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this version of // windows.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this version of
// Windows. // Windows.
windows.SetConsoleMode(m.h, m.mode|windows.DISABLE_NEWLINE_AUTO_RETURN)
} windows.SetConsoleMode(m.out, m.outMode|windows.DISABLE_NEWLINE_AUTO_RETURN)
windows.SetConsoleMode(m.err, m.errMode|windows.DISABLE_NEWLINE_AUTO_RETURN)
return nil return nil
} }
func (m *master) Reset() error { func (m *master) Reset() error {
if err := windows.SetConsoleMode(m.h, m.mode); err != nil { for _, s := range []struct {
fd windows.Handle
mode uint32
}{
{m.in, m.inMode},
{m.out, m.outMode},
{m.err, m.errMode},
} {
if err := windows.SetConsoleMode(s.fd, s.mode); err != nil {
return errors.Wrap(err, "unable to restore console mode") return errors.Wrap(err, "unable to restore console mode")
} }
}
return nil return nil
} }
func (m *master) Size() (WinSize, error) { func (m *master) Size() (WinSize, error) {
var info windows.ConsoleScreenBufferInfo var info windows.ConsoleScreenBufferInfo
err := windows.GetConsoleScreenBufferInfo(m.h, &info) err := windows.GetConsoleScreenBufferInfo(m.out, &info)
if err != nil { if err != nil {
return WinSize{}, errors.Wrap(err, "unable to get console info") return WinSize{}, errors.Wrap(err, "unable to get console info")
} }
@ -98,11 +134,11 @@ func (m *master) ResizeFrom(c Console) error {
} }
func (m *master) DisableEcho() error { func (m *master) DisableEcho() error {
mode := m.mode &^ windows.ENABLE_ECHO_INPUT mode := m.inMode &^ windows.ENABLE_ECHO_INPUT
mode |= windows.ENABLE_PROCESSED_INPUT mode |= windows.ENABLE_PROCESSED_INPUT
mode |= windows.ENABLE_LINE_INPUT mode |= windows.ENABLE_LINE_INPUT
if err := windows.SetConsoleMode(m.h, mode); err != nil { if err := windows.SetConsoleMode(m.in, mode); err != nil {
return errors.Wrap(err, "unable to set console to disable echo") return errors.Wrap(err, "unable to set console to disable echo")
} }
@ -114,15 +150,15 @@ func (m *master) Close() error {
} }
func (m *master) Read(b []byte) (int, error) { func (m *master) Read(b []byte) (int, error) {
return m.f.Read(b) return os.Stdin.Read(b)
} }
func (m *master) Write(b []byte) (int, error) { func (m *master) Write(b []byte) (int, error) {
return m.f.Write(b) return os.Stdout.Write(b)
} }
func (m *master) Fd() uintptr { func (m *master) Fd() uintptr {
return uintptr(m.h) return uintptr(m.in)
} }
// on windows, console can only be made from os.Std{in,out,err}, hence there // on windows, console can only be made from os.Std{in,out,err}, hence there
@ -174,7 +210,7 @@ func newMaster(f *os.File) (Console, error) {
if f != os.Stdin && f != os.Stdout && f != os.Stderr { if f != os.Stdin && f != os.Stdout && f != os.Stderr {
return nil, errors.New("creating a console from a file is not supported on windows") return nil, errors.New("creating a console from a file is not supported on windows")
} }
m := &master{f: f} m := &master{}
m.init() m.initStdios()
return m, nil return m, nil
} }