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