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