tty.c revision 1.60 1 /* $NetBSD: tty.c,v 1.60 2016/04/09 18:43:17 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.60 2016/04/09 18:43:17 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[(unsigned char)old[0]] = dmap[(unsigned char)old[0]];
923 keymacro_clear(el, map, new);
924 /* MAP_VI == 1, MAP_EMACS == 0... */
925 map[(unsigned char)new[0]] = tp->bind[el->el_map.type];
926 if (dalt) {
927 keymacro_clear(el, alt, old);
928 alt[(unsigned char)old[0]] =
929 dalt[(unsigned char)old[0]];
930 keymacro_clear(el, alt, new);
931 alt[(unsigned char)new[0]] =
932 tp->bind[el->el_map.type + 1];
933 }
934 }
935 }
936
937
938 private tcflag_t *
939 tty__get_flag(struct termios *t, int kind) {
940 switch (kind) {
941 case MD_INP:
942 return &t->c_iflag;
943 case MD_OUT:
944 return &t->c_oflag;
945 case MD_CTL:
946 return &t->c_cflag;
947 case MD_LIN:
948 return &t->c_lflag;
949 default:
950 abort();
951 /*NOTREACHED*/
952 }
953 }
954
955
956 private tcflag_t
957 tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
958 {
959 f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
960 f |= el->el_tty.t_t[mode][kind].t_setmask;
961 return f;
962 }
963
964
965 private void
966 tty_update_flags(EditLine *el, int kind)
967 {
968 tcflag_t *tt, *ed, *ex;
969 tt = tty__get_flag(&el->el_tty.t_ts, kind);
970 ed = tty__get_flag(&el->el_tty.t_ed, kind);
971 ex = tty__get_flag(&el->el_tty.t_ex, kind);
972
973 if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) {
974 *ed = tty_update_flag(el, *tt, ED_IO, kind);
975 *ex = tty_update_flag(el, *tt, EX_IO, kind);
976 }
977 }
978
979
980 private void
981 tty_update_char(EditLine *el, int mode, int c) {
982 if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c)))
983 && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c]))
984 el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c];
985 if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c))
986 el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable;
987 }
988
989
990 /* tty_rawmode():
991 * Set terminal into 1 character at a time mode.
992 */
993 protected int
994 tty_rawmode(EditLine *el)
995 {
996
997 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO)
998 return 0;
999
1000 if (el->el_flags & EDIT_DISABLED)
1001 return 0;
1002
1003 if (tty_getty(el, &el->el_tty.t_ts) == -1) {
1004 #ifdef DEBUG_TTY
1005 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__,
1006 strerror(errno));
1007 #endif /* DEBUG_TTY */
1008 return -1;
1009 }
1010 /*
1011 * We always keep up with the eight bit setting and the speed of the
1012 * tty. But we only believe changes that are made to cooked mode!
1013 */
1014 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts);
1015 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts);
1016
1017 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed ||
1018 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) {
1019 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1020 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed);
1021 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1022 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
1023 }
1024 if (tty__cooked_mode(&el->el_tty.t_ts)) {
1025 int i;
1026
1027 for (i = MD_INP; i <= MD_LIN; i++)
1028 tty_update_flags(el, i);
1029
1030 if (tty__gettabs(&el->el_tty.t_ex) == 0)
1031 el->el_tty.t_tabs = 0;
1032 else
1033 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
1034
1035 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
1036 /*
1037 * Check if the user made any changes.
1038 * If he did, then propagate the changes to the
1039 * edit and execute data structures.
1040 */
1041 for (i = 0; i < C_NCC; i++)
1042 if (el->el_tty.t_c[TS_IO][i] !=
1043 el->el_tty.t_c[EX_IO][i])
1044 break;
1045
1046 if (i != C_NCC) {
1047 /*
1048 * Propagate changes only to the unprotected
1049 * chars that have been modified just now.
1050 */
1051 for (i = 0; i < C_NCC; i++)
1052 tty_update_char(el, ED_IO, i);
1053
1054 tty_bind_char(el, 0);
1055 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
1056
1057 for (i = 0; i < C_NCC; i++)
1058 tty_update_char(el, EX_IO, i);
1059
1060 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
1061 }
1062 }
1063 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1064 #ifdef DEBUG_TTY
1065 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1066 strerror(errno));
1067 #endif /* DEBUG_TTY */
1068 return -1;
1069 }
1070 el->el_tty.t_mode = ED_IO;
1071 return 0;
1072 }
1073
1074
1075 /* tty_cookedmode():
1076 * Set the tty back to normal mode
1077 */
1078 protected int
1079 tty_cookedmode(EditLine *el)
1080 { /* set tty in normal setup */
1081
1082 if (el->el_tty.t_mode == EX_IO)
1083 return 0;
1084
1085 if (el->el_flags & EDIT_DISABLED)
1086 return 0;
1087
1088 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) {
1089 #ifdef DEBUG_TTY
1090 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1091 strerror(errno));
1092 #endif /* DEBUG_TTY */
1093 return -1;
1094 }
1095 el->el_tty.t_mode = EX_IO;
1096 return 0;
1097 }
1098
1099
1100 /* tty_quotemode():
1101 * Turn on quote mode
1102 */
1103 protected int
1104 tty_quotemode(EditLine *el)
1105 {
1106 if (el->el_tty.t_mode == QU_IO)
1107 return 0;
1108
1109 el->el_tty.t_qu = el->el_tty.t_ed;
1110
1111 tty_setup_flags(el, &el->el_tty.t_qu, QU_IO);
1112
1113 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
1114 #ifdef DEBUG_TTY
1115 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1116 strerror(errno));
1117 #endif /* DEBUG_TTY */
1118 return -1;
1119 }
1120 el->el_tty.t_mode = QU_IO;
1121 return 0;
1122 }
1123
1124
1125 /* tty_noquotemode():
1126 * Turn off quote mode
1127 */
1128 protected int
1129 tty_noquotemode(EditLine *el)
1130 {
1131
1132 if (el->el_tty.t_mode != QU_IO)
1133 return 0;
1134 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
1135 #ifdef DEBUG_TTY
1136 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__,
1137 strerror(errno));
1138 #endif /* DEBUG_TTY */
1139 return -1;
1140 }
1141 el->el_tty.t_mode = ED_IO;
1142 return 0;
1143 }
1144
1145
1146 /* tty_stty():
1147 * Stty builtin
1148 */
1149 protected int
1150 /*ARGSUSED*/
1151 tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
1152 {
1153 const ttymodes_t *m;
1154 char x;
1155 int aflag = 0;
1156 const Char *s, *d;
1157 char name[EL_BUFSIZ];
1158 struct termios *tios = &el->el_tty.t_ex;
1159 int z = EX_IO;
1160
1161 if (argv == NULL)
1162 return -1;
1163 strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name));
1164 name[sizeof(name) - 1] = '\0';
1165
1166 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0')
1167 switch (argv[0][1]) {
1168 case 'a':
1169 aflag++;
1170 argv++;
1171 break;
1172 case 'd':
1173 argv++;
1174 tios = &el->el_tty.t_ed;
1175 z = ED_IO;
1176 break;
1177 case 'x':
1178 argv++;
1179 tios = &el->el_tty.t_ex;
1180 z = EX_IO;
1181 break;
1182 case 'q':
1183 argv++;
1184 tios = &el->el_tty.t_ts;
1185 z = QU_IO;
1186 break;
1187 default:
1188 (void) fprintf(el->el_errfile,
1189 "%s: Unknown switch `%lc'.\n",
1190 name, (wint_t)argv[0][1]);
1191 return -1;
1192 }
1193
1194 if (!argv || !*argv) {
1195 int i = -1;
1196 size_t len = 0, st = 0, cu;
1197 for (m = ttymodes; m->m_name; m++) {
1198 if (m->m_type != i) {
1199 (void) fprintf(el->el_outfile, "%s%s",
1200 i != -1 ? "\n" : "",
1201 el->el_tty.t_t[z][m->m_type].t_name);
1202 i = m->m_type;
1203 st = len =
1204 strlen(el->el_tty.t_t[z][m->m_type].t_name);
1205 }
1206 if (i != -1) {
1207 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value)
1208 ? '+' : '\0';
1209
1210 if (el->el_tty.t_t[z][i].t_clrmask & m->m_value)
1211 x = '-';
1212 } else {
1213 x = '\0';
1214 }
1215
1216 if (x != '\0' || aflag) {
1217
1218 cu = strlen(m->m_name) + (x != '\0') + 1;
1219
1220 if (len + cu >=
1221 (size_t)el->el_terminal.t_size.h) {
1222 (void) fprintf(el->el_outfile, "\n%*s",
1223 (int)st, "");
1224 len = st + cu;
1225 } else
1226 len += cu;
1227
1228 if (x != '\0')
1229 (void) fprintf(el->el_outfile, "%c%s ",
1230 x, m->m_name);
1231 else
1232 (void) fprintf(el->el_outfile, "%s ",
1233 m->m_name);
1234 }
1235 }
1236 (void) fprintf(el->el_outfile, "\n");
1237 return 0;
1238 }
1239 while (argv && (s = *argv++)) {
1240 const Char *p;
1241 switch (*s) {
1242 case '+':
1243 case '-':
1244 x = (char)*s++;
1245 break;
1246 default:
1247 x = '\0';
1248 break;
1249 }
1250 d = s;
1251 p = Strchr(s, '=');
1252 for (m = ttymodes; m->m_name; m++)
1253 if ((p ? strncmp(m->m_name, ct_encode_string(d,
1254 &el->el_scratch), (size_t)(p - d)) :
1255 strcmp(m->m_name, ct_encode_string(d,
1256 &el->el_scratch))) == 0 &&
1257 (p == NULL || m->m_type == MD_CHAR))
1258 break;
1259
1260 if (!m->m_name) {
1261 (void) fprintf(el->el_errfile,
1262 "%s: Invalid argument `%ls'.\n", name, d);
1263 return -1;
1264 }
1265 if (p) {
1266 int c = ffs((int)m->m_value);
1267 int v = *++p ? parse__escape(&p) :
1268 el->el_tty.t_vdisable;
1269 assert(c != 0);
1270 c--;
1271 c = tty__getcharindex(c);
1272 assert(c != -1);
1273 tios->c_cc[c] = (cc_t)v;
1274 continue;
1275 }
1276 switch (x) {
1277 case '+':
1278 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value;
1279 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1280 break;
1281 case '-':
1282 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1283 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value;
1284 break;
1285 default:
1286 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value;
1287 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value;
1288 break;
1289 }
1290 }
1291
1292 tty_setup_flags(el, tios, z);
1293 if (el->el_tty.t_mode == z) {
1294 if (tty_setty(el, TCSADRAIN, tios) == -1) {
1295 #ifdef DEBUG_TTY
1296 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n",
1297 __func__, strerror(errno));
1298 #endif /* DEBUG_TTY */
1299 return -1;
1300 }
1301 }
1302
1303 return 0;
1304 }
1305
1306
1307 #ifdef notyet
1308 /* tty_printchar():
1309 * DEbugging routine to print the tty characters
1310 */
1311 private void
1312 tty_printchar(EditLine *el, unsigned char *s)
1313 {
1314 ttyperm_t *m;
1315 int i;
1316
1317 for (i = 0; i < C_NCC; i++) {
1318 for (m = el->el_tty.t_t; m->m_name; m++)
1319 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value)
1320 break;
1321 if (m->m_name)
1322 (void) fprintf(el->el_errfile, "%s ^%c ",
1323 m->m_name, s[i] + 'A' - 1);
1324 if (i % 5 == 0)
1325 (void) fprintf(el->el_errfile, "\n");
1326 }
1327 (void) fprintf(el->el_errfile, "\n");
1328 }
1329 #endif /* notyet */
1330
1331
1332 private void
1333 tty_setup_flags(EditLine *el, struct termios *tios, int mode)
1334 {
1335 int kind;
1336 for (kind = MD_INP; kind <= MD_LIN; kind++) {
1337 tcflag_t *f = tty__get_flag(tios, kind);
1338 *f = tty_update_flag(el, *f, mode, kind);
1339 }
1340 }
1341