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