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