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