1 /* $NetBSD: tty.c,v 1.59 2016/03/22 01:34:32 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.59 2016/03/22 01:34:32 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 <stdlib.h> /* for abort */ 50 #include <string.h> 51 #include <strings.h> /* for ffs */ 52 #include <unistd.h> /* for isatty */ 53 54 #include "el.h" 55 #include "parse.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 wint_t 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 {(wint_t)-1, (wint_t)-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 (el->el_tty.t_initialized) 505 return -1; 506 507 if (!isatty(el->el_outfd)) { 508 #ifdef DEBUG_TTY 509 (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__, 510 strerror(errno)); 511 #endif /* DEBUG_TTY */ 512 return -1; 513 } 514 if (tty_getty(el, &el->el_tty.t_or) == -1) { 515 #ifdef DEBUG_TTY 516 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__, 517 strerror(errno)); 518 #endif /* DEBUG_TTY */ 519 return -1; 520 } 521 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or; 522 523 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex); 524 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex); 525 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex); 526 527 tty_setup_flags(el, &el->el_tty.t_ex, EX_IO); 528 529 /* 530 * Reset the tty chars to reasonable defaults 531 * If they are disabled, then enable them. 532 */ 533 if (rst) { 534 if (tty__cooked_mode(&el->el_tty.t_ts)) { 535 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); 536 /* 537 * Don't affect CMIN and CTIME for the editor mode 538 */ 539 for (rst = 0; rst < C_NCC - 2; rst++) 540 if (el->el_tty.t_c[TS_IO][rst] != 541 el->el_tty.t_vdisable 542 && el->el_tty.t_c[ED_IO][rst] != 543 el->el_tty.t_vdisable) 544 el->el_tty.t_c[ED_IO][rst] = 545 el->el_tty.t_c[TS_IO][rst]; 546 for (rst = 0; rst < C_NCC; rst++) 547 if (el->el_tty.t_c[TS_IO][rst] != 548 el->el_tty.t_vdisable) 549 el->el_tty.t_c[EX_IO][rst] = 550 el->el_tty.t_c[TS_IO][rst]; 551 } 552 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); 553 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { 554 #ifdef DEBUG_TTY 555 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", 556 __func__, strerror(errno)); 557 #endif /* DEBUG_TTY */ 558 return -1; 559 } 560 } 561 562 tty_setup_flags(el, &el->el_tty.t_ed, ED_IO); 563 564 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); 565 tty_bind_char(el, 1); 566 el->el_tty.t_initialized = 1; 567 return 0; 568 } 569 570 protected int 571 tty_init(EditLine *el) 572 { 573 574 el->el_tty.t_mode = EX_IO; 575 el->el_tty.t_vdisable = _POSIX_VDISABLE; 576 el->el_tty.t_initialized = 0; 577 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); 578 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); 579 return tty_setup(el); 580 } 581 582 583 /* tty_end(): 584 * Restore the tty to its original settings 585 */ 586 protected void 587 /*ARGSUSED*/ 588 tty_end(EditLine *el) 589 { 590 if (el->el_flags & EDIT_DISABLED) 591 return; 592 593 if (!el->el_tty.t_initialized) 594 return; 595 596 if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) { 597 #ifdef DEBUG_TTY 598 (void) fprintf(el->el_errfile, 599 "%s: tty_setty: %s\n", __func__, strerror(errno)); 600 #endif /* DEBUG_TTY */ 601 } 602 } 603 604 605 /* tty__getspeed(): 606 * Get the tty speed 607 */ 608 private speed_t 609 tty__getspeed(struct termios *td) 610 { 611 speed_t spd; 612 613 if ((spd = cfgetispeed(td)) == 0) 614 spd = cfgetospeed(td); 615 return spd; 616 } 617 618 /* tty__getspeed(): 619 * Return the index of the asked char in the c_cc array 620 */ 621 private int 622 tty__getcharindex(int i) 623 { 624 switch (i) { 625 #ifdef VINTR 626 case C_INTR: 627 return VINTR; 628 #endif /* VINTR */ 629 #ifdef VQUIT 630 case C_QUIT: 631 return VQUIT; 632 #endif /* VQUIT */ 633 #ifdef VERASE 634 case C_ERASE: 635 return VERASE; 636 #endif /* VERASE */ 637 #ifdef VKILL 638 case C_KILL: 639 return VKILL; 640 #endif /* VKILL */ 641 #ifdef VEOF 642 case C_EOF: 643 return VEOF; 644 #endif /* VEOF */ 645 #ifdef VEOL 646 case C_EOL: 647 return VEOL; 648 #endif /* VEOL */ 649 #ifdef VEOL2 650 case C_EOL2: 651 return VEOL2; 652 #endif /* VEOL2 */ 653 #ifdef VSWTCH 654 case C_SWTCH: 655 return VSWTCH; 656 #endif /* VSWTCH */ 657 #ifdef VDSWTCH 658 case C_DSWTCH: 659 return VDSWTCH; 660 #endif /* VDSWTCH */ 661 #ifdef VERASE2 662 case C_ERASE2: 663 return VERASE2; 664 #endif /* VERASE2 */ 665 #ifdef VSTART 666 case C_START: 667 return VSTART; 668 #endif /* VSTART */ 669 #ifdef VSTOP 670 case C_STOP: 671 return VSTOP; 672 #endif /* VSTOP */ 673 #ifdef VWERASE 674 case C_WERASE: 675 return VWERASE; 676 #endif /* VWERASE */ 677 #ifdef VSUSP 678 case C_SUSP: 679 return VSUSP; 680 #endif /* VSUSP */ 681 #ifdef VDSUSP 682 case C_DSUSP: 683 return VDSUSP; 684 #endif /* VDSUSP */ 685 #ifdef VREPRINT 686 case C_REPRINT: 687 return VREPRINT; 688 #endif /* VREPRINT */ 689 #ifdef VDISCARD 690 case C_DISCARD: 691 return VDISCARD; 692 #endif /* VDISCARD */ 693 #ifdef VLNEXT 694 case C_LNEXT: 695 return VLNEXT; 696 #endif /* VLNEXT */ 697 #ifdef VSTATUS 698 case C_STATUS: 699 return VSTATUS; 700 #endif /* VSTATUS */ 701 #ifdef VPAGE 702 case C_PAGE: 703 return VPAGE; 704 #endif /* VPAGE */ 705 #ifdef VPGOFF 706 case C_PGOFF: 707 return VPGOFF; 708 #endif /* VPGOFF */ 709 #ifdef VKILL2 710 case C_KILL2: 711 return VKILL2; 712 #endif /* KILL2 */ 713 #ifdef VMIN 714 case C_MIN: 715 return VMIN; 716 #endif /* VMIN */ 717 #ifdef VTIME 718 case C_TIME: 719 return VTIME; 720 #endif /* VTIME */ 721 default: 722 return -1; 723 } 724 } 725 726 /* tty__getchar(): 727 * Get the tty characters 728 */ 729 private void 730 tty__getchar(struct termios *td, unsigned char *s) 731 { 732 733 #ifdef VINTR 734 s[C_INTR] = td->c_cc[VINTR]; 735 #endif /* VINTR */ 736 #ifdef VQUIT 737 s[C_QUIT] = td->c_cc[VQUIT]; 738 #endif /* VQUIT */ 739 #ifdef VERASE 740 s[C_ERASE] = td->c_cc[VERASE]; 741 #endif /* VERASE */ 742 #ifdef VKILL 743 s[C_KILL] = td->c_cc[VKILL]; 744 #endif /* VKILL */ 745 #ifdef VEOF 746 s[C_EOF] = td->c_cc[VEOF]; 747 #endif /* VEOF */ 748 #ifdef VEOL 749 s[C_EOL] = td->c_cc[VEOL]; 750 #endif /* VEOL */ 751 #ifdef VEOL2 752 s[C_EOL2] = td->c_cc[VEOL2]; 753 #endif /* VEOL2 */ 754 #ifdef VSWTCH 755 s[C_SWTCH] = td->c_cc[VSWTCH]; 756 #endif /* VSWTCH */ 757 #ifdef VDSWTCH 758 s[C_DSWTCH] = td->c_cc[VDSWTCH]; 759 #endif /* VDSWTCH */ 760 #ifdef VERASE2 761 s[C_ERASE2] = td->c_cc[VERASE2]; 762 #endif /* VERASE2 */ 763 #ifdef VSTART 764 s[C_START] = td->c_cc[VSTART]; 765 #endif /* VSTART */ 766 #ifdef VSTOP 767 s[C_STOP] = td->c_cc[VSTOP]; 768 #endif /* VSTOP */ 769 #ifdef VWERASE 770 s[C_WERASE] = td->c_cc[VWERASE]; 771 #endif /* VWERASE */ 772 #ifdef VSUSP 773 s[C_SUSP] = td->c_cc[VSUSP]; 774 #endif /* VSUSP */ 775 #ifdef VDSUSP 776 s[C_DSUSP] = td->c_cc[VDSUSP]; 777 #endif /* VDSUSP */ 778 #ifdef VREPRINT 779 s[C_REPRINT] = td->c_cc[VREPRINT]; 780 #endif /* VREPRINT */ 781 #ifdef VDISCARD 782 s[C_DISCARD] = td->c_cc[VDISCARD]; 783 #endif /* VDISCARD */ 784 #ifdef VLNEXT 785 s[C_LNEXT] = td->c_cc[VLNEXT]; 786 #endif /* VLNEXT */ 787 #ifdef VSTATUS 788 s[C_STATUS] = td->c_cc[VSTATUS]; 789 #endif /* VSTATUS */ 790 #ifdef VPAGE 791 s[C_PAGE] = td->c_cc[VPAGE]; 792 #endif /* VPAGE */ 793 #ifdef VPGOFF 794 s[C_PGOFF] = td->c_cc[VPGOFF]; 795 #endif /* VPGOFF */ 796 #ifdef VKILL2 797 s[C_KILL2] = td->c_cc[VKILL2]; 798 #endif /* KILL2 */ 799 #ifdef VMIN 800 s[C_MIN] = td->c_cc[VMIN]; 801 #endif /* VMIN */ 802 #ifdef VTIME 803 s[C_TIME] = td->c_cc[VTIME]; 804 #endif /* VTIME */ 805 } /* tty__getchar */ 806 807 808 /* tty__setchar(): 809 * Set the tty characters 810 */ 811 private void 812 tty__setchar(struct termios *td, unsigned char *s) 813 { 814 815 #ifdef VINTR 816 td->c_cc[VINTR] = s[C_INTR]; 817 #endif /* VINTR */ 818 #ifdef VQUIT 819 td->c_cc[VQUIT] = s[C_QUIT]; 820 #endif /* VQUIT */ 821 #ifdef VERASE 822 td->c_cc[VERASE] = s[C_ERASE]; 823 #endif /* VERASE */ 824 #ifdef VKILL 825 td->c_cc[VKILL] = s[C_KILL]; 826 #endif /* VKILL */ 827 #ifdef VEOF 828 td->c_cc[VEOF] = s[C_EOF]; 829 #endif /* VEOF */ 830 #ifdef VEOL 831 td->c_cc[VEOL] = s[C_EOL]; 832 #endif /* VEOL */ 833 #ifdef VEOL2 834 td->c_cc[VEOL2] = s[C_EOL2]; 835 #endif /* VEOL2 */ 836 #ifdef VSWTCH 837 td->c_cc[VSWTCH] = s[C_SWTCH]; 838 #endif /* VSWTCH */ 839 #ifdef VDSWTCH 840 td->c_cc[VDSWTCH] = s[C_DSWTCH]; 841 #endif /* VDSWTCH */ 842 #ifdef VERASE2 843 td->c_cc[VERASE2] = s[C_ERASE2]; 844 #endif /* VERASE2 */ 845 #ifdef VSTART 846 td->c_cc[VSTART] = s[C_START]; 847 #endif /* VSTART */ 848 #ifdef VSTOP 849 td->c_cc[VSTOP] = s[C_STOP]; 850 #endif /* VSTOP */ 851 #ifdef VWERASE 852 td->c_cc[VWERASE] = s[C_WERASE]; 853 #endif /* VWERASE */ 854 #ifdef VSUSP 855 td->c_cc[VSUSP] = s[C_SUSP]; 856 #endif /* VSUSP */ 857 #ifdef VDSUSP 858 td->c_cc[VDSUSP] = s[C_DSUSP]; 859 #endif /* VDSUSP */ 860 #ifdef VREPRINT 861 td->c_cc[VREPRINT] = s[C_REPRINT]; 862 #endif /* VREPRINT */ 863 #ifdef VDISCARD 864 td->c_cc[VDISCARD] = s[C_DISCARD]; 865 #endif /* VDISCARD */ 866 #ifdef VLNEXT 867 td->c_cc[VLNEXT] = s[C_LNEXT]; 868 #endif /* VLNEXT */ 869 #ifdef VSTATUS 870 td->c_cc[VSTATUS] = s[C_STATUS]; 871 #endif /* VSTATUS */ 872 #ifdef VPAGE 873 td->c_cc[VPAGE] = s[C_PAGE]; 874 #endif /* VPAGE */ 875 #ifdef VPGOFF 876 td->c_cc[VPGOFF] = s[C_PGOFF]; 877 #endif /* VPGOFF */ 878 #ifdef VKILL2 879 td->c_cc[VKILL2] = s[C_KILL2]; 880 #endif /* VKILL2 */ 881 #ifdef VMIN 882 td->c_cc[VMIN] = s[C_MIN]; 883 #endif /* VMIN */ 884 #ifdef VTIME 885 td->c_cc[VTIME] = s[C_TIME]; 886 #endif /* VTIME */ 887 } /* tty__setchar */ 888 889 890 /* tty_bind_char(): 891 * Rebind the editline functions 892 */ 893 protected void 894 tty_bind_char(EditLine *el, int force) 895 { 896 897 unsigned char *t_n = el->el_tty.t_c[ED_IO]; 898 unsigned char *t_o = el->el_tty.t_ed.c_cc; 899 Char new[2], old[2]; 900 const ttymap_t *tp; 901 el_action_t *map, *alt; 902 const el_action_t *dmap, *dalt; 903 new[1] = old[1] = '\0'; 904 905 map = el->el_map.key; 906 alt = el->el_map.alt; 907 if (el->el_map.type == MAP_VI) { 908 dmap = el->el_map.vii; 909 dalt = el->el_map.vic; 910 } else { 911 dmap = el->el_map.emacs; 912 dalt = NULL; 913 } 914 915 for (tp = tty_map; tp->nch != (wint_t)-1; tp++) { 916 new[0] = (Char)t_n[tp->nch]; 917 old[0] = (Char)t_o[tp->och]; 918 if (new[0] == old[0] && !force) 919 continue; 920 /* Put the old default binding back, and set the new binding */ 921 keymacro_clear(el, map, old); 922 map[UC(old[0])] = dmap[UC(old[0])]; 923 keymacro_clear(el, map, new); 924 /* MAP_VI == 1, MAP_EMACS == 0... */ 925 map[UC(new[0])] = tp->bind[el->el_map.type]; 926 if (dalt) { 927 keymacro_clear(el, alt, old); 928 alt[UC(old[0])] = dalt[UC(old[0])]; 929 keymacro_clear(el, alt, new); 930 alt[UC(new[0])] = tp->bind[el->el_map.type + 1]; 931 } 932 } 933 } 934 935 936 private tcflag_t * 937 tty__get_flag(struct termios *t, int kind) { 938 switch (kind) { 939 case MD_INP: 940 return &t->c_iflag; 941 case MD_OUT: 942 return &t->c_oflag; 943 case MD_CTL: 944 return &t->c_cflag; 945 case MD_LIN: 946 return &t->c_lflag; 947 default: 948 abort(); 949 /*NOTREACHED*/ 950 } 951 } 952 953 954 private tcflag_t 955 tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind) 956 { 957 f &= ~el->el_tty.t_t[mode][kind].t_clrmask; 958 f |= el->el_tty.t_t[mode][kind].t_setmask; 959 return f; 960 } 961 962 963 private void 964 tty_update_flags(EditLine *el, int kind) 965 { 966 tcflag_t *tt, *ed, *ex; 967 tt = tty__get_flag(&el->el_tty.t_ts, kind); 968 ed = tty__get_flag(&el->el_tty.t_ed, kind); 969 ex = tty__get_flag(&el->el_tty.t_ex, kind); 970 971 if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) { 972 *ed = tty_update_flag(el, *tt, ED_IO, kind); 973 *ex = tty_update_flag(el, *tt, EX_IO, kind); 974 } 975 } 976 977 978 private void 979 tty_update_char(EditLine *el, int mode, int c) { 980 if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c))) 981 && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c])) 982 el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c]; 983 if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c)) 984 el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable; 985 } 986 987 988 /* tty_rawmode(): 989 * Set terminal into 1 character at a time mode. 990 */ 991 protected int 992 tty_rawmode(EditLine *el) 993 { 994 995 if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO) 996 return 0; 997 998 if (el->el_flags & EDIT_DISABLED) 999 return 0; 1000 1001 if (tty_getty(el, &el->el_tty.t_ts) == -1) { 1002 #ifdef DEBUG_TTY 1003 (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__, 1004 strerror(errno)); 1005 #endif /* DEBUG_TTY */ 1006 return -1; 1007 } 1008 /* 1009 * We always keep up with the eight bit setting and the speed of the 1010 * tty. But we only believe changes that are made to cooked mode! 1011 */ 1012 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts); 1013 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts); 1014 1015 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed || 1016 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) { 1017 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed); 1018 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed); 1019 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed); 1020 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed); 1021 } 1022 if (tty__cooked_mode(&el->el_tty.t_ts)) { 1023 int i; 1024 1025 for (i = MD_INP; i <= MD_LIN; i++) 1026 tty_update_flags(el, i); 1027 1028 if (tty__gettabs(&el->el_tty.t_ex) == 0) 1029 el->el_tty.t_tabs = 0; 1030 else 1031 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0; 1032 1033 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); 1034 /* 1035 * Check if the user made any changes. 1036 * If he did, then propagate the changes to the 1037 * edit and execute data structures. 1038 */ 1039 for (i = 0; i < C_NCC; i++) 1040 if (el->el_tty.t_c[TS_IO][i] != 1041 el->el_tty.t_c[EX_IO][i]) 1042 break; 1043 1044 if (i != C_NCC) { 1045 /* 1046 * Propagate changes only to the unprotected 1047 * chars that have been modified just now. 1048 */ 1049 for (i = 0; i < C_NCC; i++) 1050 tty_update_char(el, ED_IO, i); 1051 1052 tty_bind_char(el, 0); 1053 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); 1054 1055 for (i = 0; i < C_NCC; i++) 1056 tty_update_char(el, EX_IO, i); 1057 1058 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); 1059 } 1060 } 1061 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { 1062 #ifdef DEBUG_TTY 1063 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, 1064 strerror(errno)); 1065 #endif /* DEBUG_TTY */ 1066 return -1; 1067 } 1068 el->el_tty.t_mode = ED_IO; 1069 return 0; 1070 } 1071 1072 1073 /* tty_cookedmode(): 1074 * Set the tty back to normal mode 1075 */ 1076 protected int 1077 tty_cookedmode(EditLine *el) 1078 { /* set tty in normal setup */ 1079 1080 if (el->el_tty.t_mode == EX_IO) 1081 return 0; 1082 1083 if (el->el_flags & EDIT_DISABLED) 1084 return 0; 1085 1086 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { 1087 #ifdef DEBUG_TTY 1088 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, 1089 strerror(errno)); 1090 #endif /* DEBUG_TTY */ 1091 return -1; 1092 } 1093 el->el_tty.t_mode = EX_IO; 1094 return 0; 1095 } 1096 1097 1098 /* tty_quotemode(): 1099 * Turn on quote mode 1100 */ 1101 protected int 1102 tty_quotemode(EditLine *el) 1103 { 1104 if (el->el_tty.t_mode == QU_IO) 1105 return 0; 1106 1107 el->el_tty.t_qu = el->el_tty.t_ed; 1108 1109 tty_setup_flags(el, &el->el_tty.t_qu, QU_IO); 1110 1111 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) { 1112 #ifdef DEBUG_TTY 1113 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, 1114 strerror(errno)); 1115 #endif /* DEBUG_TTY */ 1116 return -1; 1117 } 1118 el->el_tty.t_mode = QU_IO; 1119 return 0; 1120 } 1121 1122 1123 /* tty_noquotemode(): 1124 * Turn off quote mode 1125 */ 1126 protected int 1127 tty_noquotemode(EditLine *el) 1128 { 1129 1130 if (el->el_tty.t_mode != QU_IO) 1131 return 0; 1132 if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { 1133 #ifdef DEBUG_TTY 1134 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, 1135 strerror(errno)); 1136 #endif /* DEBUG_TTY */ 1137 return -1; 1138 } 1139 el->el_tty.t_mode = ED_IO; 1140 return 0; 1141 } 1142 1143 1144 /* tty_stty(): 1145 * Stty builtin 1146 */ 1147 protected int 1148 /*ARGSUSED*/ 1149 tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv) 1150 { 1151 const ttymodes_t *m; 1152 char x; 1153 int aflag = 0; 1154 const Char *s, *d; 1155 char name[EL_BUFSIZ]; 1156 struct termios *tios = &el->el_tty.t_ex; 1157 int z = EX_IO; 1158 1159 if (argv == NULL) 1160 return -1; 1161 strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name)); 1162 name[sizeof(name) - 1] = '\0'; 1163 1164 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0') 1165 switch (argv[0][1]) { 1166 case 'a': 1167 aflag++; 1168 argv++; 1169 break; 1170 case 'd': 1171 argv++; 1172 tios = &el->el_tty.t_ed; 1173 z = ED_IO; 1174 break; 1175 case 'x': 1176 argv++; 1177 tios = &el->el_tty.t_ex; 1178 z = EX_IO; 1179 break; 1180 case 'q': 1181 argv++; 1182 tios = &el->el_tty.t_ts; 1183 z = QU_IO; 1184 break; 1185 default: 1186 (void) fprintf(el->el_errfile, 1187 "%s: Unknown switch `%lc'.\n", 1188 name, (wint_t)argv[0][1]); 1189 return -1; 1190 } 1191 1192 if (!argv || !*argv) { 1193 int i = -1; 1194 size_t len = 0, st = 0, cu; 1195 for (m = ttymodes; m->m_name; m++) { 1196 if (m->m_type != i) { 1197 (void) fprintf(el->el_outfile, "%s%s", 1198 i != -1 ? "\n" : "", 1199 el->el_tty.t_t[z][m->m_type].t_name); 1200 i = m->m_type; 1201 st = len = 1202 strlen(el->el_tty.t_t[z][m->m_type].t_name); 1203 } 1204 if (i != -1) { 1205 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) 1206 ? '+' : '\0'; 1207 1208 if (el->el_tty.t_t[z][i].t_clrmask & m->m_value) 1209 x = '-'; 1210 } else { 1211 x = '\0'; 1212 } 1213 1214 if (x != '\0' || aflag) { 1215 1216 cu = strlen(m->m_name) + (x != '\0') + 1; 1217 1218 if (len + cu >= 1219 (size_t)el->el_terminal.t_size.h) { 1220 (void) fprintf(el->el_outfile, "\n%*s", 1221 (int)st, ""); 1222 len = st + cu; 1223 } else 1224 len += cu; 1225 1226 if (x != '\0') 1227 (void) fprintf(el->el_outfile, "%c%s ", 1228 x, m->m_name); 1229 else 1230 (void) fprintf(el->el_outfile, "%s ", 1231 m->m_name); 1232 } 1233 } 1234 (void) fprintf(el->el_outfile, "\n"); 1235 return 0; 1236 } 1237 while (argv && (s = *argv++)) { 1238 const Char *p; 1239 switch (*s) { 1240 case '+': 1241 case '-': 1242 x = (char)*s++; 1243 break; 1244 default: 1245 x = '\0'; 1246 break; 1247 } 1248 d = s; 1249 p = Strchr(s, '='); 1250 for (m = ttymodes; m->m_name; m++) 1251 if ((p ? strncmp(m->m_name, ct_encode_string(d, 1252 &el->el_scratch), (size_t)(p - d)) : 1253 strcmp(m->m_name, ct_encode_string(d, 1254 &el->el_scratch))) == 0 && 1255 (p == NULL || m->m_type == MD_CHAR)) 1256 break; 1257 1258 if (!m->m_name) { 1259 (void) fprintf(el->el_errfile, 1260 "%s: Invalid argument `" FSTR "'.\n", name, d); 1261 return -1; 1262 } 1263 if (p) { 1264 int c = ffs((int)m->m_value); 1265 int v = *++p ? parse__escape(&p) : 1266 el->el_tty.t_vdisable; 1267 assert(c != 0); 1268 c--; 1269 c = tty__getcharindex(c); 1270 assert(c != -1); 1271 tios->c_cc[c] = (cc_t)v; 1272 continue; 1273 } 1274 switch (x) { 1275 case '+': 1276 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; 1277 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; 1278 break; 1279 case '-': 1280 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; 1281 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value; 1282 break; 1283 default: 1284 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; 1285 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; 1286 break; 1287 } 1288 } 1289 1290 tty_setup_flags(el, tios, z); 1291 if (el->el_tty.t_mode == z) { 1292 if (tty_setty(el, TCSADRAIN, tios) == -1) { 1293 #ifdef DEBUG_TTY 1294 (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", 1295 __func__, strerror(errno)); 1296 #endif /* DEBUG_TTY */ 1297 return -1; 1298 } 1299 } 1300 1301 return 0; 1302 } 1303 1304 1305 #ifdef notyet 1306 /* tty_printchar(): 1307 * DEbugging routine to print the tty characters 1308 */ 1309 private void 1310 tty_printchar(EditLine *el, unsigned char *s) 1311 { 1312 ttyperm_t *m; 1313 int i; 1314 1315 for (i = 0; i < C_NCC; i++) { 1316 for (m = el->el_tty.t_t; m->m_name; m++) 1317 if (m->m_type == MD_CHAR && C_SH(i) == m->m_value) 1318 break; 1319 if (m->m_name) 1320 (void) fprintf(el->el_errfile, "%s ^%c ", 1321 m->m_name, s[i] + 'A' - 1); 1322 if (i % 5 == 0) 1323 (void) fprintf(el->el_errfile, "\n"); 1324 } 1325 (void) fprintf(el->el_errfile, "\n"); 1326 } 1327 #endif /* notyet */ 1328 1329 1330 private void 1331 tty_setup_flags(EditLine *el, struct termios *tios, int mode) 1332 { 1333 int kind; 1334 for (kind = MD_INP; kind <= MD_LIN; kind++) { 1335 tcflag_t *f = tty__get_flag(tios, kind); 1336 *f = tty_update_flag(el, *f, mode, kind); 1337 } 1338 } 1339