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