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