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