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