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