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