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