ed.term.c revision 231990
1/* $Header: /p/tcsh/cvsroot/tcsh/ed.term.c,v 1.38 2011/02/25 23:58:34 christos Exp $ */ 2/* 3 * ed.term.c: Low level terminal interface 4 */ 5/*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33#include "sh.h" 34#ifndef WINNT_NATIVE 35 36RCSID("$tcsh: ed.term.c,v 1.38 2011/02/25 23:58:34 christos Exp $") 37#include <assert.h> 38#include "ed.h" 39 40int didsetty = 0; 41ttyperm_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 87static const 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#define RETRY(x) \ 572do { \ 573 int count; \ 574 \ 575 for (count = 0;; count++) \ 576 if ((x) == -1) { \ 577 if (OKERROR(errno) || KLUDGE) \ 578 continue; \ 579 else \ 580 return -1; \ 581 } \ 582 else \ 583 break; \ 584} while (0) 585 586/*ARGSUSED*/ 587void 588dosetty(Char **v, struct command *t) 589{ 590 const struct tcshmodes *m; 591 char x, *d, *cmdname; 592 int aflag = 0; 593 Char *s; 594 int z = EX_IO; 595 596 USE(t); 597 cmdname = strsave(short2str(*v++)); 598 cleanup_push(cmdname, xfree); 599 setname(cmdname); 600 601 while (v && *v && v[0][0] == '-' && v[0][2] == '\0') 602 switch (v[0][1]) { 603 case 'a': 604 aflag++; 605 v++; 606 break; 607 case 'd': 608 v++; 609 z = ED_IO; 610 break; 611 case 'x': 612 v++; 613 z = EX_IO; 614 break; 615 case 'q': 616 v++; 617 z = QU_IO; 618 break; 619 default: 620 stderror(ERR_NAME | ERR_SYSTEM, short2str(v[0]), 621 CGETS(8, 1, "Unknown switch")); 622 break; 623 } 624 625 didsetty = 1; 626 if (!v || !*v) { 627 int i = -1; 628 int len = 0, st = 0, cu; 629 for (m = modelist; m->m_name; m++) { 630 if (m->m_type != i) { 631 xprintf("%s%s", i != -1 ? "\n" : "", 632 ttylist[z][m->m_type].t_name); 633 i = m->m_type; 634 st = len = strlen(ttylist[z][m->m_type].t_name); 635 } 636 assert(i != -1); 637 638 x = (ttylist[z][i].t_setmask & m->m_value) ? '+' : '\0'; 639 x = (ttylist[z][i].t_clrmask & m->m_value) ? '-' : x; 640 641 if (x != '\0' || aflag) { 642 cu = strlen(m->m_name) + (x != '\0') + 1; 643 if (len + cu >= TermH) { 644 xprintf("\n%*s", st, ""); 645 len = st + cu; 646 } 647 else 648 len += cu; 649 if (x != '\0') 650 xprintf("%c%s ", x, m->m_name); 651 else 652 xprintf("%s ", m->m_name); 653 } 654 } 655 xputchar('\n'); 656 cleanup_until(cmdname); 657 return; 658 } 659 while (v && (s = *v++)) { 660 switch (*s) { 661 case '+': 662 case '-': 663 x = *s++; 664 break; 665 default: 666 x = '\0'; 667 break; 668 } 669 d = short2str(s); 670 for (m = modelist; m->m_name; m++) 671 if (strcmp(m->m_name, d) == 0) 672 break; 673 if (!m->m_name) 674 stderror(ERR_NAME | ERR_SYSTEM, d, CGETS(8, 2, "Invalid argument")); 675 676 switch (x) { 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 case '-': 682 ttylist[z][m->m_type].t_setmask &= ~m->m_value; 683 ttylist[z][m->m_type].t_clrmask |= m->m_value; 684 break; 685 default: 686 ttylist[z][m->m_type].t_setmask &= ~m->m_value; 687 ttylist[z][m->m_type].t_clrmask &= ~m->m_value; 688 break; 689 } 690 } 691 cleanup_until(cmdname); 692} /* end dosetty */ 693 694int 695tty_getty(int fd, ttydata_t *td) 696{ 697#ifdef POSIX 698 RETRY(tcgetattr(fd, &td->d_t)); 699#else /* TERMIO || GSTTY */ 700# ifdef TERMIO 701 RETRY(ioctl(fd, TCGETA, (ioctl_t) &td->d_t)); 702# else /* GSTTY */ 703# ifdef TIOCGETP 704 RETRY(ioctl(fd, TIOCGETP, (ioctl_t) &td->d_t)); 705# endif /* TIOCGETP */ 706# ifdef TIOCGETC 707 RETRY(ioctl(fd, TIOCGETC, (ioctl_t) &td->d_tc)); 708# endif /* TIOCGETC */ 709# ifdef TIOCGPAGE 710 RETRY(ioctl(fd, TIOCGPAGE, (ioctl_t) &td->d_pc)); 711# endif /* TIOCGPAGE */ 712# ifdef TIOCLGET 713 RETRY(ioctl(fd, TIOCLGET, (ioctl_t) &td->d_lb)); 714# endif /* TIOCLGET */ 715# endif /* TERMIO */ 716#endif /* POSIX */ 717 718#ifdef TIOCGLTC 719 RETRY(ioctl(fd, TIOCGLTC, (ioctl_t) &td->d_ltc)); 720#endif /* TIOCGLTC */ 721 722 return 0; 723} 724 725int 726tty_setty(int fd, ttydata_t *td) 727{ 728#ifdef POSIX 729 RETRY(xtcsetattr(fd, TCSADRAIN, &td->d_t)); 730#else 731# ifdef TERMIO 732 RETRY(ioctl(fd, TCSETAW, (ioctl_t) &td->d_t)); 733# else 734# ifdef TIOCSETN 735 RETRY(ioctl(fd, TIOCSETN, (ioctl_t) &td->d_t)); 736# endif /* TIOCSETN */ 737# ifdef TIOCGETC 738 RETRY(ioctl(fd, TIOCSETC, (ioctl_t) &td->d_tc)); 739# endif /* TIOCGETC */ 740# ifdef TIOCGPAGE 741 RETRY(ioctl(fd, TIOCSPAGE, (ioctl_t) &td->d_pc)); 742# endif /* TIOCGPAGE */ 743# ifdef TIOCLGET 744 RETRY(ioctl(fd, TIOCLSET, (ioctl_t) &td->d_lb)); 745# endif /* TIOCLGET */ 746# endif /* TERMIO */ 747#endif /* POSIX */ 748 749#ifdef TIOCGLTC 750 RETRY(ioctl(fd, TIOCSLTC, (ioctl_t) &td->d_ltc)); 751#endif /* TIOCGLTC */ 752 753 return 0; 754} 755 756void 757tty_getchar(ttydata_t *td, unsigned char *s) 758{ 759#ifdef TIOCGLTC 760 { 761 struct ltchars *n = &td->d_ltc; 762 763 s[C_SUSP] = n->t_suspc; 764 s[C_DSUSP] = n->t_dsuspc; 765 s[C_REPRINT] = n->t_rprntc; 766 s[C_DISCARD] = n->t_flushc; 767 s[C_WERASE] = n->t_werasc; 768 s[C_LNEXT] = n->t_lnextc; 769 } 770#endif /* TIOCGLTC */ 771 772#if defined(POSIX) || defined(TERMIO) 773 { 774# ifdef POSIX 775 struct termios *n = &td->d_t; 776# else 777 struct termio *n = &td->d_t; 778# endif /* POSIX */ 779 780# ifdef VINTR 781 s[C_INTR] = n->c_cc[VINTR]; 782# endif /* VINTR */ 783# ifdef VQUIT 784 s[C_QUIT] = n->c_cc[VQUIT]; 785# endif /* VQUIT */ 786# ifdef VERASE 787 s[C_ERASE] = n->c_cc[VERASE]; 788# endif /* VERASE */ 789# ifdef VKILL 790 s[C_KILL] = n->c_cc[VKILL]; 791# endif /* VKILL */ 792# ifdef VEOF 793 s[C_EOF] = n->c_cc[VEOF]; 794# endif /* VEOF */ 795# ifdef VEOL 796 s[C_EOL] = n->c_cc[VEOL]; 797# endif /* VEOL */ 798# ifdef VEOL2 799 s[C_EOL2] = n->c_cc[VEOL2]; 800# endif /* VEOL2 */ 801# ifdef VSWTCH 802 s[C_SWTCH] = n->c_cc[VSWTCH]; 803# endif /* VSWTCH */ 804# ifdef VDSWTCH 805 s[C_DSWTCH] = n->c_cc[VDSWTCH]; 806# endif /* VDSWTCH */ 807# ifdef VERASE2 808 s[C_ERASE2] = n->c_cc[VERASE2]; 809# endif /* VERASE2 */ 810# ifdef VSTART 811 s[C_START] = n->c_cc[VSTART]; 812# endif /* VSTART */ 813# ifdef VSTOP 814 s[C_STOP] = n->c_cc[VSTOP]; 815# endif /* VSTOP */ 816# ifdef VWERASE 817 s[C_WERASE] = n->c_cc[VWERASE]; 818# endif /* VWERASE */ 819# ifdef VSUSP 820 s[C_SUSP] = n->c_cc[VSUSP]; 821# endif /* VSUSP */ 822# ifdef VDSUSP 823 s[C_DSUSP] = n->c_cc[VDSUSP]; 824# endif /* VDSUSP */ 825# ifdef VREPRINT 826 s[C_REPRINT] = n->c_cc[VREPRINT]; 827# endif /* WREPRINT */ 828# ifdef VDISCARD 829 s[C_DISCARD] = n->c_cc[VDISCARD]; 830# endif /* VDISCARD */ 831# ifdef VLNEXT 832 s[C_LNEXT] = n->c_cc[VLNEXT]; 833# endif /* VLNEXT */ 834# ifdef VSTATUS 835 s[C_STATUS] = n->c_cc[VSTATUS]; 836# endif /* VSTATUS */ 837# ifdef VPAGE 838 s[C_PAGE] = n->c_cc[VPAGE]; 839# endif /* VPAGE */ 840# ifdef VPGOFF 841 s[C_PGOFF] = n->c_cc[VPGOFF]; 842# endif /* VPGOFF */ 843# ifdef VKILL2 844 s[C_KILL2] = n->c_cc[VKILL2]; 845# endif /* KILL2 */ 846# ifdef VMIN 847 s[C_MIN] = n->c_cc[VMIN]; 848# endif /* VMIN */ 849# ifdef VTIME 850 s[C_TIME] = n->c_cc[VTIME]; 851# endif /* VTIME */ 852 } 853 854#else /* SGTTY */ 855 856# ifdef TIOCGPAGE 857 { 858 struct ttypagestat *n = &td->d_pc; 859 860 s[C_STATUS] = n->tps_statc; 861 s[C_PAGE] = n->tps_pagec; 862 s[C_PGOFF] = n->tps_pgoffc; 863 } 864# endif /* TIOCGPAGE */ 865 866# ifdef TIOCGETC 867 { 868 struct tchars *n = &td->d_tc; 869 870 s[C_INTR] = n->t_intrc; 871 s[C_QUIT] = n->t_quitc; 872 s[C_START] = n->t_startc; 873 s[C_STOP] = n->t_stopc; 874 s[C_EOF] = n->t_eofc; 875 s[C_BRK] = n->t_brkc; 876 } 877# endif /* TIOCGETC */ 878 879# ifdef TIOCGETP 880 { 881 struct sgttyb *n = &td->d_t; 882 883 s[C_ERASE] = n->sg_erase; 884 s[C_KILL] = n->sg_kill; 885 } 886# endif /* TIOCGETP */ 887#endif /* !POSIX || TERMIO */ 888 889} /* tty_getchar */ 890 891 892void 893tty_setchar(ttydata_t *td, unsigned char *s) 894{ 895#ifdef TIOCGLTC 896 { 897 struct ltchars *n = &td->d_ltc; 898 899 n->t_suspc = s[C_SUSP]; 900 n->t_dsuspc = s[C_DSUSP]; 901 n->t_rprntc = s[C_REPRINT]; 902 n->t_flushc = s[C_DISCARD]; 903 n->t_werasc = s[C_WERASE]; 904 n->t_lnextc = s[C_LNEXT]; 905 } 906#endif /* TIOCGLTC */ 907 908#if defined(POSIX) || defined(TERMIO) 909 { 910# ifdef POSIX 911 struct termios *n = &td->d_t; 912# else 913 struct termio *n = &td->d_t; 914# endif /* POSIX */ 915 916# ifdef VINTR 917 n->c_cc[VINTR] = s[C_INTR]; 918# endif /* VINTR */ 919# ifdef VQUIT 920 n->c_cc[VQUIT] = s[C_QUIT]; 921# endif /* VQUIT */ 922# ifdef VERASE 923 n->c_cc[VERASE] = s[C_ERASE]; 924# endif /* VERASE */ 925# ifdef VKILL 926 n->c_cc[VKILL] = s[C_KILL]; 927# endif /* VKILL */ 928# ifdef VEOF 929 n->c_cc[VEOF] = s[C_EOF]; 930# endif /* VEOF */ 931# ifdef VEOL 932 n->c_cc[VEOL] = s[C_EOL]; 933# endif /* VEOL */ 934# ifdef VEOL2 935 n->c_cc[VEOL2] = s[C_EOL2]; 936# endif /* VEOL2 */ 937# ifdef VSWTCH 938 n->c_cc[VSWTCH] = s[C_SWTCH]; 939# endif /* VSWTCH */ 940# ifdef VDSWTCH 941 n->c_cc[VDSWTCH] = s[C_DSWTCH]; 942# endif /* VDSWTCH */ 943# ifdef VERASE2 944 n->c_cc[VERASE2] = s[C_ERASE2]; 945# endif /* VERASE2 */ 946# ifdef VSTART 947 n->c_cc[VSTART] = s[C_START]; 948# endif /* VSTART */ 949# ifdef VSTOP 950 n->c_cc[VSTOP] = s[C_STOP]; 951# endif /* VSTOP */ 952# ifdef VWERASE 953 n->c_cc[VWERASE] = s[C_WERASE]; 954# endif /* VWERASE */ 955# ifdef VSUSP 956 n->c_cc[VSUSP] = s[C_SUSP]; 957# endif /* VSUSP */ 958# ifdef VDSUSP 959 n->c_cc[VDSUSP] = s[C_DSUSP]; 960# endif /* VDSUSP */ 961# ifdef VREPRINT 962 n->c_cc[VREPRINT] = s[C_REPRINT]; 963# endif /* WREPRINT */ 964# ifdef VDISCARD 965 n->c_cc[VDISCARD] = s[C_DISCARD]; 966# endif /* VDISCARD */ 967# ifdef VLNEXT 968 n->c_cc[VLNEXT] = s[C_LNEXT]; 969# endif /* VLNEXT */ 970# ifdef VSTATUS 971 n->c_cc[VSTATUS] = s[C_STATUS]; 972# endif /* VSTATUS */ 973# ifdef VPAGE 974 n->c_cc[VPAGE] = s[C_PAGE]; 975# endif /* VPAGE */ 976# ifdef VPGOFF 977 n->c_cc[VPGOFF] = s[C_PGOFF]; 978# endif /* VPGOFF */ 979# ifdef VKILL2 980 n->c_cc[VKILL2] = s[C_KILL2]; 981# endif /* VKILL2 */ 982# ifdef VMIN 983 n->c_cc[VMIN] = s[C_MIN]; 984# endif /* VMIN */ 985# ifdef VTIME 986 n->c_cc[VTIME] = s[C_TIME]; 987# endif /* VTIME */ 988 } 989 990#else /* GSTTY */ 991 992# ifdef TIOCGPAGE 993 { 994 struct ttypagestat *n = &td->d_pc; 995 996 n->tps_length = 0; 997 n->tps_lpos = 0; 998 n->tps_statc = s[C_STATUS]; 999 n->tps_pagec = s[C_PAGE]; 1000 n->tps_pgoffc = s[C_PGOFF]; 1001 n->tps_flag = 0; 1002 } 1003# endif /* TIOCGPAGE */ 1004 1005# ifdef TIOCGETC 1006 { 1007 struct tchars *n = &td->d_tc; 1008 n->t_intrc = s[C_INTR]; 1009 n->t_quitc = s[C_QUIT]; 1010 n->t_startc = s[C_START]; 1011 n->t_stopc = s[C_STOP]; 1012 n->t_eofc = s[C_EOF]; 1013 n->t_brkc = s[C_BRK]; 1014 } 1015# endif /* TIOCGETC */ 1016 1017# ifdef TIOCGETP 1018 { 1019 struct sgttyb *n = &td->d_t; 1020 1021 n->sg_erase = s[C_ERASE]; 1022 n->sg_kill = s[C_KILL]; 1023 } 1024# endif /* TIOCGETP */ 1025#endif /* !POSIX || TERMIO */ 1026 1027} /* tty_setchar */ 1028 1029speed_t 1030tty_getspeed(ttydata_t *td) 1031{ 1032 speed_t spd; 1033 1034#ifdef POSIX 1035 if ((spd = cfgetispeed(&td->d_t)) == 0) 1036 spd = cfgetospeed(&td->d_t); 1037#else /* ! POSIX */ 1038# ifdef TERMIO 1039# ifdef CBAUD 1040 spd = td->d_t.c_cflag & CBAUD; 1041# else 1042 spd = 0; 1043# endif 1044# else /* SGTTY */ 1045 spd = td->d_t.sg_ispeed; 1046# endif /* TERMIO */ 1047#endif /* POSIX */ 1048 1049 return spd; 1050} /* end tty_getspeed */ 1051 1052int 1053tty_gettabs(ttydata_t *td) 1054{ 1055#if defined(POSIX) || defined(TERMIO) 1056 return ((td->d_t.c_oflag & TAB3) == TAB3) ? 0 : 1; 1057#else /* SGTTY */ 1058 return (td->d_t.sg_flags & XTABS) == XTABS ? 0 : 1; 1059#endif /* POSIX || TERMIO */ 1060} /* end tty_gettabs */ 1061 1062int 1063tty_geteightbit(ttydata_t *td) 1064{ 1065#if defined(POSIX) || defined(TERMIO) 1066 return (td->d_t.c_cflag & CSIZE) == CS8; 1067#else /* SGTTY */ 1068 return td->d_lb & (LPASS8 | LLITOUT); 1069#endif /* POSIX || TERMIO */ 1070} /* end tty_geteightbit */ 1071 1072int 1073tty_cooked_mode(ttydata_t *td) 1074{ 1075#if defined(POSIX) || defined(TERMIO) 1076 return (td->d_t.c_lflag & ICANON); 1077#else /* SGTTY */ 1078 return !(td->d_t.sg_flags & (RAW | CBREAK)); 1079#endif /* POSIX || TERMIO */ 1080} /* end tty_cooked_mode */ 1081 1082#ifdef _IBMR2 1083void 1084tty_setdisc(int fd, int dis) 1085{ 1086 static int edit_discipline = 0; 1087 static union txname tx_disc; 1088 extern char strPOSIX[]; 1089 1090 switch (dis) { 1091 case EX_IO: 1092 if (edit_discipline) { 1093 if (ioctl(fd, TXSETLD, (ioctl_t) & tx_disc) == -1) 1094 return; 1095 edit_discipline = 0; 1096 } 1097 return; 1098 1099 case ED_IO: 1100 tx_disc.tx_which = 0; 1101 if (ioctl(fd, TXGETLD, (ioctl_t) & tx_disc) == -1) 1102 return; 1103 if (strcmp(tx_disc.tx_name, strPOSIX) != 0) { 1104 edit_discipline = 1; 1105 if (ioctl(fd, TXSETLD, (ioctl_t) strPOSIX) == -1) 1106 return; 1107 } 1108 return; 1109 1110 default: 1111 return; 1112 } 1113} /* end tty_setdisc */ 1114#endif /* _IBMR2 */ 1115 1116#ifdef DEBUG_TTY 1117static void 1118tty_printchar(unsigned char *s) 1119{ 1120 struct tcshmodes *m; 1121 int i; 1122 1123 for (i = 0; i < C_NCC; i++) { 1124 for (m = modelist; m->m_name; m++) 1125 if (m->m_type == M_CHAR && C_SH(i) == m->m_value) 1126 break; 1127 if (m->m_name) 1128 xprintf("%s ^%c ", m->m_name, s[i] + 'A' - 1); 1129 if (i % 5 == 0) 1130 xputchar('\n'); 1131 } 1132 xputchar('\n'); 1133} 1134#endif /* DEBUG_TTY */ 1135#else /* WINNT_NATIVE */ 1136int 1137tty_cooked_mode(void *td) 1138{ 1139 return do_nt_check_cooked_mode(); 1140} 1141#endif /* !WINNT_NATIVE */ 1142