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