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