1 /*- 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Christos Zoulas of Cornell University. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #if !defined(lint) && !defined(SCCSID) 12 static char sccsid[] = "@(#)tty.c 5.2 (Berkeley) 07/03/92"; 13 #endif /* not lint && not SCCSID */ 14 15 /* 16 * tty.c: tty interface stuff 17 */ 18 #include "sys.h" 19 #include "tty.h" 20 #include "el.h" 21 22 private ttyperm_t ttyperm = { 23 { 24 { "iflag:", ICRNL, (INLCR|IGNCR) }, 25 { "oflag:", (OPOST|ONLCR), ONLRET }, 26 { "cflag:", 0, 0 }, 27 { "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN), 28 (NOFLSH|ECHONL|EXTPROC|FLUSHO) }, 29 { "chars:", 0, 0 }, 30 }, 31 { 32 { "iflag:", (INLCR|ICRNL), IGNCR }, 33 { "oflag:", (OPOST|ONLCR), ONLRET }, 34 { "cflag:", 0, 0 }, 35 { "lflag:", ISIG, 36 (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO) }, 37 { "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)| 38 C_SH(C_WERASE)|C_SH(C_REPRINT)|C_SH(C_SUSP)|C_SH(C_DSUSP)| 39 C_SH(C_EOF)|C_SH(C_EOL)|C_SH(C_DISCARD)|C_SH(C_PGOFF)| 40 C_SH(C_KILL2)|C_SH(C_PAGE)|C_SH(C_STATUS)|C_SH(C_LNEXT)), 41 0 } 42 }, 43 { 44 { "iflag:", 0, IXON | IXOFF }, 45 { "oflag:", 0, 0 }, 46 { "cflag:", 0, 0 }, 47 { "lflag:", 0, ISIG | IEXTEN }, 48 { "chars:", 0, 0 }, 49 } 50 }; 51 52 private ttychar_t ttychar = { 53 { 54 CINTR, CQUIT, CERASE, CKILL, 55 CEOF, CEOL, CEOL2, CSWTCH, 56 CDSWTCH, CERASE2, CSTART, CSTOP, 57 CWERASE, CSUSP, CDSUSP, CREPRINT, 58 CDISCARD, CLNEXT, CSTATUS, CPAGE, 59 CPGOFF, CKILL2, CBRK, CMIN, 60 CTIME 61 }, 62 { 63 CINTR, CQUIT, CERASE, CKILL, 64 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 65 _POSIX_VDISABLE, CERASE2, CSTART, CSTOP, 66 _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE, 67 CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 68 _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1, 69 0 70 }, 71 { 72 0, 0, 0, 0, 73 0, 0, 0, 0, 74 0, 0, 0, 0, 75 0, 0, 0, 0, 76 0, 0, 0, 0, 77 0, 0, 0, 0, 78 0 79 } 80 }; 81 82 typedef struct ttymodes_t { 83 char *m_name; 84 int m_value; 85 int m_type; 86 } ttymodes_t; 87 88 private ttymodes_t ttymodes[] = { 89 # ifdef IGNBRK 90 { "ignbrk", IGNBRK, M_INP }, 91 # endif /* IGNBRK */ 92 # ifdef BRKINT 93 { "brkint", BRKINT, M_INP }, 94 # endif /* BRKINT */ 95 # ifdef IGNPAR 96 { "ignpar", IGNPAR, M_INP }, 97 # endif /* IGNPAR */ 98 # ifdef PARMRK 99 { "parmrk", PARMRK, M_INP }, 100 # endif /* PARMRK */ 101 # ifdef INPCK 102 { "inpck", INPCK, M_INP }, 103 # endif /* INPCK */ 104 # ifdef ISTRIP 105 { "istrip", ISTRIP, M_INP }, 106 # endif /* ISTRIP */ 107 # ifdef INLCR 108 { "inlcr", INLCR, M_INP }, 109 # endif /* INLCR */ 110 # ifdef IGNCR 111 { "igncr", IGNCR, M_INP }, 112 # endif /* IGNCR */ 113 # ifdef ICRNL 114 { "icrnl", ICRNL, M_INP }, 115 # endif /* ICRNL */ 116 # ifdef IUCLC 117 { "iuclc", IUCLC, M_INP }, 118 # endif /* IUCLC */ 119 # ifdef IXON 120 { "ixon", IXON, M_INP }, 121 # endif /* IXON */ 122 # ifdef IXANY 123 { "ixany", IXANY, M_INP }, 124 # endif /* IXANY */ 125 # ifdef IXOFF 126 { "ixoff", IXOFF, M_INP }, 127 # endif /* IXOFF */ 128 # ifdef IMAXBEL 129 { "imaxbel",IMAXBEL,M_INP }, 130 # endif /* IMAXBEL */ 131 132 # ifdef OPOST 133 { "opost", OPOST, M_OUT }, 134 # endif /* OPOST */ 135 # ifdef OLCUC 136 { "olcuc", OLCUC, M_OUT }, 137 # endif /* OLCUC */ 138 # ifdef ONLCR 139 { "onlcr", ONLCR, M_OUT }, 140 # endif /* ONLCR */ 141 # ifdef OCRNL 142 { "ocrnl", OCRNL, M_OUT }, 143 # endif /* OCRNL */ 144 # ifdef ONOCR 145 { "onocr", ONOCR, M_OUT }, 146 # endif /* ONOCR */ 147 # ifdef ONOEOT 148 { "onoeot", ONOEOT, M_OUT }, 149 # endif /* ONOEOT */ 150 # ifdef ONLRET 151 { "onlret", ONLRET, M_OUT }, 152 # endif /* ONLRET */ 153 # ifdef OFILL 154 { "ofill", OFILL, M_OUT }, 155 # endif /* OFILL */ 156 # ifdef OFDEL 157 { "ofdel", OFDEL, M_OUT }, 158 # endif /* OFDEL */ 159 # ifdef NLDLY 160 { "nldly", NLDLY, M_OUT }, 161 # endif /* NLDLY */ 162 # ifdef CRDLY 163 { "crdly", CRDLY, M_OUT }, 164 # endif /* CRDLY */ 165 # ifdef TABDLY 166 { "tabdly", TABDLY, M_OUT }, 167 # endif /* TABDLY */ 168 # ifdef XTABS 169 { "xtabs", XTABS, M_OUT }, 170 # endif /* XTABS */ 171 # ifdef BSDLY 172 { "bsdly", BSDLY, M_OUT }, 173 # endif /* BSDLY */ 174 # ifdef VTDLY 175 { "vtdly", VTDLY, M_OUT }, 176 # endif /* VTDLY */ 177 # ifdef FFDLY 178 { "ffdly", FFDLY, M_OUT }, 179 # endif /* FFDLY */ 180 # ifdef PAGEOUT 181 { "pageout",PAGEOUT,M_OUT }, 182 # endif /* PAGEOUT */ 183 # ifdef WRAP 184 { "wrap", WRAP, M_OUT }, 185 # endif /* WRAP */ 186 187 # ifdef CIGNORE 188 { "cignore",CIGNORE,M_CTL }, 189 # endif /* CBAUD */ 190 # ifdef CBAUD 191 { "cbaud", CBAUD, M_CTL }, 192 # endif /* CBAUD */ 193 # ifdef CSTOPB 194 { "cstopb", CSTOPB, M_CTL }, 195 # endif /* CSTOPB */ 196 # ifdef CREAD 197 { "cread", CREAD, M_CTL }, 198 # endif /* CREAD */ 199 # ifdef PARENB 200 { "parenb", PARENB, M_CTL }, 201 # endif /* PARENB */ 202 # ifdef PARODD 203 { "parodd", PARODD, M_CTL }, 204 # endif /* PARODD */ 205 # ifdef HUPCL 206 { "hupcl", HUPCL, M_CTL }, 207 # endif /* HUPCL */ 208 # ifdef CLOCAL 209 { "clocal", CLOCAL, M_CTL }, 210 # endif /* CLOCAL */ 211 # ifdef LOBLK 212 { "loblk", LOBLK, M_CTL }, 213 # endif /* LOBLK */ 214 # ifdef CIBAUD 215 { "cibaud", CIBAUD, M_CTL }, 216 # endif /* CIBAUD */ 217 # ifdef CRTSCTS 218 # ifdef CCTS_OFLOW 219 { "ccts_oflow",CCTS_OFLOW,M_CTL }, 220 # else 221 { "crtscts",CRTSCTS,M_CTL }, 222 # endif /* CCTS_OFLOW */ 223 # endif /* CRTSCTS */ 224 # ifdef CRTS_IFLOW 225 { "crts_iflow",CRTS_IFLOW,M_CTL }, 226 # endif /* CRTS_IFLOW */ 227 # ifdef MDMBUF 228 { "mdmbuf", MDMBUF, M_CTL }, 229 # endif /* MDMBUF */ 230 # ifdef RCV1EN 231 { "rcv1en", RCV1EN, M_CTL }, 232 # endif /* RCV1EN */ 233 # ifdef XMT1EN 234 { "xmt1en", XMT1EN, M_CTL }, 235 # endif /* XMT1EN */ 236 237 # ifdef ISIG 238 { "isig", ISIG, M_LIN }, 239 # endif /* ISIG */ 240 # ifdef ICANON 241 { "icanon", ICANON, M_LIN }, 242 # endif /* ICANON */ 243 # ifdef XCASE 244 { "xcase", XCASE, M_LIN }, 245 # endif /* XCASE */ 246 # ifdef ECHO 247 { "echo", ECHO, M_LIN }, 248 # endif /* ECHO */ 249 # ifdef ECHOE 250 { "echoe", ECHOE, M_LIN }, 251 # endif /* ECHOE */ 252 # ifdef ECHOK 253 { "echok", ECHOK, M_LIN }, 254 # endif /* ECHOK */ 255 # ifdef ECHONL 256 { "echonl", ECHONL, M_LIN }, 257 # endif /* ECHONL */ 258 # ifdef NOFLSH 259 { "noflsh", NOFLSH, M_LIN }, 260 # endif /* NOFLSH */ 261 # ifdef TOSTOP 262 { "tostop", TOSTOP, M_LIN }, 263 # endif /* TOSTOP */ 264 # ifdef ECHOCTL 265 { "echoctl",ECHOCTL,M_LIN }, 266 # endif /* ECHOCTL */ 267 # ifdef ECHOPRT 268 { "echoprt",ECHOPRT,M_LIN }, 269 # endif /* ECHOPRT */ 270 # ifdef ECHOKE 271 { "echoke", ECHOKE, M_LIN }, 272 # endif /* ECHOKE */ 273 # ifdef DEFECHO 274 { "defecho",DEFECHO,M_LIN }, 275 # endif /* DEFECHO */ 276 # ifdef FLUSHO 277 { "flusho", FLUSHO, M_LIN }, 278 # endif /* FLUSHO */ 279 # ifdef PENDIN 280 { "pendin", PENDIN, M_LIN }, 281 # endif /* PENDIN */ 282 # ifdef IEXTEN 283 { "iexten", IEXTEN, M_LIN }, 284 # endif /* IEXTEN */ 285 # ifdef NOKERNINFO 286 { "nokerninfo",NOKERNINFO,M_LIN }, 287 # endif /* NOKERNINFO */ 288 # ifdef ALTWERASE 289 { "altwerase",ALTWERASE,M_LIN }, 290 # endif /* ALTWERASE */ 291 # ifdef EXTPROC 292 { "extproc",EXTPROC, M_LIN }, 293 # endif /* EXTPROC */ 294 295 # if defined(VINTR) 296 { "intr", C_SH(C_INTR), M_CHAR }, 297 # endif /* VINTR */ 298 # if defined(VQUIT) 299 { "quit", C_SH(C_QUIT), M_CHAR }, 300 # endif /* VQUIT */ 301 # if defined(VERASE) 302 { "erase", C_SH(C_ERASE), M_CHAR }, 303 # endif /* VERASE */ 304 # if defined(VKILL) 305 { "kill", C_SH(C_KILL), M_CHAR }, 306 # endif /* VKILL */ 307 # if defined(VEOF) 308 { "eof", C_SH(C_EOF), M_CHAR }, 309 # endif /* VEOF */ 310 # if defined(VEOL) 311 { "eol", C_SH(C_EOL), M_CHAR }, 312 # endif /* VEOL */ 313 # if defined(VEOL2) 314 { "eol2", C_SH(C_EOL2), M_CHAR }, 315 # endif /* VEOL2 */ 316 # if defined(VSWTCH) 317 { "swtch", C_SH(C_SWTCH), M_CHAR }, 318 # endif /* VSWTCH */ 319 # if defined(VDSWTCH) 320 { "dswtch", C_SH(C_DSWTCH), M_CHAR }, 321 # endif /* VDSWTCH */ 322 # if defined(VERASE2) 323 { "erase2", C_SH(C_ERASE2), M_CHAR }, 324 # endif /* VERASE2 */ 325 # if defined(VSTART) 326 { "start", C_SH(C_START), M_CHAR }, 327 # endif /* VSTART */ 328 # if defined(VSTOP) 329 { "stop", C_SH(C_STOP), M_CHAR }, 330 # endif /* VSTOP */ 331 # if defined(VWERASE) 332 { "werase", C_SH(C_WERASE), M_CHAR }, 333 # endif /* VWERASE */ 334 # if defined(VSUSP) 335 { "susp", C_SH(C_SUSP), M_CHAR }, 336 # endif /* VSUSP */ 337 # if defined(VDSUSP) 338 { "dsusp", C_SH(C_DSUSP), M_CHAR }, 339 # endif /* VDSUSP */ 340 # if defined(VREPRINT) 341 { "reprint", C_SH(C_REPRINT),M_CHAR }, 342 # endif /* WREPRINT */ 343 # if defined(VDISCARD) 344 { "discard", C_SH(C_DISCARD),M_CHAR }, 345 # endif /* VDISCARD */ 346 # if defined(VLNEXT) 347 { "lnext", C_SH(C_LNEXT), M_CHAR }, 348 # endif /* VLNEXT */ 349 # if defined(VSTATUS) 350 { "status", C_SH(C_STATUS), M_CHAR }, 351 # endif /* VSTATUS */ 352 # if defined(VPAGE) 353 { "page", C_SH(C_PAGE), M_CHAR }, 354 # endif /* VPAGE */ 355 # if defined(VPGOFF) 356 { "pgoff", C_SH(C_PGOFF), M_CHAR }, 357 # endif /* VPGOFF */ 358 # if defined(VKILL2) 359 { "kill2", C_SH(C_KILL2), M_CHAR }, 360 # endif /* VKILL2 */ 361 # if defined(VBRK) 362 { "brk", C_SH(C_BRK), M_CHAR }, 363 # endif /* VBRK */ 364 # if defined(VMIN) 365 { "min", C_SH(C_MIN), M_CHAR }, 366 # endif /* VMIN */ 367 # if defined(VTIME) 368 { "time", C_SH(C_TIME), M_CHAR }, 369 # endif /* VTIME */ 370 { NULL, 0, -1 }, 371 }; 372 373 374 375 #define tty_getty(el, td) tcgetattr((el)->el_infd, (td)) 376 #define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td)) 377 378 #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) 379 #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) 380 #define tty__cooked_mode(td) ((td)->c_lflag & ICANON) 381 382 private void tty__getchar __P((struct termios *, unsigned char *)); 383 private void tty__setchar __P((struct termios *, unsigned char *)); 384 private speed_t tty__getspeed __P((struct termios *)); 385 private int tty_setup __P((EditLine *)); 386 387 #define t_qu t_ts 388 389 390 /* tty_setup(): 391 * Get the tty parameters and initialize the editing state 392 */ 393 private int 394 tty_setup(el) 395 EditLine *el; 396 { 397 int rst = 1; 398 if (tty_getty(el, &el->el_tty.t_ed) == -1) { 399 #ifdef DEBUG_TTY 400 (void) fprintf(el->el_errfile, 401 "tty_setup: tty_getty: %s\n", strerror(errno)); 402 #endif /* DEBUG_TTY */ 403 return(-1); 404 } 405 el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed; 406 407 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex); 408 el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex); 409 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex); 410 411 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask; 412 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask; 413 414 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask; 415 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask; 416 417 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask; 418 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask; 419 420 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask; 421 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask; 422 423 /* 424 * Reset the tty chars to reasonable defaults 425 * If they are disabled, then enable them. 426 */ 427 if (rst) { 428 if (tty__cooked_mode(&el->el_tty.t_ts)) { 429 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); 430 /* 431 * Don't affect CMIN and CTIME for the editor mode 432 */ 433 for (rst = 0; rst < C_NCC - 2; rst++) 434 if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable && 435 el->el_tty.t_c[ED_IO][rst] != el->el_tty.t_vdisable) 436 el->el_tty.t_c[ED_IO][rst] = el->el_tty.t_c[TS_IO][rst]; 437 for (rst = 0; rst < C_NCC; rst++) 438 if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable && 439 el->el_tty.t_c[EX_IO][rst] != el->el_tty.t_vdisable) 440 el->el_tty.t_c[EX_IO][rst] = el->el_tty.t_c[TS_IO][rst]; 441 } 442 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); 443 if (tty_setty(el, &el->el_tty.t_ex) == -1) { 444 #ifdef DEBUG_TTY 445 (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n", 446 strerror(errno)); 447 #endif /* DEBUG_TTY */ 448 return(-1); 449 } 450 } 451 else 452 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); 453 454 el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask; 455 el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask; 456 457 el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask; 458 el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask; 459 460 el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask; 461 el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask; 462 463 el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask; 464 el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask; 465 466 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); 467 return 0; 468 } 469 470 protected int 471 tty_init(el) 472 EditLine *el; 473 { 474 el->el_tty.t_mode = EX_IO; 475 el->el_tty.t_vdisable = _POSIX_VDISABLE; 476 (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); 477 (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); 478 return tty_setup(el); 479 } /* end tty_init */ 480 481 482 /* tty_end(): 483 * Restore the tty to its original settings 484 */ 485 protected void 486 /*ARGSUSED*/ 487 tty_end(el) 488 EditLine *el; 489 { 490 /* XXX: Maybe reset to an initial state? */ 491 } 492 493 494 /* tty__getspeed(): 495 * Get the tty speed 496 */ 497 private speed_t 498 tty__getspeed(td) 499 struct termios *td; 500 { 501 speed_t spd; 502 503 if ((spd = cfgetispeed(td)) == 0) 504 spd = cfgetospeed(td); 505 return spd; 506 } /* end tty__getspeed */ 507 508 509 /* tty__getchar(): 510 * Get the tty characters 511 */ 512 private void 513 tty__getchar(td, s) 514 struct termios *td; 515 unsigned char *s; 516 { 517 # ifdef VINTR 518 s[C_INTR] = td->c_cc[VINTR]; 519 # endif /* VINTR */ 520 # ifdef VQUIT 521 s[C_QUIT] = td->c_cc[VQUIT]; 522 # endif /* VQUIT */ 523 # ifdef VERASE 524 s[C_ERASE] = td->c_cc[VERASE]; 525 # endif /* VERASE */ 526 # ifdef VKILL 527 s[C_KILL] = td->c_cc[VKILL]; 528 # endif /* VKILL */ 529 # ifdef VEOF 530 s[C_EOF] = td->c_cc[VEOF]; 531 # endif /* VEOF */ 532 # ifdef VEOL 533 s[C_EOL] = td->c_cc[VEOL]; 534 # endif /* VEOL */ 535 # ifdef VEOL2 536 s[C_EOL2] = td->c_cc[VEOL2]; 537 # endif /* VEOL2 */ 538 # ifdef VSWTCH 539 s[C_SWTCH] = td->c_cc[VSWTCH]; 540 # endif /* VSWTCH */ 541 # ifdef VDSWTCH 542 s[C_DSWTCH] = td->c_cc[VDSWTCH]; 543 # endif /* VDSWTCH */ 544 # ifdef VERASE2 545 s[C_ERASE2] = td->c_cc[VERASE2]; 546 # endif /* VERASE2 */ 547 # ifdef VSTART 548 s[C_START] = td->c_cc[VSTART]; 549 # endif /* VSTART */ 550 # ifdef VSTOP 551 s[C_STOP] = td->c_cc[VSTOP]; 552 # endif /* VSTOP */ 553 # ifdef VWERASE 554 s[C_WERASE] = td->c_cc[VWERASE]; 555 # endif /* VWERASE */ 556 # ifdef VSUSP 557 s[C_SUSP] = td->c_cc[VSUSP]; 558 # endif /* VSUSP */ 559 # ifdef VDSUSP 560 s[C_DSUSP] = td->c_cc[VDSUSP]; 561 # endif /* VDSUSP */ 562 # ifdef VREPRINT 563 s[C_REPRINT]= td->c_cc[VREPRINT]; 564 # endif /* WREPRINT */ 565 # ifdef VDISCARD 566 s[C_DISCARD]= td->c_cc[VDISCARD]; 567 # endif /* VDISCARD */ 568 # ifdef VLNEXT 569 s[C_LNEXT] = td->c_cc[VLNEXT]; 570 # endif /* VLNEXT */ 571 # ifdef VSTATUS 572 s[C_STATUS] = td->c_cc[VSTATUS]; 573 # endif /* VSTATUS */ 574 # ifdef VPAGE 575 s[C_PAGE] = td->c_cc[VPAGE]; 576 # endif /* VPAGE */ 577 # ifdef VPGOFF 578 s[C_PGOFF] = td->c_cc[VPGOFF]; 579 # endif /* VPGOFF */ 580 # ifdef VKILL2 581 s[C_KILL2] = td->c_cc[VKILL2]; 582 # endif /* KILL2 */ 583 # ifdef VMIN 584 s[C_MIN] = td->c_cc[VMIN]; 585 # endif /* VMIN */ 586 # ifdef VTIME 587 s[C_TIME] = td->c_cc[VTIME]; 588 # endif /* VTIME */ 589 } /* tty__getchar */ 590 591 592 /* tty__setchar(): 593 * Set the tty characters 594 */ 595 private void 596 tty__setchar(td, s) 597 struct termios *td; 598 unsigned char *s; 599 { 600 # ifdef VINTR 601 td->c_cc[VINTR] = s[C_INTR]; 602 # endif /* VINTR */ 603 # ifdef VQUIT 604 td->c_cc[VQUIT] = s[C_QUIT]; 605 # endif /* VQUIT */ 606 # ifdef VERASE 607 td->c_cc[VERASE] = s[C_ERASE]; 608 # endif /* VERASE */ 609 # ifdef VKILL 610 td->c_cc[VKILL] = s[C_KILL]; 611 # endif /* VKILL */ 612 # ifdef VEOF 613 td->c_cc[VEOF] = s[C_EOF]; 614 # endif /* VEOF */ 615 # ifdef VEOL 616 td->c_cc[VEOL] = s[C_EOL]; 617 # endif /* VEOL */ 618 # ifdef VEOL2 619 td->c_cc[VEOL2] = s[C_EOL2]; 620 # endif /* VEOL2 */ 621 # ifdef VSWTCH 622 td->c_cc[VSWTCH] = s[C_SWTCH]; 623 # endif /* VSWTCH */ 624 # ifdef VDSWTCH 625 td->c_cc[VDSWTCH] = s[C_DSWTCH]; 626 # endif /* VDSWTCH */ 627 # ifdef VERASE2 628 td->c_cc[VERASE2] = s[C_ERASE2]; 629 # endif /* VERASE2 */ 630 # ifdef VSTART 631 td->c_cc[VSTART] = s[C_START]; 632 # endif /* VSTART */ 633 # ifdef VSTOP 634 td->c_cc[VSTOP] = s[C_STOP]; 635 # endif /* VSTOP */ 636 # ifdef VWERASE 637 td->c_cc[VWERASE] = s[C_WERASE]; 638 # endif /* VWERASE */ 639 # ifdef VSUSP 640 td->c_cc[VSUSP] = s[C_SUSP]; 641 # endif /* VSUSP */ 642 # ifdef VDSUSP 643 td->c_cc[VDSUSP] = s[C_DSUSP]; 644 # endif /* VDSUSP */ 645 # ifdef VREPRINT 646 td->c_cc[VREPRINT] = s[C_REPRINT]; 647 # endif /* WREPRINT */ 648 # ifdef VDISCARD 649 td->c_cc[VDISCARD] = s[C_DISCARD]; 650 # endif /* VDISCARD */ 651 # ifdef VLNEXT 652 td->c_cc[VLNEXT] = s[C_LNEXT]; 653 # endif /* VLNEXT */ 654 # ifdef VSTATUS 655 td->c_cc[VSTATUS] = s[C_STATUS]; 656 # endif /* VSTATUS */ 657 # ifdef VPAGE 658 td->c_cc[VPAGE] = s[C_PAGE]; 659 # endif /* VPAGE */ 660 # ifdef VPGOFF 661 td->c_cc[VPGOFF] = s[C_PGOFF]; 662 # endif /* VPGOFF */ 663 # ifdef VKILL2 664 td->c_cc[VKILL2] = s[C_KILL2]; 665 # endif /* VKILL2 */ 666 # ifdef VMIN 667 td->c_cc[VMIN] = s[C_MIN]; 668 # endif /* VMIN */ 669 # ifdef VTIME 670 td->c_cc[VTIME] = s[C_TIME]; 671 # endif /* VTIME */ 672 } /* tty__setchar */ 673 674 675 /* tty_rawmode(): 676 * Set terminal into 1 character at a time mode. 677 */ 678 protected int 679 tty_rawmode(el) 680 EditLine *el; 681 { 682 if (el->el_tty.t_mode == ED_IO) 683 return (0); 684 685 if (tty_getty(el, &el->el_tty.t_ts) == -1) { 686 #ifdef DEBUG_TTY 687 (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", strerror(errno)); 688 #endif /* DEBUG_TTY */ 689 return(-1); 690 } 691 692 /* 693 * We always keep up with the eight bit setting and the speed of the 694 * tty. But only we only believe changes that are made to cooked mode! 695 */ 696 el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts); 697 el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts); 698 699 if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed || 700 tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) { 701 (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed); 702 (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed); 703 (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed); 704 (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed); 705 } 706 707 if (tty__cooked_mode(&el->el_tty.t_ts)) { 708 if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) { 709 el->el_tty.t_ex.c_cflag = el->el_tty.t_ts.c_cflag; 710 el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][M_CTL].t_clrmask; 711 el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][M_CTL].t_setmask; 712 713 el->el_tty.t_ed.c_cflag = el->el_tty.t_ts.c_cflag; 714 el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][M_CTL].t_clrmask; 715 el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][M_CTL].t_setmask; 716 } 717 718 if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) && 719 (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) { 720 el->el_tty.t_ex.c_lflag = el->el_tty.t_ts.c_lflag; 721 el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][M_LIN].t_clrmask; 722 el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][M_LIN].t_setmask; 723 724 el->el_tty.t_ed.c_lflag = el->el_tty.t_ts.c_lflag; 725 el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][M_LIN].t_clrmask; 726 el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][M_LIN].t_setmask; 727 } 728 729 if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) && 730 (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) { 731 el->el_tty.t_ex.c_iflag = el->el_tty.t_ts.c_iflag; 732 el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][M_INP].t_clrmask; 733 el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][M_INP].t_setmask; 734 735 el->el_tty.t_ed.c_iflag = el->el_tty.t_ts.c_iflag; 736 el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][M_INP].t_clrmask; 737 el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][M_INP].t_setmask; 738 } 739 740 if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) && 741 (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) { 742 el->el_tty.t_ex.c_oflag = el->el_tty.t_ts.c_oflag; 743 el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][M_OUT].t_clrmask; 744 el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][M_OUT].t_setmask; 745 746 el->el_tty.t_ed.c_oflag = el->el_tty.t_ts.c_oflag; 747 el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][M_OUT].t_clrmask; 748 el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][M_OUT].t_setmask; 749 } 750 751 if (tty__gettabs(&el->el_tty.t_ex) == 0) 752 el->el_tty.t_tabs = 0; 753 else 754 el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0; 755 756 { 757 int i; 758 759 tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); 760 /* 761 * Check if the user made any changes. 762 * If he did, then propagate the changes to the 763 * edit and execute data structures. 764 */ 765 for (i = 0; i < C_NCC; i++) 766 if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]) 767 break; 768 769 if (i != C_NCC) { 770 /* 771 * Propagate changes only to the unprotected chars 772 * that have been modified just now. 773 */ 774 for (i = 0; i < C_NCC; i++) { 775 if (!((el->el_tty.t_t[ED_IO][M_CHAR].t_setmask & C_SH(i))) 776 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) 777 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i]; 778 if (el->el_tty.t_t[ED_IO][M_CHAR].t_clrmask & C_SH(i)) 779 el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable; 780 } 781 tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); 782 783 for (i = 0; i < C_NCC; i++) { 784 if (!((el->el_tty.t_t[EX_IO][M_CHAR].t_setmask & C_SH(i))) 785 && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) 786 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i]; 787 if (el->el_tty.t_t[EX_IO][M_CHAR].t_clrmask & C_SH(i)) 788 el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable; 789 } 790 tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); 791 } 792 793 } 794 } 795 796 if (tty_setty(el, &el->el_tty.t_ed) == -1) { 797 #ifdef DEBUG_TTY 798 (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n", 799 strerror(errno)); 800 #endif /* DEBUG_TTY */ 801 return -1; 802 } 803 el->el_tty.t_mode = ED_IO; 804 return (0); 805 } /* end tty_rawmode */ 806 807 808 /* tty_cookedmode(): 809 * Set the tty back to normal mode 810 */ 811 protected int 812 tty_cookedmode(el) 813 EditLine *el; 814 { /* set tty in normal setup */ 815 if (el->el_tty.t_mode == EX_IO) 816 return (0); 817 818 if (tty_setty(el, &el->el_tty.t_ex) == -1) { 819 #ifdef DEBUG_TTY 820 (void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n", 821 strerror(errno)); 822 #endif /* DEBUG_TTY */ 823 return -1; 824 } 825 el->el_tty.t_mode = EX_IO; 826 return (0); 827 } /* end tty_cookedmode */ 828 829 830 /* tty_quotemode(): 831 * Turn on quote mode 832 */ 833 protected int 834 tty_quotemode(el) 835 EditLine *el; 836 { 837 if (el->el_tty.t_mode == QU_IO) 838 return 0; 839 840 el->el_tty.t_qu = el->el_tty.t_ed; 841 842 el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][M_INP].t_clrmask; 843 el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][M_INP].t_setmask; 844 845 el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][M_OUT].t_clrmask; 846 el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][M_OUT].t_setmask; 847 848 el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][M_CTL].t_clrmask; 849 el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][M_CTL].t_setmask; 850 851 el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][M_LIN].t_clrmask; 852 el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][M_LIN].t_setmask; 853 854 if (tty_setty(el, &el->el_tty.t_qu) == -1) { 855 #ifdef DEBUG_TTY 856 (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n", 857 strerror(errno)); 858 #endif /* DEBUG_TTY */ 859 return -1; 860 } 861 el->el_tty.t_mode = QU_IO; 862 return 0; 863 } /* end tty_quotemode */ 864 865 866 /* tty_noquotemode(): 867 * Turn off quote mode 868 */ 869 protected int 870 tty_noquotemode(el) 871 EditLine *el; 872 { 873 if (el->el_tty.t_mode != QU_IO) 874 return 0; 875 if (tty_setty(el, &el->el_tty.t_ed) == -1) { 876 #ifdef DEBUG_TTY 877 (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n", 878 strerror(errno)); 879 #endif /* DEBUG_TTY */ 880 return -1; 881 } 882 el->el_tty.t_mode = ED_IO; 883 return 0; 884 } 885 886 /* tty_stty(): 887 * Stty builtin 888 */ 889 protected int 890 /*ARGSUSED*/ 891 tty_stty(el, argc, argv) 892 EditLine *el; 893 int argc; 894 char **argv; 895 { 896 ttymodes_t *m; 897 char x, *d; 898 int aflag = 0; 899 char *s; 900 char *name; 901 int z = EX_IO; 902 903 if (argv == NULL) 904 return -1; 905 name = *argv++; 906 907 while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0') 908 switch (argv[0][1]) { 909 case 'a': 910 aflag++; 911 argv++; 912 break; 913 case 'd': 914 argv++; 915 z = ED_IO; 916 break; 917 case 'x': 918 argv++; 919 z = EX_IO; 920 break; 921 case 'q': 922 argv++; 923 z = QU_IO; 924 break; 925 default: 926 (void) fprintf(el->el_errfile, "%s: Unknown switch `%c'.\n", 927 name, argv[0][1]); 928 return -1; 929 } 930 931 if (!argv || !*argv) { 932 int i = -1; 933 int len = 0, st = 0, cu; 934 for (m = ttymodes; m->m_name; m++) { 935 if (m->m_type != i) { 936 (void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "", 937 el->el_tty.t_t[z][m->m_type].t_name); 938 i = m->m_type; 939 st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name); 940 } 941 942 x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0'; 943 x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) ? '-' : x; 944 945 if (x != '\0' || aflag) { 946 947 cu = strlen(m->m_name) + (x != '\0') + 1; 948 949 if (len + cu >= el->el_term.t_size.h) { 950 (void) fprintf(el->el_outfile, "\n%*s", st, ""); 951 len = st + cu; 952 } 953 else 954 len += cu; 955 956 if (x != '\0') 957 (void) fprintf(el->el_outfile, "%c%s ", x, m->m_name); 958 else 959 (void) fprintf(el->el_outfile, "%s ", m->m_name); 960 } 961 } 962 (void) fprintf(el->el_outfile, "\n"); 963 return 0; 964 } 965 966 while (argv && (s = *argv++)) { 967 switch (*s) { 968 case '+': 969 case '-': 970 x = *s++; 971 break; 972 default: 973 x = '\0'; 974 break; 975 } 976 d = s; 977 for (m = ttymodes; m->m_name; m++) 978 if (strcmp(m->m_name, d) == 0) 979 break; 980 981 if (!m->m_name) { 982 (void) fprintf(el->el_errfile, "%s: Invalid argument `%s'.\n", 983 name, d); 984 return -1; 985 } 986 987 switch (x) { 988 case '+': 989 el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; 990 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; 991 break; 992 case '-': 993 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; 994 el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value; 995 break; 996 default: 997 el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; 998 el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; 999 break; 1000 } 1001 } 1002 return 0; 1003 } /* end tty_stty */ 1004 1005 1006 #ifdef notyet 1007 /* tty_printchar(): 1008 * DEbugging routine to print the tty characters 1009 */ 1010 private void 1011 tty_printchar(el, s) 1012 EditLine *el; 1013 unsigned char *s; 1014 { 1015 ttyperm_t *m; 1016 int i; 1017 1018 for (i = 0; i < C_NCC; i++) { 1019 for (m = el->el_tty.t_t; m->m_name; m++) 1020 if (m->m_type == M_CHAR && C_SH(i) == m->m_value) 1021 break; 1022 if (m->m_name) 1023 (void) fprintf(el->el_errfile, "%s ^%c ", m->m_name, s[i] + 'A'-1); 1024 if (i % 5 == 0) 1025 (void) fprintf(el->el_errfile, "\n"); 1026 } 1027 (void) fprintf(el->el_errfile, "\n"); 1028 } 1029 #endif /* notyet */ 1030