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