1 /* $Header: /p/tcsh/cvsroot/tcsh/ed.term.c,v 1.38 2011/02/25 23:58:34 christos Exp $ */ 2 /* 3 * ed.term.c: Low level terminal interface 4 */ 5 /*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 #include "sh.h" 34 #ifndef WINNT_NATIVE 35 36 RCSID("$tcsh: ed.term.c,v 1.38 2011/02/25 23:58:34 christos Exp $") 37 #include <assert.h> 38 #include "ed.h" 39 40 int didsetty = 0; 41 ttyperm_t ttylist = { 42 { 43 #if defined(POSIX) || defined(TERMIO) 44 { "iflag:", ICRNL, (INLCR|IGNCR) }, 45 { "oflag:", (OPOST|ONLCR), ONLRET }, 46 { "cflag:", 0, 0 }, 47 { "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN), 48 (NOFLSH|ECHONL|EXTPROC|FLUSHO|IDEFAULT) }, 49 #else /* GSTTY */ 50 { "nrmal:", (ECHO|CRMOD|ANYP), (CBREAK|RAW|LCASE|VTDELAY|ALLDELAY) }, 51 { "local:", (LCRTBS|LCRTERA|LCRTKIL), (LPRTERA|LFLUSHO) }, 52 #endif /* POSIX || TERMIO */ 53 { "chars:", 0, 0 }, 54 }, 55 { 56 #if defined(POSIX) || defined(TERMIO) 57 { "iflag:", (INLCR|ICRNL), IGNCR }, 58 { "oflag:", (OPOST|ONLCR), ONLRET }, 59 { "cflag:", 0, 0 }, 60 { "lflag:", ISIG, 61 (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO| 62 IDEFAULT) }, 63 #else /* GSTTY */ 64 { "nrmal:", (CBREAK|CRMOD|ANYP), (RAW|ECHO|LCASE|VTDELAY|ALLDELAY) }, 65 { "local:", (LCRTBS|LCRTERA|LCRTKIL), (LPRTERA|LFLUSHO) }, 66 #endif /* POSIX || TERMIO */ 67 { "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)| 68 C_SH(C_WERASE)|C_SH(C_REPRINT)|C_SH(C_SUSP)|C_SH(C_DSUSP)| 69 C_SH(C_EOF)|C_SH(C_EOL)|C_SH(C_DISCARD)|C_SH(C_PGOFF)| 70 C_SH(C_KILL2)|C_SH(C_PAGE)|C_SH(C_STATUS)|C_SH(C_CHECKPT)| 71 C_SH(C_LNEXT)), 72 0 } 73 }, 74 { 75 #if defined(POSIX) || defined(TERMIO) 76 { "iflag:", 0, IXON | IXOFF }, 77 { "oflag:", 0, 0 }, 78 { "cflag:", 0, 0 }, 79 { "lflag:", 0, ISIG | IEXTEN }, 80 #else /* GSTTY */ 81 { "nrmal:", RAW, CBREAK }, 82 { "local:", 0, 0 }, 83 #endif /* POSIX || TERMIO */ 84 { "chars:", 0, 0 }, 85 } 86 }; 87 88 static const struct tcshmodes { 89 const char *m_name; 90 #ifdef SOLARIS2 91 unsigned long m_value; 92 #else /* !SOLARIS2 */ 93 int m_value; 94 #endif /* SOLARIS2 */ 95 int m_type; 96 } modelist[] = { 97 #if defined(POSIX) || defined(TERMIO) 98 99 # ifdef IGNBRK 100 { "ignbrk", IGNBRK, M_INPUT }, 101 # endif /* IGNBRK */ 102 # ifdef BRKINT 103 { "brkint", BRKINT, M_INPUT }, 104 # endif /* BRKINT */ 105 # ifdef IGNPAR 106 { "ignpar", IGNPAR, M_INPUT }, 107 # endif /* IGNPAR */ 108 # ifdef PARMRK 109 { "parmrk", PARMRK, M_INPUT }, 110 # endif /* PARMRK */ 111 # ifdef INPCK 112 { "inpck", INPCK, M_INPUT }, 113 # endif /* INPCK */ 114 # ifdef ISTRIP 115 { "istrip", ISTRIP, M_INPUT }, 116 # endif /* ISTRIP */ 117 # ifdef INLCR 118 { "inlcr", INLCR, M_INPUT }, 119 # endif /* INLCR */ 120 # ifdef IGNCR 121 { "igncr", IGNCR, M_INPUT }, 122 # endif /* IGNCR */ 123 # ifdef ICRNL 124 { "icrnl", ICRNL, M_INPUT }, 125 # endif /* ICRNL */ 126 # ifdef IUCLC 127 { "iuclc", IUCLC, M_INPUT }, 128 # endif /* IUCLC */ 129 # ifdef IXON 130 { "ixon", IXON, M_INPUT }, 131 # endif /* IXON */ 132 # ifdef IXANY 133 { "ixany", IXANY, M_INPUT }, 134 # endif /* IXANY */ 135 # ifdef IXOFF 136 { "ixoff", IXOFF, M_INPUT }, 137 # endif /* IXOFF */ 138 # ifdef IMAXBEL 139 { "imaxbel",IMAXBEL,M_INPUT }, 140 # endif /* IMAXBEL */ 141 # ifdef IDELETE 142 { "idelete",IDELETE,M_INPUT }, 143 # endif /* IDELETE */ 144 145 # ifdef OPOST 146 { "opost", OPOST, M_OUTPUT }, 147 # endif /* OPOST */ 148 # ifdef OLCUC 149 { "olcuc", OLCUC, M_OUTPUT }, 150 # endif /* OLCUC */ 151 # ifdef ONLCR 152 { "onlcr", ONLCR, M_OUTPUT }, 153 # endif /* ONLCR */ 154 # ifdef OCRNL 155 { "ocrnl", OCRNL, M_OUTPUT }, 156 # endif /* OCRNL */ 157 # ifdef ONOCR 158 { "onocr", ONOCR, M_OUTPUT }, 159 # endif /* ONOCR */ 160 # ifdef ONOEOT 161 { "onoeot", ONOEOT, M_OUTPUT }, 162 # endif /* ONOEOT */ 163 # ifdef ONLRET 164 { "onlret", ONLRET, M_OUTPUT }, 165 # endif /* ONLRET */ 166 # ifdef OFILL 167 { "ofill", OFILL, M_OUTPUT }, 168 # endif /* OFILL */ 169 # ifdef OFDEL 170 { "ofdel", OFDEL, M_OUTPUT }, 171 # endif /* OFDEL */ 172 # ifdef NLDLY 173 { "nldly", NLDLY, M_OUTPUT }, 174 # endif /* NLDLY */ 175 # ifdef CRDLY 176 { "crdly", CRDLY, M_OUTPUT }, 177 # endif /* CRDLY */ 178 # ifdef TABDLY 179 { "tabdly", TABDLY, M_OUTPUT }, 180 # endif /* TABDLY */ 181 # ifdef XTABS 182 { "xtabs", XTABS, M_OUTPUT }, 183 # endif /* XTABS */ 184 # ifdef BSDLY 185 { "bsdly", BSDLY, M_OUTPUT }, 186 # endif /* BSDLY */ 187 # ifdef VTDLY 188 { "vtdly", VTDLY, M_OUTPUT }, 189 # endif /* VTDLY */ 190 # ifdef FFDLY 191 { "ffdly", FFDLY, M_OUTPUT }, 192 # endif /* FFDLY */ 193 # ifdef PAGEOUT 194 { "pageout",PAGEOUT,M_OUTPUT }, 195 # endif /* PAGEOUT */ 196 # ifdef WRAP 197 { "wrap", WRAP, M_OUTPUT }, 198 # endif /* WRAP */ 199 200 # ifdef CIGNORE 201 { "cignore",CIGNORE,M_CONTROL }, 202 # endif /* CBAUD */ 203 # ifdef CBAUD 204 { "cbaud", CBAUD, M_CONTROL }, 205 # endif /* CBAUD */ 206 # ifdef CSTOPB 207 { "cstopb", CSTOPB, M_CONTROL }, 208 # endif /* CSTOPB */ 209 # ifdef CREAD 210 { "cread", CREAD, M_CONTROL }, 211 # endif /* CREAD */ 212 # ifdef PARENB 213 { "parenb", PARENB, M_CONTROL }, 214 # endif /* PARENB */ 215 # ifdef PARODD 216 { "parodd", PARODD, M_CONTROL }, 217 # endif /* PARODD */ 218 # ifdef HUPCL 219 { "hupcl", HUPCL, M_CONTROL }, 220 # endif /* HUPCL */ 221 # ifdef CLOCAL 222 { "clocal", CLOCAL, M_CONTROL }, 223 # endif /* CLOCAL */ 224 # ifdef LOBLK 225 { "loblk", LOBLK, M_CONTROL }, 226 # endif /* LOBLK */ 227 # ifdef CIBAUD 228 { "cibaud", CIBAUD, M_CONTROL }, 229 # endif /* CIBAUD */ 230 # ifdef CRTSCTS 231 # ifdef CCTS_OFLOW 232 { "ccts_oflow",CCTS_OFLOW,M_CONTROL }, 233 # else 234 { "crtscts",CRTSCTS,M_CONTROL }, 235 # endif /* CCTS_OFLOW */ 236 # endif /* CRTSCTS */ 237 # ifdef CRTS_IFLOW 238 { "crts_iflow",CRTS_IFLOW,M_CONTROL }, 239 # endif /* CRTS_IFLOW */ 240 # ifdef MDMBUF 241 { "mdmbuf", MDMBUF, M_CONTROL }, 242 # endif /* MDMBUF */ 243 # ifdef RCV1EN 244 { "rcv1en", RCV1EN, M_CONTROL }, 245 # endif /* RCV1EN */ 246 # ifdef XMT1EN 247 { "xmt1en", XMT1EN, M_CONTROL }, 248 # endif /* XMT1EN */ 249 250 # ifdef ISIG 251 { "isig", ISIG, M_LINED }, 252 # endif /* ISIG */ 253 # ifdef ICANON 254 { "icanon", ICANON, M_LINED }, 255 # endif /* ICANON */ 256 # ifdef XCASE 257 { "xcase", XCASE, M_LINED }, 258 # endif /* XCASE */ 259 # ifdef ECHO 260 { "echo", ECHO, M_LINED }, 261 # endif /* ECHO */ 262 # ifdef ECHOE 263 { "echoe", ECHOE, M_LINED }, 264 # endif /* ECHOE */ 265 # ifdef ECHOK 266 { "echok", ECHOK, M_LINED }, 267 # endif /* ECHOK */ 268 # ifdef ECHONL 269 { "echonl", ECHONL, M_LINED }, 270 # endif /* ECHONL */ 271 # ifdef NOFLSH 272 { "noflsh", NOFLSH, M_LINED }, 273 # endif /* NOFLSH */ 274 # ifdef TOSTOP 275 { "tostop", TOSTOP, M_LINED }, 276 # endif /* TOSTOP */ 277 # ifdef ECHOCTL 278 { "echoctl",ECHOCTL,M_LINED }, 279 # endif /* ECHOCTL */ 280 # ifdef ECHOPRT 281 { "echoprt",ECHOPRT,M_LINED }, 282 # endif /* ECHOPRT */ 283 # ifdef ECHOKE 284 { "echoke", ECHOKE, M_LINED }, 285 # endif /* ECHOKE */ 286 # ifdef DEFECHO 287 { "defecho",DEFECHO,M_LINED }, 288 # endif /* DEFECHO */ 289 # ifdef FLUSHO 290 { "flusho", FLUSHO, M_LINED }, 291 # endif /* FLUSHO */ 292 # ifdef PENDIN 293 { "pendin", PENDIN, M_LINED }, 294 # endif /* PENDIN */ 295 # ifdef IEXTEN 296 { "iexten", IEXTEN, M_LINED }, 297 # endif /* IEXTEN */ 298 # ifdef NOKERNINFO 299 { "nokerninfo",NOKERNINFO,M_LINED }, 300 # endif /* NOKERNINFO */ 301 # ifdef ALTWERASE 302 { "altwerase",ALTWERASE,M_LINED }, 303 # endif /* ALTWERASE */ 304 # ifdef EXTPROC 305 { "extproc",EXTPROC,M_LINED }, 306 # endif /* EXTPROC */ 307 # ifdef IDEFAULT 308 { "idefault",IDEFAULT,M_LINED }, 309 # endif /* IDEFAULT */ 310 311 #else /* GSTTY */ 312 313 # ifdef TANDEM 314 { "tandem", TANDEM, M_CONTROL }, 315 # endif /* TANDEM */ 316 # ifdef CBREAK 317 { "cbreak", CBREAK, M_CONTROL }, 318 # endif /* CBREAK */ 319 # ifdef LCASE 320 { "lcase", LCASE, M_CONTROL }, 321 # endif /* LCASE */ 322 # ifdef ECHO 323 { "echo", ECHO, M_CONTROL }, 324 # endif /* ECHO */ 325 # ifdef CRMOD 326 { "crmod", CRMOD, M_CONTROL }, 327 # endif /* CRMOD */ 328 # ifdef RAW 329 { "raw", RAW, M_CONTROL }, 330 # endif /* RAW */ 331 # ifdef ODDP 332 { "oddp", ODDP, M_CONTROL }, 333 # endif /* ODDP */ 334 # ifdef EVENP 335 { "evenp", EVENP, M_CONTROL }, 336 # endif /* EVENP */ 337 # ifdef ANYP 338 { "anyp", ANYP, M_CONTROL }, 339 # endif /* ANYP */ 340 # ifdef NLDELAY 341 { "nldelay",NLDELAY,M_CONTROL }, 342 # endif /* NLDELAY */ 343 # ifdef TBDELAY 344 { "tbdelay",TBDELAY,M_CONTROL }, 345 # endif /* TBDELAY */ 346 # ifdef XTABS 347 { "xtabs", XTABS, M_CONTROL }, 348 # endif /* XTABS */ 349 # ifdef CRDELAY 350 { "crdelay",CRDELAY,M_CONTROL }, 351 # endif /* CRDELAY */ 352 # ifdef VTDELAY 353 { "vtdelay",VTDELAY,M_CONTROL }, 354 # endif /* VTDELAY */ 355 # ifdef BSDELAY 356 { "bsdelay",BSDELAY,M_CONTROL }, 357 # endif /* BSDELAY */ 358 # ifdef CRTBS 359 { "crtbs", CRTBS, M_CONTROL }, 360 # endif /* CRTBS */ 361 # ifdef PRTERA 362 { "prtera", PRTERA, M_CONTROL }, 363 # endif /* PRTERA */ 364 # ifdef CRTERA 365 { "crtera", CRTERA, M_CONTROL }, 366 # endif /* CRTERA */ 367 # ifdef TILDE 368 { "tilde", TILDE, M_CONTROL }, 369 # endif /* TILDE */ 370 # ifdef MDMBUF 371 { "mdmbuf", MDMBUF, M_CONTROL }, 372 # endif /* MDMBUF */ 373 # ifdef LITOUT 374 { "litout", LITOUT, M_CONTROL }, 375 # endif /* LITOUT */ 376 # ifdef TOSTOP 377 { "tostop", TOSTOP, M_CONTROL }, 378 # endif /* TOSTOP */ 379 # ifdef FLUSHO 380 { "flusho", FLUSHO, M_CONTROL }, 381 # endif /* FLUSHO */ 382 # ifdef NOHANG 383 { "nohang", NOHANG, M_CONTROL }, 384 # endif /* NOHANG */ 385 # ifdef L001000 386 { "l001000",L001000,M_CONTROL }, 387 # endif /* L001000 */ 388 # ifdef CRTKIL 389 { "crtkil", CRTKIL, M_CONTROL }, 390 # endif /* CRTKIL */ 391 # ifdef PASS8 392 { "pass8", PASS8, M_CONTROL }, 393 # endif /* PASS8 */ 394 # ifdef CTLECH 395 { "ctlech", CTLECH, M_CONTROL }, 396 # endif /* CTLECH */ 397 # ifdef PENDIN 398 { "pendin", PENDIN, M_CONTROL }, 399 # endif /* PENDIN */ 400 # ifdef DECCTQ 401 { "decctq", DECCTQ, M_CONTROL }, 402 # endif /* DECCTQ */ 403 # ifdef NOFLSH 404 { "noflsh", NOFLSH, M_CONTROL }, 405 # endif /* NOFLSH */ 406 407 # ifdef LCRTBS 408 { "lcrtbs", LCRTBS, M_LOCAL }, 409 # endif /* LCRTBS */ 410 # ifdef LPRTERA 411 { "lprtera",LPRTERA,M_LOCAL }, 412 # endif /* LPRTERA */ 413 # ifdef LCRTERA 414 { "lcrtera",LCRTERA,M_LOCAL }, 415 # endif /* LCRTERA */ 416 # ifdef LTILDE 417 { "ltilde", LTILDE, M_LOCAL }, 418 # endif /* LTILDE */ 419 # ifdef LMDMBUF 420 { "lmdmbuf",LMDMBUF,M_LOCAL }, 421 # endif /* LMDMBUF */ 422 # ifdef LLITOUT 423 { "llitout",LLITOUT,M_LOCAL }, 424 # endif /* LLITOUT */ 425 # ifdef LTOSTOP 426 { "ltostop",LTOSTOP,M_LOCAL }, 427 # endif /* LTOSTOP */ 428 # ifdef LFLUSHO 429 { "lflusho",LFLUSHO,M_LOCAL }, 430 # endif /* LFLUSHO */ 431 # ifdef LNOHANG 432 { "lnohang",LNOHANG,M_LOCAL }, 433 # endif /* LNOHANG */ 434 # ifdef LCRTKIL 435 { "lcrtkil",LCRTKIL,M_LOCAL }, 436 # endif /* LCRTKIL */ 437 # ifdef LPASS8 438 { "lpass8", LPASS8, M_LOCAL }, 439 # endif /* LPASS8 */ 440 # ifdef LCTLECH 441 { "lctlech",LCTLECH,M_LOCAL }, 442 # endif /* LCTLECH */ 443 # ifdef LPENDIN 444 { "lpendin",LPENDIN,M_LOCAL }, 445 # endif /* LPENDIN */ 446 # ifdef LDECCTQ 447 { "ldecctq",LDECCTQ,M_LOCAL }, 448 # endif /* LDECCTQ */ 449 # ifdef LNOFLSH 450 { "lnoflsh",LNOFLSH,M_LOCAL }, 451 # endif /* LNOFLSH */ 452 453 #endif /* POSIX || TERMIO */ 454 # if defined(VINTR) || defined(TIOCGETC) 455 { "intr", C_SH(C_INTR), M_CHAR }, 456 # endif /* VINTR */ 457 # if defined(VQUIT) || defined(TIOCGETC) 458 { "quit", C_SH(C_QUIT), M_CHAR }, 459 # endif /* VQUIT */ 460 # if defined(VERASE) || defined(TIOCGETP) 461 { "erase", C_SH(C_ERASE), M_CHAR }, 462 # endif /* VERASE */ 463 # if defined(VKILL) || defined(TIOCGETP) 464 { "kill", C_SH(C_KILL), M_CHAR }, 465 # endif /* VKILL */ 466 # if defined(VEOF) || defined(TIOCGETC) 467 { "eof", C_SH(C_EOF), M_CHAR }, 468 # endif /* VEOF */ 469 # if defined(VEOL) 470 { "eol", C_SH(C_EOL), M_CHAR }, 471 # endif /* VEOL */ 472 # if defined(VEOL2) 473 { "eol2", C_SH(C_EOL2), M_CHAR }, 474 # endif /* VEOL2 */ 475 # if defined(VSWTCH) 476 { "swtch", C_SH(C_SWTCH), M_CHAR }, 477 # endif /* VSWTCH */ 478 # if defined(VDSWTCH) 479 { "dswtch", C_SH(C_DSWTCH), M_CHAR }, 480 # endif /* VDSWTCH */ 481 # if defined(VERASE2) 482 { "erase2", C_SH(C_ERASE2), M_CHAR }, 483 # endif /* VERASE2 */ 484 # if defined(VSTART) || defined(TIOCGETC) 485 { "start", C_SH(C_START), M_CHAR }, 486 # endif /* VSTART */ 487 # if defined(VSTOP) || defined(TIOCGETC) 488 { "stop", C_SH(C_STOP), M_CHAR }, 489 # endif /* VSTOP */ 490 # if defined(VWERASE) || defined(TIOCGLTC) 491 { "werase", C_SH(C_WERASE), M_CHAR }, 492 # endif /* VWERASE */ 493 # if defined(VSUSP) || defined(TIOCGLTC) 494 { "susp", C_SH(C_SUSP), M_CHAR }, 495 # endif /* VSUSP */ 496 # if defined(VDSUSP) || defined(TIOCGLTC) 497 { "dsusp", C_SH(C_DSUSP), M_CHAR }, 498 # endif /* VDSUSP */ 499 # if defined(VREPRINT) || defined(TIOCGLTC) 500 { "reprint", C_SH(C_REPRINT),M_CHAR }, 501 # endif /* WREPRINT */ 502 # if defined(VDISCARD) || defined(TIOCGLTC) 503 { "discard", C_SH(C_DISCARD),M_CHAR }, 504 # endif /* VDISCARD */ 505 # if defined(VLNEXT) || defined(TIOCGLTC) 506 { "lnext", C_SH(C_LNEXT), M_CHAR }, 507 # endif /* VLNEXT */ 508 # if defined(VSTATUS) || defined(TIOCGPAGE) 509 { "status", C_SH(C_STATUS), M_CHAR }, 510 # endif /* VSTATUS */ 511 # if defined(VCHECKPT) || defined(TIOCGPAGE) 512 { "ckpt", C_SH(C_CHECKPT),M_CHAR }, 513 # endif /* VCHECKPT */ 514 # if defined(VPAGE) || defined(TIOCGPAGE) 515 { "page", C_SH(C_PAGE), M_CHAR }, 516 # endif /* VPAGE */ 517 # if defined(VPGOFF) || defined(TIOCGPAGE) 518 { "pgoff", C_SH(C_PGOFF), M_CHAR }, 519 # endif /* VPGOFF */ 520 # if defined(VKILL2) 521 { "kill2", C_SH(C_KILL2), M_CHAR }, 522 # endif /* VKILL2 */ 523 # if defined(VBRK) || defined(TIOCGETC) 524 { "brk", C_SH(C_BRK), M_CHAR }, 525 # endif /* VBRK */ 526 # if defined(VMIN) 527 { "min", C_SH(C_MIN), M_CHAR }, 528 # endif /* VMIN */ 529 # if defined(VTIME) 530 { "time", C_SH(C_TIME), M_CHAR }, 531 # endif /* VTIME */ 532 { NULL, 0, -1 }, 533 }; 534 535 /* 536 * If EAGAIN and/or EWOULDBLOCK are defined, we can't just return -1 in all 537 * situations where ioctl() does. 538 * 539 * On AIX 4.1.5 (and presumably some other versions and OSes), as you 540 * perform the manual test suite in the README, if you 'bg' vi immediately 541 * after suspending it, all is well, but if you wait a few seconds, 542 * usually ioctl() will return -1, which previously caused tty_setty() to 543 * return -1, causing Rawmode() to return -1, causing Inputl() to return 544 * 0, causing bgetc() to return -1, causing readc() to set doneinp to 1, 545 * causing process() to break out of the main loop, causing tcsh to exit 546 * prematurely. 547 * 548 * If ioctl()'s errno is EAGAIN/EWOULDBLOCK ("Resource temporarily 549 * unavailable"), apparently the tty is being messed with by the OS and we 550 * need to try again. In my testing, ioctl() was never called more than 551 * twice in a row. 552 * 553 * -- Dan Harkless <dan@wave.eng.uci.edu> 554 * 555 * So, I retry all ioctl's in case others happen to fail too (christos) 556 */ 557 558 #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) 559 # define OKERROR(e) (((e) == EAGAIN) || ((e) == EWOULDBLOCK) || ((e) == EINTR)) 560 #elif defined(EAGAIN) 561 # define OKERROR(e) (((e) == EAGAIN) || ((e) == EINTR)) 562 #elif defined(EWOULDBLOCK) 563 # define OKERROR(e) (((e) == EWOULDBLOCK) || ((e) == EINTR)) 564 #else 565 # define OKERROR(e) ((e) == EINTR) 566 #endif 567 568 #ifdef __NetBSD__ 569 #define KLUDGE (errno == ENOTTY && count < 10) 570 #else 571 #define KLUDGE 0 572 #endif 573 574 /* Retry a system call */ 575 #define RETRY(x) \ 576 do { \ 577 int count; \ 578 \ 579 for (count = 0;; count++) \ 580 if ((x) == -1) { \ 581 if (OKERROR(errno) || KLUDGE) \ 582 continue; \ 583 else \ 584 return -1; \ 585 } \ 586 else \ 587 break; \ 588 } while (0) 589 590 /*ARGSUSED*/ 591 void 592 dosetty(Char **v, struct command *t) 593 { 594 const struct tcshmodes *m; 595 char x, *d, *cmdname; 596 int aflag = 0; 597 Char *s; 598 int z = EX_IO; 599 600 USE(t); 601 cmdname = strsave(short2str(*v++)); 602 cleanup_push(cmdname, xfree); 603 setname(cmdname); 604 605 while (v && *v && v[0][0] == '-' && v[0][2] == '\0') 606 switch (v[0][1]) { 607 case 'a': 608 aflag++; 609 v++; 610 break; 611 case 'd': 612 v++; 613 z = ED_IO; 614 break; 615 case 'x': 616 v++; 617 z = EX_IO; 618 break; 619 case 'q': 620 v++; 621 z = QU_IO; 622 break; 623 default: 624 stderror(ERR_NAME | ERR_SYSTEM, short2str(v[0]), 625 CGETS(8, 1, "Unknown switch")); 626 break; 627 } 628 629 didsetty = 1; 630 if (!v || !*v) { 631 int i = -1; 632 int len = 0, st = 0, cu; 633 for (m = modelist; m->m_name; m++) { 634 if (m->m_type != i) { 635 xprintf("%s%s", i != -1 ? "\n" : "", 636 ttylist[z][m->m_type].t_name); 637 i = m->m_type; 638 st = len = strlen(ttylist[z][m->m_type].t_name); 639 } 640 assert(i != -1); 641 642 x = (ttylist[z][i].t_setmask & m->m_value) ? '+' : '\0'; 643 x = (ttylist[z][i].t_clrmask & m->m_value) ? '-' : x; 644 645 if (x != '\0' || aflag) { 646 cu = strlen(m->m_name) + (x != '\0') + 1; 647 if (len + cu >= TermH) { 648 xprintf("\n%*s", st, ""); 649 len = st + cu; 650 } 651 else 652 len += cu; 653 if (x != '\0') 654 xprintf("%c%s ", x, m->m_name); 655 else 656 xprintf("%s ", m->m_name); 657 } 658 } 659 xputchar('\n'); 660 cleanup_until(cmdname); 661 return; 662 } 663 while (v && (s = *v++)) { 664 switch (*s) { 665 case '+': 666 case '-': 667 x = *s++; 668 break; 669 default: 670 x = '\0'; 671 break; 672 } 673 d = short2str(s); 674 for (m = modelist; m->m_name; m++) 675 if (strcmp(m->m_name, d) == 0) 676 break; 677 if (!m->m_name) 678 stderror(ERR_NAME | ERR_SYSTEM, d, CGETS(8, 2, "Invalid argument")); 679 680 switch (x) { 681 case '+': 682 ttylist[z][m->m_type].t_setmask |= m->m_value; 683 ttylist[z][m->m_type].t_clrmask &= ~m->m_value; 684 break; 685 case '-': 686 ttylist[z][m->m_type].t_setmask &= ~m->m_value; 687 ttylist[z][m->m_type].t_clrmask |= m->m_value; 688 break; 689 default: 690 ttylist[z][m->m_type].t_setmask &= ~m->m_value; 691 ttylist[z][m->m_type].t_clrmask &= ~m->m_value; 692 break; 693 } 694 } 695 cleanup_until(cmdname); 696 } /* end dosetty */ 697 698 int 699 tty_getty(int fd, ttydata_t *td) 700 { 701 #ifdef POSIX 702 RETRY(tcgetattr(fd, &td->d_t)); 703 #else /* TERMIO || GSTTY */ 704 # ifdef TERMIO 705 RETRY(ioctl(fd, TCGETA, (ioctl_t) &td->d_t)); 706 # else /* GSTTY */ 707 # ifdef TIOCGETP 708 RETRY(ioctl(fd, TIOCGETP, (ioctl_t) &td->d_t)); 709 # endif /* TIOCGETP */ 710 # ifdef TIOCGETC 711 RETRY(ioctl(fd, TIOCGETC, (ioctl_t) &td->d_tc)); 712 # endif /* TIOCGETC */ 713 # ifdef TIOCGPAGE 714 RETRY(ioctl(fd, TIOCGPAGE, (ioctl_t) &td->d_pc)); 715 # endif /* TIOCGPAGE */ 716 # ifdef TIOCLGET 717 RETRY(ioctl(fd, TIOCLGET, (ioctl_t) &td->d_lb)); 718 # endif /* TIOCLGET */ 719 # endif /* TERMIO */ 720 #endif /* POSIX */ 721 722 #ifdef TIOCGLTC 723 RETRY(ioctl(fd, TIOCGLTC, (ioctl_t) &td->d_ltc)); 724 #endif /* TIOCGLTC */ 725 726 return 0; 727 } 728 729 int 730 tty_setty(int fd, ttydata_t *td) 731 { 732 #ifdef POSIX 733 RETRY(xtcsetattr(fd, TCSADRAIN, &td->d_t)); 734 #else 735 # ifdef TERMIO 736 RETRY(ioctl(fd, TCSETAW, (ioctl_t) &td->d_t)); 737 # else 738 # ifdef TIOCSETN 739 RETRY(ioctl(fd, TIOCSETN, (ioctl_t) &td->d_t)); 740 # endif /* TIOCSETN */ 741 # ifdef TIOCGETC 742 RETRY(ioctl(fd, TIOCSETC, (ioctl_t) &td->d_tc)); 743 # endif /* TIOCGETC */ 744 # ifdef TIOCGPAGE 745 RETRY(ioctl(fd, TIOCSPAGE, (ioctl_t) &td->d_pc)); 746 # endif /* TIOCGPAGE */ 747 # ifdef TIOCLGET 748 RETRY(ioctl(fd, TIOCLSET, (ioctl_t) &td->d_lb)); 749 # endif /* TIOCLGET */ 750 # endif /* TERMIO */ 751 #endif /* POSIX */ 752 753 #ifdef TIOCGLTC 754 RETRY(ioctl(fd, TIOCSLTC, (ioctl_t) &td->d_ltc)); 755 #endif /* TIOCGLTC */ 756 757 return 0; 758 } 759 760 void 761 tty_getchar(ttydata_t *td, unsigned char *s) 762 { 763 #ifdef TIOCGLTC 764 { 765 struct ltchars *n = &td->d_ltc; 766 767 s[C_SUSP] = n->t_suspc; 768 s[C_DSUSP] = n->t_dsuspc; 769 s[C_REPRINT] = n->t_rprntc; 770 s[C_DISCARD] = n->t_flushc; 771 s[C_WERASE] = n->t_werasc; 772 s[C_LNEXT] = n->t_lnextc; 773 } 774 #endif /* TIOCGLTC */ 775 776 #if defined(POSIX) || defined(TERMIO) 777 { 778 # ifdef POSIX 779 struct termios *n = &td->d_t; 780 # else 781 struct termio *n = &td->d_t; 782 # endif /* POSIX */ 783 784 # ifdef VINTR 785 s[C_INTR] = n->c_cc[VINTR]; 786 # endif /* VINTR */ 787 # ifdef VQUIT 788 s[C_QUIT] = n->c_cc[VQUIT]; 789 # endif /* VQUIT */ 790 # ifdef VERASE 791 s[C_ERASE] = n->c_cc[VERASE]; 792 # endif /* VERASE */ 793 # ifdef VKILL 794 s[C_KILL] = n->c_cc[VKILL]; 795 # endif /* VKILL */ 796 # ifdef VEOF 797 s[C_EOF] = n->c_cc[VEOF]; 798 # endif /* VEOF */ 799 # ifdef VEOL 800 s[C_EOL] = n->c_cc[VEOL]; 801 # endif /* VEOL */ 802 # ifdef VEOL2 803 s[C_EOL2] = n->c_cc[VEOL2]; 804 # endif /* VEOL2 */ 805 # ifdef VSWTCH 806 s[C_SWTCH] = n->c_cc[VSWTCH]; 807 # endif /* VSWTCH */ 808 # ifdef VDSWTCH 809 s[C_DSWTCH] = n->c_cc[VDSWTCH]; 810 # endif /* VDSWTCH */ 811 # ifdef VERASE2 812 s[C_ERASE2] = n->c_cc[VERASE2]; 813 # endif /* VERASE2 */ 814 # ifdef VSTART 815 s[C_START] = n->c_cc[VSTART]; 816 # endif /* VSTART */ 817 # ifdef VSTOP 818 s[C_STOP] = n->c_cc[VSTOP]; 819 # endif /* VSTOP */ 820 # ifdef VWERASE 821 s[C_WERASE] = n->c_cc[VWERASE]; 822 # endif /* VWERASE */ 823 # ifdef VSUSP 824 s[C_SUSP] = n->c_cc[VSUSP]; 825 # endif /* VSUSP */ 826 # ifdef VDSUSP 827 s[C_DSUSP] = n->c_cc[VDSUSP]; 828 # endif /* VDSUSP */ 829 # ifdef VREPRINT 830 s[C_REPRINT] = n->c_cc[VREPRINT]; 831 # endif /* WREPRINT */ 832 # ifdef VDISCARD 833 s[C_DISCARD] = n->c_cc[VDISCARD]; 834 # endif /* VDISCARD */ 835 # ifdef VLNEXT 836 s[C_LNEXT] = n->c_cc[VLNEXT]; 837 # endif /* VLNEXT */ 838 # ifdef VSTATUS 839 s[C_STATUS] = n->c_cc[VSTATUS]; 840 # endif /* VSTATUS */ 841 # ifdef VCHECKPT 842 s[C_CHECKPT] = n->c_cc[VCHECKPT]; 843 # endif /* VCHECKPT */ 844 # ifdef VPAGE 845 s[C_PAGE] = n->c_cc[VPAGE]; 846 # endif /* VPAGE */ 847 # ifdef VPGOFF 848 s[C_PGOFF] = n->c_cc[VPGOFF]; 849 # endif /* VPGOFF */ 850 # ifdef VKILL2 851 s[C_KILL2] = n->c_cc[VKILL2]; 852 # endif /* KILL2 */ 853 # ifdef VMIN 854 s[C_MIN] = n->c_cc[VMIN]; 855 # endif /* VMIN */ 856 # ifdef VTIME 857 s[C_TIME] = n->c_cc[VTIME]; 858 # endif /* VTIME */ 859 } 860 861 #else /* SGTTY */ 862 863 # ifdef TIOCGPAGE 864 { 865 struct ttypagestat *n = &td->d_pc; 866 867 s[C_STATUS] = n->tps_statc; 868 s[C_CHECKPT] = n->tps_checkp; 869 s[C_PAGE] = n->tps_pagec; 870 s[C_PGOFF] = n->tps_pgoffc; 871 } 872 # endif /* TIOCGPAGE */ 873 874 # ifdef TIOCGETC 875 { 876 struct tchars *n = &td->d_tc; 877 878 s[C_INTR] = n->t_intrc; 879 s[C_QUIT] = n->t_quitc; 880 s[C_START] = n->t_startc; 881 s[C_STOP] = n->t_stopc; 882 s[C_EOF] = n->t_eofc; 883 s[C_BRK] = n->t_brkc; 884 } 885 # endif /* TIOCGETC */ 886 887 # ifdef TIOCGETP 888 { 889 struct sgttyb *n = &td->d_t; 890 891 s[C_ERASE] = n->sg_erase; 892 s[C_KILL] = n->sg_kill; 893 } 894 # endif /* TIOCGETP */ 895 #endif /* !POSIX || TERMIO */ 896 897 } /* tty_getchar */ 898 899 900 void 901 tty_setchar(ttydata_t *td, unsigned char *s) 902 { 903 #ifdef TIOCGLTC 904 { 905 struct ltchars *n = &td->d_ltc; 906 907 n->t_suspc = s[C_SUSP]; 908 n->t_dsuspc = s[C_DSUSP]; 909 n->t_rprntc = s[C_REPRINT]; 910 n->t_flushc = s[C_DISCARD]; 911 n->t_werasc = s[C_WERASE]; 912 n->t_lnextc = s[C_LNEXT]; 913 } 914 #endif /* TIOCGLTC */ 915 916 #if defined(POSIX) || defined(TERMIO) 917 { 918 # ifdef POSIX 919 struct termios *n = &td->d_t; 920 # else 921 struct termio *n = &td->d_t; 922 # endif /* POSIX */ 923 924 # ifdef VINTR 925 n->c_cc[VINTR] = s[C_INTR]; 926 # endif /* VINTR */ 927 # ifdef VQUIT 928 n->c_cc[VQUIT] = s[C_QUIT]; 929 # endif /* VQUIT */ 930 # ifdef VERASE 931 n->c_cc[VERASE] = s[C_ERASE]; 932 # endif /* VERASE */ 933 # ifdef VKILL 934 n->c_cc[VKILL] = s[C_KILL]; 935 # endif /* VKILL */ 936 # ifdef VEOF 937 n->c_cc[VEOF] = s[C_EOF]; 938 # endif /* VEOF */ 939 # ifdef VEOL 940 n->c_cc[VEOL] = s[C_EOL]; 941 # endif /* VEOL */ 942 # ifdef VEOL2 943 n->c_cc[VEOL2] = s[C_EOL2]; 944 # endif /* VEOL2 */ 945 # ifdef VSWTCH 946 n->c_cc[VSWTCH] = s[C_SWTCH]; 947 # endif /* VSWTCH */ 948 # ifdef VDSWTCH 949 n->c_cc[VDSWTCH] = s[C_DSWTCH]; 950 # endif /* VDSWTCH */ 951 # ifdef VERASE2 952 n->c_cc[VERASE2] = s[C_ERASE2]; 953 # endif /* VERASE2 */ 954 # ifdef VSTART 955 n->c_cc[VSTART] = s[C_START]; 956 # endif /* VSTART */ 957 # ifdef VSTOP 958 n->c_cc[VSTOP] = s[C_STOP]; 959 # endif /* VSTOP */ 960 # ifdef VWERASE 961 n->c_cc[VWERASE] = s[C_WERASE]; 962 # endif /* VWERASE */ 963 # ifdef VSUSP 964 n->c_cc[VSUSP] = s[C_SUSP]; 965 # endif /* VSUSP */ 966 # ifdef VDSUSP 967 n->c_cc[VDSUSP] = s[C_DSUSP]; 968 # endif /* VDSUSP */ 969 # ifdef VREPRINT 970 n->c_cc[VREPRINT] = s[C_REPRINT]; 971 # endif /* WREPRINT */ 972 # ifdef VDISCARD 973 n->c_cc[VDISCARD] = s[C_DISCARD]; 974 # endif /* VDISCARD */ 975 # ifdef VLNEXT 976 n->c_cc[VLNEXT] = s[C_LNEXT]; 977 # endif /* VLNEXT */ 978 # ifdef VSTATUS 979 n->c_cc[VSTATUS] = s[C_STATUS]; 980 # endif /* VSTATUS */ 981 # ifdef VCHECKPT 982 n->c_cc[VCHECKPT] = s[C_CHECKPT]; 983 # endif /* VCHECKPT */ 984 # ifdef VPAGE 985 n->c_cc[VPAGE] = s[C_PAGE]; 986 # endif /* VPAGE */ 987 # ifdef VPGOFF 988 n->c_cc[VPGOFF] = s[C_PGOFF]; 989 # endif /* VPGOFF */ 990 # ifdef VKILL2 991 n->c_cc[VKILL2] = s[C_KILL2]; 992 # endif /* VKILL2 */ 993 # ifdef VMIN 994 n->c_cc[VMIN] = s[C_MIN]; 995 # endif /* VMIN */ 996 # ifdef VTIME 997 n->c_cc[VTIME] = s[C_TIME]; 998 # endif /* VTIME */ 999 } 1000 1001 #else /* GSTTY */ 1002 1003 # ifdef TIOCGPAGE 1004 { 1005 struct ttypagestat *n = &td->d_pc; 1006 1007 n->tps_length = 0; 1008 n->tps_lpos = 0; 1009 n->tps_statc = s[C_STATUS]; 1010 n->tps_pagec = s[C_PAGE]; 1011 n->tps_pgoffc = s[C_PGOFF]; 1012 n->tps_flag = 0; 1013 } 1014 # endif /* TIOCGPAGE */ 1015 1016 # ifdef TIOCGETC 1017 { 1018 struct tchars *n = &td->d_tc; 1019 n->t_intrc = s[C_INTR]; 1020 n->t_quitc = s[C_QUIT]; 1021 n->t_startc = s[C_START]; 1022 n->t_stopc = s[C_STOP]; 1023 n->t_eofc = s[C_EOF]; 1024 n->t_brkc = s[C_BRK]; 1025 } 1026 # endif /* TIOCGETC */ 1027 1028 # ifdef TIOCGETP 1029 { 1030 struct sgttyb *n = &td->d_t; 1031 1032 n->sg_erase = s[C_ERASE]; 1033 n->sg_kill = s[C_KILL]; 1034 } 1035 # endif /* TIOCGETP */ 1036 #endif /* !POSIX || TERMIO */ 1037 1038 } /* tty_setchar */ 1039 1040 speed_t 1041 tty_getspeed(ttydata_t *td) 1042 { 1043 speed_t spd; 1044 1045 #ifdef POSIX 1046 if ((spd = cfgetispeed(&td->d_t)) == 0) 1047 spd = cfgetospeed(&td->d_t); 1048 #else /* ! POSIX */ 1049 # ifdef TERMIO 1050 # ifdef CBAUD 1051 spd = td->d_t.c_cflag & CBAUD; 1052 # else 1053 spd = 0; 1054 # endif 1055 # else /* SGTTY */ 1056 spd = td->d_t.sg_ispeed; 1057 # endif /* TERMIO */ 1058 #endif /* POSIX */ 1059 1060 return spd; 1061 } /* end tty_getspeed */ 1062 1063 int 1064 tty_gettabs(ttydata_t *td) 1065 { 1066 #if defined(POSIX) || defined(TERMIO) 1067 return ((td->d_t.c_oflag & TAB3) == TAB3) ? 0 : 1; 1068 #else /* SGTTY */ 1069 return (td->d_t.sg_flags & XTABS) == XTABS ? 0 : 1; 1070 #endif /* POSIX || TERMIO */ 1071 } /* end tty_gettabs */ 1072 1073 int 1074 tty_geteightbit(ttydata_t *td) 1075 { 1076 #if defined(POSIX) || defined(TERMIO) 1077 return (td->d_t.c_cflag & CSIZE) == CS8; 1078 #else /* SGTTY */ 1079 return td->d_lb & (LPASS8 | LLITOUT); 1080 #endif /* POSIX || TERMIO */ 1081 } /* end tty_geteightbit */ 1082 1083 int 1084 tty_cooked_mode(ttydata_t *td) 1085 { 1086 #if defined(POSIX) || defined(TERMIO) 1087 return (td->d_t.c_lflag & ICANON); 1088 #else /* SGTTY */ 1089 return !(td->d_t.sg_flags & (RAW | CBREAK)); 1090 #endif /* POSIX || TERMIO */ 1091 } /* end tty_cooked_mode */ 1092 1093 #ifdef _IBMR2 1094 void 1095 tty_setdisc(int fd, int dis) 1096 { 1097 static int edit_discipline = 0; 1098 static union txname tx_disc; 1099 extern char strPOSIX[]; 1100 1101 switch (dis) { 1102 case EX_IO: 1103 if (edit_discipline) { 1104 if (ioctl(fd, TXSETLD, (ioctl_t) & tx_disc) == -1) 1105 return; 1106 edit_discipline = 0; 1107 } 1108 return; 1109 1110 case ED_IO: 1111 tx_disc.tx_which = 0; 1112 if (ioctl(fd, TXGETLD, (ioctl_t) & tx_disc) == -1) 1113 return; 1114 if (strcmp(tx_disc.tx_name, strPOSIX) != 0) { 1115 edit_discipline = 1; 1116 if (ioctl(fd, TXSETLD, (ioctl_t) strPOSIX) == -1) 1117 return; 1118 } 1119 return; 1120 1121 default: 1122 return; 1123 } 1124 } /* end tty_setdisc */ 1125 #endif /* _IBMR2 */ 1126 1127 #ifdef DEBUG_TTY 1128 static void 1129 tty_printchar(unsigned char *s) 1130 { 1131 struct tcshmodes *m; 1132 int i; 1133 1134 for (i = 0; i < C_NCC; i++) { 1135 for (m = modelist; m->m_name; m++) 1136 if (m->m_type == M_CHAR && C_SH(i) == m->m_value) 1137 break; 1138 if (m->m_name) 1139 xprintf("%s ^%c ", m->m_name, s[i] + 'A' - 1); 1140 if (i % 5 == 0) 1141 xputchar('\n'); 1142 } 1143 xputchar('\n'); 1144 } 1145 #endif /* DEBUG_TTY */ 1146 #else /* WINNT_NATIVE */ 1147 int 1148 tty_cooked_mode(void *td) 1149 { 1150 return do_nt_check_cooked_mode(); 1151 } 1152 #endif /* !WINNT_NATIVE */ 1153