ssh/terminal: store termios copy in terminal state on Solaris
TestMakeRawState currently fails on Solaris:
--- FAIL: TestMakeRawState (0.00s)
terminal_test.go:334: states do not match; was &{0xc420015dd0}, expected &{0xc420015da0}
Change terminal.State to include a copy to the unix.Termios (like the
implementation for Linux and the BSDs) which also makes terminal.MakeRaw behave
as expected and lets TestMakeRawState pass.
Change-Id: I29382f83b84ff301991e1db170f32f41e144aec8
Reviewed-on: https://go-review.googlesource.com/99456
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
committed by
Tobias Klauser
parent
526a373fd7
commit
7effd64e11
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
// State contains the state of a terminal.
|
// State contains the state of a terminal.
|
||||||
type State struct {
|
type State struct {
|
||||||
state *unix.Termios
|
termios unix.Termios
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTerminal returns true if the given file descriptor is a terminal.
|
// IsTerminal returns true if the given file descriptor is a terminal.
|
||||||
@@ -75,47 +75,43 @@ func ReadPassword(fd int) ([]byte, error) {
|
|||||||
// restored.
|
// restored.
|
||||||
// see http://cr.illumos.org/~webrev/andy_js/1060/
|
// see http://cr.illumos.org/~webrev/andy_js/1060/
|
||||||
func MakeRaw(fd int) (*State, error) {
|
func MakeRaw(fd int) (*State, error) {
|
||||||
oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
oldTermios := *oldTermiosPtr
|
|
||||||
|
|
||||||
newTermios := oldTermios
|
oldState := State{termios: *termios}
|
||||||
newTermios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON
|
|
||||||
newTermios.Oflag &^= syscall.OPOST
|
|
||||||
newTermios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN
|
|
||||||
newTermios.Cflag &^= syscall.CSIZE | syscall.PARENB
|
|
||||||
newTermios.Cflag |= syscall.CS8
|
|
||||||
newTermios.Cc[unix.VMIN] = 1
|
|
||||||
newTermios.Cc[unix.VTIME] = 0
|
|
||||||
|
|
||||||
if err := unix.IoctlSetTermios(fd, unix.TCSETS, &newTermios); err != nil {
|
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
|
||||||
|
termios.Oflag &^= unix.OPOST
|
||||||
|
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
|
||||||
|
termios.Cflag &^= unix.CSIZE | unix.PARENB
|
||||||
|
termios.Cflag |= unix.CS8
|
||||||
|
termios.Cc[unix.VMIN] = 1
|
||||||
|
termios.Cc[unix.VTIME] = 0
|
||||||
|
|
||||||
|
if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &State{
|
return &oldState, nil
|
||||||
state: oldTermiosPtr,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore restores the terminal connected to the given file descriptor to a
|
// Restore restores the terminal connected to the given file descriptor to a
|
||||||
// previous state.
|
// previous state.
|
||||||
func Restore(fd int, oldState *State) error {
|
func Restore(fd int, oldState *State) error {
|
||||||
return unix.IoctlSetTermios(fd, unix.TCSETS, oldState.state)
|
return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetState returns the current state of a terminal which may be useful to
|
// GetState returns the current state of a terminal which may be useful to
|
||||||
// restore the terminal after a signal.
|
// restore the terminal after a signal.
|
||||||
func GetState(fd int) (*State, error) {
|
func GetState(fd int) (*State, error) {
|
||||||
oldTermiosPtr, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &State{
|
return &State{termios: *termios}, nil
|
||||||
state: oldTermiosPtr,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSize returns the dimensions of the given terminal.
|
// GetSize returns the dimensions of the given terminal.
|
||||||
|
|||||||
Reference in New Issue
Block a user