Skip to content

Commit d7a7210

Browse files
committed
all: import golang.org/x/crypto/ssh/terminal
This merges all code from x/crypto/ssh/terminal at commit 0c6587e931a935f573efb6988c8470cd8c0a58de with no refactoring, simply mapping util_* files to term_*. The x/crypto history for the merge was rewritten with git filter-repo --path ssh/terminal/ --path-rename ssh/terminal/: and then stitched together with "git replace --graft". The merge preserves git blame visibility. Updates #31044 Change-Id: Ic51fc8ec20b3a384cdd8868fde06fe69b6317695
2 parents ad39bd3 + c955d0b commit d7a7210

11 files changed

+1759
-10
lines changed

term.go

+8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44

55
// Package term provides support functions for dealing with terminals, as
66
// commonly found on UNIX systems.
7+
//
8+
// Putting a terminal into raw mode is the most common requirement:
9+
//
10+
// oldState, err := terminal.MakeRaw(0)
11+
// if err != nil {
12+
// panic(err)
13+
// }
14+
// defer terminal.Restore(0, oldState)
715
package term
816

917
// IsTerminal returns whether the given file descriptor is a terminal.

term_aix.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
package term
66

7-
import (
8-
"golang.org/x/sys/unix"
9-
)
7+
import "golang.org/x/sys/unix"
108

119
const ioctlReadTermios = unix.TCGETS
10+
const ioctlWriteTermios = unix.TCSETS

term_bsd.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66

77
package term
88

9-
import (
10-
"golang.org/x/sys/unix"
11-
)
9+
import "golang.org/x/sys/unix"
1210

1311
const ioctlReadTermios = unix.TIOCGETA
12+
const ioctlWriteTermios = unix.TIOCSETA

term_linux.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
package term
66

7-
import (
8-
"golang.org/x/sys/unix"
9-
)
7+
import "golang.org/x/sys/unix"
108

119
const ioctlReadTermios = unix.TCGETS
10+
const ioctlWriteTermios = unix.TCSETS

term_plan9.go

+36
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,49 @@
55
package term
66

77
import (
8+
"fmt"
9+
"runtime"
10+
811
"golang.org/x/sys/plan9"
912
)
1013

14+
type State struct{}
15+
1116
func isTerminal(fd int) bool {
1217
path, err := plan9.Fd2path(fd)
1318
if err != nil {
1419
return false
1520
}
1621
return path == "/dev/cons" || path == "/mnt/term/dev/cons"
1722
}
23+
24+
// MakeRaw put the terminal connected to the given file descriptor into raw
25+
// mode and returns the previous state of the terminal so that it can be
26+
// restored.
27+
func MakeRaw(fd int) (*State, error) {
28+
return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
29+
}
30+
31+
// GetState returns the current state of a terminal which may be useful to
32+
// restore the terminal after a signal.
33+
func GetState(fd int) (*State, error) {
34+
return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
35+
}
36+
37+
// Restore restores the terminal connected to the given file descriptor to a
38+
// previous state.
39+
func Restore(fd int, state *State) error {
40+
return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
41+
}
42+
43+
// GetSize returns the dimensions of the given terminal.
44+
func GetSize(fd int) (width, height int, err error) {
45+
return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
46+
}
47+
48+
// ReadPassword reads a line of input from a terminal without local echo. This
49+
// is commonly used for inputting passwords and other sensitive data. The slice
50+
// returned does not include the \n.
51+
func ReadPassword(fd int) ([]byte, error) {
52+
return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
53+
}

term_solaris.go

+108
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,118 @@
55
package term
66

77
import (
8+
"io"
9+
"syscall"
10+
811
"golang.org/x/sys/unix"
912
)
1013

14+
// State contains the state of a terminal.
15+
type State struct {
16+
termios unix.Termios
17+
}
18+
1119
func isTerminal(fd int) bool {
1220
_, err := unix.IoctlGetTermio(fd, unix.TCGETA)
1321
return err == nil
1422
}
23+
24+
// ReadPassword reads a line of input from a terminal without local echo. This
25+
// is commonly used for inputting passwords and other sensitive data. The slice
26+
// returned does not include the \n.
27+
func ReadPassword(fd int) ([]byte, error) {
28+
// see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c
29+
val, err := unix.IoctlGetTermios(fd, unix.TCGETS)
30+
if err != nil {
31+
return nil, err
32+
}
33+
oldState := *val
34+
35+
newState := oldState
36+
newState.Lflag &^= syscall.ECHO
37+
newState.Lflag |= syscall.ICANON | syscall.ISIG
38+
newState.Iflag |= syscall.ICRNL
39+
err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState)
40+
if err != nil {
41+
return nil, err
42+
}
43+
44+
defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState)
45+
46+
var buf [16]byte
47+
var ret []byte
48+
for {
49+
n, err := syscall.Read(fd, buf[:])
50+
if err != nil {
51+
return nil, err
52+
}
53+
if n == 0 {
54+
if len(ret) == 0 {
55+
return nil, io.EOF
56+
}
57+
break
58+
}
59+
if buf[n-1] == '\n' {
60+
n--
61+
}
62+
ret = append(ret, buf[:n]...)
63+
if n < len(buf) {
64+
break
65+
}
66+
}
67+
68+
return ret, nil
69+
}
70+
71+
// MakeRaw puts the terminal connected to the given file descriptor into raw
72+
// mode and returns the previous state of the terminal so that it can be
73+
// restored.
74+
// see http://cr.illumos.org/~webrev/andy_js/1060/
75+
func MakeRaw(fd int) (*State, error) {
76+
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
77+
if err != nil {
78+
return nil, err
79+
}
80+
81+
oldState := State{termios: *termios}
82+
83+
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
84+
termios.Oflag &^= unix.OPOST
85+
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
86+
termios.Cflag &^= unix.CSIZE | unix.PARENB
87+
termios.Cflag |= unix.CS8
88+
termios.Cc[unix.VMIN] = 1
89+
termios.Cc[unix.VTIME] = 0
90+
91+
if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil {
92+
return nil, err
93+
}
94+
95+
return &oldState, nil
96+
}
97+
98+
// Restore restores the terminal connected to the given file descriptor to a
99+
// previous state.
100+
func Restore(fd int, oldState *State) error {
101+
return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios)
102+
}
103+
104+
// GetState returns the current state of a terminal which may be useful to
105+
// restore the terminal after a signal.
106+
func GetState(fd int) (*State, error) {
107+
termios, err := unix.IoctlGetTermios(fd, unix.TCGETS)
108+
if err != nil {
109+
return nil, err
110+
}
111+
112+
return &State{termios: *termios}, nil
113+
}
114+
115+
// GetSize returns the dimensions of the given terminal.
116+
func GetSize(fd int) (width, height int, err error) {
117+
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
118+
if err != nil {
119+
return 0, 0, err
120+
}
121+
return int(ws.Col), int(ws.Row), nil
122+
}

term_unix.go

+88-1
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,102 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build aix darwin dragonfly freebsd linux netbsd openbsd
5+
// +build aix darwin dragonfly freebsd linux,!appengine netbsd openbsd zos
66

77
package term
88

99
import (
1010
"golang.org/x/sys/unix"
1111
)
1212

13+
// State contains the state of a terminal.
14+
type State struct {
15+
termios unix.Termios
16+
}
17+
1318
func isTerminal(fd int) bool {
1419
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
1520
return err == nil
1621
}
22+
23+
// MakeRaw put the terminal connected to the given file descriptor into raw
24+
// mode and returns the previous state of the terminal so that it can be
25+
// restored.
26+
func MakeRaw(fd int) (*State, error) {
27+
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
28+
if err != nil {
29+
return nil, err
30+
}
31+
32+
oldState := State{termios: *termios}
33+
34+
// This attempts to replicate the behaviour documented for cfmakeraw in
35+
// the termios(3) manpage.
36+
termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
37+
termios.Oflag &^= unix.OPOST
38+
termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
39+
termios.Cflag &^= unix.CSIZE | unix.PARENB
40+
termios.Cflag |= unix.CS8
41+
termios.Cc[unix.VMIN] = 1
42+
termios.Cc[unix.VTIME] = 0
43+
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
44+
return nil, err
45+
}
46+
47+
return &oldState, nil
48+
}
49+
50+
// GetState returns the current state of a terminal which may be useful to
51+
// restore the terminal after a signal.
52+
func GetState(fd int) (*State, error) {
53+
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
54+
if err != nil {
55+
return nil, err
56+
}
57+
58+
return &State{termios: *termios}, nil
59+
}
60+
61+
// Restore restores the terminal connected to the given file descriptor to a
62+
// previous state.
63+
func Restore(fd int, state *State) error {
64+
return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
65+
}
66+
67+
// GetSize returns the dimensions of the given terminal.
68+
func GetSize(fd int) (width, height int, err error) {
69+
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
70+
if err != nil {
71+
return -1, -1, err
72+
}
73+
return int(ws.Col), int(ws.Row), nil
74+
}
75+
76+
// passwordReader is an io.Reader that reads from a specific file descriptor.
77+
type passwordReader int
78+
79+
func (r passwordReader) Read(buf []byte) (int, error) {
80+
return unix.Read(int(r), buf)
81+
}
82+
83+
// ReadPassword reads a line of input from a terminal without local echo. This
84+
// is commonly used for inputting passwords and other sensitive data. The slice
85+
// returned does not include the \n.
86+
func ReadPassword(fd int) ([]byte, error) {
87+
termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
88+
if err != nil {
89+
return nil, err
90+
}
91+
92+
newState := *termios
93+
newState.Lflag &^= unix.ECHO
94+
newState.Lflag |= unix.ICANON | unix.ISIG
95+
newState.Iflag |= unix.ICRNL
96+
if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
97+
return nil, err
98+
}
99+
100+
defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
101+
102+
return readPasswordLine(passwordReader(fd))
103+
}

0 commit comments

Comments
 (0)