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