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