1 /* $Header: /p/tcsh/cvsroot/tcsh/ed.term.c,v 1.36 2006/03/02 18:46:44 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.36 2006/03/02 18:46:44 christos Exp $") 37 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 641 x = (ttylist[z][i].t_setmask & m->m_value) ? '+' : '\0'; 642 x = (ttylist[z][i].t_clrmask & m->m_value) ? '-' : x; 643 644 if (x != '\0' || aflag) { 645 cu = strlen(m->m_name) + (x != '\0') + 1; 646 if (len + cu >= TermH) { 647 xprintf("\n%*s", st, ""); 648 len = st + cu; 649 } 650 else 651 len += cu; 652 if (x != '\0') 653 xprintf("%c%s ", x, m->m_name); 654 else 655 xprintf("%s ", m->m_name); 656 } 657 } 658 xputchar('\n'); 659 cleanup_until(cmdname); 660 return; 661 } 662 while (v && (s = *v++)) { 663 switch (*s) { 664 case '+': 665 case '-': 666 x = *s++; 667 break; 668 default: 669 x = '\0'; 670 break; 671 } 672 d = short2str(s); 673 for (m = modelist; m->m_name; m++) 674 if (strcmp(m->m_name, d) == 0) 675 break; 676 if (!m->m_name) 677 stderror(ERR_NAME | ERR_SYSTEM, d, CGETS(8, 2, "Invalid argument")); 678 679 switch (x) { 680 case '+': 681 ttylist[z][m->m_type].t_setmask |= m->m_value; 682 ttylist[z][m->m_type].t_clrmask &= ~m->m_value; 683 break; 684 case '-': 685 ttylist[z][m->m_type].t_setmask &= ~m->m_value; 686 ttylist[z][m->m_type].t_clrmask |= m->m_value; 687 break; 688 default: 689 ttylist[z][m->m_type].t_setmask &= ~m->m_value; 690 ttylist[z][m->m_type].t_clrmask &= ~m->m_value; 691 break; 692 } 693 } 694 cleanup_until(cmdname); 695 } /* end dosetty */ 696 697 int 698 tty_getty(int fd, ttydata_t *td) 699 { 700 #ifdef POSIX 701 RETRY(tcgetattr(fd, &td->d_t)); 702 #else /* TERMIO || GSTTY */ 703 # ifdef TERMIO 704 RETRY(ioctl(fd, TCGETA, (ioctl_t) &td->d_t)); 705 # else /* GSTTY */ 706 # ifdef TIOCGETP 707 RETRY(ioctl(fd, TIOCGETP, (ioctl_t) &td->d_t)); 708 # endif /* TIOCGETP */ 709 # ifdef TIOCGETC 710 RETRY(ioctl(fd, TIOCGETC, (ioctl_t) &td->d_tc)); 711 # endif /* TIOCGETC */ 712 # ifdef TIOCGPAGE 713 RETRY(ioctl(fd, TIOCGPAGE, (ioctl_t) &td->d_pc)); 714 # endif /* TIOCGPAGE */ 715 # ifdef TIOCLGET 716 RETRY(ioctl(fd, TIOCLGET, (ioctl_t) &td->d_lb)); 717 # endif /* TIOCLGET */ 718 # endif /* TERMIO */ 719 #endif /* POSIX */ 720 721 #ifdef TIOCGLTC 722 RETRY(ioctl(fd, TIOCGLTC, (ioctl_t) &td->d_ltc)); 723 #endif /* TIOCGLTC */ 724 725 return 0; 726 } 727 728 int 729 tty_setty(int fd, ttydata_t *td) 730 { 731 #ifdef POSIX 732 RETRY(xtcsetattr(fd, TCSADRAIN, &td->d_t)); 733 #else 734 # ifdef TERMIO 735 RETRY(ioctl(fd, TCSETAW, (ioctl_t) &td->d_t)); 736 # else 737 # ifdef TIOCSETN 738 RETRY(ioctl(fd, TIOCSETN, (ioctl_t) &td->d_t)); 739 # endif /* TIOCSETN */ 740 # ifdef TIOCGETC 741 RETRY(ioctl(fd, TIOCSETC, (ioctl_t) &td->d_tc)); 742 # endif /* TIOCGETC */ 743 # ifdef TIOCGPAGE 744 RETRY(ioctl(fd, TIOCSPAGE, (ioctl_t) &td->d_pc)); 745 # endif /* TIOCGPAGE */ 746 # ifdef TIOCLGET 747 RETRY(ioctl(fd, TIOCLSET, (ioctl_t) &td->d_lb)); 748 # endif /* TIOCLGET */ 749 # endif /* TERMIO */ 750 #endif /* POSIX */ 751 752 #ifdef TIOCGLTC 753 RETRY(ioctl(fd, TIOCSLTC, (ioctl_t) &td->d_ltc)); 754 #endif /* TIOCGLTC */ 755 756 return 0; 757 } 758 759 void 760 tty_getchar(ttydata_t *td, unsigned char *s) 761 { 762 #ifdef TIOCGLTC 763 { 764 struct ltchars *n = &td->d_ltc; 765 766 s[C_SUSP] = n->t_suspc; 767 s[C_DSUSP] = n->t_dsuspc; 768 s[C_REPRINT] = n->t_rprntc; 769 s[C_DISCARD] = n->t_flushc; 770 s[C_WERASE] = n->t_werasc; 771 s[C_LNEXT] = n->t_lnextc; 772 } 773 #endif /* TIOCGLTC */ 774 775 #if defined(POSIX) || defined(TERMIO) 776 { 777 # ifdef POSIX 778 struct termios *n = &td->d_t; 779 # else 780 struct termio *n = &td->d_t; 781 # endif /* POSIX */ 782 783 # ifdef VINTR 784 s[C_INTR] = n->c_cc[VINTR]; 785 # endif /* VINTR */ 786 # ifdef VQUIT 787 s[C_QUIT] = n->c_cc[VQUIT]; 788 # endif /* VQUIT */ 789 # ifdef VERASE 790 s[C_ERASE] = n->c_cc[VERASE]; 791 # endif /* VERASE */ 792 # ifdef VKILL 793 s[C_KILL] = n->c_cc[VKILL]; 794 # endif /* VKILL */ 795 # ifdef VEOF 796 s[C_EOF] = n->c_cc[VEOF]; 797 # endif /* VEOF */ 798 # ifdef VEOL 799 s[C_EOL] = n->c_cc[VEOL]; 800 # endif /* VEOL */ 801 # ifdef VEOL2 802 s[C_EOL2] = n->c_cc[VEOL2]; 803 # endif /* VEOL2 */ 804 # ifdef VSWTCH 805 s[C_SWTCH] = n->c_cc[VSWTCH]; 806 # endif /* VSWTCH */ 807 # ifdef VDSWTCH 808 s[C_DSWTCH] = n->c_cc[VDSWTCH]; 809 # endif /* VDSWTCH */ 810 # ifdef VERASE2 811 s[C_ERASE2] = n->c_cc[VERASE2]; 812 # endif /* VERASE2 */ 813 # ifdef VSTART 814 s[C_START] = n->c_cc[VSTART]; 815 # endif /* VSTART */ 816 # ifdef VSTOP 817 s[C_STOP] = n->c_cc[VSTOP]; 818 # endif /* VSTOP */ 819 # ifdef VWERASE 820 s[C_WERASE] = n->c_cc[VWERASE]; 821 # endif /* VWERASE */ 822 # ifdef VSUSP 823 s[C_SUSP] = n->c_cc[VSUSP]; 824 # endif /* VSUSP */ 825 # ifdef VDSUSP 826 s[C_DSUSP] = n->c_cc[VDSUSP]; 827 # endif /* VDSUSP */ 828 # ifdef VREPRINT 829 s[C_REPRINT] = n->c_cc[VREPRINT]; 830 # endif /* WREPRINT */ 831 # ifdef VDISCARD 832 s[C_DISCARD] = n->c_cc[VDISCARD]; 833 # endif /* VDISCARD */ 834 # ifdef VLNEXT 835 s[C_LNEXT] = n->c_cc[VLNEXT]; 836 # endif /* VLNEXT */ 837 # ifdef VSTATUS 838 s[C_STATUS] = n->c_cc[VSTATUS]; 839 # endif /* VSTATUS */ 840 # ifdef VCHECKPT 841 s[C_CHECKPT] = n->c_cc[VCHECKPT]; 842 # endif /* VCHECKPT */ 843 # ifdef VPAGE 844 s[C_PAGE] = n->c_cc[VPAGE]; 845 # endif /* VPAGE */ 846 # ifdef VPGOFF 847 s[C_PGOFF] = n->c_cc[VPGOFF]; 848 # endif /* VPGOFF */ 849 # ifdef VKILL2 850 s[C_KILL2] = n->c_cc[VKILL2]; 851 # endif /* KILL2 */ 852 # ifdef VMIN 853 s[C_MIN] = n->c_cc[VMIN]; 854 # endif /* VMIN */ 855 # ifdef VTIME 856 s[C_TIME] = n->c_cc[VTIME]; 857 # endif /* VTIME */ 858 } 859 860 #else /* SGTTY */ 861 862 # ifdef TIOCGPAGE 863 { 864 struct ttypagestat *n = &td->d_pc; 865 866 s[C_STATUS] = n->tps_statc; 867 s[C_CHECKPT] = n->tps_checkp; 868 s[C_PAGE] = n->tps_pagec; 869 s[C_PGOFF] = n->tps_pgoffc; 870 } 871 # endif /* TIOCGPAGE */ 872 873 # ifdef TIOCGETC 874 { 875 struct tchars *n = &td->d_tc; 876 877 s[C_INTR] = n->t_intrc; 878 s[C_QUIT] = n->t_quitc; 879 s[C_START] = n->t_startc; 880 s[C_STOP] = n->t_stopc; 881 s[C_EOF] = n->t_eofc; 882 s[C_BRK] = n->t_brkc; 883 } 884 # endif /* TIOCGETC */ 885 886 # ifdef TIOCGETP 887 { 888 struct sgttyb *n = &td->d_t; 889 890 s[C_ERASE] = n->sg_erase; 891 s[C_KILL] = n->sg_kill; 892 } 893 # endif /* TIOCGETP */ 894 #endif /* !POSIX || TERMIO */ 895 896 } /* tty_getchar */ 897 898 899 void 900 tty_setchar(ttydata_t *td, unsigned char *s) 901 { 902 #ifdef TIOCGLTC 903 { 904 struct ltchars *n = &td->d_ltc; 905 906 n->t_suspc = s[C_SUSP]; 907 n->t_dsuspc = s[C_DSUSP]; 908 n->t_rprntc = s[C_REPRINT]; 909 n->t_flushc = s[C_DISCARD]; 910 n->t_werasc = s[C_WERASE]; 911 n->t_lnextc = s[C_LNEXT]; 912 } 913 #endif /* TIOCGLTC */ 914 915 #if defined(POSIX) || defined(TERMIO) 916 { 917 # ifdef POSIX 918 struct termios *n = &td->d_t; 919 # else 920 struct termio *n = &td->d_t; 921 # endif /* POSIX */ 922 923 # ifdef VINTR 924 n->c_cc[VINTR] = s[C_INTR]; 925 # endif /* VINTR */ 926 # ifdef VQUIT 927 n->c_cc[VQUIT] = s[C_QUIT]; 928 # endif /* VQUIT */ 929 # ifdef VERASE 930 n->c_cc[VERASE] = s[C_ERASE]; 931 # endif /* VERASE */ 932 # ifdef VKILL 933 n->c_cc[VKILL] = s[C_KILL]; 934 # endif /* VKILL */ 935 # ifdef VEOF 936 n->c_cc[VEOF] = s[C_EOF]; 937 # endif /* VEOF */ 938 # ifdef VEOL 939 n->c_cc[VEOL] = s[C_EOL]; 940 # endif /* VEOL */ 941 # ifdef VEOL2 942 n->c_cc[VEOL2] = s[C_EOL2]; 943 # endif /* VEOL2 */ 944 # ifdef VSWTCH 945 n->c_cc[VSWTCH] = s[C_SWTCH]; 946 # endif /* VSWTCH */ 947 # ifdef VDSWTCH 948 n->c_cc[VDSWTCH] = s[C_DSWTCH]; 949 # endif /* VDSWTCH */ 950 # ifdef VERASE2 951 n->c_cc[VERASE2] = s[C_ERASE2]; 952 # endif /* VERASE2 */ 953 # ifdef VSTART 954 n->c_cc[VSTART] = s[C_START]; 955 # endif /* VSTART */ 956 # ifdef VSTOP 957 n->c_cc[VSTOP] = s[C_STOP]; 958 # endif /* VSTOP */ 959 # ifdef VWERASE 960 n->c_cc[VWERASE] = s[C_WERASE]; 961 # endif /* VWERASE */ 962 # ifdef VSUSP 963 n->c_cc[VSUSP] = s[C_SUSP]; 964 # endif /* VSUSP */ 965 # ifdef VDSUSP 966 n->c_cc[VDSUSP] = s[C_DSUSP]; 967 # endif /* VDSUSP */ 968 # ifdef VREPRINT 969 n->c_cc[VREPRINT] = s[C_REPRINT]; 970 # endif /* WREPRINT */ 971 # ifdef VDISCARD 972 n->c_cc[VDISCARD] = s[C_DISCARD]; 973 # endif /* VDISCARD */ 974 # ifdef VLNEXT 975 n->c_cc[VLNEXT] = s[C_LNEXT]; 976 # endif /* VLNEXT */ 977 # ifdef VSTATUS 978 n->c_cc[VSTATUS] = s[C_STATUS]; 979 # endif /* VSTATUS */ 980 # ifdef VCHECKPT 981 n->c_cc[VCHECKPT] = s[C_CHECKPT]; 982 # endif /* VCHECKPT */ 983 # ifdef VPAGE 984 n->c_cc[VPAGE] = s[C_PAGE]; 985 # endif /* VPAGE */ 986 # ifdef VPGOFF 987 n->c_cc[VPGOFF] = s[C_PGOFF]; 988 # endif /* VPGOFF */ 989 # ifdef VKILL2 990 n->c_cc[VKILL2] = s[C_KILL2]; 991 # endif /* VKILL2 */ 992 # ifdef VMIN 993 n->c_cc[VMIN] = s[C_MIN]; 994 # endif /* VMIN */ 995 # ifdef VTIME 996 n->c_cc[VTIME] = s[C_TIME]; 997 # endif /* VTIME */ 998 } 999 1000 #else /* GSTTY */ 1001 1002 # ifdef TIOCGPAGE 1003 { 1004 struct ttypagestat *n = &td->d_pc; 1005 1006 n->tps_length = 0; 1007 n->tps_lpos = 0; 1008 n->tps_statc = s[C_STATUS]; 1009 n->tps_pagec = s[C_PAGE]; 1010 n->tps_pgoffc = s[C_PGOFF]; 1011 n->tps_flag = 0; 1012 } 1013 # endif /* TIOCGPAGE */ 1014 1015 # ifdef TIOCGETC 1016 { 1017 struct tchars *n = &td->d_tc; 1018 n->t_intrc = s[C_INTR]; 1019 n->t_quitc = s[C_QUIT]; 1020 n->t_startc = s[C_START]; 1021 n->t_stopc = s[C_STOP]; 1022 n->t_eofc = s[C_EOF]; 1023 n->t_brkc = s[C_BRK]; 1024 } 1025 # endif /* TIOCGETC */ 1026 1027 # ifdef TIOCGETP 1028 { 1029 struct sgttyb *n = &td->d_t; 1030 1031 n->sg_erase = s[C_ERASE]; 1032 n->sg_kill = s[C_KILL]; 1033 } 1034 # endif /* TIOCGETP */ 1035 #endif /* !POSIX || TERMIO */ 1036 1037 } /* tty_setchar */ 1038 1039 speed_t 1040 tty_getspeed(ttydata_t *td) 1041 { 1042 speed_t spd; 1043 1044 #ifdef POSIX 1045 if ((spd = cfgetispeed(&td->d_t)) == 0) 1046 spd = cfgetospeed(&td->d_t); 1047 #else /* ! POSIX */ 1048 # ifdef TERMIO 1049 # ifdef CBAUD 1050 spd = td->d_t.c_cflag & CBAUD; 1051 # else 1052 spd = 0; 1053 # endif 1054 # else /* SGTTY */ 1055 spd = td->d_t.sg_ispeed; 1056 # endif /* TERMIO */ 1057 #endif /* POSIX */ 1058 1059 return spd; 1060 } /* end tty_getspeed */ 1061 1062 int 1063 tty_gettabs(ttydata_t *td) 1064 { 1065 #if defined(POSIX) || defined(TERMIO) 1066 return ((td->d_t.c_oflag & TAB3) == TAB3) ? 0 : 1; 1067 #else /* SGTTY */ 1068 return (td->d_t.sg_flags & XTABS) == XTABS ? 0 : 1; 1069 #endif /* POSIX || TERMIO */ 1070 } /* end tty_gettabs */ 1071 1072 int 1073 tty_geteightbit(ttydata_t *td) 1074 { 1075 #if defined(POSIX) || defined(TERMIO) 1076 return (td->d_t.c_cflag & CSIZE) == CS8; 1077 #else /* SGTTY */ 1078 return td->d_lb & (LPASS8 | LLITOUT); 1079 #endif /* POSIX || TERMIO */ 1080 } /* end tty_geteightbit */ 1081 1082 int 1083 tty_cooked_mode(ttydata_t *td) 1084 { 1085 #if defined(POSIX) || defined(TERMIO) 1086 return (td->d_t.c_lflag & ICANON); 1087 #else /* SGTTY */ 1088 return !(td->d_t.sg_flags & (RAW | CBREAK)); 1089 #endif /* POSIX || TERMIO */ 1090 } /* end tty_cooked_mode */ 1091 1092 #ifdef _IBMR2 1093 void 1094 tty_setdisc(int fd, int dis) 1095 { 1096 static int edit_discipline = 0; 1097 static union txname tx_disc; 1098 extern char strPOSIX[]; 1099 1100 switch (dis) { 1101 case EX_IO: 1102 if (edit_discipline) { 1103 if (ioctl(fd, TXSETLD, (ioctl_t) & tx_disc) == -1) 1104 return; 1105 edit_discipline = 0; 1106 } 1107 return; 1108 1109 case ED_IO: 1110 tx_disc.tx_which = 0; 1111 if (ioctl(fd, TXGETLD, (ioctl_t) & tx_disc) == -1) 1112 return; 1113 if (strcmp(tx_disc.tx_name, strPOSIX) != 0) { 1114 edit_discipline = 1; 1115 if (ioctl(fd, TXSETLD, (ioctl_t) strPOSIX) == -1) 1116 return; 1117 } 1118 return; 1119 1120 default: 1121 return; 1122 } 1123 } /* end tty_setdisc */ 1124 #endif /* _IBMR2 */ 1125 1126 #ifdef DEBUG_TTY 1127 static void 1128 tty_printchar(unsigned char *s) 1129 { 1130 struct tcshmodes *m; 1131 int i; 1132 1133 for (i = 0; i < C_NCC; i++) { 1134 for (m = modelist; m->m_name; m++) 1135 if (m->m_type == M_CHAR && C_SH(i) == m->m_value) 1136 break; 1137 if (m->m_name) 1138 xprintf("%s ^%c ", m->m_name, s[i] + 'A' - 1); 1139 if (i % 5 == 0) 1140 xputchar('\n'); 1141 } 1142 xputchar('\n'); 1143 } 1144 #endif /* DEBUG_TTY */ 1145 #else /* WINNT_NATIVE */ 1146 int 1147 tty_cooked_mode(void *td) 1148 { 1149 return do_nt_check_cooked_mode(); 1150 } 1151 #endif /* !WINNT_NATIVE */ 1152