Import illumos compatibility patch from @cneira's nomad work
Signed-off-by: Till Wegmueller <till.wegmueller@openflowlabs.com>
Till Wegmueller authored 4 years ago
Till Wegmueller committed 4 years ago
4 | 4 | require ( |
5 | 5 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 |
6 | 6 | github.com/creack/pty v1.1.9 |
7 | github.com/google/go-cmp v0.3.1 | |
7 | github.com/google/go-cmp v0.4.0 | |
8 | 8 | github.com/pkg/errors v0.9.1 // indirect |
9 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 | |
9 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd | |
10 | 10 | gotest.tools v2.2.0+incompatible |
11 | 11 | ) |
1 | 1 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= |
2 | 2 | github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= |
3 | 3 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= |
4 | github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= | |
5 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |
4 | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= | |
5 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |
6 | 6 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= |
7 | 7 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= |
8 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= | |
9 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
8 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= | |
9 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
10 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | |
11 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |
10 | 12 | gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= |
11 | 13 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= |
0 | //+build solaris illumos | |
1 | ||
2 | package term | |
3 | ||
4 | import ( | |
5 | "golang.org/x/sys/unix" | |
6 | "syscall" | |
7 | ) | |
8 | ||
9 | func tcget(fd uintptr, p *Termios) syscall.Errno { | |
10 | ||
11 | termios, err := unix.IoctlGetTermios(int(fd), getTermios) | |
12 | if err != nil { | |
13 | return syscall.EINVAL | |
14 | } | |
15 | p = (*Termios)(termios) | |
16 | return 0 | |
17 | } | |
18 | ||
19 | func tcset(fd uintptr, p *Termios) syscall.Errno { | |
20 | if err := unix.IoctlSetTermios(int(fd), setTermios, (*unix.Termios)(p)); err != nil { | |
21 | return syscall.EINVAL | |
22 | } | |
23 | return 0 | |
24 | } |
0 | // +build !windows | |
0 | // +build !windows,!illumos,!solaris | |
1 | 1 | |
2 | 2 | // Package term provides structures and helper functions to work with |
3 | 3 | // terminal (state, sizes). |
0 | //+build solaris illumos | |
1 | ||
2 | // Package term provides structures and helper functions to work with | |
3 | // terminal (state, sizes). | |
4 | package term | |
5 | ||
6 | import ( | |
7 | "errors" | |
8 | "fmt" | |
9 | "io" | |
10 | "os" | |
11 | "os/signal" | |
12 | ||
13 | "golang.org/x/sys/unix" | |
14 | ) | |
15 | ||
16 | var ( | |
17 | // ErrInvalidState is returned if the state of the terminal is invalid. | |
18 | ErrInvalidState = errors.New("Invalid terminal state") | |
19 | ) | |
20 | ||
21 | // State represents the state of the terminal. | |
22 | type State struct { | |
23 | termios Termios | |
24 | } | |
25 | ||
26 | // Winsize represents the size of the terminal window. | |
27 | type Winsize struct { | |
28 | Height uint16 | |
29 | Width uint16 | |
30 | x uint16 | |
31 | y uint16 | |
32 | } | |
33 | ||
34 | // StdStreams returns the standard streams (stdin, stdout, stderr). | |
35 | func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { | |
36 | return os.Stdin, os.Stdout, os.Stderr | |
37 | } | |
38 | ||
39 | // GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. | |
40 | func GetFdInfo(in interface{}) (uintptr, bool) { | |
41 | var inFd uintptr | |
42 | var isTerminalIn bool | |
43 | if file, ok := in.(*os.File); ok { | |
44 | inFd = file.Fd() | |
45 | isTerminalIn = IsTerminal(inFd) | |
46 | } | |
47 | return inFd, isTerminalIn | |
48 | } | |
49 | ||
50 | // IsTerminal returns true if the given file descriptor is a terminal. | |
51 | func IsTerminal(fd uintptr) bool { | |
52 | var termios Termios | |
53 | return tcget(fd, &termios) == 0 | |
54 | } | |
55 | ||
56 | // RestoreTerminal restores the terminal connected to the given file descriptor | |
57 | // to a previous state. | |
58 | func RestoreTerminal(fd uintptr, state *State) error { | |
59 | if state == nil { | |
60 | return ErrInvalidState | |
61 | } | |
62 | if err := tcset(fd, &state.termios); err != 0 { | |
63 | return err | |
64 | } | |
65 | return nil | |
66 | } | |
67 | ||
68 | // SaveState saves the state of the terminal connected to the given file descriptor. | |
69 | func SaveState(fd uintptr) (*State, error) { | |
70 | var oldState State | |
71 | if err := tcget(fd, &oldState.termios); err != 0 { | |
72 | return nil, err | |
73 | } | |
74 | ||
75 | return &oldState, nil | |
76 | } | |
77 | ||
78 | // DisableEcho applies the specified state to the terminal connected to the file | |
79 | // descriptor, with echo disabled. | |
80 | func DisableEcho(fd uintptr, state *State) error { | |
81 | newState := state.termios | |
82 | newState.Lflag &^= unix.ECHO | |
83 | ||
84 | if err := tcset(fd, &newState); err != 0 { | |
85 | return err | |
86 | } | |
87 | handleInterrupt(fd, state) | |
88 | return nil | |
89 | } | |
90 | ||
91 | // SetRawTerminal puts the terminal connected to the given file descriptor into | |
92 | // raw mode and returns the previous state. On UNIX, this puts both the input | |
93 | // and output into raw mode. On Windows, it only puts the input into raw mode. | |
94 | func SetRawTerminal(fd uintptr) (*State, error) { | |
95 | oldState, err := MakeRaw(fd) | |
96 | if err != nil { | |
97 | return nil, err | |
98 | } | |
99 | handleInterrupt(fd, oldState) | |
100 | return oldState, err | |
101 | } | |
102 | ||
103 | // SetRawTerminalOutput puts the output of terminal connected to the given file | |
104 | // descriptor into raw mode. On UNIX, this does nothing and returns nil for the | |
105 | // state. On Windows, it disables LF -> CRLF translation. | |
106 | func SetRawTerminalOutput(fd uintptr) (*State, error) { | |
107 | return nil, nil | |
108 | } | |
109 | ||
110 | func handleInterrupt(fd uintptr, state *State) { | |
111 | sigchan := make(chan os.Signal, 1) | |
112 | signal.Notify(sigchan, os.Interrupt) | |
113 | go func() { | |
114 | for range sigchan { | |
115 | // quit cleanly and the new terminal item is on a new line | |
116 | fmt.Println() | |
117 | signal.Stop(sigchan) | |
118 | close(sigchan) | |
119 | RestoreTerminal(fd, state) | |
120 | os.Exit(1) | |
121 | } | |
122 | }() | |
123 | } |
0 | //+build solaris illumos | |
1 | ||
2 | package term | |
3 | ||
4 | import ( | |
5 | "golang.org/x/sys/unix" | |
6 | ) | |
7 | ||
8 | const ( | |
9 | getTermios = unix.TCGETS | |
10 | setTermios = unix.TCSETS | |
11 | ) | |
12 | ||
13 | // Termios is the Unix API for terminal I/O. | |
14 | type Termios unix.Termios | |
15 | ||
16 | // MakeRaw put the terminal connected to the given file descriptor into raw | |
17 | // mode and returns the previous state of the terminal so that it can be | |
18 | // restored. | |
19 | func MakeRaw(fd uintptr) (*State, error) { | |
20 | termios, err := unix.IoctlGetTermios(int(fd), getTermios) | |
21 | if err != nil { | |
22 | return nil, err | |
23 | } | |
24 | ||
25 | var oldState State | |
26 | oldState.termios = Termios(*termios) | |
27 | ||
28 | termios.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON) | |
29 | termios.Oflag &^= unix.OPOST | |
30 | termios.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN) | |
31 | termios.Cflag &^= (unix.CSIZE | unix.PARENB) | |
32 | termios.Cflag |= unix.CS8 | |
33 | termios.Cc[unix.VMIN] = 1 | |
34 | termios.Cc[unix.VTIME] = 0 | |
35 | ||
36 | if err := unix.IoctlSetTermios(int(fd), setTermios, termios); err != nil { | |
37 | return nil, err | |
38 | } | |
39 | return &oldState, nil | |
40 | } |