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