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