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