1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)tty.c 7.16 (Berkeley) 05/01/89 7 */ 8 9 #include "param.h" 10 #include "systm.h" 11 #include "dir.h" 12 #include "user.h" 13 #include "ioctl.h" 14 #include "tty.h" 15 #define TTYDEFCHARS 16 #include "ttydefaults.h" 17 #undef TTYDEFCHARS 18 #include "termios.h" 19 #include "proc.h" 20 #include "file.h" 21 #include "conf.h" 22 #include "dkstat.h" 23 #include "uio.h" 24 #include "kernel.h" 25 #include "syslog.h" 26 27 #include "machine/reg.h" 28 29 /* 30 * Table giving parity for characters and indicating 31 * character classes to tty driver. The 8th bit 32 * indicates parity, the 7th bit indicates the character 33 * is an alphameric or underscore (for ALTWERASE), and the 34 * low 6 bits indicate delay type. If the low 6 bits are 0 35 * then the character needs no special processing on output. 36 */ 37 38 char partab[] = { 39 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 40 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 41 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 42 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 43 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 44 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 45 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 46 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 47 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 48 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 49 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 50 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 51 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 52 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 53 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 54 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 55 /* 56 * meta chars 57 */ 58 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 59 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 60 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 61 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 62 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 63 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 64 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 65 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 66 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 67 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 68 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 69 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 70 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 71 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 72 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 73 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 74 }; 75 76 extern struct tty *constty; /* temporary virtual console */ 77 extern char partab[], maptab[]; 78 79 /* 80 * Is 'c' a line delimiter ("break" character)? 81 */ 82 #define ttbreakc(c) (c == '\n' || CCEQ(cc[VEOF], c) || \ 83 CCEQ(cc[VEOL], c) || CCEQ(cc[VEOL2], c)) 84 85 ttychars(tp) 86 struct tty *tp; 87 { 88 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); 89 } 90 91 /* 92 * Wait for output to drain, then flush input waiting. 93 */ 94 ttywflush(tp) 95 struct tty *tp; 96 { 97 98 ttywait(tp); 99 ttyflush(tp, FREAD); 100 } 101 102 /* 103 * Wait for output to drain. 104 */ 105 ttywait(tp) 106 register struct tty *tp; 107 { 108 int s = spltty(); 109 110 while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && 111 (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 112 tp->t_oproc) { 113 (*tp->t_oproc)(tp); 114 tp->t_state |= TS_ASLEEP; 115 sleep((caddr_t)&tp->t_outq, TTOPRI); 116 } 117 splx(s); 118 } 119 120 /* 121 * Flush all TTY queues 122 */ 123 ttyflush(tp, rw) 124 register struct tty *tp; 125 { 126 register s; 127 128 s = spltty(); 129 if (rw & FREAD) { 130 while (getc(&tp->t_canq) >= 0) 131 ; 132 ttwakeup(tp); 133 } 134 if (rw & FWRITE) { 135 wakeup((caddr_t)&tp->t_outq); /* XXX? what about selwakeup? */ 136 tp->t_state &= ~TS_TTSTOP; 137 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 138 while (getc(&tp->t_outq) >= 0) 139 ; 140 } 141 if (rw & FREAD) { 142 while (getc(&tp->t_rawq) >= 0) 143 ; 144 tp->t_rocount = 0; 145 tp->t_rocol = 0; 146 tp->t_state &= ~TS_LOCAL; 147 } 148 splx(s); 149 } 150 151 /* 152 * Send stop character on input overflow. 153 */ 154 ttyblock(tp) 155 register struct tty *tp; 156 { 157 register x; 158 159 x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 160 if (tp->t_rawq.c_cc > TTYHOG) { 161 ttyflush(tp, FREAD|FWRITE); 162 tp->t_state &= ~TS_TBLOCK; 163 } 164 /* 165 * Block further input iff: 166 * Current input > threshold AND input is available to user program 167 */ 168 if (x >= TTYHOG/2 && 169 (!(tp->t_lflag&ICANON)) || (tp->t_canq.c_cc > 0) && 170 tp->t_cc[VSTOP] != _POSIX_VDISABLE) { 171 if (putc(tp->t_cc[VSTOP], &tp->t_outq)==0) { 172 tp->t_state |= TS_TBLOCK; 173 ttstart(tp); 174 } 175 } 176 } 177 178 /* 179 * Restart typewriter output following a delay 180 * timeout. 181 * The name of the routine is passed to the timeout 182 * subroutine and it is called during a clock interrupt. 183 */ 184 ttrstrt(tp) 185 struct tty *tp; 186 { 187 188 if (tp == 0) 189 panic("ttrstrt"); 190 tp->t_state &= ~TS_TIMEOUT; 191 ttstart(tp); 192 } 193 194 /* 195 * Start output on the typewriter. It is used from the top half 196 * after some characters have been put on the output queue, 197 * from the interrupt routine to transmit the next 198 * character, and after a timeout has finished. 199 */ 200 ttstart(tp) 201 struct tty *tp; 202 { 203 204 if (tp->t_oproc) /* kludge for pty */ 205 (*tp->t_oproc)(tp); 206 } 207 208 /* 209 * Common code for tty ioctls. 210 */ 211 /*ARGSUSED*/ 212 ttioctl(tp, com, data, flag) 213 register struct tty *tp; 214 caddr_t data; 215 { 216 extern int nldisp; 217 int softset = 0; 218 int s, error; 219 220 221 /* 222 * If the ioctl involves modification, 223 * hang if in the background. 224 */ 225 switch (com) { 226 227 case TIOCSETD: 228 case TIOCFLUSH: 229 /*case TIOCSPGRP:*/ 230 case TIOCSTI: 231 case TIOCSWINSZ: 232 case TIOCSETA: 233 case TIOCSETAW: 234 case TIOCSETAF: 235 case TIOCSETAS: 236 case TIOCSETAWS: 237 case TIOCSETAFS: 238 while (u.u_procp->p_pgid != tp->t_pgid && 239 tp == u.u_ttyp && 240 u.u_procp->p_pgrp->pg_jobc && 241 (u.u_procp->p_flag&SVFORK) == 0 && 242 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 243 !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { 244 pgsignal(u.u_procp->p_pgrp, SIGTTOU); 245 sleep((caddr_t)&lbolt, TTOPRI); 246 } 247 break; 248 } 249 250 /* 251 * Process the ioctl. 252 */ 253 switch (com) { 254 255 /* get discipline number */ 256 case TIOCGETD: 257 *(int *)data = tp->t_line; 258 break; 259 260 /* set line discipline */ 261 case TIOCSETD: { 262 register int t = *(int *)data; 263 dev_t dev = tp->t_dev; 264 int error = 0; 265 266 if ((unsigned)t >= nldisp) 267 return (ENXIO); 268 if (t != tp->t_line) { 269 s = spltty(); 270 (*linesw[tp->t_line].l_close)(tp); 271 error = (*linesw[t].l_open)(dev, tp); 272 if (error) { 273 (void)(*linesw[tp->t_line].l_open)(dev, tp); 274 splx(s); 275 return (error); 276 } 277 tp->t_line = t; 278 splx(s); 279 } 280 break; 281 } 282 283 /* prevent more opens on channel */ 284 case TIOCEXCL: 285 tp->t_state |= TS_XCLUDE; 286 break; 287 288 case TIOCNXCL: 289 tp->t_state &= ~TS_XCLUDE; 290 break; 291 292 case TIOCHPCL: 293 tp->t_cflag |= HUPCL; 294 break; 295 296 case TIOCFLUSH: { 297 register int flags = *(int *)data; 298 299 if (flags == 0) 300 flags = FREAD|FWRITE; 301 else 302 flags &= FREAD|FWRITE; 303 ttyflush(tp, flags); 304 break; 305 } 306 307 case FIOASYNC: 308 if (*(int *)data) 309 tp->t_state |= TS_ASYNC; 310 else 311 tp->t_state &= ~TS_ASYNC; 312 break; 313 314 case FIONBIO: 315 break; /* XXX remove */ 316 317 /* return number of characters immediately available */ 318 case FIONREAD: 319 *(off_t *)data = ttnread(tp); 320 break; 321 322 case TIOCOUTQ: 323 *(int *)data = tp->t_outq.c_cc; 324 break; 325 326 case TIOCSTOP: 327 s = spltty(); 328 if ((tp->t_state&TS_TTSTOP) == 0) { 329 tp->t_state |= TS_TTSTOP; 330 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 331 } 332 splx(s); 333 break; 334 335 case TIOCSTART: 336 s = spltty(); 337 if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) { 338 tp->t_state &= ~TS_TTSTOP; 339 tp->t_lflag &= ~FLUSHO; 340 ttstart(tp); 341 } 342 splx(s); 343 break; 344 345 /* 346 * Simulate typing of a character at the terminal. 347 */ 348 case TIOCSTI: 349 if (u.u_uid && (flag & FREAD) == 0) 350 return (EPERM); 351 if (u.u_uid && u.u_ttyp != tp) 352 return (EACCES); 353 (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 354 break; 355 356 case TIOCGETA: { 357 struct termios *t = (struct termios *)data; 358 359 bcopy(&tp->t_termios, t, sizeof(struct termios)); 360 break; 361 } 362 363 case TIOCSETAS: 364 case TIOCSETAWS: 365 case TIOCSETAFS: 366 softset = 1; 367 /*FALLTHROUGH*/ 368 case TIOCSETA: 369 case TIOCSETAW: 370 case TIOCSETAF: { 371 register struct termios *t = (struct termios *)data; 372 int error; 373 374 s = spltty(); 375 if (!softset) { 376 /* 377 * set device hardware 378 */ 379 if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 380 splx(s); 381 return (error); 382 } else { 383 if (!(tp->t_state&TS_CARR_ON) && 384 (tp->t_cflag&CLOCAL) && 385 !(t->c_cflag&CLOCAL)) { 386 tp->t_state &= ~TS_ISOPEN; 387 tp->t_state |= TS_WOPEN; 388 ttwakeup(tp); 389 } 390 tp->t_cflag = t->c_cflag; 391 tp->t_ispeed = t->c_ispeed; 392 tp->t_ospeed = t->c_ospeed; 393 } 394 ttsetwater(tp); 395 } 396 if (com == TIOCSETAF || com == TIOCSETAFS) 397 ttywflush(tp); 398 else { 399 if (com == TIOCSETAW || com == TIOCSETAWS) 400 ttywait(tp); 401 if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON)) 402 if (t->c_lflag&ICANON) { 403 tp->t_lflag |= PENDIN; 404 ttwakeup(tp); 405 } 406 else { 407 struct clist tq; 408 409 catq(&tp->t_rawq, &tp->t_canq); 410 tq = tp->t_rawq; 411 tp->t_rawq = tp->t_canq; 412 tp->t_canq = tq; 413 } 414 } 415 tp->t_iflag = t->c_iflag; 416 tp->t_oflag = t->c_oflag; 417 tp->t_lflag = t->c_lflag; 418 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 419 splx(s); 420 break; 421 } 422 423 /* 424 * Acquire controlling terminal. 425 */ 426 case TIOCSCTTY: { 427 register struct proc *p = u.u_procp; 428 429 /* RETHINK - whether non-session leader 430 * can allocate a new ctty for a session. 431 */ 432 if (u.u_ttyp || 433 (tp->t_session && tp->t_session != p->p_session) || 434 (!tp->t_session && !SESS_LEADER(p))) 435 return(EPERM); 436 u.u_ttyp = tp; 437 u.u_ttyd = tp->t_dev; 438 if (tp->t_pgid == 0) 439 tp->t_pgid = p->p_pgrp->pg_id; 440 tp->t_session = p->p_session; 441 break; 442 } 443 444 /* 445 * Set terminal process group. 446 */ 447 case TIOCSPGRP: { 448 register struct proc *p = u.u_procp; 449 register struct pgrp *pgrp = pgfind(*(int *)data); 450 451 if (u.u_uid && 452 (tp != u.u_ttyp || 453 (pgrp && pgrp->pg_session != p->p_session))) { 454 if (u.u_ttyp == NULL) 455 return (ENOTTY); 456 else 457 return (EPERM); 458 } 459 tp->t_pgid = *(int *)data; 460 break; 461 } 462 463 case TIOCGPGRP: 464 *(int *)data = tp->t_pgid; 465 break; 466 467 case TIOCSWINSZ: 468 if (bcmp((caddr_t)&tp->t_winsize, data, 469 sizeof (struct winsize))) { 470 tp->t_winsize = *(struct winsize *)data; 471 gsignal(tp->t_pgid, SIGWINCH); 472 } 473 break; 474 475 case TIOCGWINSZ: 476 *(struct winsize *)data = tp->t_winsize; 477 break; 478 479 case TIOCCONS: 480 if (*(int *)data) { 481 if (constty != NULL) 482 return (EBUSY); 483 #ifndef UCONSOLE 484 if (error = suser(u.u_cred, &u.u_acflag)) 485 return (error); 486 #endif 487 constty = tp; 488 } else if (tp == constty) 489 constty = NULL; 490 break; 491 492 #ifdef COMPAT_43 493 case TIOCGETP: 494 case TIOCSETP: 495 case TIOCSETN: 496 case TIOCGETC: 497 case TIOCSETC: 498 case TIOCSLTC: 499 case TIOCGLTC: 500 case TIOCLBIS: 501 case TIOCLBIC: 502 case TIOCLSET: 503 case TIOCLGET: 504 case TIOCGETDCOMPAT: 505 case TIOCSETDCOMPAT: 506 return(ttcompat(tp, com, data, flag)); 507 #endif 508 509 default: 510 return (-1); 511 } 512 return (0); 513 } 514 515 ttnread(tp) 516 struct tty *tp; 517 { 518 int nread = 0; 519 520 if (tp->t_lflag & PENDIN) 521 ttypend(tp); 522 nread = tp->t_canq.c_cc; 523 if ((tp->t_lflag & ICANON) == 0) 524 nread += tp->t_rawq.c_cc; 525 return (nread); 526 } 527 528 ttselect(dev, rw) 529 dev_t dev; 530 int rw; 531 { 532 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 533 int nread; 534 int s = spltty(); 535 536 switch (rw) { 537 538 case FREAD: 539 nread = ttnread(tp); 540 if (nread > 0 || 541 (!(tp->t_cflag&CLOCAL) && !(tp->t_state&TS_CARR_ON))) 542 goto win; 543 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 544 tp->t_state |= TS_RCOLL; 545 else 546 tp->t_rsel = u.u_procp; 547 break; 548 549 case FWRITE: 550 if (tp->t_outq.c_cc <= tp->t_lowat) 551 goto win; 552 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 553 tp->t_state |= TS_WCOLL; 554 else 555 tp->t_wsel = u.u_procp; 556 break; 557 } 558 splx(s); 559 return (0); 560 win: 561 splx(s); 562 return (1); 563 } 564 565 /* 566 * Initial open of tty, or (re)entry to line discipline. 567 */ 568 ttyopen(dev, tp) 569 dev_t dev; 570 register struct tty *tp; 571 { 572 register struct proc *pp; 573 574 tp->t_dev = dev; 575 576 tp->t_state &= ~TS_WOPEN; 577 if ((tp->t_state & TS_ISOPEN) == 0) { 578 tp->t_state |= TS_ISOPEN; 579 bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 580 } 581 return (0); 582 } 583 584 /* 585 * "close" a line discipline 586 */ 587 ttylclose(tp) 588 register struct tty *tp; 589 { 590 591 ttywflush(tp); 592 } 593 594 /* 595 * clean tp on last close 596 */ 597 ttyclose(tp) 598 register struct tty *tp; 599 { 600 if (constty == tp) 601 constty = NULL; 602 ttyflush(tp, FREAD|FWRITE); 603 tp->t_pgid = 0; 604 tp->t_state = 0; 605 } 606 607 /* 608 * Handle modem control transition on a tty. 609 * Flag indicates new state of carrier. 610 * Returns 0 if the line should be turned off, otherwise 1. 611 */ 612 ttymodem(tp, flag) 613 register struct tty *tp; 614 { 615 616 if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag & MDMBUF)) { 617 /* 618 * MDMBUF: do flow control according to carrier flag 619 */ 620 if (flag) { 621 tp->t_state &= ~TS_TTSTOP; 622 ttstart(tp); 623 } else if ((tp->t_state&TS_TTSTOP) == 0) { 624 tp->t_state |= TS_TTSTOP; 625 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 626 } 627 } else if (flag == 0) { 628 /* 629 * Lost carrier. 630 */ 631 tp->t_state &= ~TS_CARR_ON; 632 if (tp->t_state & TS_ISOPEN) { 633 if ((tp->t_lflag & NOHANG) == 0) { 634 gsignal(tp->t_pgid, SIGHUP); 635 gsignal(tp->t_pgid, SIGCONT); 636 ttyflush(tp, FREAD|FWRITE); 637 return (0); 638 } 639 } 640 } else { 641 /* 642 * Carrier now on. 643 */ 644 tp->t_state |= TS_CARR_ON; 645 ttwakeup(tp); 646 } 647 return (1); 648 } 649 650 /* 651 * Default modem control routine (for other line disciplines). 652 * Return argument flag, to turn off device on carrier drop. 653 */ 654 nullmodem(tp, flag) 655 register struct tty *tp; 656 int flag; 657 { 658 659 if (flag) 660 tp->t_state |= TS_CARR_ON; 661 else 662 tp->t_state &= ~TS_CARR_ON; 663 return (flag); 664 } 665 666 /* 667 * reinput pending characters after state switch 668 * call at spltty(). 669 */ 670 ttypend(tp) 671 register struct tty *tp; 672 { 673 struct clist tq; 674 register c; 675 676 tp->t_lflag &= ~PENDIN; 677 tp->t_state |= TS_TYPEN; 678 tq = tp->t_rawq; 679 tp->t_rawq.c_cc = 0; 680 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 681 while ((c = getc(&tq)) >= 0) 682 ttyinput(c, tp); 683 tp->t_state &= ~TS_TYPEN; 684 } 685 686 /* 687 * 688 * Place a character on raw TTY input queue, 689 * putting in delimiters and waking up top 690 * half as needed. Also echo if required. 691 * The arguments are the character and the 692 * appropriate tty structure. 693 */ 694 ttyinput(c, tp) 695 register c; 696 register struct tty *tp; 697 { 698 register int iflag = tp->t_iflag; 699 register int lflag = tp->t_lflag; 700 register u_char *cc = tp->t_cc; 701 int i, err; 702 703 /* 704 * If input is pending take it first. 705 */ 706 if (lflag&PENDIN) 707 ttypend(tp); 708 /* 709 * Gather stats. 710 */ 711 tk_nin++; 712 if (lflag&ICANON) { 713 tk_cancc++; 714 tp->t_cancc++; 715 } else { 716 tk_rawcc++; 717 tp->t_rawcc++; 718 } 719 /* 720 * Handle exceptional conditions (break, parity, framing). 721 */ 722 if (err = (c&TTY_ERRORMASK)) { 723 c &= ~TTY_ERRORMASK; 724 if (err&TTY_FE && !c) { /* break */ 725 if (iflag&IGNBRK) 726 goto endcase; 727 else if (iflag&BRKINT && lflag&ISIG && 728 (cc[VINTR] != _POSIX_VDISABLE)) 729 c = cc[VINTR]; 730 else { 731 c = 0; 732 if (iflag&PARMRK) 733 goto parmrk; 734 } 735 } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) { 736 if (iflag&IGNPAR) 737 goto endcase; 738 else if (iflag&PARMRK) { 739 parmrk: 740 putc(0377|TTY_QUOTE, &tp->t_rawq); 741 putc(0|TTY_QUOTE, &tp->t_rawq); 742 putc(c|TTY_QUOTE, &tp->t_rawq); 743 goto endcase; 744 } else 745 c = 0; 746 } 747 } 748 /* 749 * In tandem mode, check high water mark. 750 */ 751 if (iflag&IXOFF) 752 ttyblock(tp); 753 if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP)) 754 c &= 0177; 755 /* 756 * Check for literal nexting very first 757 */ 758 if (tp->t_state&TS_LNCH) { 759 c |= TTY_QUOTE; 760 tp->t_state &= ~TS_LNCH; 761 } 762 /* 763 * Scan for special characters. This code 764 * is really just a big case statement with 765 * non-constant cases. The bottom of the 766 * case statement is labeled ``endcase'', so goto 767 * it after a case match, or similar. 768 */ 769 /* 770 * Control chars which aren't controlled 771 * by ICANON, ISIG, or IXON. 772 */ 773 if (iflag&IEXTEN) { 774 if (CCEQ(cc[VLNEXT],c)) { 775 if (lflag&ECHO) { 776 if (lflag&ECHOE) 777 ttyout("^\b", tp); 778 else 779 ttyecho(c, tp); 780 } 781 tp->t_state |= TS_LNCH; 782 goto endcase; 783 } 784 if (CCEQ(cc[VFLUSHO],c)) { 785 if (lflag&FLUSHO) 786 tp->t_lflag &= ~FLUSHO; 787 else { 788 ttyflush(tp, FWRITE); 789 ttyecho(c, tp); 790 if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 791 ttyretype(tp); 792 tp->t_lflag |= FLUSHO; 793 } 794 goto startoutput; 795 } 796 } 797 /* 798 * Signals. 799 */ 800 if (lflag&ISIG) { 801 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 802 if ((lflag&NOFLSH) == 0) 803 ttyflush(tp, FREAD|FWRITE); 804 ttyecho(c, tp); 805 gsignal(tp->t_pgid, CCEQ(cc[VINTR],c) ? 806 SIGINT : SIGQUIT); 807 goto endcase; 808 } 809 if (CCEQ(cc[VSUSP],c)) { 810 if ((lflag&NOFLSH) == 0) 811 ttyflush(tp, FREAD); 812 ttyecho(c, tp); 813 gsignal(tp->t_pgid, SIGTSTP); 814 goto endcase; 815 } 816 } 817 /* 818 * Handle start/stop characters. 819 */ 820 if (iflag&IXON) { 821 if (CCEQ(cc[VSTOP],c)) { 822 if ((tp->t_state&TS_TTSTOP) == 0) { 823 tp->t_state |= TS_TTSTOP; 824 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 825 return; 826 } 827 if (!CCEQ(cc[VSTART], c)) 828 return; 829 /* 830 * if VSTART == VSTOP then toggle 831 */ 832 goto endcase; 833 } 834 if (CCEQ(cc[VSTART], c)) 835 goto restartoutput; 836 } 837 /* 838 * IGNCR, ICRNL, & INLCR 839 */ 840 if (c == '\r') { 841 if (iflag&IGNCR) 842 goto endcase; 843 else if (iflag&ICRNL) 844 c = '\n'; 845 } 846 else if (c == '\n' && iflag&INLCR) 847 c = '\r'; 848 /* 849 * Non canonical mode; don't process line editing 850 * characters; check high water mark for wakeup. 851 * 852 */ 853 if (!(lflag&ICANON)) { 854 if (tp->t_rawq.c_cc > TTYHOG) { 855 if (iflag&IMAXBEL) { 856 if (tp->t_outq.c_cc < tp->t_hiwat) 857 (void) ttyoutput(CTRL('g'), tp); 858 } else 859 ttyflush(tp, FREAD | FWRITE); 860 } else { 861 if (putc(c, &tp->t_rawq) >= 0) { 862 ttwakeup(tp); 863 ttyecho(c, tp); 864 } 865 } 866 goto endcase; 867 } 868 /* 869 * From here on down canonical mode character 870 * processing takes place. 871 */ 872 /* 873 * erase (^H / ^?) 874 */ 875 if (CCEQ(cc[VERASE], c) || CCEQ(cc[VERASE2], c)) { 876 if (tp->t_rawq.c_cc) 877 ttyrub(unputc(&tp->t_rawq), tp); 878 goto endcase; 879 } 880 /* 881 * kill (^U) 882 */ 883 if (CCEQ(cc[VKILL], c)) { 884 if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount && 885 !(lflag&ECHOPRT)) { 886 while (tp->t_rawq.c_cc) 887 ttyrub(unputc(&tp->t_rawq), tp); 888 } else { 889 ttyecho(c, tp); 890 if (lflag&ECHOK || lflag&ECHOKE) 891 ttyecho('\n', tp); 892 while (getc(&tp->t_rawq) > 0) 893 ; 894 tp->t_rocount = 0; 895 } 896 tp->t_state &= ~TS_LOCAL; 897 goto endcase; 898 } 899 /* 900 * word erase (^W) 901 */ 902 if (CCEQ(cc[VWERASE], c)) { 903 int ctype; 904 905 #define CTYPE(c) ((lflag&ALTWERASE) ? (partab[(c)&TTY_CHARMASK]&0100) : 0) 906 /* 907 * erase whitespace 908 */ 909 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 910 ttyrub(c, tp); 911 if (c == -1) 912 goto endcase; 913 /* 914 * special case last char of token 915 */ 916 ttyrub(c, tp); 917 c = unputc(&tp->t_rawq); 918 if (c == -1 || c == ' ' || c == '\t') { 919 if (c != -1) 920 (void) putc(c, &tp->t_rawq); 921 goto endcase; 922 } 923 /* 924 * erase rest of token 925 */ 926 ctype = CTYPE(c); 927 do { 928 ttyrub(c, tp); 929 c = unputc(&tp->t_rawq); 930 if (c == -1) 931 goto endcase; 932 } while (c != ' ' && c != '\t' && CTYPE(c) == ctype); 933 (void) putc(c, &tp->t_rawq); 934 goto endcase; 935 #undef CTYPE 936 } 937 /* 938 * reprint line (^R) 939 */ 940 if (CCEQ(cc[VREPRINT], c)) { 941 ttyretype(tp); 942 goto endcase; 943 } 944 /* 945 * Check for input buffer overflow 946 */ 947 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 948 if (iflag&IMAXBEL) { 949 if (tp->t_outq.c_cc < tp->t_hiwat) 950 (void) ttyoutput(CTRL('g'), tp); 951 } else 952 ttyflush(tp, FREAD | FWRITE); 953 goto endcase; 954 } 955 /* 956 * Put data char in q for user and 957 * wakeup on seeing a line delimiter. 958 */ 959 if (putc(c, &tp->t_rawq) >= 0) { 960 if (ttbreakc(c)) { 961 tp->t_rocount = 0; 962 catq(&tp->t_rawq, &tp->t_canq); 963 ttwakeup(tp); 964 } else if (tp->t_rocount++ == 0) 965 tp->t_rocol = tp->t_col; 966 if (tp->t_state&TS_ERASE) { 967 /* 968 * end of prterase \.../ 969 */ 970 tp->t_state &= ~TS_ERASE; 971 (void) ttyoutput('/', tp); 972 } 973 i = tp->t_col; 974 ttyecho(c, tp); 975 if (CCEQ(cc[VEOF], c) && lflag&ECHO) { 976 /* 977 * Place the cursor over the '^' of the ^D. 978 */ 979 i = MIN(2, tp->t_col - i); 980 while (i > 0) { 981 (void) ttyoutput('\b', tp); 982 i--; 983 } 984 } 985 } 986 endcase: 987 /* 988 * IXANY means allow any character to restart output. 989 */ 990 if ((tp->t_state&TS_TTSTOP) && !(iflag&IXANY) 991 && cc[VSTART] != cc[VSTOP]) 992 return; 993 restartoutput: 994 tp->t_state &= ~TS_TTSTOP; 995 tp->t_lflag &= ~FLUSHO; 996 startoutput: 997 ttstart(tp); 998 } 999 1000 /* 1001 * Put character on TTY output queue, adding delays, 1002 * expanding tabs, and handling the CR/NL bit. 1003 * This is called both from the top half for output, 1004 * and from interrupt level for echoing. 1005 * The arguments are the character and the tty structure. 1006 * Returns < 0 if putc succeeds, otherwise returns char to resend 1007 * Must be recursive. 1008 */ 1009 ttyoutput(c, tp) 1010 register c; 1011 register struct tty *tp; 1012 { 1013 register char *colp; 1014 register ctype; 1015 register long oflag = tp->t_oflag; 1016 1017 if (!(oflag&OPOST)) { 1018 if (tp->t_lflag&FLUSHO) 1019 return (-1); 1020 if (putc(c, &tp->t_outq)) 1021 return (c); 1022 tk_nout++; 1023 tp->t_outcc++; 1024 return (-1); 1025 } 1026 c &= TTY_CHARMASK; 1027 /* 1028 * Turn tabs to spaces as required 1029 */ 1030 if (c == '\t' && oflag&OXTABS ) { 1031 register int s; 1032 1033 c = 8 - (tp->t_col&7); 1034 if ((tp->t_lflag&FLUSHO) == 0) { 1035 s = spltty(); /* don't interrupt tabs */ 1036 c -= b_to_q(" ", c, &tp->t_outq); 1037 tk_nout += c; 1038 tp->t_outcc += c; 1039 splx(s); 1040 } 1041 tp->t_col += c; 1042 return (c ? -1 : '\t'); 1043 } 1044 if (c == CEOT && oflag&ONOEOT) 1045 return(-1); 1046 tk_nout++; 1047 tp->t_outcc++; 1048 /* 1049 * turn <nl> to <cr><lf> if desired. 1050 */ 1051 if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0) 1052 return (c); 1053 if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq)) 1054 return (c); 1055 /* 1056 * Calculate delays. 1057 * The numbers here represent clock ticks 1058 * and are not necessarily optimal for all terminals. 1059 * 1060 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS 1061 * 1062 * (actually, should THROW AWAY terminals which need delays) 1063 */ 1064 colp = &tp->t_col; 1065 ctype = partab[c]; 1066 c = 0; 1067 switch (ctype&077) { 1068 1069 case ORDINARY: 1070 (*colp)++; 1071 1072 case CONTROL: 1073 break; 1074 1075 case BACKSPACE: 1076 if (*colp) 1077 (*colp)--; 1078 break; 1079 1080 /* 1081 * This macro is close enough to the correct thing; 1082 * it should be replaced by real user settable delays 1083 * in any event... 1084 */ 1085 #define mstohz(ms) (((ms) * hz) >> 10) 1086 case NEWLINE: 1087 ctype = (tp->t_flags >> 8) & 03; 1088 if (ctype == 1) { /* tty 37 */ 1089 if (*colp > 0) { 1090 c = (((unsigned)*colp) >> 4) + 3; 1091 if ((unsigned)c > 6) 1092 c = 6; 1093 } 1094 } else if (ctype == 2) /* vt05 */ 1095 c = mstohz(100); 1096 *colp = 0; 1097 break; 1098 1099 case TAB: 1100 ctype = (tp->t_flags >> 10) & 03; 1101 if (ctype == 1) { /* tty 37 */ 1102 c = 1 - (*colp | ~07); 1103 if (c < 5) 1104 c = 0; 1105 } 1106 *colp |= 07; 1107 (*colp)++; 1108 break; 1109 1110 case VTAB: 1111 if (tp->t_flags&VTDELAY) /* tty 37 */ 1112 c = 0177; 1113 break; 1114 1115 case RETURN: 1116 ctype = (tp->t_flags >> 12) & 03; 1117 if (ctype == 1) /* tn 300 */ 1118 c = mstohz(83); 1119 else if (ctype == 2) /* ti 700 */ 1120 c = mstohz(166); 1121 else if (ctype == 3) { /* concept 100 */ 1122 int i; 1123 1124 if ((i = *colp) >= 0) 1125 for (; i < 9; i++) 1126 (void) putc(0177, &tp->t_outq); 1127 } 1128 *colp = 0; 1129 } 1130 if (c && (tp->t_lflag&FLUSHO) == 0) 1131 (void) putc(c|TTY_QUOTE, &tp->t_outq); 1132 return (-1); 1133 } 1134 #undef mstohz 1135 1136 /* 1137 * Called from device's read routine after it has 1138 * calculated the tty-structure given as argument. 1139 */ 1140 ttread(tp, uio, flag) 1141 register struct tty *tp; 1142 struct uio *uio; 1143 { 1144 register struct clist *qp; 1145 register int c; 1146 register long lflag = tp->t_lflag; 1147 register long iflag = tp->t_iflag; 1148 register u_char *cc = tp->t_cc; 1149 int s, first, error = 0; 1150 1151 loop: 1152 s = spltty(); 1153 /* 1154 * take pending input first 1155 */ 1156 if (lflag&PENDIN) 1157 ttypend(tp); 1158 /* 1159 * Handle carrier. 1160 */ 1161 if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) { 1162 if (tp->t_state&TS_ISOPEN) { 1163 splx(s); 1164 return (0); /* EOF */ 1165 } else if (flag&FNDELAY) { 1166 splx(s); 1167 return (EWOULDBLOCK); 1168 } else { 1169 /* 1170 * sleep awaiting carrier 1171 */ 1172 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1173 splx(s); 1174 goto loop; 1175 } 1176 } 1177 splx(s); 1178 /* 1179 * Hang process if it's in the background. 1180 */ 1181 if (u.u_ttyp == tp && u.u_procp->p_pgid != tp->t_pgid) { 1182 if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 1183 (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 1184 u.u_procp->p_flag&SVFORK || u.u_procp->p_pgrp->pg_jobc == 0) 1185 return (EIO); 1186 pgsignal(u.u_procp->p_pgrp, SIGTTIN); 1187 sleep((caddr_t)&lbolt, TTIPRI); 1188 goto loop; 1189 } 1190 /* 1191 * If canonical, use the canonical queue, 1192 * else use the raw queue. 1193 * 1194 * XXX - should get rid of canonical queue. 1195 * (actually, should get rid of clists...) 1196 */ 1197 qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq; 1198 /* 1199 * No input, sleep on rawq awaiting hardware 1200 * receipt and notification. 1201 */ 1202 s = spltty(); 1203 if (qp->c_cc <= 0) { 1204 /** XXX ??? ask mike why TS_CARR_ON was (once) necessary here 1205 if ((tp->t_state&TS_CARR_ON) == 0 || 1206 (tp->t_state&TS_NBIO)) { 1207 splx(s); 1208 return (EWOULDBLOCK); 1209 } 1210 **/ 1211 if (flag&FNDELAY) { 1212 splx(s); 1213 return (EWOULDBLOCK); 1214 } 1215 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1216 splx(s); 1217 goto loop; 1218 } 1219 splx(s); 1220 /* 1221 * Input present, check for input mapping and processing. 1222 */ 1223 first = 1; 1224 while ((c = getc(qp)) >= 0) { 1225 /* 1226 * delayed suspend (^Y) 1227 */ 1228 if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) { 1229 gsignal(tp->t_pgid, SIGTSTP); 1230 if (first) { 1231 sleep((caddr_t)&lbolt, TTIPRI); 1232 goto loop; 1233 } 1234 break; 1235 } 1236 /* 1237 * Interpret EOF only in canonical mode. 1238 */ 1239 if (CCEQ(cc[VEOF], c) && lflag&ICANON) 1240 break; 1241 /* 1242 * Give user character. 1243 */ 1244 error = ureadc(c , uio); 1245 if (error) 1246 break; 1247 if (uio->uio_resid == 0) 1248 break; 1249 /* 1250 * In canonical mode check for a "break character" 1251 * marking the end of a "line of input". 1252 */ 1253 if (lflag&ICANON && ttbreakc(c)) { 1254 break; 1255 } 1256 first = 0; 1257 } 1258 checktandem: 1259 /* 1260 * Look to unblock output now that (presumably) 1261 * the input queue has gone down. 1262 */ 1263 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 1264 if (cc[VSTART] != _POSIX_VDISABLE 1265 && putc(cc[VSTART], &tp->t_outq) == 0) { 1266 tp->t_state &= ~TS_TBLOCK; 1267 ttstart(tp); 1268 } 1269 } 1270 return (error); 1271 } 1272 1273 /* 1274 * Check the output queue on tp for space for a kernel message 1275 * (from uprintf/tprintf). Allow some space over the normal 1276 * hiwater mark so we don't lose messages due to normal flow 1277 * control, but don't let the tty run amok. 1278 * Sleeps here are not interruptible, but we return prematurely 1279 * if new signals come in. 1280 */ 1281 ttycheckoutq(tp, wait) 1282 register struct tty *tp; 1283 int wait; 1284 { 1285 int hiwat, s, oldsig; 1286 1287 hiwat = tp->t_hiwat; 1288 s = spltty(); 1289 oldsig = u.u_procp->p_sig; 1290 if (tp->t_outq.c_cc > hiwat + 200) 1291 while (tp->t_outq.c_cc > hiwat) { 1292 ttstart(tp); 1293 if (wait == 0 || u.u_procp->p_sig != oldsig) { 1294 splx(s); 1295 return (0); 1296 } 1297 timeout(wakeup, (caddr_t)&tp->t_outq, hz); 1298 tp->t_state |= TS_ASLEEP; 1299 sleep((caddr_t)&tp->t_outq, PZERO - 1); 1300 } 1301 splx(s); 1302 return (1); 1303 } 1304 1305 /* 1306 * Called from the device's write routine after it has 1307 * calculated the tty-structure given as argument. 1308 */ 1309 ttwrite(tp, uio, flag) 1310 register struct tty *tp; 1311 register struct uio *uio; 1312 { 1313 register char *cp; 1314 register int cc, ce, c; 1315 int i, hiwat, cnt, error, s; 1316 char obuf[OBUFSIZ]; 1317 1318 hiwat = tp->t_hiwat; 1319 cnt = uio->uio_resid; 1320 error = 0; 1321 loop: 1322 s = spltty(); 1323 if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) { 1324 if (tp->t_state&TS_ISOPEN) { 1325 splx(s); 1326 return (EIO); 1327 } else if (flag&FNDELAY) { 1328 splx(s); 1329 return (EWOULDBLOCK); 1330 } else { 1331 /* 1332 * sleep awaiting carrier 1333 */ 1334 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1335 splx(s); 1336 goto loop; 1337 } 1338 } 1339 splx(s); 1340 /* 1341 * Hang the process if it's in the background. 1342 */ 1343 if (u.u_ttyp == tp && 1344 u.u_procp->p_pgid != tp->t_pgid && 1345 (tp->t_lflag&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1346 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 1347 !(u.u_procp->p_sigmask & sigmask(SIGTTOU)) && 1348 u.u_procp->p_pgrp->pg_jobc) { 1349 pgsignal(u.u_procp->p_pgrp, SIGTTOU); 1350 sleep((caddr_t)&lbolt, TTIPRI); 1351 goto loop; 1352 } 1353 /* 1354 * Process the user's data in at most OBUFSIZ 1355 * chunks. Perform lower case simulation and 1356 * similar hacks. Keep track of high water 1357 * mark, sleep on overflow awaiting device aid 1358 * in acquiring new space. 1359 */ 1360 while (uio->uio_resid > 0) { 1361 if (tp->t_outq.c_cc > hiwat) { 1362 cc = 0; 1363 goto ovhiwat; 1364 } 1365 /* 1366 * Grab a hunk of data from the user. 1367 */ 1368 cc = uio->uio_iov->iov_len; 1369 if (cc == 0) { 1370 uio->uio_iovcnt--; 1371 uio->uio_iov++; 1372 if (uio->uio_iovcnt <= 0) 1373 panic("ttwrite"); 1374 continue; 1375 } 1376 if (cc > OBUFSIZ) 1377 cc = OBUFSIZ; 1378 cp = obuf; 1379 error = uiomove(cp, cc, UIO_WRITE, uio); 1380 if (error) 1381 break; 1382 if (tp->t_lflag&FLUSHO) 1383 continue; 1384 /* 1385 * If nothing fancy need be done, grab those characters we 1386 * can handle without any of ttyoutput's processing and 1387 * just transfer them to the output q. For those chars 1388 * which require special processing (as indicated by the 1389 * bits in partab), call ttyoutput. After processing 1390 * a hunk of data, look for FLUSHO so ^O's will take effect 1391 * immediately. 1392 */ 1393 while (cc > 0) { 1394 if (!(tp->t_oflag&OPOST)) 1395 ce = cc; 1396 else { 1397 ce = cc - scanc((unsigned)cc, (u_char *)cp, 1398 (u_char *)partab, 077); 1399 /* 1400 * If ce is zero, then we're processing 1401 * a special character through ttyoutput. 1402 */ 1403 if (ce == 0) { 1404 tp->t_rocount = 0; 1405 if (ttyoutput(*cp, tp) >= 0) { 1406 /* no c-lists, wait a bit */ 1407 ttstart(tp); 1408 sleep((caddr_t)&lbolt, TTOPRI); 1409 if (cc != 0) { 1410 uio->uio_iov->iov_base -= cc; 1411 uio->uio_iov->iov_len += cc; 1412 uio->uio_resid += cc; 1413 uio->uio_offset -= cc; 1414 } 1415 goto loop; 1416 } 1417 cp++, cc--; 1418 if ((tp->t_lflag&FLUSHO) || 1419 tp->t_outq.c_cc > hiwat) 1420 goto ovhiwat; 1421 continue; 1422 } 1423 } 1424 /* 1425 * A bunch of normal characters have been found, 1426 * transfer them en masse to the output queue and 1427 * continue processing at the top of the loop. 1428 * If there are any further characters in this 1429 * <= OBUFSIZ chunk, the first should be a character 1430 * requiring special handling by ttyoutput. 1431 */ 1432 tp->t_rocount = 0; 1433 i = b_to_q(cp, ce, &tp->t_outq); 1434 ce -= i; 1435 tp->t_col += ce; 1436 cp += ce, cc -= ce, tk_nout += ce; 1437 tp->t_outcc += ce; 1438 if (i > 0) { 1439 /* out of c-lists, wait a bit */ 1440 ttstart(tp); 1441 sleep((caddr_t)&lbolt, TTOPRI); 1442 uio->uio_iov->iov_base -= cc; 1443 uio->uio_iov->iov_len += cc; 1444 uio->uio_resid += cc; 1445 uio->uio_offset -= cc; 1446 goto loop; 1447 } 1448 if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat) 1449 goto ovhiwat; 1450 } 1451 ttstart(tp); 1452 } 1453 return (error); 1454 ovhiwat: 1455 if (cc != 0) { 1456 uio->uio_iov->iov_base -= cc; 1457 uio->uio_iov->iov_len += cc; 1458 uio->uio_resid += cc; 1459 uio->uio_offset -= cc; 1460 } 1461 ttstart(tp); 1462 s = spltty(); 1463 /* 1464 * This can only occur if FLUSHO is set in t_lflag, 1465 * or if ttstart/oproc is synchronous (or very fast). 1466 */ 1467 if (tp->t_outq.c_cc <= hiwat) { 1468 splx(s); 1469 goto loop; 1470 } 1471 if (flag&FNDELAY) { 1472 splx(s); 1473 if (uio->uio_resid == cnt) 1474 return (EWOULDBLOCK); 1475 return (0); 1476 } 1477 tp->t_state |= TS_ASLEEP; 1478 sleep((caddr_t)&tp->t_outq, TTOPRI); 1479 splx(s); 1480 goto loop; 1481 } 1482 1483 /* 1484 * Rubout one character from the rawq of tp 1485 * as cleanly as possible. 1486 */ 1487 ttyrub(c, tp) 1488 register c; 1489 register struct tty *tp; 1490 { 1491 register char *cp; 1492 register int savecol; 1493 int s; 1494 char *nextc(); 1495 1496 if ((tp->t_lflag&ECHO) == 0) 1497 return; 1498 tp->t_lflag &= ~FLUSHO; 1499 if (tp->t_lflag&ECHOE) { 1500 if (tp->t_rocount == 0) { 1501 /* 1502 * Screwed by ttwrite; retype 1503 */ 1504 ttyretype(tp); 1505 return; 1506 } 1507 if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE)) 1508 ttyrubo(tp, 2); 1509 else switch (partab[c&=0377]&077) { 1510 1511 case ORDINARY: 1512 ttyrubo(tp, 1); 1513 break; 1514 1515 case VTAB: 1516 case BACKSPACE: 1517 case CONTROL: 1518 case RETURN: 1519 if (tp->t_lflag&ECHOCTL) 1520 ttyrubo(tp, 2); 1521 break; 1522 1523 case TAB: { 1524 int c; 1525 1526 if (tp->t_rocount < tp->t_rawq.c_cc) { 1527 ttyretype(tp); 1528 return; 1529 } 1530 s = spltty(); 1531 savecol = tp->t_col; 1532 tp->t_state |= TS_CNTTB; 1533 tp->t_lflag |= FLUSHO; 1534 tp->t_col = tp->t_rocol; 1535 cp = tp->t_rawq.c_cf; 1536 c = *cp; /* XXX FIX NEXTC */ 1537 for (; cp; cp = nextc(&tp->t_rawq, cp, &c)) 1538 ttyecho(c, tp); 1539 tp->t_lflag &= ~FLUSHO; 1540 tp->t_state &= ~TS_CNTTB; 1541 splx(s); 1542 /* 1543 * savecol will now be length of the tab 1544 */ 1545 savecol -= tp->t_col; 1546 tp->t_col += savecol; 1547 if (savecol > 8) 1548 savecol = 8; /* overflow screw */ 1549 while (--savecol >= 0) 1550 (void) ttyoutput('\b', tp); 1551 break; 1552 } 1553 1554 default: 1555 /* XXX */ 1556 printf("ttyrub: would panic c = %d, val = %d\n", 1557 c, partab[c&=0377]&077); 1558 /*panic("ttyrub");*/ 1559 } 1560 } else if (tp->t_lflag&ECHOPRT) { 1561 if ((tp->t_state&TS_ERASE) == 0) { 1562 (void) ttyoutput('\\', tp); 1563 tp->t_state |= TS_ERASE; 1564 } 1565 ttyecho(c, tp); 1566 } else 1567 ttyecho(tp->t_cc[VERASE], tp); 1568 tp->t_rocount--; 1569 } 1570 1571 /* 1572 * Crt back over cnt chars perhaps 1573 * erasing them. 1574 */ 1575 ttyrubo(tp, cnt) 1576 register struct tty *tp; 1577 int cnt; 1578 { 1579 1580 while (--cnt >= 0) 1581 ttyout("\b \b", tp); 1582 } 1583 1584 /* 1585 * Reprint the rawq line. 1586 * We assume c_cc has already been checked. 1587 */ 1588 ttyretype(tp) 1589 register struct tty *tp; 1590 { 1591 register char *cp; 1592 char *nextc(); 1593 int s, c; 1594 1595 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 1596 ttyecho(tp->t_cc[VREPRINT], tp); 1597 (void) ttyoutput('\n', tp); 1598 s = spltty(); 1599 /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE 1600 BIT OF FIRST CHAR ****/ 1601 for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) { 1602 ttyecho(c, tp); 1603 } 1604 for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) { 1605 ttyecho(c, tp); 1606 } 1607 tp->t_state &= ~TS_ERASE; 1608 splx(s); 1609 tp->t_rocount = tp->t_rawq.c_cc; 1610 tp->t_rocol = 0; 1611 } 1612 1613 /* 1614 * Echo a typed character to the terminal. 1615 */ 1616 ttyecho(c, tp) 1617 register c; 1618 register struct tty *tp; 1619 { 1620 if ((tp->t_state&TS_CNTTB) == 0) 1621 tp->t_lflag &= ~FLUSHO; 1622 if ((tp->t_lflag&ECHO) == 0 && !(tp->t_lflag&ECHONL && c == '\n')) 1623 return; 1624 if (tp->t_lflag&ECHOCTL) { 1625 if ((c&TTY_CHARMASK)<=037 && c!='\t' && c!='\n' || c==0177) { 1626 (void) ttyoutput('^', tp); 1627 c &= TTY_CHARMASK; 1628 if (c == 0177) 1629 c = '?'; 1630 else 1631 c += 'A' - 1; 1632 } 1633 } 1634 (void) ttyoutput(c, tp); 1635 } 1636 1637 /* 1638 * send string cp to tp 1639 */ 1640 ttyout(cp, tp) 1641 register char *cp; 1642 register struct tty *tp; 1643 { 1644 register char c; 1645 1646 while (c = *cp++) 1647 (void) ttyoutput(c, tp); 1648 } 1649 1650 ttwakeup(tp) 1651 struct tty *tp; 1652 { 1653 1654 if (tp->t_rsel) { 1655 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 1656 tp->t_state &= ~TS_RCOLL; 1657 tp->t_rsel = 0; 1658 } 1659 if (tp->t_state & TS_ASYNC) 1660 gsignal(tp->t_pgid, SIGIO); 1661 wakeup((caddr_t)&tp->t_rawq); 1662 } 1663 1664 /* 1665 * set tty hi and low water marks 1666 * 1667 * Try to arrange the dynamics so there's about one second 1668 * from hi to low water. 1669 * 1670 */ 1671 ttsetwater(tp) 1672 struct tty *tp; 1673 { 1674 register cps = tp->t_ospeed / 10; 1675 register x; 1676 1677 #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x)) 1678 tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT); 1679 x += cps; 1680 x = clamp(x, TTMAXHIWAT, TTMINHIWAT); 1681 tp->t_hiwat = roundup(x, CBSIZE); 1682 #undef clamp 1683 } 1684 1685 ttspeedtab(speed, table) 1686 struct speedtab table[]; 1687 { 1688 register int i; 1689 1690 for (i = 0; table[i].sp_speed != -1; i++) 1691 if (table[i].sp_speed == speed) 1692 return(table[i].sp_code); 1693 return(-1); 1694 } 1695