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