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