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