tty.c revision 1.51 1 1.51 christos /* $NetBSD: tty.c,v 1.51 2016/02/14 14:49:34 christos Exp $ */
2 1.2 lukem
3 1.1 cgd /*-
4 1.1 cgd * Copyright (c) 1992, 1993
5 1.1 cgd * The Regents of the University of California. All rights reserved.
6 1.1 cgd *
7 1.1 cgd * This code is derived from software contributed to Berkeley by
8 1.1 cgd * Christos Zoulas of Cornell University.
9 1.1 cgd *
10 1.1 cgd * Redistribution and use in source and binary forms, with or without
11 1.1 cgd * modification, are permitted provided that the following conditions
12 1.1 cgd * are met:
13 1.1 cgd * 1. Redistributions of source code must retain the above copyright
14 1.1 cgd * notice, this list of conditions and the following disclaimer.
15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 cgd * notice, this list of conditions and the following disclaimer in the
17 1.1 cgd * documentation and/or other materials provided with the distribution.
18 1.18 agc * 3. Neither the name of the University nor the names of its contributors
19 1.1 cgd * may be used to endorse or promote products derived from this software
20 1.1 cgd * without specific prior written permission.
21 1.1 cgd *
22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 cgd * SUCH DAMAGE.
33 1.1 cgd */
34 1.1 cgd
35 1.16 christos #include "config.h"
36 1.1 cgd #if !defined(lint) && !defined(SCCSID)
37 1.2 lukem #if 0
38 1.1 cgd static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
39 1.2 lukem #else
40 1.51 christos __RCSID("$NetBSD: tty.c,v 1.51 2016/02/14 14:49:34 christos Exp $");
41 1.2 lukem #endif
42 1.1 cgd #endif /* not lint && not SCCSID */
43 1.1 cgd
44 1.11 simonb /*
45 1.1 cgd * tty.c: tty interface stuff
46 1.1 cgd */
47 1.19 christos #include <assert.h>
48 1.28 sketch #include <errno.h>
49 1.34 christos #include <unistd.h> /* for isatty */
50 1.33 christos #include <strings.h> /* for ffs */
51 1.46 christos #include <stdlib.h> /* for abort */
52 1.32 christos #include "el.h"
53 1.1 cgd #include "tty.h"
54 1.1 cgd
55 1.1 cgd typedef struct ttymodes_t {
56 1.14 jdolecek const char *m_name;
57 1.23 lukem unsigned int m_value;
58 1.13 lukem int m_type;
59 1.13 lukem } ttymodes_t;
60 1.1 cgd
61 1.1 cgd typedef struct ttymap_t {
62 1.51 christos wint_t nch, och; /* Internal and termio rep of chars */
63 1.13 lukem el_action_t bind[3]; /* emacs, vi, and vi-cmd */
64 1.16 christos } ttymap_t;
65 1.1 cgd
66 1.1 cgd
67 1.14 jdolecek private const ttyperm_t ttyperm = {
68 1.13 lukem {
69 1.13 lukem {"iflag:", ICRNL, (INLCR | IGNCR)},
70 1.13 lukem {"oflag:", (OPOST | ONLCR), ONLRET},
71 1.13 lukem {"cflag:", 0, 0},
72 1.13 lukem {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN),
73 1.13 lukem (NOFLSH | ECHONL | EXTPROC | FLUSHO)},
74 1.13 lukem {"chars:", 0, 0},
75 1.13 lukem },
76 1.13 lukem {
77 1.13 lukem {"iflag:", (INLCR | ICRNL), IGNCR},
78 1.13 lukem {"oflag:", (OPOST | ONLCR), ONLRET},
79 1.13 lukem {"cflag:", 0, 0},
80 1.13 lukem {"lflag:", ISIG,
81 1.13 lukem (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)},
82 1.13 lukem {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) |
83 1.13 lukem C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) |
84 1.13 lukem C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0}
85 1.13 lukem },
86 1.13 lukem {
87 1.13 lukem {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL},
88 1.13 lukem {"oflag:", 0, 0},
89 1.13 lukem {"cflag:", 0, 0},
90 1.13 lukem {"lflag:", 0, ISIG | IEXTEN},
91 1.13 lukem {"chars:", 0, 0},
92 1.13 lukem }
93 1.1 cgd };
94 1.1 cgd
95 1.14 jdolecek private const ttychar_t ttychar = {
96 1.13 lukem {
97 1.13 lukem CINTR, CQUIT, CERASE, CKILL,
98 1.13 lukem CEOF, CEOL, CEOL2, CSWTCH,
99 1.13 lukem CDSWTCH, CERASE2, CSTART, CSTOP,
100 1.13 lukem CWERASE, CSUSP, CDSUSP, CREPRINT,
101 1.13 lukem CDISCARD, CLNEXT, CSTATUS, CPAGE,
102 1.13 lukem CPGOFF, CKILL2, CBRK, CMIN,
103 1.13 lukem CTIME
104 1.13 lukem },
105 1.13 lukem {
106 1.13 lukem CINTR, CQUIT, CERASE, CKILL,
107 1.13 lukem _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
108 1.13 lukem _POSIX_VDISABLE, CERASE2, CSTART, CSTOP,
109 1.13 lukem _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE,
110 1.13 lukem CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE,
111 1.13 lukem _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1,
112 1.13 lukem 0
113 1.13 lukem },
114 1.13 lukem {
115 1.13 lukem 0, 0, 0, 0,
116 1.13 lukem 0, 0, 0, 0,
117 1.13 lukem 0, 0, 0, 0,
118 1.13 lukem 0, 0, 0, 0,
119 1.13 lukem 0, 0, 0, 0,
120 1.13 lukem 0, 0, 0, 0,
121 1.13 lukem 0
122 1.13 lukem }
123 1.1 cgd };
124 1.1 cgd
125 1.14 jdolecek private const ttymap_t tty_map[] = {
126 1.1 cgd #ifdef VERASE
127 1.13 lukem {C_ERASE, VERASE,
128 1.21 mycroft {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
129 1.1 cgd #endif /* VERASE */
130 1.1 cgd #ifdef VERASE2
131 1.13 lukem {C_ERASE2, VERASE2,
132 1.21 mycroft {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
133 1.1 cgd #endif /* VERASE2 */
134 1.1 cgd #ifdef VKILL
135 1.13 lukem {C_KILL, VKILL,
136 1.13 lukem {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
137 1.1 cgd #endif /* VKILL */
138 1.1 cgd #ifdef VKILL2
139 1.13 lukem {C_KILL2, VKILL2,
140 1.13 lukem {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}},
141 1.1 cgd #endif /* VKILL2 */
142 1.1 cgd #ifdef VEOF
143 1.13 lukem {C_EOF, VEOF,
144 1.13 lukem {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}},
145 1.1 cgd #endif /* VEOF */
146 1.1 cgd #ifdef VWERASE
147 1.13 lukem {C_WERASE, VWERASE,
148 1.13 lukem {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}},
149 1.1 cgd #endif /* VWERASE */
150 1.1 cgd #ifdef VREPRINT
151 1.13 lukem {C_REPRINT, VREPRINT,
152 1.13 lukem {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}},
153 1.1 cgd #endif /* VREPRINT */
154 1.1 cgd #ifdef VLNEXT
155 1.13 lukem {C_LNEXT, VLNEXT,
156 1.13 lukem {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}},
157 1.1 cgd #endif /* VLNEXT */
158 1.51 christos {(wint_t)-1, (wint_t)-1,
159 1.13 lukem {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
160 1.13 lukem };
161 1.1 cgd
162 1.14 jdolecek private const ttymodes_t ttymodes[] = {
163 1.13 lukem #ifdef IGNBRK
164 1.13 lukem {"ignbrk", IGNBRK, MD_INP},
165 1.13 lukem #endif /* IGNBRK */
166 1.13 lukem #ifdef BRKINT
167 1.13 lukem {"brkint", BRKINT, MD_INP},
168 1.13 lukem #endif /* BRKINT */
169 1.13 lukem #ifdef IGNPAR
170 1.13 lukem {"ignpar", IGNPAR, MD_INP},
171 1.13 lukem #endif /* IGNPAR */
172 1.13 lukem #ifdef PARMRK
173 1.13 lukem {"parmrk", PARMRK, MD_INP},
174 1.13 lukem #endif /* PARMRK */
175 1.13 lukem #ifdef INPCK
176 1.13 lukem {"inpck", INPCK, MD_INP},
177 1.13 lukem #endif /* INPCK */
178 1.13 lukem #ifdef ISTRIP
179 1.13 lukem {"istrip", ISTRIP, MD_INP},
180 1.13 lukem #endif /* ISTRIP */
181 1.13 lukem #ifdef INLCR
182 1.13 lukem {"inlcr", INLCR, MD_INP},
183 1.13 lukem #endif /* INLCR */
184 1.13 lukem #ifdef IGNCR
185 1.13 lukem {"igncr", IGNCR, MD_INP},
186 1.13 lukem #endif /* IGNCR */
187 1.13 lukem #ifdef ICRNL
188 1.13 lukem {"icrnl", ICRNL, MD_INP},
189 1.13 lukem #endif /* ICRNL */
190 1.13 lukem #ifdef IUCLC
191 1.13 lukem {"iuclc", IUCLC, MD_INP},
192 1.13 lukem #endif /* IUCLC */
193 1.13 lukem #ifdef IXON
194 1.13 lukem {"ixon", IXON, MD_INP},
195 1.13 lukem #endif /* IXON */
196 1.13 lukem #ifdef IXANY
197 1.13 lukem {"ixany", IXANY, MD_INP},
198 1.13 lukem #endif /* IXANY */
199 1.13 lukem #ifdef IXOFF
200 1.13 lukem {"ixoff", IXOFF, MD_INP},
201 1.13 lukem #endif /* IXOFF */
202 1.13 lukem #ifdef IMAXBEL
203 1.13 lukem {"imaxbel", IMAXBEL, MD_INP},
204 1.13 lukem #endif /* IMAXBEL */
205 1.13 lukem
206 1.13 lukem #ifdef OPOST
207 1.13 lukem {"opost", OPOST, MD_OUT},
208 1.13 lukem #endif /* OPOST */
209 1.13 lukem #ifdef OLCUC
210 1.13 lukem {"olcuc", OLCUC, MD_OUT},
211 1.13 lukem #endif /* OLCUC */
212 1.13 lukem #ifdef ONLCR
213 1.13 lukem {"onlcr", ONLCR, MD_OUT},
214 1.13 lukem #endif /* ONLCR */
215 1.13 lukem #ifdef OCRNL
216 1.13 lukem {"ocrnl", OCRNL, MD_OUT},
217 1.13 lukem #endif /* OCRNL */
218 1.13 lukem #ifdef ONOCR
219 1.13 lukem {"onocr", ONOCR, MD_OUT},
220 1.13 lukem #endif /* ONOCR */
221 1.13 lukem #ifdef ONOEOT
222 1.13 lukem {"onoeot", ONOEOT, MD_OUT},
223 1.13 lukem #endif /* ONOEOT */
224 1.13 lukem #ifdef ONLRET
225 1.13 lukem {"onlret", ONLRET, MD_OUT},
226 1.13 lukem #endif /* ONLRET */
227 1.13 lukem #ifdef OFILL
228 1.13 lukem {"ofill", OFILL, MD_OUT},
229 1.13 lukem #endif /* OFILL */
230 1.13 lukem #ifdef OFDEL
231 1.13 lukem {"ofdel", OFDEL, MD_OUT},
232 1.13 lukem #endif /* OFDEL */
233 1.13 lukem #ifdef NLDLY
234 1.13 lukem {"nldly", NLDLY, MD_OUT},
235 1.13 lukem #endif /* NLDLY */
236 1.13 lukem #ifdef CRDLY
237 1.13 lukem {"crdly", CRDLY, MD_OUT},
238 1.13 lukem #endif /* CRDLY */
239 1.13 lukem #ifdef TABDLY
240 1.13 lukem {"tabdly", TABDLY, MD_OUT},
241 1.13 lukem #endif /* TABDLY */
242 1.13 lukem #ifdef XTABS
243 1.13 lukem {"xtabs", XTABS, MD_OUT},
244 1.13 lukem #endif /* XTABS */
245 1.13 lukem #ifdef BSDLY
246 1.13 lukem {"bsdly", BSDLY, MD_OUT},
247 1.13 lukem #endif /* BSDLY */
248 1.13 lukem #ifdef VTDLY
249 1.13 lukem {"vtdly", VTDLY, MD_OUT},
250 1.13 lukem #endif /* VTDLY */
251 1.13 lukem #ifdef FFDLY
252 1.13 lukem {"ffdly", FFDLY, MD_OUT},
253 1.13 lukem #endif /* FFDLY */
254 1.13 lukem #ifdef PAGEOUT
255 1.13 lukem {"pageout", PAGEOUT, MD_OUT},
256 1.13 lukem #endif /* PAGEOUT */
257 1.13 lukem #ifdef WRAP
258 1.13 lukem {"wrap", WRAP, MD_OUT},
259 1.13 lukem #endif /* WRAP */
260 1.13 lukem
261 1.13 lukem #ifdef CIGNORE
262 1.13 lukem {"cignore", CIGNORE, MD_CTL},
263 1.13 lukem #endif /* CBAUD */
264 1.13 lukem #ifdef CBAUD
265 1.13 lukem {"cbaud", CBAUD, MD_CTL},
266 1.13 lukem #endif /* CBAUD */
267 1.13 lukem #ifdef CSTOPB
268 1.13 lukem {"cstopb", CSTOPB, MD_CTL},
269 1.13 lukem #endif /* CSTOPB */
270 1.13 lukem #ifdef CREAD
271 1.13 lukem {"cread", CREAD, MD_CTL},
272 1.13 lukem #endif /* CREAD */
273 1.13 lukem #ifdef PARENB
274 1.13 lukem {"parenb", PARENB, MD_CTL},
275 1.13 lukem #endif /* PARENB */
276 1.13 lukem #ifdef PARODD
277 1.13 lukem {"parodd", PARODD, MD_CTL},
278 1.13 lukem #endif /* PARODD */
279 1.13 lukem #ifdef HUPCL
280 1.13 lukem {"hupcl", HUPCL, MD_CTL},
281 1.13 lukem #endif /* HUPCL */
282 1.13 lukem #ifdef CLOCAL
283 1.13 lukem {"clocal", CLOCAL, MD_CTL},
284 1.13 lukem #endif /* CLOCAL */
285 1.13 lukem #ifdef LOBLK
286 1.13 lukem {"loblk", LOBLK, MD_CTL},
287 1.13 lukem #endif /* LOBLK */
288 1.13 lukem #ifdef CIBAUD
289 1.13 lukem {"cibaud", CIBAUD, MD_CTL},
290 1.13 lukem #endif /* CIBAUD */
291 1.13 lukem #ifdef CRTSCTS
292 1.13 lukem #ifdef CCTS_OFLOW
293 1.13 lukem {"ccts_oflow", CCTS_OFLOW, MD_CTL},
294 1.13 lukem #else
295 1.13 lukem {"crtscts", CRTSCTS, MD_CTL},
296 1.13 lukem #endif /* CCTS_OFLOW */
297 1.13 lukem #endif /* CRTSCTS */
298 1.13 lukem #ifdef CRTS_IFLOW
299 1.13 lukem {"crts_iflow", CRTS_IFLOW, MD_CTL},
300 1.13 lukem #endif /* CRTS_IFLOW */
301 1.13 lukem #ifdef CDTRCTS
302 1.13 lukem {"cdtrcts", CDTRCTS, MD_CTL},
303 1.13 lukem #endif /* CDTRCTS */
304 1.13 lukem #ifdef MDMBUF
305 1.13 lukem {"mdmbuf", MDMBUF, MD_CTL},
306 1.13 lukem #endif /* MDMBUF */
307 1.13 lukem #ifdef RCV1EN
308 1.13 lukem {"rcv1en", RCV1EN, MD_CTL},
309 1.13 lukem #endif /* RCV1EN */
310 1.13 lukem #ifdef XMT1EN
311 1.13 lukem {"xmt1en", XMT1EN, MD_CTL},
312 1.13 lukem #endif /* XMT1EN */
313 1.13 lukem
314 1.13 lukem #ifdef ISIG
315 1.13 lukem {"isig", ISIG, MD_LIN},
316 1.13 lukem #endif /* ISIG */
317 1.13 lukem #ifdef ICANON
318 1.13 lukem {"icanon", ICANON, MD_LIN},
319 1.13 lukem #endif /* ICANON */
320 1.13 lukem #ifdef XCASE
321 1.13 lukem {"xcase", XCASE, MD_LIN},
322 1.13 lukem #endif /* XCASE */
323 1.13 lukem #ifdef ECHO
324 1.13 lukem {"echo", ECHO, MD_LIN},
325 1.13 lukem #endif /* ECHO */
326 1.13 lukem #ifdef ECHOE
327 1.13 lukem {"echoe", ECHOE, MD_LIN},
328 1.13 lukem #endif /* ECHOE */
329 1.13 lukem #ifdef ECHOK
330 1.13 lukem {"echok", ECHOK, MD_LIN},
331 1.13 lukem #endif /* ECHOK */
332 1.13 lukem #ifdef ECHONL
333 1.13 lukem {"echonl", ECHONL, MD_LIN},
334 1.13 lukem #endif /* ECHONL */
335 1.13 lukem #ifdef NOFLSH
336 1.13 lukem {"noflsh", NOFLSH, MD_LIN},
337 1.13 lukem #endif /* NOFLSH */
338 1.13 lukem #ifdef TOSTOP
339 1.13 lukem {"tostop", TOSTOP, MD_LIN},
340 1.13 lukem #endif /* TOSTOP */
341 1.13 lukem #ifdef ECHOCTL
342 1.13 lukem {"echoctl", ECHOCTL, MD_LIN},
343 1.13 lukem #endif /* ECHOCTL */
344 1.13 lukem #ifdef ECHOPRT
345 1.13 lukem {"echoprt", ECHOPRT, MD_LIN},
346 1.13 lukem #endif /* ECHOPRT */
347 1.13 lukem #ifdef ECHOKE
348 1.13 lukem {"echoke", ECHOKE, MD_LIN},
349 1.13 lukem #endif /* ECHOKE */
350 1.13 lukem #ifdef DEFECHO
351 1.13 lukem {"defecho", DEFECHO, MD_LIN},
352 1.13 lukem #endif /* DEFECHO */
353 1.13 lukem #ifdef FLUSHO
354 1.13 lukem {"flusho", FLUSHO, MD_LIN},
355 1.13 lukem #endif /* FLUSHO */
356 1.13 lukem #ifdef PENDIN
357 1.13 lukem {"pendin", PENDIN, MD_LIN},
358 1.13 lukem #endif /* PENDIN */
359 1.13 lukem #ifdef IEXTEN
360 1.13 lukem {"iexten", IEXTEN, MD_LIN},
361 1.13 lukem #endif /* IEXTEN */
362 1.13 lukem #ifdef NOKERNINFO
363 1.13 lukem {"nokerninfo", NOKERNINFO, MD_LIN},
364 1.13 lukem #endif /* NOKERNINFO */
365 1.13 lukem #ifdef ALTWERASE
366 1.13 lukem {"altwerase", ALTWERASE, MD_LIN},
367 1.13 lukem #endif /* ALTWERASE */
368 1.13 lukem #ifdef EXTPROC
369 1.13 lukem {"extproc", EXTPROC, MD_LIN},
370 1.13 lukem #endif /* EXTPROC */
371 1.13 lukem
372 1.13 lukem #if defined(VINTR)
373 1.13 lukem {"intr", C_SH(C_INTR), MD_CHAR},
374 1.13 lukem #endif /* VINTR */
375 1.13 lukem #if defined(VQUIT)
376 1.13 lukem {"quit", C_SH(C_QUIT), MD_CHAR},
377 1.13 lukem #endif /* VQUIT */
378 1.13 lukem #if defined(VERASE)
379 1.13 lukem {"erase", C_SH(C_ERASE), MD_CHAR},
380 1.13 lukem #endif /* VERASE */
381 1.13 lukem #if defined(VKILL)
382 1.13 lukem {"kill", C_SH(C_KILL), MD_CHAR},
383 1.13 lukem #endif /* VKILL */
384 1.13 lukem #if defined(VEOF)
385 1.13 lukem {"eof", C_SH(C_EOF), MD_CHAR},
386 1.13 lukem #endif /* VEOF */
387 1.13 lukem #if defined(VEOL)
388 1.13 lukem {"eol", C_SH(C_EOL), MD_CHAR},
389 1.13 lukem #endif /* VEOL */
390 1.13 lukem #if defined(VEOL2)
391 1.13 lukem {"eol2", C_SH(C_EOL2), MD_CHAR},
392 1.13 lukem #endif /* VEOL2 */
393 1.13 lukem #if defined(VSWTCH)
394 1.13 lukem {"swtch", C_SH(C_SWTCH), MD_CHAR},
395 1.13 lukem #endif /* VSWTCH */
396 1.13 lukem #if defined(VDSWTCH)
397 1.13 lukem {"dswtch", C_SH(C_DSWTCH), MD_CHAR},
398 1.13 lukem #endif /* VDSWTCH */
399 1.13 lukem #if defined(VERASE2)
400 1.13 lukem {"erase2", C_SH(C_ERASE2), MD_CHAR},
401 1.13 lukem #endif /* VERASE2 */
402 1.13 lukem #if defined(VSTART)
403 1.13 lukem {"start", C_SH(C_START), MD_CHAR},
404 1.13 lukem #endif /* VSTART */
405 1.13 lukem #if defined(VSTOP)
406 1.13 lukem {"stop", C_SH(C_STOP), MD_CHAR},
407 1.13 lukem #endif /* VSTOP */
408 1.13 lukem #if defined(VWERASE)
409 1.13 lukem {"werase", C_SH(C_WERASE), MD_CHAR},
410 1.13 lukem #endif /* VWERASE */
411 1.13 lukem #if defined(VSUSP)
412 1.13 lukem {"susp", C_SH(C_SUSP), MD_CHAR},
413 1.13 lukem #endif /* VSUSP */
414 1.13 lukem #if defined(VDSUSP)
415 1.13 lukem {"dsusp", C_SH(C_DSUSP), MD_CHAR},
416 1.13 lukem #endif /* VDSUSP */
417 1.13 lukem #if defined(VREPRINT)
418 1.13 lukem {"reprint", C_SH(C_REPRINT), MD_CHAR},
419 1.13 lukem #endif /* VREPRINT */
420 1.13 lukem #if defined(VDISCARD)
421 1.13 lukem {"discard", C_SH(C_DISCARD), MD_CHAR},
422 1.13 lukem #endif /* VDISCARD */
423 1.13 lukem #if defined(VLNEXT)
424 1.13 lukem {"lnext", C_SH(C_LNEXT), MD_CHAR},
425 1.13 lukem #endif /* VLNEXT */
426 1.13 lukem #if defined(VSTATUS)
427 1.13 lukem {"status", C_SH(C_STATUS), MD_CHAR},
428 1.13 lukem #endif /* VSTATUS */
429 1.13 lukem #if defined(VPAGE)
430 1.13 lukem {"page", C_SH(C_PAGE), MD_CHAR},
431 1.13 lukem #endif /* VPAGE */
432 1.13 lukem #if defined(VPGOFF)
433 1.13 lukem {"pgoff", C_SH(C_PGOFF), MD_CHAR},
434 1.13 lukem #endif /* VPGOFF */
435 1.13 lukem #if defined(VKILL2)
436 1.13 lukem {"kill2", C_SH(C_KILL2), MD_CHAR},
437 1.13 lukem #endif /* VKILL2 */
438 1.13 lukem #if defined(VBRK)
439 1.13 lukem {"brk", C_SH(C_BRK), MD_CHAR},
440 1.13 lukem #endif /* VBRK */
441 1.13 lukem #if defined(VMIN)
442 1.13 lukem {"min", C_SH(C_MIN), MD_CHAR},
443 1.13 lukem #endif /* VMIN */
444 1.13 lukem #if defined(VTIME)
445 1.13 lukem {"time", C_SH(C_TIME), MD_CHAR},
446 1.13 lukem #endif /* VTIME */
447 1.13 lukem {NULL, 0, -1},
448 1.1 cgd };
449 1.1 cgd
450 1.1 cgd
451 1.1 cgd
452 1.13 lukem #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1)
453 1.13 lukem #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
454 1.13 lukem #define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
455 1.13 lukem
456 1.26 christos private int tty_getty(EditLine *, struct termios *);
457 1.26 christos private int tty_setty(EditLine *, int, const struct termios *);
458 1.19 christos private int tty__getcharindex(int);
459 1.13 lukem private void tty__getchar(struct termios *, unsigned char *);
460 1.13 lukem private void tty__setchar(struct termios *, unsigned char *);
461 1.13 lukem private speed_t tty__getspeed(struct termios *);
462 1.13 lukem private int tty_setup(EditLine *);
463 1.43 christos private void tty_setup_flags(EditLine *, struct termios *, int);
464 1.1 cgd
465 1.13 lukem #define t_qu t_ts
466 1.1 cgd
467 1.26 christos /* tty_getty():
468 1.26 christos * Wrapper for tcgetattr to handle EINTR
469 1.26 christos */
470 1.26 christos private int
471 1.26 christos tty_getty(EditLine *el, struct termios *t)
472 1.26 christos {
473 1.26 christos int rv;
474 1.26 christos while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR)
475 1.26 christos continue;
476 1.26 christos return rv;
477 1.26 christos }
478 1.26 christos
479 1.26 christos /* tty_setty():
480 1.26 christos * Wrapper for tcsetattr to handle EINTR
481 1.26 christos */
482 1.26 christos private int
483 1.26 christos tty_setty(EditLine *el, int action, const struct termios *t)
484 1.26 christos {
485 1.26 christos int rv;
486 1.26 christos while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR)
487 1.26 christos continue;
488 1.26 christos return rv;
489 1.26 christos }
490 1.1 cgd
491 1.1 cgd /* tty_setup():
492 1.1 cgd * Get the tty parameters and initialize the editing state
493 1.1 cgd */
494 1.11 simonb private int
495 1.13 lukem tty_setup(EditLine *el)
496 1.1 cgd {
497 1.13 lukem int rst = 1;
498 1.12 sommerfe
499 1.13 lukem if (el->el_flags & EDIT_DISABLED)
500 1.38 christos return 0;
501 1.13 lukem
502 1.34 christos if (!isatty(el->el_outfd)) {
503 1.34 christos #ifdef DEBUG_TTY
504 1.42 christos (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__,
505 1.42 christos strerror(errno));
506 1.34 christos #endif /* DEBUG_TTY */
507 1.38 christos return -1;
508 1.34 christos }
509 1.42 christos if (tty_getty(el, &el->el_tty.t_or) == -1) {
510 1.1 cgd #ifdef DEBUG_TTY
511 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
512 1.42 christos strerror(errno));
513 1.1 cgd #endif /* DEBUG_TTY */
514 1.38 christos return -1;
515 1.13 lukem }
516 1.42 christos el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or;
517 1.13 lukem
518 1.13 lukem el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
519 1.13 lukem el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
520 1.13 lukem el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
521 1.13 lukem
522 1.43 christos tty_setup_flags(el, &el->el_tty.t_ex, EX_IO);
523 1.13 lukem
524 1.13 lukem /*
525 1.13 lukem * Reset the tty chars to reasonable defaults
526 1.13 lukem * If they are disabled, then enable them.
527 1.13 lukem */
528 1.13 lukem if (rst) {
529 1.13 lukem if (tty__cooked_mode(&el->el_tty.t_ts)) {
530 1.13 lukem tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
531 1.13 lukem /*
532 1.13 lukem * Don't affect CMIN and CTIME for the editor mode
533 1.13 lukem */
534 1.13 lukem for (rst = 0; rst < C_NCC - 2; rst++)
535 1.13 lukem if (el->el_tty.t_c[TS_IO][rst] !=
536 1.13 lukem el->el_tty.t_vdisable
537 1.13 lukem && el->el_tty.t_c[ED_IO][rst] !=
538 1.13 lukem el->el_tty.t_vdisable)
539 1.13 lukem el->el_tty.t_c[ED_IO][rst] =
540 1.13 lukem el->el_tty.t_c[TS_IO][rst];
541 1.13 lukem for (rst = 0; rst < C_NCC; rst++)
542 1.13 lukem if (el->el_tty.t_c[TS_IO][rst] !=
543 1.13 lukem el->el_tty.t_vdisable)
544 1.13 lukem el->el_tty.t_c[EX_IO][rst] =
545 1.13 lukem el->el_tty.t_c[TS_IO][rst];
546 1.13 lukem }
547 1.13 lukem tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
548 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
549 1.1 cgd #ifdef DEBUG_TTY
550 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
551 1.42 christos __func__, strerror(errno));
552 1.1 cgd #endif /* DEBUG_TTY */
553 1.38 christos return -1;
554 1.13 lukem }
555 1.25 christos }
556 1.13 lukem
557 1.43 christos tty_setup_flags(el, &el->el_tty.t_ed, ED_IO);
558 1.13 lukem
559 1.13 lukem tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
560 1.13 lukem tty_bind_char(el, 1);
561 1.38 christos return 0;
562 1.1 cgd }
563 1.1 cgd
564 1.1 cgd protected int
565 1.13 lukem tty_init(EditLine *el)
566 1.1 cgd {
567 1.13 lukem
568 1.13 lukem el->el_tty.t_mode = EX_IO;
569 1.13 lukem el->el_tty.t_vdisable = _POSIX_VDISABLE;
570 1.13 lukem (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
571 1.13 lukem (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
572 1.38 christos return tty_setup(el);
573 1.13 lukem }
574 1.1 cgd
575 1.1 cgd
576 1.1 cgd /* tty_end():
577 1.1 cgd * Restore the tty to its original settings
578 1.1 cgd */
579 1.1 cgd protected void
580 1.1 cgd /*ARGSUSED*/
581 1.42 christos tty_end(EditLine *el)
582 1.1 cgd {
583 1.48 christos if (el->el_flags & EDIT_DISABLED)
584 1.49 gson return;
585 1.48 christos
586 1.42 christos if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
587 1.42 christos #ifdef DEBUG_TTY
588 1.42 christos (void) fprintf(el->el_errfile,
589 1.42 christos "%s: tty_setty: %s\n", __func__, strerror(errno));
590 1.42 christos #endif /* DEBUG_TTY */
591 1.42 christos }
592 1.1 cgd }
593 1.1 cgd
594 1.1 cgd
595 1.1 cgd /* tty__getspeed():
596 1.1 cgd * Get the tty speed
597 1.1 cgd */
598 1.1 cgd private speed_t
599 1.13 lukem tty__getspeed(struct termios *td)
600 1.1 cgd {
601 1.13 lukem speed_t spd;
602 1.1 cgd
603 1.13 lukem if ((spd = cfgetispeed(td)) == 0)
604 1.13 lukem spd = cfgetospeed(td);
605 1.38 christos return spd;
606 1.13 lukem }
607 1.1 cgd
608 1.19 christos /* tty__getspeed():
609 1.19 christos * Return the index of the asked char in the c_cc array
610 1.19 christos */
611 1.19 christos private int
612 1.19 christos tty__getcharindex(int i)
613 1.19 christos {
614 1.19 christos switch (i) {
615 1.19 christos #ifdef VINTR
616 1.19 christos case C_INTR:
617 1.19 christos return VINTR;
618 1.19 christos #endif /* VINTR */
619 1.19 christos #ifdef VQUIT
620 1.19 christos case C_QUIT:
621 1.19 christos return VQUIT;
622 1.19 christos #endif /* VQUIT */
623 1.19 christos #ifdef VERASE
624 1.19 christos case C_ERASE:
625 1.19 christos return VERASE;
626 1.19 christos #endif /* VERASE */
627 1.19 christos #ifdef VKILL
628 1.19 christos case C_KILL:
629 1.19 christos return VKILL;
630 1.19 christos #endif /* VKILL */
631 1.19 christos #ifdef VEOF
632 1.19 christos case C_EOF:
633 1.19 christos return VEOF;
634 1.19 christos #endif /* VEOF */
635 1.19 christos #ifdef VEOL
636 1.19 christos case C_EOL:
637 1.19 christos return VEOL;
638 1.19 christos #endif /* VEOL */
639 1.19 christos #ifdef VEOL2
640 1.19 christos case C_EOL2:
641 1.19 christos return VEOL2;
642 1.19 christos #endif /* VEOL2 */
643 1.19 christos #ifdef VSWTCH
644 1.19 christos case C_SWTCH:
645 1.19 christos return VSWTCH;
646 1.19 christos #endif /* VSWTCH */
647 1.19 christos #ifdef VDSWTCH
648 1.19 christos case C_DSWTCH:
649 1.19 christos return VDSWTCH;
650 1.19 christos #endif /* VDSWTCH */
651 1.19 christos #ifdef VERASE2
652 1.19 christos case C_ERASE2:
653 1.19 christos return VERASE2;
654 1.19 christos #endif /* VERASE2 */
655 1.19 christos #ifdef VSTART
656 1.19 christos case C_START:
657 1.19 christos return VSTART;
658 1.19 christos #endif /* VSTART */
659 1.19 christos #ifdef VSTOP
660 1.19 christos case C_STOP:
661 1.19 christos return VSTOP;
662 1.19 christos #endif /* VSTOP */
663 1.19 christos #ifdef VWERASE
664 1.19 christos case C_WERASE:
665 1.19 christos return VWERASE;
666 1.19 christos #endif /* VWERASE */
667 1.19 christos #ifdef VSUSP
668 1.19 christos case C_SUSP:
669 1.19 christos return VSUSP;
670 1.19 christos #endif /* VSUSP */
671 1.19 christos #ifdef VDSUSP
672 1.19 christos case C_DSUSP:
673 1.19 christos return VDSUSP;
674 1.19 christos #endif /* VDSUSP */
675 1.19 christos #ifdef VREPRINT
676 1.19 christos case C_REPRINT:
677 1.19 christos return VREPRINT;
678 1.19 christos #endif /* VREPRINT */
679 1.19 christos #ifdef VDISCARD
680 1.19 christos case C_DISCARD:
681 1.19 christos return VDISCARD;
682 1.19 christos #endif /* VDISCARD */
683 1.19 christos #ifdef VLNEXT
684 1.19 christos case C_LNEXT:
685 1.19 christos return VLNEXT;
686 1.19 christos #endif /* VLNEXT */
687 1.19 christos #ifdef VSTATUS
688 1.19 christos case C_STATUS:
689 1.19 christos return VSTATUS;
690 1.19 christos #endif /* VSTATUS */
691 1.19 christos #ifdef VPAGE
692 1.19 christos case C_PAGE:
693 1.19 christos return VPAGE;
694 1.19 christos #endif /* VPAGE */
695 1.19 christos #ifdef VPGOFF
696 1.19 christos case C_PGOFF:
697 1.19 christos return VPGOFF;
698 1.19 christos #endif /* VPGOFF */
699 1.19 christos #ifdef VKILL2
700 1.19 christos case C_KILL2:
701 1.19 christos return VKILL2;
702 1.19 christos #endif /* KILL2 */
703 1.19 christos #ifdef VMIN
704 1.19 christos case C_MIN:
705 1.19 christos return VMIN;
706 1.19 christos #endif /* VMIN */
707 1.19 christos #ifdef VTIME
708 1.19 christos case C_TIME:
709 1.19 christos return VTIME;
710 1.19 christos #endif /* VTIME */
711 1.19 christos default:
712 1.19 christos return -1;
713 1.19 christos }
714 1.19 christos }
715 1.1 cgd
716 1.1 cgd /* tty__getchar():
717 1.1 cgd * Get the tty characters
718 1.1 cgd */
719 1.1 cgd private void
720 1.13 lukem tty__getchar(struct termios *td, unsigned char *s)
721 1.11 simonb {
722 1.13 lukem
723 1.13 lukem #ifdef VINTR
724 1.13 lukem s[C_INTR] = td->c_cc[VINTR];
725 1.13 lukem #endif /* VINTR */
726 1.13 lukem #ifdef VQUIT
727 1.13 lukem s[C_QUIT] = td->c_cc[VQUIT];
728 1.13 lukem #endif /* VQUIT */
729 1.13 lukem #ifdef VERASE
730 1.13 lukem s[C_ERASE] = td->c_cc[VERASE];
731 1.13 lukem #endif /* VERASE */
732 1.13 lukem #ifdef VKILL
733 1.13 lukem s[C_KILL] = td->c_cc[VKILL];
734 1.13 lukem #endif /* VKILL */
735 1.13 lukem #ifdef VEOF
736 1.13 lukem s[C_EOF] = td->c_cc[VEOF];
737 1.13 lukem #endif /* VEOF */
738 1.13 lukem #ifdef VEOL
739 1.13 lukem s[C_EOL] = td->c_cc[VEOL];
740 1.13 lukem #endif /* VEOL */
741 1.13 lukem #ifdef VEOL2
742 1.13 lukem s[C_EOL2] = td->c_cc[VEOL2];
743 1.13 lukem #endif /* VEOL2 */
744 1.13 lukem #ifdef VSWTCH
745 1.13 lukem s[C_SWTCH] = td->c_cc[VSWTCH];
746 1.13 lukem #endif /* VSWTCH */
747 1.13 lukem #ifdef VDSWTCH
748 1.13 lukem s[C_DSWTCH] = td->c_cc[VDSWTCH];
749 1.13 lukem #endif /* VDSWTCH */
750 1.13 lukem #ifdef VERASE2
751 1.13 lukem s[C_ERASE2] = td->c_cc[VERASE2];
752 1.13 lukem #endif /* VERASE2 */
753 1.13 lukem #ifdef VSTART
754 1.13 lukem s[C_START] = td->c_cc[VSTART];
755 1.13 lukem #endif /* VSTART */
756 1.13 lukem #ifdef VSTOP
757 1.13 lukem s[C_STOP] = td->c_cc[VSTOP];
758 1.13 lukem #endif /* VSTOP */
759 1.13 lukem #ifdef VWERASE
760 1.13 lukem s[C_WERASE] = td->c_cc[VWERASE];
761 1.13 lukem #endif /* VWERASE */
762 1.13 lukem #ifdef VSUSP
763 1.13 lukem s[C_SUSP] = td->c_cc[VSUSP];
764 1.13 lukem #endif /* VSUSP */
765 1.13 lukem #ifdef VDSUSP
766 1.13 lukem s[C_DSUSP] = td->c_cc[VDSUSP];
767 1.13 lukem #endif /* VDSUSP */
768 1.13 lukem #ifdef VREPRINT
769 1.13 lukem s[C_REPRINT] = td->c_cc[VREPRINT];
770 1.13 lukem #endif /* VREPRINT */
771 1.13 lukem #ifdef VDISCARD
772 1.13 lukem s[C_DISCARD] = td->c_cc[VDISCARD];
773 1.13 lukem #endif /* VDISCARD */
774 1.13 lukem #ifdef VLNEXT
775 1.13 lukem s[C_LNEXT] = td->c_cc[VLNEXT];
776 1.13 lukem #endif /* VLNEXT */
777 1.13 lukem #ifdef VSTATUS
778 1.13 lukem s[C_STATUS] = td->c_cc[VSTATUS];
779 1.13 lukem #endif /* VSTATUS */
780 1.13 lukem #ifdef VPAGE
781 1.13 lukem s[C_PAGE] = td->c_cc[VPAGE];
782 1.13 lukem #endif /* VPAGE */
783 1.13 lukem #ifdef VPGOFF
784 1.13 lukem s[C_PGOFF] = td->c_cc[VPGOFF];
785 1.13 lukem #endif /* VPGOFF */
786 1.13 lukem #ifdef VKILL2
787 1.13 lukem s[C_KILL2] = td->c_cc[VKILL2];
788 1.13 lukem #endif /* KILL2 */
789 1.13 lukem #ifdef VMIN
790 1.13 lukem s[C_MIN] = td->c_cc[VMIN];
791 1.13 lukem #endif /* VMIN */
792 1.13 lukem #ifdef VTIME
793 1.13 lukem s[C_TIME] = td->c_cc[VTIME];
794 1.13 lukem #endif /* VTIME */
795 1.13 lukem } /* tty__getchar */
796 1.1 cgd
797 1.1 cgd
798 1.1 cgd /* tty__setchar():
799 1.1 cgd * Set the tty characters
800 1.1 cgd */
801 1.1 cgd private void
802 1.13 lukem tty__setchar(struct termios *td, unsigned char *s)
803 1.11 simonb {
804 1.13 lukem
805 1.13 lukem #ifdef VINTR
806 1.13 lukem td->c_cc[VINTR] = s[C_INTR];
807 1.13 lukem #endif /* VINTR */
808 1.13 lukem #ifdef VQUIT
809 1.13 lukem td->c_cc[VQUIT] = s[C_QUIT];
810 1.13 lukem #endif /* VQUIT */
811 1.13 lukem #ifdef VERASE
812 1.13 lukem td->c_cc[VERASE] = s[C_ERASE];
813 1.13 lukem #endif /* VERASE */
814 1.13 lukem #ifdef VKILL
815 1.13 lukem td->c_cc[VKILL] = s[C_KILL];
816 1.13 lukem #endif /* VKILL */
817 1.13 lukem #ifdef VEOF
818 1.13 lukem td->c_cc[VEOF] = s[C_EOF];
819 1.13 lukem #endif /* VEOF */
820 1.13 lukem #ifdef VEOL
821 1.13 lukem td->c_cc[VEOL] = s[C_EOL];
822 1.13 lukem #endif /* VEOL */
823 1.13 lukem #ifdef VEOL2
824 1.13 lukem td->c_cc[VEOL2] = s[C_EOL2];
825 1.13 lukem #endif /* VEOL2 */
826 1.13 lukem #ifdef VSWTCH
827 1.13 lukem td->c_cc[VSWTCH] = s[C_SWTCH];
828 1.13 lukem #endif /* VSWTCH */
829 1.13 lukem #ifdef VDSWTCH
830 1.13 lukem td->c_cc[VDSWTCH] = s[C_DSWTCH];
831 1.13 lukem #endif /* VDSWTCH */
832 1.13 lukem #ifdef VERASE2
833 1.13 lukem td->c_cc[VERASE2] = s[C_ERASE2];
834 1.13 lukem #endif /* VERASE2 */
835 1.13 lukem #ifdef VSTART
836 1.13 lukem td->c_cc[VSTART] = s[C_START];
837 1.13 lukem #endif /* VSTART */
838 1.13 lukem #ifdef VSTOP
839 1.13 lukem td->c_cc[VSTOP] = s[C_STOP];
840 1.13 lukem #endif /* VSTOP */
841 1.13 lukem #ifdef VWERASE
842 1.13 lukem td->c_cc[VWERASE] = s[C_WERASE];
843 1.13 lukem #endif /* VWERASE */
844 1.13 lukem #ifdef VSUSP
845 1.13 lukem td->c_cc[VSUSP] = s[C_SUSP];
846 1.13 lukem #endif /* VSUSP */
847 1.13 lukem #ifdef VDSUSP
848 1.13 lukem td->c_cc[VDSUSP] = s[C_DSUSP];
849 1.13 lukem #endif /* VDSUSP */
850 1.13 lukem #ifdef VREPRINT
851 1.13 lukem td->c_cc[VREPRINT] = s[C_REPRINT];
852 1.13 lukem #endif /* VREPRINT */
853 1.13 lukem #ifdef VDISCARD
854 1.13 lukem td->c_cc[VDISCARD] = s[C_DISCARD];
855 1.13 lukem #endif /* VDISCARD */
856 1.13 lukem #ifdef VLNEXT
857 1.13 lukem td->c_cc[VLNEXT] = s[C_LNEXT];
858 1.13 lukem #endif /* VLNEXT */
859 1.13 lukem #ifdef VSTATUS
860 1.13 lukem td->c_cc[VSTATUS] = s[C_STATUS];
861 1.13 lukem #endif /* VSTATUS */
862 1.13 lukem #ifdef VPAGE
863 1.13 lukem td->c_cc[VPAGE] = s[C_PAGE];
864 1.13 lukem #endif /* VPAGE */
865 1.13 lukem #ifdef VPGOFF
866 1.13 lukem td->c_cc[VPGOFF] = s[C_PGOFF];
867 1.13 lukem #endif /* VPGOFF */
868 1.13 lukem #ifdef VKILL2
869 1.13 lukem td->c_cc[VKILL2] = s[C_KILL2];
870 1.13 lukem #endif /* VKILL2 */
871 1.13 lukem #ifdef VMIN
872 1.13 lukem td->c_cc[VMIN] = s[C_MIN];
873 1.13 lukem #endif /* VMIN */
874 1.13 lukem #ifdef VTIME
875 1.13 lukem td->c_cc[VTIME] = s[C_TIME];
876 1.13 lukem #endif /* VTIME */
877 1.13 lukem } /* tty__setchar */
878 1.1 cgd
879 1.1 cgd
880 1.1 cgd /* tty_bind_char():
881 1.1 cgd * Rebind the editline functions
882 1.1 cgd */
883 1.1 cgd protected void
884 1.13 lukem tty_bind_char(EditLine *el, int force)
885 1.1 cgd {
886 1.13 lukem
887 1.13 lukem unsigned char *t_n = el->el_tty.t_c[ED_IO];
888 1.13 lukem unsigned char *t_o = el->el_tty.t_ed.c_cc;
889 1.32 christos Char new[2], old[2];
890 1.14 jdolecek const ttymap_t *tp;
891 1.14 jdolecek el_action_t *map, *alt;
892 1.14 jdolecek const el_action_t *dmap, *dalt;
893 1.13 lukem new[1] = old[1] = '\0';
894 1.13 lukem
895 1.13 lukem map = el->el_map.key;
896 1.13 lukem alt = el->el_map.alt;
897 1.13 lukem if (el->el_map.type == MAP_VI) {
898 1.13 lukem dmap = el->el_map.vii;
899 1.13 lukem dalt = el->el_map.vic;
900 1.13 lukem } else {
901 1.13 lukem dmap = el->el_map.emacs;
902 1.13 lukem dalt = NULL;
903 1.13 lukem }
904 1.13 lukem
905 1.51 christos for (tp = tty_map; tp->nch != (wint_t)-1; tp++) {
906 1.50 christos new[0] = (Char)t_n[tp->nch];
907 1.50 christos old[0] = (Char)t_o[tp->och];
908 1.13 lukem if (new[0] == old[0] && !force)
909 1.13 lukem continue;
910 1.13 lukem /* Put the old default binding back, and set the new binding */
911 1.37 christos keymacro_clear(el, map, old);
912 1.32 christos map[UC(old[0])] = dmap[UC(old[0])];
913 1.37 christos keymacro_clear(el, map, new);
914 1.13 lukem /* MAP_VI == 1, MAP_EMACS == 0... */
915 1.32 christos map[UC(new[0])] = tp->bind[el->el_map.type];
916 1.13 lukem if (dalt) {
917 1.37 christos keymacro_clear(el, alt, old);
918 1.32 christos alt[UC(old[0])] = dalt[UC(old[0])];
919 1.37 christos keymacro_clear(el, alt, new);
920 1.32 christos alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
921 1.13 lukem }
922 1.1 cgd }
923 1.1 cgd }
924 1.1 cgd
925 1.13 lukem
926 1.44 christos private tcflag_t *
927 1.44 christos tty__get_flag(struct termios *t, int kind) {
928 1.44 christos switch (kind) {
929 1.44 christos case MD_INP:
930 1.44 christos return &t->c_iflag;
931 1.44 christos case MD_OUT:
932 1.44 christos return &t->c_oflag;
933 1.44 christos case MD_CTL:
934 1.44 christos return &t->c_cflag;
935 1.44 christos case MD_LIN:
936 1.44 christos return &t->c_lflag;
937 1.44 christos default:
938 1.44 christos abort();
939 1.44 christos /*NOTREACHED*/
940 1.44 christos }
941 1.44 christos }
942 1.44 christos
943 1.44 christos
944 1.44 christos private tcflag_t
945 1.44 christos tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
946 1.44 christos {
947 1.44 christos f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
948 1.44 christos f |= el->el_tty.t_t[mode][kind].t_setmask;
949 1.44 christos return f;
950 1.44 christos }
951 1.44 christos
952 1.44 christos
953 1.44 christos private void
954 1.44 christos tty_update_flags(EditLine *el, int kind)
955 1.44 christos {
956 1.44 christos tcflag_t *tt, *ed, *ex;
957 1.44 christos tt = tty__get_flag(&el->el_tty.t_ts, kind);
958 1.44 christos ed = tty__get_flag(&el->el_tty.t_ed, kind);
959 1.44 christos ex = tty__get_flag(&el->el_tty.t_ex, kind);
960 1.44 christos
961 1.44 christos if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) {
962 1.44 christos *ed = tty_update_flag(el, *tt, ED_IO, kind);
963 1.44 christos *ex = tty_update_flag(el, *tt, EX_IO, kind);
964 1.44 christos }
965 1.44 christos }
966 1.44 christos
967 1.44 christos
968 1.44 christos private void
969 1.44 christos tty_update_char(EditLine *el, int mode, int c) {
970 1.44 christos if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c)))
971 1.44 christos && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c]))
972 1.44 christos el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c];
973 1.44 christos if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c))
974 1.44 christos el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable;
975 1.44 christos }
976 1.44 christos
977 1.44 christos
978 1.1 cgd /* tty_rawmode():
979 1.1 cgd * Set terminal into 1 character at a time mode.
980 1.1 cgd */
981 1.1 cgd protected int
982 1.13 lukem tty_rawmode(EditLine *el)
983 1.1 cgd {
984 1.1 cgd
985 1.13 lukem if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
986 1.38 christos return 0;
987 1.13 lukem
988 1.13 lukem if (el->el_flags & EDIT_DISABLED)
989 1.38 christos return 0;
990 1.12 sommerfe
991 1.13 lukem if (tty_getty(el, &el->el_tty.t_ts) == -1) {
992 1.1 cgd #ifdef DEBUG_TTY
993 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
994 1.13 lukem strerror(errno));
995 1.1 cgd #endif /* DEBUG_TTY */
996 1.38 christos return -1;
997 1.1 cgd }
998 1.13 lukem /*
999 1.13 lukem * We always keep up with the eight bit setting and the speed of the
1000 1.32 christos * tty. But we only believe changes that are made to cooked mode!
1001 1.13 lukem */
1002 1.13 lukem el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
1003 1.13 lukem el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
1004 1.13 lukem
1005 1.13 lukem if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
1006 1.13 lukem tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
1007 1.13 lukem (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1008 1.13 lukem (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1009 1.13 lukem (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1010 1.13 lukem (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1011 1.1 cgd }
1012 1.13 lukem if (tty__cooked_mode(&el->el_tty.t_ts)) {
1013 1.44 christos int i;
1014 1.44 christos
1015 1.44 christos for (i = MD_INP; i <= MD_LIN; i++)
1016 1.44 christos tty_update_flags(el, i);
1017 1.44 christos
1018 1.13 lukem if (tty__gettabs(&el->el_tty.t_ex) == 0)
1019 1.13 lukem el->el_tty.t_tabs = 0;
1020 1.13 lukem else
1021 1.13 lukem el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1022 1.1 cgd
1023 1.44 christos tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1024 1.44 christos /*
1025 1.44 christos * Check if the user made any changes.
1026 1.44 christos * If he did, then propagate the changes to the
1027 1.44 christos * edit and execute data structures.
1028 1.44 christos */
1029 1.44 christos for (i = 0; i < C_NCC; i++)
1030 1.44 christos if (el->el_tty.t_c[TS_IO][i] !=
1031 1.44 christos el->el_tty.t_c[EX_IO][i])
1032 1.44 christos break;
1033 1.1 cgd
1034 1.44 christos if (i != C_NCC) {
1035 1.13 lukem /*
1036 1.44 christos * Propagate changes only to the unprotected
1037 1.44 christos * chars that have been modified just now.
1038 1.44 christos */
1039 1.44 christos for (i = 0; i < C_NCC; i++)
1040 1.44 christos tty_update_char(el, ED_IO, i);
1041 1.44 christos
1042 1.44 christos tty_bind_char(el, 0);
1043 1.44 christos tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1044 1.44 christos
1045 1.13 lukem for (i = 0; i < C_NCC; i++)
1046 1.44 christos tty_update_char(el, EX_IO, i);
1047 1.44 christos
1048 1.44 christos tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1049 1.1 cgd }
1050 1.1 cgd }
1051 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1052 1.1 cgd #ifdef DEBUG_TTY
1053 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1054 1.13 lukem strerror(errno));
1055 1.1 cgd #endif /* DEBUG_TTY */
1056 1.38 christos return -1;
1057 1.13 lukem }
1058 1.13 lukem el->el_tty.t_mode = ED_IO;
1059 1.38 christos return 0;
1060 1.13 lukem }
1061 1.1 cgd
1062 1.1 cgd
1063 1.1 cgd /* tty_cookedmode():
1064 1.1 cgd * Set the tty back to normal mode
1065 1.1 cgd */
1066 1.1 cgd protected int
1067 1.13 lukem tty_cookedmode(EditLine *el)
1068 1.1 cgd { /* set tty in normal setup */
1069 1.1 cgd
1070 1.13 lukem if (el->el_tty.t_mode == EX_IO)
1071 1.38 christos return 0;
1072 1.13 lukem
1073 1.13 lukem if (el->el_flags & EDIT_DISABLED)
1074 1.38 christos return 0;
1075 1.13 lukem
1076 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1077 1.1 cgd #ifdef DEBUG_TTY
1078 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1079 1.13 lukem strerror(errno));
1080 1.1 cgd #endif /* DEBUG_TTY */
1081 1.38 christos return -1;
1082 1.13 lukem }
1083 1.13 lukem el->el_tty.t_mode = EX_IO;
1084 1.38 christos return 0;
1085 1.13 lukem }
1086 1.1 cgd
1087 1.1 cgd
1088 1.1 cgd /* tty_quotemode():
1089 1.1 cgd * Turn on quote mode
1090 1.1 cgd */
1091 1.1 cgd protected int
1092 1.13 lukem tty_quotemode(EditLine *el)
1093 1.1 cgd {
1094 1.13 lukem if (el->el_tty.t_mode == QU_IO)
1095 1.38 christos return 0;
1096 1.1 cgd
1097 1.13 lukem el->el_tty.t_qu = el->el_tty.t_ed;
1098 1.1 cgd
1099 1.43 christos tty_setup_flags(el, &el->el_tty.t_qu, QU_IO);
1100 1.1 cgd
1101 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
1102 1.1 cgd #ifdef DEBUG_TTY
1103 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1104 1.13 lukem strerror(errno));
1105 1.1 cgd #endif /* DEBUG_TTY */
1106 1.38 christos return -1;
1107 1.13 lukem }
1108 1.13 lukem el->el_tty.t_mode = QU_IO;
1109 1.38 christos return 0;
1110 1.13 lukem }
1111 1.1 cgd
1112 1.1 cgd
1113 1.1 cgd /* tty_noquotemode():
1114 1.1 cgd * Turn off quote mode
1115 1.1 cgd */
1116 1.1 cgd protected int
1117 1.13 lukem tty_noquotemode(EditLine *el)
1118 1.1 cgd {
1119 1.13 lukem
1120 1.13 lukem if (el->el_tty.t_mode != QU_IO)
1121 1.38 christos return 0;
1122 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1123 1.1 cgd #ifdef DEBUG_TTY
1124 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1125 1.13 lukem strerror(errno));
1126 1.1 cgd #endif /* DEBUG_TTY */
1127 1.38 christos return -1;
1128 1.13 lukem }
1129 1.13 lukem el->el_tty.t_mode = ED_IO;
1130 1.38 christos return 0;
1131 1.1 cgd }
1132 1.1 cgd
1133 1.13 lukem
1134 1.1 cgd /* tty_stty():
1135 1.1 cgd * Stty builtin
1136 1.1 cgd */
1137 1.1 cgd protected int
1138 1.1 cgd /*ARGSUSED*/
1139 1.32 christos tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
1140 1.1 cgd {
1141 1.14 jdolecek const ttymodes_t *m;
1142 1.16 christos char x;
1143 1.13 lukem int aflag = 0;
1144 1.32 christos const Char *s, *d;
1145 1.32 christos char name[EL_BUFSIZ];
1146 1.19 christos struct termios *tios = &el->el_tty.t_ex;
1147 1.13 lukem int z = EX_IO;
1148 1.13 lukem
1149 1.13 lukem if (argv == NULL)
1150 1.38 christos return -1;
1151 1.32 christos strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
1152 1.32 christos name[sizeof(name) - 1] = '\0';
1153 1.13 lukem
1154 1.13 lukem while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1155 1.13 lukem switch (argv[0][1]) {
1156 1.13 lukem case 'a':
1157 1.13 lukem aflag++;
1158 1.13 lukem argv++;
1159 1.13 lukem break;
1160 1.13 lukem case 'd':
1161 1.13 lukem argv++;
1162 1.19 christos tios = &el->el_tty.t_ed;
1163 1.13 lukem z = ED_IO;
1164 1.13 lukem break;
1165 1.13 lukem case 'x':
1166 1.13 lukem argv++;
1167 1.19 christos tios = &el->el_tty.t_ex;
1168 1.13 lukem z = EX_IO;
1169 1.13 lukem break;
1170 1.13 lukem case 'q':
1171 1.13 lukem argv++;
1172 1.19 christos tios = &el->el_tty.t_ts;
1173 1.13 lukem z = QU_IO;
1174 1.13 lukem break;
1175 1.13 lukem default:
1176 1.13 lukem (void) fprintf(el->el_errfile,
1177 1.51 christos "%s: Unknown switch `%lc'.\n",
1178 1.51 christos name, (wint_t)argv[0][1]);
1179 1.38 christos return -1;
1180 1.13 lukem }
1181 1.1 cgd
1182 1.13 lukem if (!argv || !*argv) {
1183 1.13 lukem int i = -1;
1184 1.29 christos size_t len = 0, st = 0, cu;
1185 1.13 lukem for (m = ttymodes; m->m_name; m++) {
1186 1.13 lukem if (m->m_type != i) {
1187 1.13 lukem (void) fprintf(el->el_outfile, "%s%s",
1188 1.13 lukem i != -1 ? "\n" : "",
1189 1.13 lukem el->el_tty.t_t[z][m->m_type].t_name);
1190 1.13 lukem i = m->m_type;
1191 1.13 lukem st = len =
1192 1.13 lukem strlen(el->el_tty.t_t[z][m->m_type].t_name);
1193 1.13 lukem }
1194 1.24 christos if (i != -1) {
1195 1.24 christos x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1196 1.24 christos ? '+' : '\0';
1197 1.40 christos
1198 1.40 christos if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1199 1.40 christos x = '-';
1200 1.24 christos } else {
1201 1.24 christos x = '\0';
1202 1.24 christos }
1203 1.13 lukem
1204 1.13 lukem if (x != '\0' || aflag) {
1205 1.13 lukem
1206 1.13 lukem cu = strlen(m->m_name) + (x != '\0') + 1;
1207 1.13 lukem
1208 1.42 christos if (len + cu >=
1209 1.42 christos (size_t)el->el_terminal.t_size.h) {
1210 1.13 lukem (void) fprintf(el->el_outfile, "\n%*s",
1211 1.29 christos (int)st, "");
1212 1.13 lukem len = st + cu;
1213 1.13 lukem } else
1214 1.13 lukem len += cu;
1215 1.13 lukem
1216 1.13 lukem if (x != '\0')
1217 1.13 lukem (void) fprintf(el->el_outfile, "%c%s ",
1218 1.13 lukem x, m->m_name);
1219 1.13 lukem else
1220 1.13 lukem (void) fprintf(el->el_outfile, "%s ",
1221 1.13 lukem m->m_name);
1222 1.13 lukem }
1223 1.1 cgd }
1224 1.13 lukem (void) fprintf(el->el_outfile, "\n");
1225 1.38 christos return 0;
1226 1.1 cgd }
1227 1.13 lukem while (argv && (s = *argv++)) {
1228 1.32 christos const Char *p;
1229 1.13 lukem switch (*s) {
1230 1.13 lukem case '+':
1231 1.13 lukem case '-':
1232 1.40 christos x = (char)*s++;
1233 1.13 lukem break;
1234 1.13 lukem default:
1235 1.13 lukem x = '\0';
1236 1.13 lukem break;
1237 1.13 lukem }
1238 1.13 lukem d = s;
1239 1.32 christos p = Strchr(s, '=');
1240 1.13 lukem for (m = ttymodes; m->m_name; m++)
1241 1.42 christos if ((p ? strncmp(m->m_name, ct_encode_string(d,
1242 1.42 christos &el->el_scratch), (size_t)(p - d)) :
1243 1.42 christos strcmp(m->m_name, ct_encode_string(d,
1244 1.42 christos &el->el_scratch))) == 0 &&
1245 1.19 christos (p == NULL || m->m_type == MD_CHAR))
1246 1.13 lukem break;
1247 1.13 lukem
1248 1.13 lukem if (!m->m_name) {
1249 1.13 lukem (void) fprintf(el->el_errfile,
1250 1.32 christos "%s: Invalid argument `" FSTR "'.\n", name, d);
1251 1.38 christos return -1;
1252 1.19 christos }
1253 1.19 christos if (p) {
1254 1.19 christos int c = ffs((int)m->m_value);
1255 1.32 christos int v = *++p ? parse__escape(&p) :
1256 1.19 christos el->el_tty.t_vdisable;
1257 1.31 christos assert(c != 0);
1258 1.31 christos c--;
1259 1.19 christos c = tty__getcharindex(c);
1260 1.19 christos assert(c != -1);
1261 1.40 christos tios->c_cc[c] = (cc_t)v;
1262 1.19 christos continue;
1263 1.13 lukem }
1264 1.13 lukem switch (x) {
1265 1.13 lukem case '+':
1266 1.13 lukem el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1267 1.13 lukem el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1268 1.13 lukem break;
1269 1.13 lukem case '-':
1270 1.13 lukem el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1271 1.13 lukem el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1272 1.13 lukem break;
1273 1.13 lukem default:
1274 1.13 lukem el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1275 1.13 lukem el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1276 1.13 lukem break;
1277 1.13 lukem }
1278 1.1 cgd }
1279 1.27 christos
1280 1.45 christos tty_setup_flags(el, tios, z);
1281 1.27 christos if (el->el_tty.t_mode == z) {
1282 1.27 christos if (tty_setty(el, TCSADRAIN, tios) == -1) {
1283 1.27 christos #ifdef DEBUG_TTY
1284 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
1285 1.42 christos __func__, strerror(errno));
1286 1.27 christos #endif /* DEBUG_TTY */
1287 1.38 christos return -1;
1288 1.27 christos }
1289 1.27 christos }
1290 1.27 christos
1291 1.38 christos return 0;
1292 1.13 lukem }
1293 1.1 cgd
1294 1.1 cgd
1295 1.1 cgd #ifdef notyet
1296 1.1 cgd /* tty_printchar():
1297 1.1 cgd * DEbugging routine to print the tty characters
1298 1.1 cgd */
1299 1.1 cgd private void
1300 1.13 lukem tty_printchar(EditLine *el, unsigned char *s)
1301 1.1 cgd {
1302 1.13 lukem ttyperm_t *m;
1303 1.13 lukem int i;
1304 1.1 cgd
1305 1.13 lukem for (i = 0; i < C_NCC; i++) {
1306 1.13 lukem for (m = el->el_tty.t_t; m->m_name; m++)
1307 1.13 lukem if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1308 1.13 lukem break;
1309 1.13 lukem if (m->m_name)
1310 1.13 lukem (void) fprintf(el->el_errfile, "%s ^%c ",
1311 1.13 lukem m->m_name, s[i] + 'A' - 1);
1312 1.13 lukem if (i % 5 == 0)
1313 1.13 lukem (void) fprintf(el->el_errfile, "\n");
1314 1.13 lukem }
1315 1.13 lukem (void) fprintf(el->el_errfile, "\n");
1316 1.1 cgd }
1317 1.1 cgd #endif /* notyet */
1318 1.43 christos
1319 1.43 christos
1320 1.43 christos private void
1321 1.43 christos tty_setup_flags(EditLine *el, struct termios *tios, int mode)
1322 1.43 christos {
1323 1.44 christos int kind;
1324 1.44 christos for (kind = MD_INP; kind <= MD_LIN; kind++) {
1325 1.44 christos tcflag_t *f = tty__get_flag(tios, kind);
1326 1.44 christos *f = tty_update_flag(el, *f, mode, kind);
1327 1.44 christos }
1328 1.43 christos }
1329