"Fossies" - the Fresh Open Source Software Archive

Member "tnftp-20200705/libedit/tty.c" (4 Jul 2020, 31309 Bytes) of package /linux/privat/tnftp-20200705.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tty.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 20151004_vs_20200705.

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