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 37int didsetty = 0; 38ttyperm_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 84static 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) \ 569do { \ 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*/ 584void 585dosetty(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 691int 692tty_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 722int 723tty_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 753void 754tty_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 889void 890tty_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 1026speed_t 1027tty_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 1049int 1050tty_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 1059int 1060tty_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 1069int 1070tty_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 1080void 1081tty_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 1114static void 1115tty_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 */ 1133int 1134tty_cooked_mode(void *td) 1135{ 1136 return do_nt_check_cooked_mode(); 1137} 1138#endif /* !WINNT_NATIVE */ 1139