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