1
2
3
4
5
6
7
8 package term
9
10 import (
11 "golang.org/x/sys/unix"
12 )
13
14 type state struct {
15 termios unix.Termios
16 }
17
18 func isTerminal(fd int) bool {
19 _, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
20 return err == nil
21 }
22
23 func makeRaw(fd int) (*State, error) {
24 termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
25 if err != nil {
26 return nil, err
27 }
28
29 oldState := State{state{termios: *termios}}
30
31
32
33 termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON
34 termios.Oflag &^= unix.OPOST
35 termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN
36 termios.Cflag &^= unix.CSIZE | unix.PARENB
37 termios.Cflag |= unix.CS8
38 termios.Cc[unix.VMIN] = 1
39 termios.Cc[unix.VTIME] = 0
40 if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil {
41 return nil, err
42 }
43
44 return &oldState, nil
45 }
46
47 func getState(fd int) (*State, error) {
48 termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
49 if err != nil {
50 return nil, err
51 }
52
53 return &State{state{termios: *termios}}, nil
54 }
55
56 func restore(fd int, state *State) error {
57 return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios)
58 }
59
60 func getSize(fd int) (width, height int, err error) {
61 ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
62 if err != nil {
63 return -1, -1, err
64 }
65 return int(ws.Col), int(ws.Row), nil
66 }
67
68
69 type passwordReader int
70
71 func (r passwordReader) Read(buf []byte) (int, error) {
72 return unix.Read(int(r), buf)
73 }
74
75 func readPassword(fd int) ([]byte, error) {
76 termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
77 if err != nil {
78 return nil, err
79 }
80
81 newState := *termios
82 newState.Lflag &^= unix.ECHO
83 newState.Lflag |= unix.ICANON | unix.ISIG
84 newState.Iflag |= unix.ICRNL
85 if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil {
86 return nil, err
87 }
88
89 defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios)
90
91 return readPasswordLine(passwordReader(fd))
92 }
93
View as plain text