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.5 (Berkeley) 03/29/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 * Sleeps here are not interruptible, but we return prematurely 1278 * if new signals come in. 1279 */ 1280 ttycheckoutq(tp, wait) 1281 register struct tty *tp; 1282 int wait; 1283 { 1284 int hiwat, s, oldsig; 1285 1286 hiwat = TTHIWAT(tp); 1287 s = spltty(); 1288 oldsig = u.u_procp->p_sig; 1289 if (tp->t_outq.c_cc > hiwat + 200) 1290 while (tp->t_outq.c_cc > hiwat) { 1291 ttstart(tp); 1292 if (wait == 0 || u.u_procp->p_sig != oldsig) { 1293 splx(s); 1294 return (0); 1295 } 1296 timeout(wakeup, (caddr_t)&tp->t_outq, hz); 1297 tp->t_state |= TS_ASLEEP; 1298 sleep((caddr_t)&tp->t_outq, PZERO - 1); 1299 } 1300 splx(s); 1301 return (1); 1302 } 1303 1304 /* 1305 * Called from the device's write routine after it has 1306 * calculated the tty-structure given as argument. 1307 */ 1308 ttwrite(tp, uio) 1309 register struct tty *tp; 1310 register struct uio *uio; 1311 { 1312 register char *cp; 1313 register int cc, ce, c; 1314 int i, hiwat, cnt, error, s; 1315 char obuf[OBUFSIZ]; 1316 1317 hiwat = TTHIWAT(tp); 1318 cnt = uio->uio_resid; 1319 error = 0; 1320 loop: 1321 if ((tp->t_state&TS_CARR_ON) == 0) 1322 return (EIO); 1323 /* 1324 * Hang the process if it's in the background. 1325 */ 1326 if (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 1327 (tp->t_flags&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1328 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 1329 !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { 1330 gsignal(u.u_procp->p_pgrp, SIGTTOU); 1331 sleep((caddr_t)&lbolt, TTIPRI); 1332 goto loop; 1333 } 1334 1335 /* 1336 * Process the user's data in at most OBUFSIZ 1337 * chunks. Perform lower case simulation and 1338 * similar hacks. Keep track of high water 1339 * mark, sleep on overflow awaiting device aid 1340 * in acquiring new space. 1341 */ 1342 while (uio->uio_resid > 0) { 1343 /* 1344 * Grab a hunk of data from the user. 1345 */ 1346 cc = uio->uio_iov->iov_len; 1347 if (cc == 0) { 1348 uio->uio_iovcnt--; 1349 uio->uio_iov++; 1350 if (uio->uio_iovcnt <= 0) 1351 panic("ttwrite"); 1352 continue; 1353 } 1354 if (cc > OBUFSIZ) 1355 cc = OBUFSIZ; 1356 cp = obuf; 1357 error = uiomove(cp, cc, UIO_WRITE, uio); 1358 if (error) 1359 break; 1360 if (tp->t_outq.c_cc > hiwat) 1361 goto ovhiwat; 1362 if (tp->t_flags&FLUSHO) 1363 continue; 1364 /* 1365 * If we're mapping lower case or kludging tildes, 1366 * then we've got to look at each character, so 1367 * just feed the stuff to ttyoutput... 1368 */ 1369 if (tp->t_flags & (LCASE|TILDE)) { 1370 while (cc > 0) { 1371 c = *cp++; 1372 tp->t_rocount = 0; 1373 while ((c = ttyoutput(c, tp)) >= 0) { 1374 /* out of clists, wait a bit */ 1375 ttstart(tp); 1376 sleep((caddr_t)&lbolt, TTOPRI); 1377 tp->t_rocount = 0; 1378 if (cc != 0) { 1379 uio->uio_iov->iov_base -= cc; 1380 uio->uio_iov->iov_len += cc; 1381 uio->uio_resid += cc; 1382 uio->uio_offset -= cc; 1383 } 1384 goto loop; 1385 } 1386 --cc; 1387 if (tp->t_outq.c_cc > hiwat) 1388 goto ovhiwat; 1389 } 1390 continue; 1391 } 1392 /* 1393 * If nothing fancy need be done, grab those characters we 1394 * can handle without any of ttyoutput's processing and 1395 * just transfer them to the output q. For those chars 1396 * which require special processing (as indicated by the 1397 * bits in partab), call ttyoutput. After processing 1398 * a hunk of data, look for FLUSHO so ^O's will take effect 1399 * immediately. 1400 */ 1401 while (cc > 0) { 1402 if (tp->t_flags & (RAW|LITOUT)) 1403 ce = cc; 1404 else { 1405 ce = cc - scanc((unsigned)cc, (caddr_t)cp, 1406 (caddr_t)partab, 077); 1407 /* 1408 * If ce is zero, then we're processing 1409 * a special character through ttyoutput. 1410 */ 1411 if (ce == 0) { 1412 tp->t_rocount = 0; 1413 if (ttyoutput(*cp, tp) >= 0) { 1414 /* no c-lists, wait a bit */ 1415 ttstart(tp); 1416 sleep((caddr_t)&lbolt, TTOPRI); 1417 if (cc != 0) { 1418 uio->uio_iov->iov_base -= cc; 1419 uio->uio_iov->iov_len += cc; 1420 uio->uio_resid += cc; 1421 uio->uio_offset -= cc; 1422 } 1423 goto loop; 1424 } 1425 cp++, cc--; 1426 if (tp->t_flags&FLUSHO || 1427 tp->t_outq.c_cc > hiwat) 1428 goto ovhiwat; 1429 continue; 1430 } 1431 } 1432 /* 1433 * A bunch of normal characters have been found, 1434 * transfer them en masse to the output queue and 1435 * continue processing at the top of the loop. 1436 * If there are any further characters in this 1437 * <= OBUFSIZ chunk, the first should be a character 1438 * requiring special handling by ttyoutput. 1439 */ 1440 tp->t_rocount = 0; 1441 i = b_to_q(cp, ce, &tp->t_outq); 1442 ce -= i; 1443 tp->t_col += ce; 1444 cp += ce, cc -= ce, tk_nout += ce; 1445 if (i > 0) { 1446 /* out of c-lists, wait a bit */ 1447 ttstart(tp); 1448 sleep((caddr_t)&lbolt, TTOPRI); 1449 uio->uio_iov->iov_base -= cc; 1450 uio->uio_iov->iov_len += cc; 1451 uio->uio_resid += cc; 1452 uio->uio_offset -= cc; 1453 goto loop; 1454 } 1455 if (tp->t_flags&FLUSHO || tp->t_outq.c_cc > hiwat) 1456 goto ovhiwat; 1457 } 1458 } 1459 ttstart(tp); 1460 return (error); 1461 1462 ovhiwat: 1463 s = spltty(); 1464 if (cc != 0) { 1465 uio->uio_iov->iov_base -= cc; 1466 uio->uio_iov->iov_len += cc; 1467 uio->uio_resid += cc; 1468 uio->uio_offset -= cc; 1469 } 1470 /* 1471 * This can only occur if FLUSHO 1472 * is also set in t_flags. 1473 */ 1474 if (tp->t_outq.c_cc <= hiwat) { 1475 splx(s); 1476 goto loop; 1477 } 1478 ttstart(tp); 1479 if (tp->t_state&TS_NBIO) { 1480 splx(s); 1481 if (uio->uio_resid == cnt) 1482 return (EWOULDBLOCK); 1483 return (0); 1484 } 1485 tp->t_state |= TS_ASLEEP; 1486 sleep((caddr_t)&tp->t_outq, TTOPRI); 1487 splx(s); 1488 goto loop; 1489 } 1490 1491 /* 1492 * Rubout one character from the rawq of tp 1493 * as cleanly as possible. 1494 */ 1495 ttyrub(c, tp) 1496 register c; 1497 register struct tty *tp; 1498 { 1499 register char *cp; 1500 register int savecol; 1501 int s; 1502 char *nextc(); 1503 1504 if ((tp->t_flags&ECHO) == 0) 1505 return; 1506 tp->t_flags &= ~FLUSHO; 1507 c &= 0377; 1508 if (tp->t_flags&CRTBS) { 1509 if (tp->t_rocount == 0) { 1510 /* 1511 * Screwed by ttwrite; retype 1512 */ 1513 ttyretype(tp); 1514 return; 1515 } 1516 if (c == ('\t'|0200) || c == ('\n'|0200)) 1517 ttyrubo(tp, 2); 1518 else switch (partab[c&=0177]&0177) { 1519 1520 case ORDINARY: 1521 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z') 1522 ttyrubo(tp, 2); 1523 else 1524 ttyrubo(tp, 1); 1525 break; 1526 1527 case VTAB: 1528 case BACKSPACE: 1529 case CONTROL: 1530 case RETURN: 1531 if (tp->t_flags&CTLECH) 1532 ttyrubo(tp, 2); 1533 break; 1534 1535 case TAB: 1536 if (tp->t_rocount < tp->t_rawq.c_cc) { 1537 ttyretype(tp); 1538 return; 1539 } 1540 s = spltty(); 1541 savecol = tp->t_col; 1542 tp->t_state |= TS_CNTTB; 1543 tp->t_flags |= FLUSHO; 1544 tp->t_col = tp->t_rocol; 1545 cp = tp->t_rawq.c_cf; 1546 for (; cp; cp = nextc(&tp->t_rawq, cp)) 1547 ttyecho(*cp, tp); 1548 tp->t_flags &= ~FLUSHO; 1549 tp->t_state &= ~TS_CNTTB; 1550 splx(s); 1551 /* 1552 * savecol will now be length of the tab 1553 */ 1554 savecol -= tp->t_col; 1555 tp->t_col += savecol; 1556 if (savecol > 8) 1557 savecol = 8; /* overflow screw */ 1558 while (--savecol >= 0) 1559 (void) ttyoutput('\b', tp); 1560 break; 1561 1562 default: 1563 panic("ttyrub"); 1564 } 1565 } else if (tp->t_flags&PRTERA) { 1566 if ((tp->t_state&TS_ERASE) == 0) { 1567 (void) ttyoutput('\\', tp); 1568 tp->t_state |= TS_ERASE; 1569 } 1570 ttyecho(c, tp); 1571 } else 1572 ttyecho(tp->t_erase, tp); 1573 tp->t_rocount--; 1574 } 1575 1576 /* 1577 * Crt back over cnt chars perhaps 1578 * erasing them. 1579 */ 1580 ttyrubo(tp, cnt) 1581 register struct tty *tp; 1582 int cnt; 1583 { 1584 register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b"; 1585 1586 while (--cnt >= 0) 1587 ttyout(rubostring, tp); 1588 } 1589 1590 /* 1591 * Reprint the rawq line. 1592 * We assume c_cc has already been checked. 1593 */ 1594 ttyretype(tp) 1595 register struct tty *tp; 1596 { 1597 register char *cp; 1598 char *nextc(); 1599 int s; 1600 1601 if (tp->t_rprntc != 0377) 1602 ttyecho(tp->t_rprntc, tp); 1603 (void) ttyoutput('\n', tp); 1604 s = spltty(); 1605 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) 1606 ttyecho(*cp, tp); 1607 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 1608 ttyecho(*cp, tp); 1609 tp->t_state &= ~TS_ERASE; 1610 splx(s); 1611 tp->t_rocount = tp->t_rawq.c_cc; 1612 tp->t_rocol = 0; 1613 } 1614 1615 /* 1616 * Echo a typed character to the terminal 1617 */ 1618 ttyecho(c, tp) 1619 register c; 1620 register struct tty *tp; 1621 { 1622 1623 if ((tp->t_state&TS_CNTTB) == 0) 1624 tp->t_flags &= ~FLUSHO; 1625 if ((tp->t_flags&ECHO) == 0) 1626 return; 1627 c &= 0377; 1628 if (tp->t_flags&RAW) { 1629 (void) ttyoutput(c, tp); 1630 return; 1631 } 1632 if (c == '\r' && tp->t_flags&CRMOD) 1633 c = '\n'; 1634 if (tp->t_flags&CTLECH) { 1635 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) { 1636 (void) ttyoutput('^', tp); 1637 c &= 0177; 1638 if (c == 0177) 1639 c = '?'; 1640 else if (tp->t_flags&LCASE) 1641 c += 'a' - 1; 1642 else 1643 c += 'A' - 1; 1644 } 1645 } 1646 (void) ttyoutput(c&0177, tp); 1647 } 1648 1649 /* 1650 * Is c a break char for tp? 1651 */ 1652 ttbreakc(c, tp) 1653 register c; 1654 register struct tty *tp; 1655 { 1656 return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc || 1657 c == '\r' && (tp->t_flags&CRMOD)); 1658 } 1659 1660 /* 1661 * send string cp to tp 1662 */ 1663 ttyout(cp, tp) 1664 register char *cp; 1665 register struct tty *tp; 1666 { 1667 register char c; 1668 1669 while (c = *cp++) 1670 (void) ttyoutput(c, tp); 1671 } 1672 1673 ttwakeup(tp) 1674 struct tty *tp; 1675 { 1676 1677 if (tp->t_rsel) { 1678 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 1679 tp->t_state &= ~TS_RCOLL; 1680 tp->t_rsel = 0; 1681 } 1682 if (tp->t_state & TS_ASYNC) 1683 gsignal(tp->t_pgrp, SIGIO); 1684 wakeup((caddr_t)&tp->t_rawq); 1685 } 1686