tty.c revision 1.52 1 1.52 christos /* $NetBSD: tty.c,v 1.52 2016/02/16 14:06:05 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.52 christos __RCSID("$NetBSD: tty.c,v 1.52 2016/02/16 14:06:05 christos Exp $");
41 1.2 lukem #endif
42 1.1 cgd #endif /* not lint && not SCCSID */
43 1.1 cgd
44 1.11 simonb /*
45 1.1 cgd * tty.c: tty interface stuff
46 1.1 cgd */
47 1.19 christos #include <assert.h>
48 1.28 sketch #include <errno.h>
49 1.34 christos #include <unistd.h> /* for isatty */
50 1.33 christos #include <strings.h> /* for ffs */
51 1.46 christos #include <stdlib.h> /* for abort */
52 1.52 christos
53 1.52 christos #include "histedit.h"
54 1.32 christos #include "el.h"
55 1.1 cgd #include "tty.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.34 christos if (!isatty(el->el_outfd)) {
505 1.34 christos #ifdef DEBUG_TTY
506 1.42 christos (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__,
507 1.42 christos strerror(errno));
508 1.34 christos #endif /* DEBUG_TTY */
509 1.38 christos return -1;
510 1.34 christos }
511 1.42 christos if (tty_getty(el, &el->el_tty.t_or) == -1) {
512 1.1 cgd #ifdef DEBUG_TTY
513 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
514 1.42 christos strerror(errno));
515 1.1 cgd #endif /* DEBUG_TTY */
516 1.38 christos return -1;
517 1.13 lukem }
518 1.42 christos el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or;
519 1.13 lukem
520 1.13 lukem el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex);
521 1.13 lukem el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
522 1.13 lukem el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
523 1.13 lukem
524 1.43 christos tty_setup_flags(el, &el->el_tty.t_ex, EX_IO);
525 1.13 lukem
526 1.13 lukem /*
527 1.13 lukem * Reset the tty chars to reasonable defaults
528 1.13 lukem * If they are disabled, then enable them.
529 1.13 lukem */
530 1.13 lukem if (rst) {
531 1.13 lukem if (tty__cooked_mode(&el->el_tty.t_ts)) {
532 1.13 lukem tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
533 1.13 lukem /*
534 1.13 lukem * Don't affect CMIN and CTIME for the editor mode
535 1.13 lukem */
536 1.13 lukem for (rst = 0; rst < C_NCC - 2; rst++)
537 1.13 lukem if (el->el_tty.t_c[TS_IO][rst] !=
538 1.13 lukem el->el_tty.t_vdisable
539 1.13 lukem && el->el_tty.t_c[ED_IO][rst] !=
540 1.13 lukem el->el_tty.t_vdisable)
541 1.13 lukem el->el_tty.t_c[ED_IO][rst] =
542 1.13 lukem el->el_tty.t_c[TS_IO][rst];
543 1.13 lukem for (rst = 0; rst < C_NCC; rst++)
544 1.13 lukem if (el->el_tty.t_c[TS_IO][rst] !=
545 1.13 lukem el->el_tty.t_vdisable)
546 1.13 lukem el->el_tty.t_c[EX_IO][rst] =
547 1.13 lukem el->el_tty.t_c[TS_IO][rst];
548 1.13 lukem }
549 1.13 lukem tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
550 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
551 1.1 cgd #ifdef DEBUG_TTY
552 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
553 1.42 christos __func__, strerror(errno));
554 1.1 cgd #endif /* DEBUG_TTY */
555 1.38 christos return -1;
556 1.13 lukem }
557 1.25 christos }
558 1.13 lukem
559 1.43 christos tty_setup_flags(el, &el->el_tty.t_ed, ED_IO);
560 1.13 lukem
561 1.13 lukem tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
562 1.13 lukem tty_bind_char(el, 1);
563 1.38 christos return 0;
564 1.1 cgd }
565 1.1 cgd
566 1.1 cgd protected int
567 1.13 lukem tty_init(EditLine *el)
568 1.1 cgd {
569 1.13 lukem
570 1.13 lukem el->el_tty.t_mode = EX_IO;
571 1.13 lukem el->el_tty.t_vdisable = _POSIX_VDISABLE;
572 1.13 lukem (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t));
573 1.13 lukem (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t));
574 1.38 christos return tty_setup(el);
575 1.13 lukem }
576 1.1 cgd
577 1.1 cgd
578 1.1 cgd /* tty_end():
579 1.1 cgd * Restore the tty to its original settings
580 1.1 cgd */
581 1.1 cgd protected void
582 1.1 cgd /*ARGSUSED*/
583 1.42 christos tty_end(EditLine *el)
584 1.1 cgd {
585 1.48 christos if (el->el_flags & EDIT_DISABLED)
586 1.49 gson return;
587 1.48 christos
588 1.42 christos if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
589 1.42 christos #ifdef DEBUG_TTY
590 1.42 christos (void) fprintf(el->el_errfile,
591 1.42 christos "%s: tty_setty: %s\n", __func__, strerror(errno));
592 1.42 christos #endif /* DEBUG_TTY */
593 1.42 christos }
594 1.1 cgd }
595 1.1 cgd
596 1.1 cgd
597 1.1 cgd /* tty__getspeed():
598 1.1 cgd * Get the tty speed
599 1.1 cgd */
600 1.1 cgd private speed_t
601 1.13 lukem tty__getspeed(struct termios *td)
602 1.1 cgd {
603 1.13 lukem speed_t spd;
604 1.1 cgd
605 1.13 lukem if ((spd = cfgetispeed(td)) == 0)
606 1.13 lukem spd = cfgetospeed(td);
607 1.38 christos return spd;
608 1.13 lukem }
609 1.1 cgd
610 1.19 christos /* tty__getspeed():
611 1.19 christos * Return the index of the asked char in the c_cc array
612 1.19 christos */
613 1.19 christos private int
614 1.19 christos tty__getcharindex(int i)
615 1.19 christos {
616 1.19 christos switch (i) {
617 1.19 christos #ifdef VINTR
618 1.19 christos case C_INTR:
619 1.19 christos return VINTR;
620 1.19 christos #endif /* VINTR */
621 1.19 christos #ifdef VQUIT
622 1.19 christos case C_QUIT:
623 1.19 christos return VQUIT;
624 1.19 christos #endif /* VQUIT */
625 1.19 christos #ifdef VERASE
626 1.19 christos case C_ERASE:
627 1.19 christos return VERASE;
628 1.19 christos #endif /* VERASE */
629 1.19 christos #ifdef VKILL
630 1.19 christos case C_KILL:
631 1.19 christos return VKILL;
632 1.19 christos #endif /* VKILL */
633 1.19 christos #ifdef VEOF
634 1.19 christos case C_EOF:
635 1.19 christos return VEOF;
636 1.19 christos #endif /* VEOF */
637 1.19 christos #ifdef VEOL
638 1.19 christos case C_EOL:
639 1.19 christos return VEOL;
640 1.19 christos #endif /* VEOL */
641 1.19 christos #ifdef VEOL2
642 1.19 christos case C_EOL2:
643 1.19 christos return VEOL2;
644 1.19 christos #endif /* VEOL2 */
645 1.19 christos #ifdef VSWTCH
646 1.19 christos case C_SWTCH:
647 1.19 christos return VSWTCH;
648 1.19 christos #endif /* VSWTCH */
649 1.19 christos #ifdef VDSWTCH
650 1.19 christos case C_DSWTCH:
651 1.19 christos return VDSWTCH;
652 1.19 christos #endif /* VDSWTCH */
653 1.19 christos #ifdef VERASE2
654 1.19 christos case C_ERASE2:
655 1.19 christos return VERASE2;
656 1.19 christos #endif /* VERASE2 */
657 1.19 christos #ifdef VSTART
658 1.19 christos case C_START:
659 1.19 christos return VSTART;
660 1.19 christos #endif /* VSTART */
661 1.19 christos #ifdef VSTOP
662 1.19 christos case C_STOP:
663 1.19 christos return VSTOP;
664 1.19 christos #endif /* VSTOP */
665 1.19 christos #ifdef VWERASE
666 1.19 christos case C_WERASE:
667 1.19 christos return VWERASE;
668 1.19 christos #endif /* VWERASE */
669 1.19 christos #ifdef VSUSP
670 1.19 christos case C_SUSP:
671 1.19 christos return VSUSP;
672 1.19 christos #endif /* VSUSP */
673 1.19 christos #ifdef VDSUSP
674 1.19 christos case C_DSUSP:
675 1.19 christos return VDSUSP;
676 1.19 christos #endif /* VDSUSP */
677 1.19 christos #ifdef VREPRINT
678 1.19 christos case C_REPRINT:
679 1.19 christos return VREPRINT;
680 1.19 christos #endif /* VREPRINT */
681 1.19 christos #ifdef VDISCARD
682 1.19 christos case C_DISCARD:
683 1.19 christos return VDISCARD;
684 1.19 christos #endif /* VDISCARD */
685 1.19 christos #ifdef VLNEXT
686 1.19 christos case C_LNEXT:
687 1.19 christos return VLNEXT;
688 1.19 christos #endif /* VLNEXT */
689 1.19 christos #ifdef VSTATUS
690 1.19 christos case C_STATUS:
691 1.19 christos return VSTATUS;
692 1.19 christos #endif /* VSTATUS */
693 1.19 christos #ifdef VPAGE
694 1.19 christos case C_PAGE:
695 1.19 christos return VPAGE;
696 1.19 christos #endif /* VPAGE */
697 1.19 christos #ifdef VPGOFF
698 1.19 christos case C_PGOFF:
699 1.19 christos return VPGOFF;
700 1.19 christos #endif /* VPGOFF */
701 1.19 christos #ifdef VKILL2
702 1.19 christos case C_KILL2:
703 1.19 christos return VKILL2;
704 1.19 christos #endif /* KILL2 */
705 1.19 christos #ifdef VMIN
706 1.19 christos case C_MIN:
707 1.19 christos return VMIN;
708 1.19 christos #endif /* VMIN */
709 1.19 christos #ifdef VTIME
710 1.19 christos case C_TIME:
711 1.19 christos return VTIME;
712 1.19 christos #endif /* VTIME */
713 1.19 christos default:
714 1.19 christos return -1;
715 1.19 christos }
716 1.19 christos }
717 1.1 cgd
718 1.1 cgd /* tty__getchar():
719 1.1 cgd * Get the tty characters
720 1.1 cgd */
721 1.1 cgd private void
722 1.13 lukem tty__getchar(struct termios *td, unsigned char *s)
723 1.11 simonb {
724 1.13 lukem
725 1.13 lukem #ifdef VINTR
726 1.13 lukem s[C_INTR] = td->c_cc[VINTR];
727 1.13 lukem #endif /* VINTR */
728 1.13 lukem #ifdef VQUIT
729 1.13 lukem s[C_QUIT] = td->c_cc[VQUIT];
730 1.13 lukem #endif /* VQUIT */
731 1.13 lukem #ifdef VERASE
732 1.13 lukem s[C_ERASE] = td->c_cc[VERASE];
733 1.13 lukem #endif /* VERASE */
734 1.13 lukem #ifdef VKILL
735 1.13 lukem s[C_KILL] = td->c_cc[VKILL];
736 1.13 lukem #endif /* VKILL */
737 1.13 lukem #ifdef VEOF
738 1.13 lukem s[C_EOF] = td->c_cc[VEOF];
739 1.13 lukem #endif /* VEOF */
740 1.13 lukem #ifdef VEOL
741 1.13 lukem s[C_EOL] = td->c_cc[VEOL];
742 1.13 lukem #endif /* VEOL */
743 1.13 lukem #ifdef VEOL2
744 1.13 lukem s[C_EOL2] = td->c_cc[VEOL2];
745 1.13 lukem #endif /* VEOL2 */
746 1.13 lukem #ifdef VSWTCH
747 1.13 lukem s[C_SWTCH] = td->c_cc[VSWTCH];
748 1.13 lukem #endif /* VSWTCH */
749 1.13 lukem #ifdef VDSWTCH
750 1.13 lukem s[C_DSWTCH] = td->c_cc[VDSWTCH];
751 1.13 lukem #endif /* VDSWTCH */
752 1.13 lukem #ifdef VERASE2
753 1.13 lukem s[C_ERASE2] = td->c_cc[VERASE2];
754 1.13 lukem #endif /* VERASE2 */
755 1.13 lukem #ifdef VSTART
756 1.13 lukem s[C_START] = td->c_cc[VSTART];
757 1.13 lukem #endif /* VSTART */
758 1.13 lukem #ifdef VSTOP
759 1.13 lukem s[C_STOP] = td->c_cc[VSTOP];
760 1.13 lukem #endif /* VSTOP */
761 1.13 lukem #ifdef VWERASE
762 1.13 lukem s[C_WERASE] = td->c_cc[VWERASE];
763 1.13 lukem #endif /* VWERASE */
764 1.13 lukem #ifdef VSUSP
765 1.13 lukem s[C_SUSP] = td->c_cc[VSUSP];
766 1.13 lukem #endif /* VSUSP */
767 1.13 lukem #ifdef VDSUSP
768 1.13 lukem s[C_DSUSP] = td->c_cc[VDSUSP];
769 1.13 lukem #endif /* VDSUSP */
770 1.13 lukem #ifdef VREPRINT
771 1.13 lukem s[C_REPRINT] = td->c_cc[VREPRINT];
772 1.13 lukem #endif /* VREPRINT */
773 1.13 lukem #ifdef VDISCARD
774 1.13 lukem s[C_DISCARD] = td->c_cc[VDISCARD];
775 1.13 lukem #endif /* VDISCARD */
776 1.13 lukem #ifdef VLNEXT
777 1.13 lukem s[C_LNEXT] = td->c_cc[VLNEXT];
778 1.13 lukem #endif /* VLNEXT */
779 1.13 lukem #ifdef VSTATUS
780 1.13 lukem s[C_STATUS] = td->c_cc[VSTATUS];
781 1.13 lukem #endif /* VSTATUS */
782 1.13 lukem #ifdef VPAGE
783 1.13 lukem s[C_PAGE] = td->c_cc[VPAGE];
784 1.13 lukem #endif /* VPAGE */
785 1.13 lukem #ifdef VPGOFF
786 1.13 lukem s[C_PGOFF] = td->c_cc[VPGOFF];
787 1.13 lukem #endif /* VPGOFF */
788 1.13 lukem #ifdef VKILL2
789 1.13 lukem s[C_KILL2] = td->c_cc[VKILL2];
790 1.13 lukem #endif /* KILL2 */
791 1.13 lukem #ifdef VMIN
792 1.13 lukem s[C_MIN] = td->c_cc[VMIN];
793 1.13 lukem #endif /* VMIN */
794 1.13 lukem #ifdef VTIME
795 1.13 lukem s[C_TIME] = td->c_cc[VTIME];
796 1.13 lukem #endif /* VTIME */
797 1.13 lukem } /* tty__getchar */
798 1.1 cgd
799 1.1 cgd
800 1.1 cgd /* tty__setchar():
801 1.1 cgd * Set the tty characters
802 1.1 cgd */
803 1.1 cgd private void
804 1.13 lukem tty__setchar(struct termios *td, unsigned char *s)
805 1.11 simonb {
806 1.13 lukem
807 1.13 lukem #ifdef VINTR
808 1.13 lukem td->c_cc[VINTR] = s[C_INTR];
809 1.13 lukem #endif /* VINTR */
810 1.13 lukem #ifdef VQUIT
811 1.13 lukem td->c_cc[VQUIT] = s[C_QUIT];
812 1.13 lukem #endif /* VQUIT */
813 1.13 lukem #ifdef VERASE
814 1.13 lukem td->c_cc[VERASE] = s[C_ERASE];
815 1.13 lukem #endif /* VERASE */
816 1.13 lukem #ifdef VKILL
817 1.13 lukem td->c_cc[VKILL] = s[C_KILL];
818 1.13 lukem #endif /* VKILL */
819 1.13 lukem #ifdef VEOF
820 1.13 lukem td->c_cc[VEOF] = s[C_EOF];
821 1.13 lukem #endif /* VEOF */
822 1.13 lukem #ifdef VEOL
823 1.13 lukem td->c_cc[VEOL] = s[C_EOL];
824 1.13 lukem #endif /* VEOL */
825 1.13 lukem #ifdef VEOL2
826 1.13 lukem td->c_cc[VEOL2] = s[C_EOL2];
827 1.13 lukem #endif /* VEOL2 */
828 1.13 lukem #ifdef VSWTCH
829 1.13 lukem td->c_cc[VSWTCH] = s[C_SWTCH];
830 1.13 lukem #endif /* VSWTCH */
831 1.13 lukem #ifdef VDSWTCH
832 1.13 lukem td->c_cc[VDSWTCH] = s[C_DSWTCH];
833 1.13 lukem #endif /* VDSWTCH */
834 1.13 lukem #ifdef VERASE2
835 1.13 lukem td->c_cc[VERASE2] = s[C_ERASE2];
836 1.13 lukem #endif /* VERASE2 */
837 1.13 lukem #ifdef VSTART
838 1.13 lukem td->c_cc[VSTART] = s[C_START];
839 1.13 lukem #endif /* VSTART */
840 1.13 lukem #ifdef VSTOP
841 1.13 lukem td->c_cc[VSTOP] = s[C_STOP];
842 1.13 lukem #endif /* VSTOP */
843 1.13 lukem #ifdef VWERASE
844 1.13 lukem td->c_cc[VWERASE] = s[C_WERASE];
845 1.13 lukem #endif /* VWERASE */
846 1.13 lukem #ifdef VSUSP
847 1.13 lukem td->c_cc[VSUSP] = s[C_SUSP];
848 1.13 lukem #endif /* VSUSP */
849 1.13 lukem #ifdef VDSUSP
850 1.13 lukem td->c_cc[VDSUSP] = s[C_DSUSP];
851 1.13 lukem #endif /* VDSUSP */
852 1.13 lukem #ifdef VREPRINT
853 1.13 lukem td->c_cc[VREPRINT] = s[C_REPRINT];
854 1.13 lukem #endif /* VREPRINT */
855 1.13 lukem #ifdef VDISCARD
856 1.13 lukem td->c_cc[VDISCARD] = s[C_DISCARD];
857 1.13 lukem #endif /* VDISCARD */
858 1.13 lukem #ifdef VLNEXT
859 1.13 lukem td->c_cc[VLNEXT] = s[C_LNEXT];
860 1.13 lukem #endif /* VLNEXT */
861 1.13 lukem #ifdef VSTATUS
862 1.13 lukem td->c_cc[VSTATUS] = s[C_STATUS];
863 1.13 lukem #endif /* VSTATUS */
864 1.13 lukem #ifdef VPAGE
865 1.13 lukem td->c_cc[VPAGE] = s[C_PAGE];
866 1.13 lukem #endif /* VPAGE */
867 1.13 lukem #ifdef VPGOFF
868 1.13 lukem td->c_cc[VPGOFF] = s[C_PGOFF];
869 1.13 lukem #endif /* VPGOFF */
870 1.13 lukem #ifdef VKILL2
871 1.13 lukem td->c_cc[VKILL2] = s[C_KILL2];
872 1.13 lukem #endif /* VKILL2 */
873 1.13 lukem #ifdef VMIN
874 1.13 lukem td->c_cc[VMIN] = s[C_MIN];
875 1.13 lukem #endif /* VMIN */
876 1.13 lukem #ifdef VTIME
877 1.13 lukem td->c_cc[VTIME] = s[C_TIME];
878 1.13 lukem #endif /* VTIME */
879 1.13 lukem } /* tty__setchar */
880 1.1 cgd
881 1.1 cgd
882 1.1 cgd /* tty_bind_char():
883 1.1 cgd * Rebind the editline functions
884 1.1 cgd */
885 1.1 cgd protected void
886 1.13 lukem tty_bind_char(EditLine *el, int force)
887 1.1 cgd {
888 1.13 lukem
889 1.13 lukem unsigned char *t_n = el->el_tty.t_c[ED_IO];
890 1.13 lukem unsigned char *t_o = el->el_tty.t_ed.c_cc;
891 1.32 christos Char new[2], old[2];
892 1.14 jdolecek const ttymap_t *tp;
893 1.14 jdolecek el_action_t *map, *alt;
894 1.14 jdolecek const el_action_t *dmap, *dalt;
895 1.13 lukem new[1] = old[1] = '\0';
896 1.13 lukem
897 1.13 lukem map = el->el_map.key;
898 1.13 lukem alt = el->el_map.alt;
899 1.13 lukem if (el->el_map.type == MAP_VI) {
900 1.13 lukem dmap = el->el_map.vii;
901 1.13 lukem dalt = el->el_map.vic;
902 1.13 lukem } else {
903 1.13 lukem dmap = el->el_map.emacs;
904 1.13 lukem dalt = NULL;
905 1.13 lukem }
906 1.13 lukem
907 1.51 christos for (tp = tty_map; tp->nch != (wint_t)-1; tp++) {
908 1.50 christos new[0] = (Char)t_n[tp->nch];
909 1.50 christos old[0] = (Char)t_o[tp->och];
910 1.13 lukem if (new[0] == old[0] && !force)
911 1.13 lukem continue;
912 1.13 lukem /* Put the old default binding back, and set the new binding */
913 1.37 christos keymacro_clear(el, map, old);
914 1.32 christos map[UC(old[0])] = dmap[UC(old[0])];
915 1.37 christos keymacro_clear(el, map, new);
916 1.13 lukem /* MAP_VI == 1, MAP_EMACS == 0... */
917 1.32 christos map[UC(new[0])] = tp->bind[el->el_map.type];
918 1.13 lukem if (dalt) {
919 1.37 christos keymacro_clear(el, alt, old);
920 1.32 christos alt[UC(old[0])] = dalt[UC(old[0])];
921 1.37 christos keymacro_clear(el, alt, new);
922 1.32 christos alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
923 1.13 lukem }
924 1.1 cgd }
925 1.1 cgd }
926 1.1 cgd
927 1.13 lukem
928 1.44 christos private tcflag_t *
929 1.44 christos tty__get_flag(struct termios *t, int kind) {
930 1.44 christos switch (kind) {
931 1.44 christos case MD_INP:
932 1.44 christos return &t->c_iflag;
933 1.44 christos case MD_OUT:
934 1.44 christos return &t->c_oflag;
935 1.44 christos case MD_CTL:
936 1.44 christos return &t->c_cflag;
937 1.44 christos case MD_LIN:
938 1.44 christos return &t->c_lflag;
939 1.44 christos default:
940 1.44 christos abort();
941 1.44 christos /*NOTREACHED*/
942 1.44 christos }
943 1.44 christos }
944 1.44 christos
945 1.44 christos
946 1.44 christos private tcflag_t
947 1.44 christos tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
948 1.44 christos {
949 1.44 christos f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
950 1.44 christos f |= el->el_tty.t_t[mode][kind].t_setmask;
951 1.44 christos return f;
952 1.44 christos }
953 1.44 christos
954 1.44 christos
955 1.44 christos private void
956 1.44 christos tty_update_flags(EditLine *el, int kind)
957 1.44 christos {
958 1.44 christos tcflag_t *tt, *ed, *ex;
959 1.44 christos tt = tty__get_flag(&el->el_tty.t_ts, kind);
960 1.44 christos ed = tty__get_flag(&el->el_tty.t_ed, kind);
961 1.44 christos ex = tty__get_flag(&el->el_tty.t_ex, kind);
962 1.44 christos
963 1.44 christos if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) {
964 1.44 christos *ed = tty_update_flag(el, *tt, ED_IO, kind);
965 1.44 christos *ex = tty_update_flag(el, *tt, EX_IO, kind);
966 1.44 christos }
967 1.44 christos }
968 1.44 christos
969 1.44 christos
970 1.44 christos private void
971 1.44 christos tty_update_char(EditLine *el, int mode, int c) {
972 1.44 christos if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c)))
973 1.44 christos && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c]))
974 1.44 christos el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c];
975 1.44 christos if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c))
976 1.44 christos el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable;
977 1.44 christos }
978 1.44 christos
979 1.44 christos
980 1.1 cgd /* tty_rawmode():
981 1.1 cgd * Set terminal into 1 character at a time mode.
982 1.1 cgd */
983 1.1 cgd protected int
984 1.13 lukem tty_rawmode(EditLine *el)
985 1.1 cgd {
986 1.1 cgd
987 1.13 lukem if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
988 1.38 christos return 0;
989 1.13 lukem
990 1.13 lukem if (el->el_flags & EDIT_DISABLED)
991 1.38 christos return 0;
992 1.12 sommerfe
993 1.13 lukem if (tty_getty(el, &el->el_tty.t_ts) == -1) {
994 1.1 cgd #ifdef DEBUG_TTY
995 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
996 1.13 lukem strerror(errno));
997 1.1 cgd #endif /* DEBUG_TTY */
998 1.38 christos return -1;
999 1.1 cgd }
1000 1.13 lukem /*
1001 1.13 lukem * We always keep up with the eight bit setting and the speed of the
1002 1.32 christos * tty. But we only believe changes that are made to cooked mode!
1003 1.13 lukem */
1004 1.13 lukem el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
1005 1.13 lukem el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
1006 1.13 lukem
1007 1.13 lukem if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
1008 1.13 lukem tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
1009 1.13 lukem (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1010 1.13 lukem (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1011 1.13 lukem (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1012 1.13 lukem (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1013 1.1 cgd }
1014 1.13 lukem if (tty__cooked_mode(&el->el_tty.t_ts)) {
1015 1.44 christos int i;
1016 1.44 christos
1017 1.44 christos for (i = MD_INP; i <= MD_LIN; i++)
1018 1.44 christos tty_update_flags(el, i);
1019 1.44 christos
1020 1.13 lukem if (tty__gettabs(&el->el_tty.t_ex) == 0)
1021 1.13 lukem el->el_tty.t_tabs = 0;
1022 1.13 lukem else
1023 1.13 lukem el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1024 1.1 cgd
1025 1.44 christos tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1026 1.44 christos /*
1027 1.44 christos * Check if the user made any changes.
1028 1.44 christos * If he did, then propagate the changes to the
1029 1.44 christos * edit and execute data structures.
1030 1.44 christos */
1031 1.44 christos for (i = 0; i < C_NCC; i++)
1032 1.44 christos if (el->el_tty.t_c[TS_IO][i] !=
1033 1.44 christos el->el_tty.t_c[EX_IO][i])
1034 1.44 christos break;
1035 1.1 cgd
1036 1.44 christos if (i != C_NCC) {
1037 1.13 lukem /*
1038 1.44 christos * Propagate changes only to the unprotected
1039 1.44 christos * chars that have been modified just now.
1040 1.44 christos */
1041 1.44 christos for (i = 0; i < C_NCC; i++)
1042 1.44 christos tty_update_char(el, ED_IO, i);
1043 1.44 christos
1044 1.44 christos tty_bind_char(el, 0);
1045 1.44 christos tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1046 1.44 christos
1047 1.13 lukem for (i = 0; i < C_NCC; i++)
1048 1.44 christos tty_update_char(el, EX_IO, i);
1049 1.44 christos
1050 1.44 christos tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1051 1.1 cgd }
1052 1.1 cgd }
1053 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1054 1.1 cgd #ifdef DEBUG_TTY
1055 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1056 1.13 lukem strerror(errno));
1057 1.1 cgd #endif /* DEBUG_TTY */
1058 1.38 christos return -1;
1059 1.13 lukem }
1060 1.13 lukem el->el_tty.t_mode = ED_IO;
1061 1.38 christos return 0;
1062 1.13 lukem }
1063 1.1 cgd
1064 1.1 cgd
1065 1.1 cgd /* tty_cookedmode():
1066 1.1 cgd * Set the tty back to normal mode
1067 1.1 cgd */
1068 1.1 cgd protected int
1069 1.13 lukem tty_cookedmode(EditLine *el)
1070 1.1 cgd { /* set tty in normal setup */
1071 1.1 cgd
1072 1.13 lukem if (el->el_tty.t_mode == EX_IO)
1073 1.38 christos return 0;
1074 1.13 lukem
1075 1.13 lukem if (el->el_flags & EDIT_DISABLED)
1076 1.38 christos return 0;
1077 1.13 lukem
1078 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1079 1.1 cgd #ifdef DEBUG_TTY
1080 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1081 1.13 lukem strerror(errno));
1082 1.1 cgd #endif /* DEBUG_TTY */
1083 1.38 christos return -1;
1084 1.13 lukem }
1085 1.13 lukem el->el_tty.t_mode = EX_IO;
1086 1.38 christos return 0;
1087 1.13 lukem }
1088 1.1 cgd
1089 1.1 cgd
1090 1.1 cgd /* tty_quotemode():
1091 1.1 cgd * Turn on quote mode
1092 1.1 cgd */
1093 1.1 cgd protected int
1094 1.13 lukem tty_quotemode(EditLine *el)
1095 1.1 cgd {
1096 1.13 lukem if (el->el_tty.t_mode == QU_IO)
1097 1.38 christos return 0;
1098 1.1 cgd
1099 1.13 lukem el->el_tty.t_qu = el->el_tty.t_ed;
1100 1.1 cgd
1101 1.43 christos tty_setup_flags(el, &el->el_tty.t_qu, QU_IO);
1102 1.1 cgd
1103 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
1104 1.1 cgd #ifdef DEBUG_TTY
1105 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1106 1.13 lukem strerror(errno));
1107 1.1 cgd #endif /* DEBUG_TTY */
1108 1.38 christos return -1;
1109 1.13 lukem }
1110 1.13 lukem el->el_tty.t_mode = QU_IO;
1111 1.38 christos return 0;
1112 1.13 lukem }
1113 1.1 cgd
1114 1.1 cgd
1115 1.1 cgd /* tty_noquotemode():
1116 1.1 cgd * Turn off quote mode
1117 1.1 cgd */
1118 1.1 cgd protected int
1119 1.13 lukem tty_noquotemode(EditLine *el)
1120 1.1 cgd {
1121 1.13 lukem
1122 1.13 lukem if (el->el_tty.t_mode != QU_IO)
1123 1.38 christos return 0;
1124 1.26 christos if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1125 1.1 cgd #ifdef DEBUG_TTY
1126 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1127 1.13 lukem strerror(errno));
1128 1.1 cgd #endif /* DEBUG_TTY */
1129 1.38 christos return -1;
1130 1.13 lukem }
1131 1.13 lukem el->el_tty.t_mode = ED_IO;
1132 1.38 christos return 0;
1133 1.1 cgd }
1134 1.1 cgd
1135 1.13 lukem
1136 1.1 cgd /* tty_stty():
1137 1.1 cgd * Stty builtin
1138 1.1 cgd */
1139 1.1 cgd protected int
1140 1.1 cgd /*ARGSUSED*/
1141 1.32 christos tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
1142 1.1 cgd {
1143 1.14 jdolecek const ttymodes_t *m;
1144 1.16 christos char x;
1145 1.13 lukem int aflag = 0;
1146 1.32 christos const Char *s, *d;
1147 1.32 christos char name[EL_BUFSIZ];
1148 1.19 christos struct termios *tios = &el->el_tty.t_ex;
1149 1.13 lukem int z = EX_IO;
1150 1.13 lukem
1151 1.13 lukem if (argv == NULL)
1152 1.38 christos return -1;
1153 1.32 christos strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
1154 1.32 christos name[sizeof(name) - 1] = '\0';
1155 1.13 lukem
1156 1.13 lukem while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1157 1.13 lukem switch (argv[0][1]) {
1158 1.13 lukem case 'a':
1159 1.13 lukem aflag++;
1160 1.13 lukem argv++;
1161 1.13 lukem break;
1162 1.13 lukem case 'd':
1163 1.13 lukem argv++;
1164 1.19 christos tios = &el->el_tty.t_ed;
1165 1.13 lukem z = ED_IO;
1166 1.13 lukem break;
1167 1.13 lukem case 'x':
1168 1.13 lukem argv++;
1169 1.19 christos tios = &el->el_tty.t_ex;
1170 1.13 lukem z = EX_IO;
1171 1.13 lukem break;
1172 1.13 lukem case 'q':
1173 1.13 lukem argv++;
1174 1.19 christos tios = &el->el_tty.t_ts;
1175 1.13 lukem z = QU_IO;
1176 1.13 lukem break;
1177 1.13 lukem default:
1178 1.13 lukem (void) fprintf(el->el_errfile,
1179 1.51 christos "%s: Unknown switch `%lc'.\n",
1180 1.51 christos name, (wint_t)argv[0][1]);
1181 1.38 christos return -1;
1182 1.13 lukem }
1183 1.1 cgd
1184 1.13 lukem if (!argv || !*argv) {
1185 1.13 lukem int i = -1;
1186 1.29 christos size_t len = 0, st = 0, cu;
1187 1.13 lukem for (m = ttymodes; m->m_name; m++) {
1188 1.13 lukem if (m->m_type != i) {
1189 1.13 lukem (void) fprintf(el->el_outfile, "%s%s",
1190 1.13 lukem i != -1 ? "\n" : "",
1191 1.13 lukem el->el_tty.t_t[z][m->m_type].t_name);
1192 1.13 lukem i = m->m_type;
1193 1.13 lukem st = len =
1194 1.13 lukem strlen(el->el_tty.t_t[z][m->m_type].t_name);
1195 1.13 lukem }
1196 1.24 christos if (i != -1) {
1197 1.24 christos x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1198 1.24 christos ? '+' : '\0';
1199 1.40 christos
1200 1.40 christos if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1201 1.40 christos x = '-';
1202 1.24 christos } else {
1203 1.24 christos x = '\0';
1204 1.24 christos }
1205 1.13 lukem
1206 1.13 lukem if (x != '\0' || aflag) {
1207 1.13 lukem
1208 1.13 lukem cu = strlen(m->m_name) + (x != '\0') + 1;
1209 1.13 lukem
1210 1.42 christos if (len + cu >=
1211 1.42 christos (size_t)el->el_terminal.t_size.h) {
1212 1.13 lukem (void) fprintf(el->el_outfile, "\n%*s",
1213 1.29 christos (int)st, "");
1214 1.13 lukem len = st + cu;
1215 1.13 lukem } else
1216 1.13 lukem len += cu;
1217 1.13 lukem
1218 1.13 lukem if (x != '\0')
1219 1.13 lukem (void) fprintf(el->el_outfile, "%c%s ",
1220 1.13 lukem x, m->m_name);
1221 1.13 lukem else
1222 1.13 lukem (void) fprintf(el->el_outfile, "%s ",
1223 1.13 lukem m->m_name);
1224 1.13 lukem }
1225 1.1 cgd }
1226 1.13 lukem (void) fprintf(el->el_outfile, "\n");
1227 1.38 christos return 0;
1228 1.1 cgd }
1229 1.13 lukem while (argv && (s = *argv++)) {
1230 1.32 christos const Char *p;
1231 1.13 lukem switch (*s) {
1232 1.13 lukem case '+':
1233 1.13 lukem case '-':
1234 1.40 christos x = (char)*s++;
1235 1.13 lukem break;
1236 1.13 lukem default:
1237 1.13 lukem x = '\0';
1238 1.13 lukem break;
1239 1.13 lukem }
1240 1.13 lukem d = s;
1241 1.32 christos p = Strchr(s, '=');
1242 1.13 lukem for (m = ttymodes; m->m_name; m++)
1243 1.42 christos if ((p ? strncmp(m->m_name, ct_encode_string(d,
1244 1.42 christos &el->el_scratch), (size_t)(p - d)) :
1245 1.42 christos strcmp(m->m_name, ct_encode_string(d,
1246 1.42 christos &el->el_scratch))) == 0 &&
1247 1.19 christos (p == NULL || m->m_type == MD_CHAR))
1248 1.13 lukem break;
1249 1.13 lukem
1250 1.13 lukem if (!m->m_name) {
1251 1.13 lukem (void) fprintf(el->el_errfile,
1252 1.32 christos "%s: Invalid argument `" FSTR "'.\n", name, d);
1253 1.38 christos return -1;
1254 1.19 christos }
1255 1.19 christos if (p) {
1256 1.19 christos int c = ffs((int)m->m_value);
1257 1.32 christos int v = *++p ? parse__escape(&p) :
1258 1.19 christos el->el_tty.t_vdisable;
1259 1.31 christos assert(c != 0);
1260 1.31 christos c--;
1261 1.19 christos c = tty__getcharindex(c);
1262 1.19 christos assert(c != -1);
1263 1.40 christos tios->c_cc[c] = (cc_t)v;
1264 1.19 christos continue;
1265 1.13 lukem }
1266 1.13 lukem switch (x) {
1267 1.13 lukem case '+':
1268 1.13 lukem el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1269 1.13 lukem el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1270 1.13 lukem break;
1271 1.13 lukem case '-':
1272 1.13 lukem el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1273 1.13 lukem el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1274 1.13 lukem break;
1275 1.13 lukem default:
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 }
1280 1.1 cgd }
1281 1.27 christos
1282 1.45 christos tty_setup_flags(el, tios, z);
1283 1.27 christos if (el->el_tty.t_mode == z) {
1284 1.27 christos if (tty_setty(el, TCSADRAIN, tios) == -1) {
1285 1.27 christos #ifdef DEBUG_TTY
1286 1.42 christos (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
1287 1.42 christos __func__, strerror(errno));
1288 1.27 christos #endif /* DEBUG_TTY */
1289 1.38 christos return -1;
1290 1.27 christos }
1291 1.27 christos }
1292 1.27 christos
1293 1.38 christos return 0;
1294 1.13 lukem }
1295 1.1 cgd
1296 1.1 cgd
1297 1.1 cgd #ifdef notyet
1298 1.1 cgd /* tty_printchar():
1299 1.1 cgd * DEbugging routine to print the tty characters
1300 1.1 cgd */
1301 1.1 cgd private void
1302 1.13 lukem tty_printchar(EditLine *el, unsigned char *s)
1303 1.1 cgd {
1304 1.13 lukem ttyperm_t *m;
1305 1.13 lukem int i;
1306 1.1 cgd
1307 1.13 lukem for (i = 0; i < C_NCC; i++) {
1308 1.13 lukem for (m = el->el_tty.t_t; m->m_name; m++)
1309 1.13 lukem if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1310 1.13 lukem break;
1311 1.13 lukem if (m->m_name)
1312 1.13 lukem (void) fprintf(el->el_errfile, "%s ^%c ",
1313 1.13 lukem m->m_name, s[i] + 'A' - 1);
1314 1.13 lukem if (i % 5 == 0)
1315 1.13 lukem (void) fprintf(el->el_errfile, "\n");
1316 1.13 lukem }
1317 1.13 lukem (void) fprintf(el->el_errfile, "\n");
1318 1.1 cgd }
1319 1.1 cgd #endif /* notyet */
1320 1.43 christos
1321 1.43 christos
1322 1.43 christos private void
1323 1.43 christos tty_setup_flags(EditLine *el, struct termios *tios, int mode)
1324 1.43 christos {
1325 1.44 christos int kind;
1326 1.44 christos for (kind = MD_INP; kind <= MD_LIN; kind++) {
1327 1.44 christos tcflag_t *f = tty__get_flag(tios, kind);
1328 1.44 christos *f = tty_update_flag(el, *f, mode, kind);
1329 1.44 christos }
1330 1.43 christos }
1331