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