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