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