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