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