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