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