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