1//go:build darwin || netbsd || freebsd || openbsd || linux || dragonfly || solaris
2// +build darwin netbsd freebsd openbsd linux dragonfly solaris
3
4package termios
5
6import (
7 "syscall"
8
9 "golang.org/x/sys/unix"
10)
11
12// SetWinsize sets window size for an fd from a Winsize.
13func SetWinsize(fd int, w *unix.Winsize) error {
14 return unix.IoctlSetWinsize(fd, ioctlSetWinSize, w)
15}
16
17// GetWinsize gets window size for an fd.
18func GetWinsize(fd int) (*unix.Winsize, error) {
19 return unix.IoctlGetWinsize(fd, ioctlGetWinSize)
20}
21
22// GetTermios gets the termios of the given fd.
23func GetTermios(fd int) (*unix.Termios, error) {
24 return unix.IoctlGetTermios(fd, ioctlGets)
25}
26
27// SetTermios sets the given termios over the given fd's current termios.
28func SetTermios(
29 fd int,
30 ispeed uint32,
31 ospeed uint32,
32 cc map[CC]uint8,
33 iflag map[I]bool,
34 oflag map[O]bool,
35 cflag map[C]bool,
36 lflag map[L]bool,
37) error {
38 term, err := unix.IoctlGetTermios(fd, ioctlGets)
39 if err != nil {
40 return err
41 }
42 setSpeed(term, ispeed, ospeed)
43
44 for key, value := range cc {
45 call, ok := allCcOpts[key]
46 if !ok {
47 continue
48 }
49 term.Cc[call] = value
50 }
51
52 for key, value := range iflag {
53 mask, ok := allInputOpts[key]
54 if ok {
55 if value {
56 term.Iflag |= bit(mask)
57 } else {
58 term.Iflag &= ^bit(mask)
59 }
60 }
61 }
62 for key, value := range oflag {
63 mask, ok := allOutputOpts[key]
64 if ok {
65 if value {
66 term.Oflag |= bit(mask)
67 } else {
68 term.Oflag &= ^bit(mask)
69 }
70 }
71 }
72 for key, value := range cflag {
73 mask, ok := allControlOpts[key]
74 if ok {
75 if value {
76 term.Cflag |= bit(mask)
77 } else {
78 term.Cflag &= ^bit(mask)
79 }
80 }
81 }
82 for key, value := range lflag {
83 mask, ok := allLineOpts[key]
84 if ok {
85 if value {
86 term.Lflag |= bit(mask)
87 } else {
88 term.Lflag &= ^bit(mask)
89 }
90 }
91 }
92 return unix.IoctlSetTermios(fd, ioctlSets, term)
93}
94
95// CC is the termios cc field.
96//
97// It stores an array of special characters related to terminal I/O.
98type CC uint8
99
100// CC possible values.
101const (
102 INTR CC = iota
103 QUIT
104 ERASE
105 KILL
106 EOF
107 EOL
108 EOL2
109 START
110 STOP
111 SUSP
112 WERASE
113 RPRNT
114 LNEXT
115 DISCARD
116 STATUS
117 SWTCH
118 DSUSP
119 FLUSH
120)
121
122// https://www.man7.org/linux/man-pages/man3/termios.3.html
123var allCcOpts = map[CC]int{
124 INTR: syscall.VINTR,
125 QUIT: syscall.VQUIT,
126 ERASE: syscall.VERASE,
127 KILL: syscall.VQUIT,
128 EOF: syscall.VEOF,
129 EOL: syscall.VEOL,
130 EOL2: syscall.VEOL2,
131 START: syscall.VSTART,
132 STOP: syscall.VSTOP,
133 SUSP: syscall.VSUSP,
134 WERASE: syscall.VWERASE,
135 RPRNT: syscall.VREPRINT,
136 LNEXT: syscall.VLNEXT,
137 DISCARD: syscall.VDISCARD,
138
139 // XXX: these syscalls don't exist for any OS
140 // FLUSH: syscall.VFLUSH,
141}
142
143// Input Controls
144type I uint8
145
146// Input possible values.
147const (
148 IGNPAR I = iota
149 PARMRK
150 INPCK
151 ISTRIP
152 INLCR
153 IGNCR
154 ICRNL
155 IXON
156 IXANY
157 IXOFF
158 IMAXBEL
159 IUCLC
160)
161
162var allInputOpts = map[I]uint32{
163 IGNPAR: syscall.IGNPAR,
164 PARMRK: syscall.PARMRK,
165 INPCK: syscall.INPCK,
166 ISTRIP: syscall.ISTRIP,
167 INLCR: syscall.INLCR,
168 IGNCR: syscall.IGNCR,
169 ICRNL: syscall.ICRNL,
170 IXON: syscall.IXON,
171 IXANY: syscall.IXANY,
172 IXOFF: syscall.IXOFF,
173 IMAXBEL: syscall.IMAXBEL,
174}
175
176// Output Controls
177type O uint8
178
179// Output possible values.
180const (
181 OPOST O = iota
182 ONLCR
183 OCRNL
184 ONOCR
185 ONLRET
186 OLCUC
187)
188
189var allOutputOpts = map[O]uint32{
190 OPOST: syscall.OPOST,
191 ONLCR: syscall.ONLCR,
192 OCRNL: syscall.OCRNL,
193 ONOCR: syscall.ONOCR,
194 ONLRET: syscall.ONLRET,
195}
196
197// Control
198type C uint8
199
200// Control possible values.
201const (
202 CS7 C = iota
203 CS8
204 PARENB
205 PARODD
206)
207
208var allControlOpts = map[C]uint32{
209 CS7: syscall.CS7,
210 CS8: syscall.CS8,
211 PARENB: syscall.PARENB,
212 PARODD: syscall.PARODD,
213}
214
215// Line Controls.
216type L uint8
217
218// Line possible values.
219const (
220 ISIG L = iota
221 ICANON
222 ECHO
223 ECHOE
224 ECHOK
225 ECHONL
226 NOFLSH
227 TOSTOP
228 IEXTEN
229 ECHOCTL
230 ECHOKE
231 PENDIN
232 IUTF8
233 XCASE
234)
235
236var allLineOpts = map[L]uint32{
237 ISIG: syscall.ISIG,
238 ICANON: syscall.ICANON,
239 ECHO: syscall.ECHO,
240 ECHOE: syscall.ECHOE,
241 ECHOK: syscall.ECHOK,
242 ECHONL: syscall.ECHONL,
243 NOFLSH: syscall.NOFLSH,
244 TOSTOP: syscall.TOSTOP,
245 IEXTEN: syscall.IEXTEN,
246 ECHOCTL: syscall.ECHOCTL,
247 ECHOKE: syscall.ECHOKE,
248 PENDIN: syscall.PENDIN,
249}