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