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