1 /* tty.c 4.27 82/08/13 */ 2 3 /* 4 * TTY subroutines common to more than one line discipline 5 */ 6 #include "../h/param.h" 7 #include "../h/systm.h" 8 #include "../h/dir.h" 9 #include "../h/user.h" 10 #include "../h/tty.h" 11 #include "../h/proc.h" 12 #include "../h/inode.h" 13 #include "../h/file.h" 14 #include "../h/reg.h" 15 #include "../h/conf.h" 16 #include "../h/buf.h" 17 #include "../h/dk.h" 18 #include "../h/uio.h" 19 20 /* 21 * Table giving parity for characters and indicating 22 * character classes to tty driver. In particular, 23 * if the low 6 bits are 0, then the character needs 24 * no special processing on output. 25 */ 26 27 char partab[] = { 28 0001,0201,0201,0001,0201,0001,0001,0201, 29 0202,0004,0003,0201,0005,0206,0201,0001, 30 0201,0001,0001,0201,0001,0201,0201,0001, 31 0001,0201,0201,0001,0201,0001,0001,0201, 32 0200,0000,0000,0200,0000,0200,0200,0000, 33 0000,0200,0200,0000,0200,0000,0000,0200, 34 0000,0200,0200,0000,0200,0000,0000,0200, 35 0200,0000,0000,0200,0000,0200,0200,0000, 36 0200,0000,0000,0200,0000,0200,0200,0000, 37 0000,0200,0200,0000,0200,0000,0000,0200, 38 0000,0200,0200,0000,0200,0000,0000,0200, 39 0200,0000,0000,0200,0000,0200,0200,0000, 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,0201, 44 45 /* 46 * 7 bit ascii ends with the last character above, 47 * but we contine through all 256 codes for the sake 48 * of the tty output routines which use special vax 49 * instructions which need a 256 character trt table. 50 */ 51 52 0007,0007,0007,0007,0007,0007,0007,0007, 53 0007,0007,0007,0007,0007,0007,0007,0007, 54 0007,0007,0007,0007,0007,0007,0007,0007, 55 0007,0007,0007,0007,0007,0007,0007,0007, 56 0007,0007,0007,0007,0007,0007,0007,0007, 57 0007,0007,0007,0007,0007,0007,0007,0007, 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 }; 69 70 /* 71 * Input mapping table-- if an entry is non-zero, when the 72 * corresponding character is typed preceded by "\" the escape 73 * sequence is replaced by the table value. Mostly used for 74 * upper-case only terminals. 75 */ 76 77 char maptab[] ={ 78 000,000,000,000,000,000,000,000, 79 000,000,000,000,000,000,000,000, 80 000,000,000,000,000,000,000,000, 81 000,000,000,000,000,000,000,000, 82 000,'|',000,000,000,000,000,'`', 83 '{','}',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,000,000, 88 000,000,000,000,000,000,000,000, 89 000,000,000,000,000,000,'~',000, 90 000,'A','B','C','D','E','F','G', 91 'H','I','J','K','L','M','N','O', 92 'P','Q','R','S','T','U','V','W', 93 'X','Y','Z',000,000,000,000,000, 94 }; 95 96 short tthiwat[16] = 97 { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 }; 98 short ttlowat[16] = 99 { 30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 }; 100 101 #define OBUFSIZ 100 102 103 /* 104 * set default control characters. 105 */ 106 ttychars(tp) 107 register struct tty *tp; 108 { 109 110 tun.t_intrc = CINTR; 111 tun.t_quitc = CQUIT; 112 tun.t_startc = CSTART; 113 tun.t_stopc = CSTOP; 114 tun.t_eofc = CEOT; 115 tun.t_brkc = CBRK; 116 tp->t_erase = CERASE; 117 tp->t_kill = CKILL; 118 /* begin local */ 119 tlun.t_suspc = CTRL(z); 120 tlun.t_dsuspc = CTRL(y); 121 tlun.t_rprntc = CTRL(r); 122 tlun.t_flushc = CTRL(o); 123 tlun.t_werasc = CTRL(w); 124 tlun.t_lnextc = CTRL(v); 125 tp->t_local = 0; 126 tp->t_lstate = 0; 127 /* end local */ 128 } 129 130 /* 131 * Wait for output to drain, then flush input waiting. 132 */ 133 wflushtty(tp) 134 register struct tty *tp; 135 { 136 137 (void) spl5(); 138 while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON 139 && tp->t_oproc) { /* kludge for pty */ 140 (*tp->t_oproc)(tp); 141 tp->t_state |= TS_ASLEEP; 142 sleep((caddr_t)&tp->t_outq, TTOPRI); 143 } 144 flushtty(tp, FREAD); 145 (void) spl0(); 146 } 147 148 /* 149 * flush all TTY queues 150 */ 151 flushtty(tp, rw) 152 register struct tty *tp; 153 { 154 register s; 155 156 s = spl6(); 157 if (rw & FREAD) { 158 while (getc(&tp->t_canq) >= 0) 159 ; 160 wakeup((caddr_t)&tp->t_rawq); 161 } 162 if (rw & FWRITE) { 163 wakeup((caddr_t)&tp->t_outq); 164 tp->t_state &= ~TS_TTSTOP; 165 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 166 while (getc(&tp->t_outq) >= 0) 167 ; 168 } 169 if (rw & FREAD) { 170 while (getc(&tp->t_rawq) >= 0) 171 ; 172 tp->t_delct = 0; 173 tp->t_rocount = 0; /* local */ 174 tp->t_rocol = 0; 175 tp->t_lstate = 0; 176 } 177 splx(s); 178 } 179 180 /* 181 * Send stop character on input overflow. 182 */ 183 ttyblock(tp) 184 register struct tty *tp; 185 { 186 register x; 187 x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 188 if (tp->t_rawq.c_cc > TTYHOG) { 189 flushtty(tp, FREAD|FWRITE); 190 tp->t_state &= ~TS_TBLOCK; 191 } 192 if (x >= TTYHOG/2) { 193 if (putc(tun.t_stopc, &tp->t_outq)==0) { 194 tp->t_state |= TS_TBLOCK; 195 tp->t_char++; 196 ttstart(tp); 197 } 198 } 199 } 200 201 /* 202 * Restart typewriter output following a delay 203 * timeout. 204 * The name of the routine is passed to the timeout 205 * subroutine and it is called during a clock interrupt. 206 */ 207 ttrstrt(tp) 208 register struct tty *tp; 209 { 210 211 if (tp == 0) { 212 printf("ttrstrt: arg was 0!\n"); 213 return; 214 } 215 tp->t_state &= ~TS_TIMEOUT; 216 ttstart(tp); 217 } 218 219 /* 220 * Start output on the typewriter. It is used from the top half 221 * after some characters have been put on the output queue, 222 * from the interrupt routine to transmit the next 223 * character, and after a timeout has finished. 224 */ 225 ttstart(tp) 226 register struct tty *tp; 227 { 228 register s; 229 230 s = spl5(); 231 if ((tp->t_state&(TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 && 232 tp->t_oproc) /* kludge for pty */ 233 (*tp->t_oproc)(tp); 234 splx(s); 235 } 236 237 /* 238 * Common code for tty ioctls. 239 */ 240 /*ARGSUSED*/ 241 ttioctl(tp, com, data, flag) 242 register struct tty *tp; 243 caddr_t data; 244 { 245 int dev; 246 extern int nldisp; 247 248 /* 249 * This is especially so that isatty() will 250 * fail when carrier is gone. 251 */ 252 if ((tp->t_state&TS_CARR_ON) == 0) { 253 u.u_error = EBADF; 254 return (1); 255 } 256 257 dev = tp->t_dev; 258 /* 259 * If the ioctl involves modification, 260 * insist on being able to write the device, 261 * and hang if in the background. 262 */ 263 switch (com) { 264 265 case TIOCSETD: 266 case TIOCSETP: 267 case TIOCSETN: 268 case TIOCFLUSH: 269 case TIOCSETC: 270 case TIOCSLTC: 271 case TIOCSPGRP: 272 case TIOCLBIS: 273 case TIOCLBIC: 274 case TIOCLSET: 275 /* this is reasonable, but impractical... 276 if ((flag & FWRITE) == 0) { 277 u.u_error = EBADF; 278 return (1); 279 } 280 */ 281 while (tp->t_line == NTTYDISC && 282 u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 283 (u.u_procp->p_flag&SVFORK) == 0 && 284 u.u_signal[SIGTTOU] != SIG_IGN && 285 u.u_signal[SIGTTOU] != SIG_HOLD 286 /* 287 && 288 (u.u_procp->p_flag&SDETACH)==0) { 289 */ 290 ) { 291 gsignal(u.u_procp->p_pgrp, SIGTTOU); 292 sleep((caddr_t)&lbolt, TTOPRI); 293 } 294 break; 295 } 296 297 /* 298 * Process the ioctl. 299 */ 300 switch (com) { 301 302 /* 303 * Get discipline number 304 */ 305 case TIOCGETD: 306 *(int *)data = tp->t_line; 307 break; 308 309 /* 310 * Set line discipline 311 */ 312 case TIOCSETD: { 313 register int t = *(int *)data; 314 315 if (t >= nldisp) { 316 u.u_error = ENXIO; 317 break; 318 } 319 (void) spl5(); 320 if (tp->t_line) 321 (*linesw[tp->t_line].l_close)(tp); 322 if (t) 323 (*linesw[t].l_open)(dev, tp); 324 if (u.u_error==0) 325 tp->t_line = t; 326 (void) spl0(); 327 break; 328 } 329 330 /* 331 * Prevent more opens on channel 332 */ 333 case TIOCEXCL: 334 tp->t_state |= TS_XCLUDE; 335 break; 336 337 case TIOCNXCL: 338 tp->t_state &= ~TS_XCLUDE; 339 break; 340 341 /* 342 * Set new parameters 343 */ 344 case TIOCSETP: 345 case TIOCSETN: { 346 register struct sgttyb *sg = (struct sgttyb *)data; 347 struct clist tq; 348 349 (void) spl5(); 350 if (tp->t_flags&RAW || sg->sg_flags&RAW || com == TIOCSETP) 351 wflushtty(tp); 352 else if ((tp->t_flags&CBREAK) != (sg->sg_flags&CBREAK)) { 353 if (sg->sg_flags & CBREAK) { 354 catq(&tp->t_rawq, &tp->t_canq); 355 tq = tp->t_rawq; 356 tp->t_rawq = tp->t_canq; 357 tp->t_canq = tq; 358 } else { 359 tp->t_local |= LPENDIN; 360 ttwakeup(tp); 361 } 362 } 363 tp->t_ispeed = sg->sg_ispeed; 364 tp->t_ospeed = sg->sg_ospeed; 365 tp->t_erase = sg->sg_erase; 366 tp->t_kill = sg->sg_kill; 367 tp->t_flags = sg->sg_flags; 368 if (tp->t_flags & RAW) { 369 tp->t_state &= ~TS_TTSTOP; 370 ttstart(tp); 371 } 372 (void) spl0(); 373 break; 374 } 375 376 /* 377 * Send current parameters to user 378 */ 379 case TIOCGETP: { 380 register struct sgttyb *sg = (struct sgttyb *)data; 381 382 sg->sg_ispeed = tp->t_ispeed; 383 sg->sg_ospeed = tp->t_ospeed; 384 sg->sg_erase = tp->t_erase; 385 sg->sg_kill = tp->t_kill; 386 sg->sg_flags = tp->t_flags; 387 break; 388 } 389 390 /* 391 * Hang up line on last close 392 */ 393 case TIOCHPCL: 394 tp->t_state |= TS_HUPCLS; 395 break; 396 397 case TIOCFLUSH: { 398 register int flags = *(int *)data; 399 400 if (flags == 0) 401 flags = FREAD|FWRITE; 402 else 403 flags &= FREAD|FWRITE; 404 flushtty(tp, flags); 405 break; 406 } 407 408 case FIONBIO: 409 if (*(int *)data) 410 tp->t_state |= TS_NBIO; 411 else 412 tp->t_state &= ~TS_NBIO; 413 break; 414 415 case FIOASYNC: 416 if (*(int *)data) 417 tp->t_state |= TS_ASYNC; 418 else 419 tp->t_state &= ~TS_ASYNC; 420 break; 421 422 /* 423 * Set and fetch special characters 424 */ 425 case TIOCSETC: 426 bcopy(data, (caddr_t)&tun, sizeof (struct tchars)); 427 break; 428 429 case TIOCGETC: 430 bcopy((caddr_t)&tun, data, sizeof (struct tchars)); 431 break; 432 433 /* local ioctls */ 434 /* 435 * Set/get local special characters. 436 */ 437 case TIOCSLTC: 438 bcopy(data, (caddr_t)&tlun, sizeof (struct ltchars)); 439 break; 440 441 case TIOCGLTC: 442 bcopy((caddr_t)&tlun, data, sizeof (struct ltchars)); 443 break; 444 445 /* 446 * Return number of characters immediately available. 447 */ 448 case FIONREAD: 449 *(off_t *)data = ttnread(tp); 450 break; 451 452 /* 453 * Should allow SPGRP and GPGRP only if tty open for reading. 454 */ 455 case TIOCSPGRP: 456 tp->t_pgrp = *(int *)data; 457 break; 458 459 case TIOCGPGRP: 460 *(int *)data = tp->t_pgrp; 461 break; 462 463 /* 464 * Modify local mode word. 465 */ 466 case TIOCLBIS: 467 tp->t_local |= *(int *)data; 468 break; 469 470 case TIOCLBIC: 471 tp->t_local &= ~(*(int *)data); 472 break; 473 474 case TIOCLSET: 475 tp->t_local = *(int *)data; 476 break; 477 478 case TIOCLGET: 479 *(int *)data = tp->t_local; 480 break; 481 482 case TIOCSTOP: { 483 int s = spl5(); 484 485 if ((tp->t_state & TS_TTSTOP) == 0) { 486 tp->t_state |= TS_TTSTOP; 487 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 488 } 489 splx(s); 490 break; 491 } 492 493 case TIOCSTART: { 494 int s = spl5(); 495 496 if ((tp->t_state & TS_TTSTOP) || (tp->t_local & LFLUSHO)) { 497 tp->t_state &= ~TS_TTSTOP; 498 tp->t_local &= ~LFLUSHO; 499 ttstart(tp); 500 } 501 splx(s); 502 break; 503 } 504 505 /* end of locals */ 506 507 default: 508 return (0); 509 } 510 return (1); 511 } 512 513 ttnread(tp) 514 struct tty *tp; 515 { 516 int nread = 0; 517 518 if (tp->t_local & LPENDIN) 519 ttypend(tp); 520 nread = tp->t_canq.c_cc; 521 if (tp->t_flags & (RAW|CBREAK)) 522 nread += tp->t_rawq.c_cc; 523 return (nread); 524 } 525 526 ttselect(dev, rw) 527 dev_t dev; 528 int rw; 529 { 530 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 531 int nread; 532 int s = spl5(); 533 534 switch (rw) { 535 536 case FREAD: 537 nread = ttnread(tp); 538 if (nread > 0) 539 goto win; 540 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 541 tp->t_state |= TS_RCOLL; 542 else 543 tp->t_rsel = u.u_procp; 544 break; 545 546 case FWRITE: 547 if (tp->t_outq.c_cc <= TTLOWAT(tp)) 548 goto win; 549 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 550 tp->t_state |= TS_WCOLL; 551 else 552 tp->t_wsel = u.u_procp; 553 break; 554 } 555 splx(s); 556 return (0); 557 win: 558 splx(s); 559 return (1); 560 } 561 562 #define OBUFSIZ 100 563 564 /* 565 * routine called on opens while tp->t_line == NTTYDISC 566 * establishes a process group for distribution of 567 * quits and interrupts from the tty. 568 * (actually, pp->p_pgrp can't be 0 when this routine 569 * is called since NTTYDISC is not the default discipline) 570 */ 571 ttyopen(dev, tp) 572 dev_t dev; 573 register struct tty *tp; 574 { 575 register struct proc *pp; 576 577 pp = u.u_procp; 578 tp->t_dev = dev; 579 if (pp->p_pgrp == 0) { 580 u.u_ttyp = tp; 581 u.u_ttyd = dev; 582 if (tp->t_pgrp == 0) 583 tp->t_pgrp = pp->p_pid; 584 pp->p_pgrp = tp->t_pgrp; 585 } 586 tp->t_state &= ~TS_WOPEN; 587 tp->t_state |= TS_ISOPEN; 588 if (tp->t_line != NTTYDISC) 589 wflushtty(tp); 590 } 591 592 /* 593 * clean tp on last close 594 */ 595 ttyclose(tp) 596 register struct tty *tp; 597 { 598 599 if (tp->t_line) { 600 wflushtty(tp); 601 tp->t_line = 0; 602 return; 603 } 604 tp->t_pgrp = 0; 605 wflushtty(tp); 606 tp->t_state = 0; 607 } 608 609 /* 610 * reinput pending characters after state switch 611 * call at spl5(). 612 */ 613 ttypend(tp) 614 register struct tty *tp; 615 { 616 struct clist tq; 617 register c; 618 619 tp->t_local &= ~LPENDIN; 620 tp->t_lstate |= LSTYPEN; 621 tq = tp->t_rawq; 622 tp->t_rawq.c_cc = 0; 623 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 624 while ((c = getc(&tq)) >= 0) 625 ttyinput(c, tp); 626 tp->t_lstate &= ~LSTYPEN; 627 } 628 629 /* 630 * Place a character on raw TTY input queue, putting in delimiters 631 * and waking up top half as needed. 632 * Also echo if required. 633 * The arguments are the character and the appropriate 634 * tty structure. 635 */ 636 ttyinput(c, tp) 637 register c; 638 register struct tty *tp; 639 { 640 register int t_flags; 641 int i; 642 643 if (tp->t_local&LPENDIN) 644 ttypend(tp); 645 tk_nin++; 646 c &= 0377; 647 t_flags = tp->t_flags; 648 if (t_flags&TANDEM) 649 ttyblock(tp); 650 if ((t_flags&RAW)==0) { 651 if ((tp->t_lstate&LSTYPEN) == 0) 652 c &= 0177; 653 /* check for literal nexting very first */ 654 if (tp->t_lstate&LSLNCH) { 655 c |= 0200; 656 tp->t_lstate &= ~LSLNCH; 657 } 658 if (tp->t_line == NTTYDISC && c==tlun.t_lnextc) { 659 if (tp->t_flags&ECHO) 660 ttyout("^\b", tp); 661 tp->t_lstate |= LSLNCH; 662 /* check for output control functions */ 663 } else if (c==tun.t_stopc) { 664 if ((tp->t_state&TS_TTSTOP)==0) { 665 tp->t_state |= TS_TTSTOP; 666 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 667 return; 668 } 669 if (c!=tun.t_startc) 670 return; 671 } else if (c==tun.t_startc) { 672 tp->t_state &= ~TS_TTSTOP; 673 tp->t_local &= ~LFLUSHO; 674 ttstart(tp); 675 return; 676 } else if (tp->t_line == NTTYDISC && c==tlun.t_flushc) { 677 if (tp->t_local & LFLUSHO) 678 tp->t_local &= ~LFLUSHO; 679 else { 680 flushtty(tp, FWRITE); 681 ttyecho(c, tp); 682 if (tp->t_rawq.c_cc+tp->t_canq.c_cc) 683 ttyretype(tp); 684 tp->t_local |= LFLUSHO; 685 } 686 ttstart(tp); 687 return; 688 } else if (c==tun.t_intrc || c==tun.t_quitc || 689 (tp->t_line == NTTYDISC && c==tlun.t_suspc)) { 690 if ((tp->t_local & LNOFLSH) == 0) 691 flushtty(tp, 692 c==tlun.t_suspc ? FREAD : FREAD|FWRITE); 693 ttyecho(c, tp); 694 c = c==tun.t_intrc ? SIGINT : 695 ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP); 696 ttsignal(tp, c); 697 /* check for buffer editing functions - cooked mode */ 698 } else if ((t_flags&CBREAK) == 0) { 699 if ((tp->t_lstate&LSQUOT) && 700 (c==tp->t_erase||c==tp->t_kill)) { 701 ttyrub(unputc(&tp->t_rawq), tp); 702 c |= 0200; 703 } 704 if (c==tp->t_erase) { 705 if (tp->t_rawq.c_cc) 706 ttyrub(unputc(&tp->t_rawq), tp); 707 } else if (c==tp->t_kill) { 708 if (tp->t_local&LCRTKIL && 709 tp->t_rawq.c_cc == tp->t_rocount) { 710 while (tp->t_rawq.c_cc) 711 ttyrub(unputc(&tp->t_rawq), tp); 712 } else { 713 ttyecho(c, tp); 714 ttyecho('\n', tp); 715 while (getc(&tp->t_rawq) > 0) 716 ; 717 tp->t_rocount = 0; 718 } 719 tp->t_lstate = 0; 720 } else if (tp->t_line == NTTYDISC && c==tlun.t_werasc) { 721 if (tp->t_rawq.c_cc == 0) 722 goto out; 723 do { 724 c = unputc(&tp->t_rawq); 725 if (c != ' ' && c != '\t') 726 goto erasenb; 727 ttyrub(c, tp); 728 } while (tp->t_rawq.c_cc); 729 goto out; 730 erasenb: 731 do { 732 ttyrub(c, tp); 733 if (tp->t_rawq.c_cc == 0) 734 goto out; 735 c = unputc(&tp->t_rawq); 736 } while (c != ' ' && c != '\t'); 737 (void) putc(c, &tp->t_rawq); 738 } else if (tp->t_line == NTTYDISC && c==tlun.t_rprntc) { 739 ttyretype(tp); 740 /* check for cooked mode input buffer overflow */ 741 } else if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 742 ; 743 /* put data char in q for user and wakeup if a break char */ 744 } else if (putc(c, &tp->t_rawq) >= 0) { 745 if (tp->t_rawq.c_cc+tp->t_canq.c_cc==TTYHOG 746 && tp->t_line == NTTYDISC) 747 (void) ttyoutput(CTRL(g), tp); 748 if (!ttbreakc(c, tp)) { 749 if (tp->t_rocount++ == 0) 750 tp->t_rocol = tp->t_col; 751 } else { 752 tp->t_rocount = 0; 753 catq(&tp->t_rawq, &tp->t_canq); 754 /* IF (TP->T_CHAN) (VOID) SDATA(TP->T_CHAN); */ 755 ttwakeup(tp); 756 } 757 tp->t_lstate &= ~LSQUOT; 758 if (c == '\\') 759 tp->t_lstate |= LSQUOT; 760 if (tp->t_lstate&LSERASE) { 761 tp->t_lstate &= ~LSERASE; 762 (void) ttyoutput('/', tp); 763 } 764 i = tp->t_col; 765 ttyecho(c, tp); 766 if (c==tun.t_eofc && tp->t_flags&ECHO) { 767 i = MIN(2, tp->t_col - i); 768 while (i > 0) { 769 (void) ttyoutput('\b', tp); 770 i--; 771 } 772 } 773 } 774 /* CBREAK mode */ 775 } else if (tp->t_rawq.c_cc > TTYHOG) { 776 if (tp->t_outq.c_cc < TTHIWAT(tp) && 777 tp->t_line == NTTYDISC) 778 (void) ttyoutput(CTRL(g), tp); 779 } else if (putc(c, &tp->t_rawq) >= 0) { 780 ttwakeup(tp); 781 ttyecho(c, tp); 782 } 783 /* RAW mode */ 784 } else if (tp->t_rawq.c_cc > TTYHOG) 785 flushtty(tp, FREAD|FWRITE); 786 else { 787 if (putc(c, &tp->t_rawq) >= 0) 788 ttwakeup(tp); 789 ttyecho(c, tp); 790 } 791 out: 792 if (tp->t_local & LDECCTQ && tp->t_state & TS_TTSTOP && 793 tun.t_startc != tun.t_stopc) 794 return; 795 tp->t_state &= ~TS_TTSTOP; 796 tp->t_local &= ~LFLUSHO; 797 ttstart(tp); 798 } 799 800 /* 801 * put character on TTY output queue, adding delays, 802 * expanding tabs, and handling the CR/NL bit. 803 * It is called both from the top half for output, and from 804 * interrupt level for echoing. 805 * The arguments are the character and the tty structure. 806 * Returns < 0 if putc succeeds, otherwise returns char to resend 807 * Must be recursive. 808 */ 809 ttyoutput(c, tp) 810 register c; 811 register struct tty *tp; 812 { 813 register char *colp; 814 register ctype; 815 816 if (tp->t_flags&RAW || tp->t_local&LLITOUT) { 817 if (tp->t_local&LFLUSHO) 818 return (-1); 819 if (putc(c, &tp->t_outq)) 820 return (c); 821 tk_nout++; 822 return (-1); 823 } 824 /* 825 * Ignore EOT in normal mode to avoid hanging up 826 * certain terminals. 827 */ 828 c &= 0177; 829 if (c==CEOT && (tp->t_flags&CBREAK)==0) 830 return (-1); 831 /* 832 * Turn tabs to spaces as required 833 */ 834 if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { 835 register int s; 836 837 c = 8 - (tp->t_col&7); 838 if ((tp->t_local&LFLUSHO) == 0) { 839 s = spl5(); /* don't interrupt tabs */ 840 c -= b_to_q(" ", c, &tp->t_outq); 841 tk_nout += c; 842 splx(s); 843 } 844 tp->t_col += c; 845 return (c ? -1 : '\t'); 846 } 847 tk_nout++; 848 /* 849 * for upper-case-only terminals, 850 * generate escapes. 851 */ 852 if (tp->t_flags&LCASE) { 853 colp = "({)}!|^~'`"; 854 while (*colp++) 855 if (c == *colp++) { 856 if (ttyoutput('\\', tp) >= 0) 857 return (c); 858 c = colp[-2]; 859 break; 860 } 861 if ('A'<=c && c<='Z') { 862 if (ttyoutput('\\', tp) >= 0) 863 return (c); 864 } else if ('a'<=c && c<='z') 865 c += 'A' - 'a'; 866 } 867 /* 868 * turn <nl> to <cr><lf> if desired. 869 */ 870 if (c=='\n' && tp->t_flags&CRMOD) 871 if (ttyoutput('\r', tp) >= 0) 872 return (c); 873 if (c=='~' && tp->t_local<ILDE) 874 c = '`'; 875 if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq)) 876 return (c); 877 /* 878 * Calculate delays. 879 * The numbers here represent clock ticks 880 * and are not necessarily optimal for all terminals. 881 * The delays are indicated by characters above 0200. 882 * In raw mode there are no delays and the 883 * transmission path is 8 bits wide. 884 */ 885 colp = &tp->t_col; 886 ctype = partab[c]; 887 c = 0; 888 switch (ctype&077) { 889 890 case ORDINARY: 891 (*colp)++; 892 893 case CONTROL: 894 break; 895 896 case BACKSPACE: 897 if (*colp) 898 (*colp)--; 899 break; 900 901 case NEWLINE: 902 ctype = (tp->t_flags >> 8) & 03; 903 if (ctype == 1) { /* tty 37 */ 904 if (*colp) 905 c = max(((unsigned)*colp>>4) + 3, (unsigned)6); 906 } else 907 if (ctype == 2) { /* vt05 */ 908 c = 6; 909 } 910 *colp = 0; 911 break; 912 913 case TAB: 914 ctype = (tp->t_flags >> 10) & 03; 915 if (ctype == 1) { /* tty 37 */ 916 c = 1 - (*colp | ~07); 917 if (c < 5) 918 c = 0; 919 } 920 *colp |= 07; 921 (*colp)++; 922 break; 923 924 case VTAB: 925 if (tp->t_flags & VTDELAY) /* tty 37 */ 926 c = 0177; 927 break; 928 929 case RETURN: 930 ctype = (tp->t_flags >> 12) & 03; 931 if (ctype == 1) { /* tn 300 */ 932 c = 5; 933 } else if (ctype == 2) { /* ti 700 */ 934 c = 10; 935 } else if (ctype == 3) { /* concept 100 */ 936 int i; 937 if ((i = *colp) >= 0) 938 for (; i<9; i++) 939 (void) putc(0177, &tp->t_outq); 940 } 941 *colp = 0; 942 } 943 if (c && (tp->t_local&LFLUSHO) == 0) 944 (void) putc(c|0200, &tp->t_outq); 945 return (-1); 946 } 947 948 /* 949 * Called from device's read routine after it has 950 * calculated the tty-structure given as argument. 951 */ 952 ttread(tp, uio) 953 register struct tty *tp; 954 struct uio *uio; 955 { 956 register struct clist *qp; 957 register c, first; 958 959 if ((tp->t_state&TS_CARR_ON)==0) 960 return (0); 961 loop: 962 (void) spl5(); 963 if (tp->t_local&LPENDIN) 964 ttypend(tp); 965 (void) spl0(); 966 while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 967 if (u.u_signal[SIGTTIN] == SIG_IGN || 968 u.u_signal[SIGTTIN] == SIG_HOLD || 969 /* 970 (u.u_procp->p_flag&SDETACH) || 971 */ 972 u.u_procp->p_flag&SVFORK) 973 return (0); 974 gsignal(u.u_procp->p_pgrp, SIGTTIN); 975 sleep((caddr_t)&lbolt, TTIPRI); 976 } 977 if (tp->t_flags&RAW) { 978 (void) spl5(); 979 if (tp->t_rawq.c_cc <= 0) { 980 if ((tp->t_state&TS_CARR_ON)==0 || 981 (tp->t_state&TS_NBIO)) { 982 (void) spl0(); 983 return (0); 984 } 985 sleep((caddr_t)&tp->t_rawq, TTIPRI); 986 (void) spl0(); 987 goto loop; 988 } 989 (void) spl0(); 990 while (tp->t_rawq.c_cc && uio->uio_iovcnt) { 991 u.u_error = passuc(getc(&tp->t_rawq), uio); 992 if (u.u_error) 993 break; 994 } 995 return (0); 996 } else { 997 qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq; 998 (void) spl5(); 999 if (qp->c_cc <= 0) { 1000 if ((tp->t_state&TS_CARR_ON)==0 || 1001 (tp->t_state&TS_NBIO)) { 1002 (void) spl0(); 1003 return (0); 1004 } 1005 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1006 (void) spl0(); 1007 goto loop; 1008 } 1009 (void) spl0(); 1010 first = 1; 1011 while ((c = getc(qp)) >= 0) { 1012 if (tp->t_flags&CRMOD && c == '\r') 1013 c = '\n'; 1014 if (tp->t_flags&LCASE && c <= 0177) 1015 if (tp->t_lstate&LSBKSL) { 1016 if (maptab[c]) 1017 c = maptab[c]; 1018 tp->t_lstate &= ~LSBKSL; 1019 } else if (c >= 'A' && c <= 'Z') 1020 c += 'a' - 'A'; 1021 else if (c == '\\') { 1022 tp->t_lstate |= LSBKSL; 1023 continue; 1024 } 1025 if (tp->t_line == NTTYDISC && c == tlun.t_dsuspc) { 1026 ttsignal(tp, SIGTSTP); 1027 if (first) { 1028 sleep((caddr_t)&lbolt, TTIPRI); 1029 goto loop; 1030 } 1031 break; 1032 } 1033 if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0) 1034 break; 1035 u.u_error = passuc(c & 0177, uio); 1036 if (u.u_error) 1037 break; 1038 if (uio->uio_iovcnt == 0) 1039 break; 1040 if ((tp->t_flags&CBREAK)==0 && ttbreakc(c, tp)) 1041 break; 1042 first = 0; 1043 } 1044 tp->t_lstate &= ~LSBKSL; 1045 } 1046 1047 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 1048 if (putc(tun.t_startc, &tp->t_outq)==0) { 1049 tp->t_state &= ~TS_TBLOCK; 1050 ttstart(tp); 1051 } 1052 tp->t_char = 0; 1053 } 1054 1055 return (tp->t_rawq.c_cc + tp->t_canq.c_cc); 1056 } 1057 1058 /* 1059 * Called from the device's write routine after it has 1060 * calculated the tty-structure given as argument. 1061 */ 1062 caddr_t 1063 ttwrite(tp) 1064 register struct tty *tp; 1065 { 1066 #ifdef vax 1067 /* 1068 * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL 1069 * AND MUST NOT BE CHANGED WITHOUT PATCHING 1070 * THE 'ASM' INLINES BELOW. WATCH OUT. 1071 */ 1072 #endif 1073 register char *cp; 1074 register int cc, ce; 1075 register i; 1076 char obuf[OBUFSIZ]; 1077 register c; 1078 int hiwat = TTHIWAT(tp); 1079 int cnt = u.u_count; 1080 1081 if ((tp->t_state&TS_CARR_ON)==0) 1082 return (NULL); 1083 loop: 1084 while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp && 1085 (tp->t_local<OSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1086 u.u_signal[SIGTTOU] != SIG_IGN && 1087 u.u_signal[SIGTTOU] != SIG_HOLD 1088 /* 1089 && 1090 (u.u_procp->p_flag&SDETACH)==0) { 1091 */ 1092 ) { 1093 gsignal(u.u_procp->p_pgrp, SIGTTOU); 1094 sleep((caddr_t)&lbolt, TTIPRI); 1095 } 1096 while (u.u_count) { 1097 cc = MIN(u.u_count, OBUFSIZ); 1098 cp = obuf; 1099 iomove(cp, (unsigned)cc, B_WRITE); 1100 if (u.u_error) 1101 break; 1102 if (tp->t_outq.c_cc > hiwat) 1103 goto ovhiwat; 1104 if (tp->t_local&LFLUSHO) 1105 continue; 1106 if (tp->t_flags&LCASE || tp->t_local<ILDE) { 1107 while (cc) { 1108 c = *cp++; 1109 tp->t_rocount = 0; 1110 while ((c = ttyoutput(c, tp)) >= 0) { 1111 /* out of clists, wait a bit */ 1112 ttstart(tp); 1113 sleep((caddr_t)&lbolt, TTOPRI); 1114 tp->t_rocount = 0; 1115 } 1116 --cc; 1117 if (tp->t_outq.c_cc > hiwat) 1118 goto ovhiwat; 1119 } 1120 continue; 1121 } 1122 while (cc) { 1123 if (tp->t_flags&RAW || tp->t_local&LLITOUT) 1124 ce = cc; 1125 else { 1126 #ifdef vax 1127 asm(" scanc r9,(r10),_partab,$077"); 1128 asm(" subl3 r0,r9,r8"); 1129 #else 1130 ce=0; 1131 while (((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc)) 1132 ce++; 1133 #endif 1134 if (ce==0) { 1135 tp->t_rocount = 0; 1136 if (ttyoutput(*cp, tp) >= 0) { 1137 ttstart(tp); 1138 sleep((caddr_t)&lbolt, TTOPRI); 1139 continue; 1140 } 1141 cp++; 1142 cc--; 1143 if (tp->t_outq.c_cc > hiwat) 1144 goto ovhiwat; 1145 } 1146 } 1147 tp->t_rocount = 0; 1148 i=b_to_q(cp,ce,&tp->t_outq); 1149 ce-=i; 1150 tk_nout+=ce; 1151 tp->t_col+=ce; 1152 cp+=ce; 1153 cc-=ce; 1154 if (i) { 1155 ttstart(tp); 1156 sleep((caddr_t)&lbolt, TTOPRI); 1157 } 1158 if (ce || tp->t_outq.c_cc > hiwat) 1159 goto ovhiwat; 1160 } 1161 } 1162 ttstart(tp); 1163 return (NULL); 1164 1165 ovhiwat: 1166 (void) spl5(); 1167 u.u_base -= cc; 1168 u.u_offset -= cc; 1169 u.u_count += cc; 1170 if (tp->t_outq.c_cc <= hiwat) { 1171 (void) spl0(); 1172 goto loop; 1173 } 1174 ttstart(tp); 1175 if (tp->t_state & TS_NBIO) { 1176 if (u.u_count == cnt) 1177 u.u_error = EWOULDBLOCK; 1178 return (NULL); 1179 } 1180 tp->t_state |= TS_ASLEEP; 1181 sleep((caddr_t)&tp->t_outq, TTOPRI); 1182 (void) spl0(); 1183 goto loop; 1184 } 1185 1186 /* 1187 * Rubout one character from the rawq of tp 1188 * as cleanly as possible. 1189 */ 1190 ttyrub(c, tp) 1191 register c; 1192 register struct tty *tp; 1193 { 1194 register char *cp; 1195 register int savecol; 1196 int s; 1197 char *nextc(); 1198 1199 if ((tp->t_flags&ECHO)==0) 1200 return; 1201 tp->t_local &= ~LFLUSHO; 1202 c &= 0377; 1203 if (tp->t_local&LCRTBS) { 1204 if (tp->t_rocount == 0) { 1205 /* 1206 * Screwed by ttwrite; retype 1207 */ 1208 ttyretype(tp); 1209 return; 1210 } 1211 if (c==('\t'|0200) || c==('\n'|0200)) 1212 ttyrubo(tp, 2); 1213 else switch (partab[c&=0177] & 0177) { 1214 1215 case ORDINARY: 1216 if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z') 1217 ttyrubo(tp, 2); 1218 else 1219 ttyrubo(tp, 1); 1220 break; 1221 1222 case VTAB: 1223 case BACKSPACE: 1224 case CONTROL: 1225 case RETURN: 1226 if (tp->t_local & LCTLECH) 1227 ttyrubo(tp, 2); 1228 break; 1229 1230 case TAB: 1231 if (tp->t_rocount < tp->t_rawq.c_cc) { 1232 ttyretype(tp); 1233 return; 1234 } 1235 s = spl5(); 1236 savecol = tp->t_col; 1237 tp->t_lstate |= LSCNTTB; 1238 tp->t_local |= LFLUSHO; 1239 tp->t_col = tp->t_rocol; 1240 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 1241 ttyecho(*cp, tp); 1242 tp->t_local &= ~LFLUSHO; 1243 tp->t_lstate &= ~LSCNTTB; 1244 splx(s); 1245 /* 1246 * savecol will now be length of the tab 1247 */ 1248 savecol -= tp->t_col; 1249 tp->t_col += savecol; 1250 if (savecol > 8) 1251 savecol = 8; /* overflow screw */ 1252 while (--savecol >= 0) 1253 (void) ttyoutput('\b', tp); 1254 break; 1255 1256 default: 1257 panic("ttyrub"); 1258 } 1259 } else if (tp->t_local&LPRTERA) { 1260 if ((tp->t_lstate&LSERASE) == 0) { 1261 (void) ttyoutput('\\', tp); 1262 tp->t_lstate |= LSERASE; 1263 } 1264 ttyecho(c, tp); 1265 } else 1266 ttyecho(tp->t_erase, tp); 1267 tp->t_rocount--; 1268 } 1269 1270 /* 1271 * Crt back over cnt chars perhaps 1272 * erasing them. 1273 */ 1274 ttyrubo(tp, cnt) 1275 register struct tty *tp; 1276 int cnt; 1277 { 1278 1279 while (--cnt >= 0) 1280 ttyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp); 1281 } 1282 1283 /* 1284 * Reprint the rawq line. 1285 * We assume c_cc has already been checked. 1286 */ 1287 ttyretype(tp) 1288 register struct tty *tp; 1289 { 1290 register char *cp; 1291 char *nextc(); 1292 int s; 1293 1294 if (tlun.t_rprntc != 0377) 1295 ttyecho(tlun.t_rprntc, tp); 1296 (void) ttyoutput('\n', tp); 1297 s = spl5(); 1298 for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp)) 1299 ttyecho(*cp, tp); 1300 for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp)) 1301 ttyecho(*cp, tp); 1302 tp->t_lstate &= ~LSERASE; 1303 splx(s); 1304 tp->t_rocount = tp->t_rawq.c_cc; 1305 tp->t_rocol = 0; 1306 } 1307 1308 /* 1309 * Echo a typed character to the terminal 1310 */ 1311 ttyecho(c, tp) 1312 register c; 1313 register struct tty *tp; 1314 { 1315 1316 if ((tp->t_lstate & LSCNTTB) == 0) 1317 tp->t_local &= ~LFLUSHO; 1318 if ((tp->t_flags&ECHO) == 0) 1319 return; 1320 c &= 0377; 1321 if (tp->t_flags&RAW) { 1322 (void) ttyoutput(c, tp); 1323 return; 1324 } 1325 if (c == '\r' && tp->t_flags&CRMOD) 1326 c = '\n'; 1327 if (tp->t_local&LCTLECH) { 1328 if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) { 1329 (void) ttyoutput('^', tp); 1330 c &= 0177; 1331 if (c == 0177) 1332 c = '?'; 1333 else if (tp->t_flags&LCASE) 1334 c += 'a' - 1; 1335 else 1336 c += 'A' - 1; 1337 } 1338 } 1339 if ((tp->t_flags&LCASE) && (c >= 'A' && c <= 'Z')) 1340 c += 'a' - 'A'; 1341 (void) ttyoutput(c & 0177, tp); 1342 } 1343 1344 /* 1345 * Is c a break char for tp? 1346 */ 1347 ttbreakc(c, tp) 1348 register c; 1349 register struct tty *tp; 1350 { 1351 return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc || 1352 c == '\r' && (tp->t_flags&CRMOD)); 1353 } 1354 1355 /* 1356 * send string cp to tp 1357 */ 1358 ttyout(cp, tp) 1359 register char *cp; 1360 register struct tty *tp; 1361 { 1362 register char c; 1363 1364 while (c = *cp++) 1365 (void) ttyoutput(c, tp); 1366 } 1367 1368 ttwakeup(tp) 1369 struct tty *tp; 1370 { 1371 1372 if (tp->t_rsel) { 1373 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 1374 tp->t_state &= ~TS_RCOLL; 1375 tp->t_rsel = 0; 1376 } 1377 wakeup((caddr_t)&tp->t_rawq); 1378 } 1379 1380 ttsignal(tp, signo) 1381 struct tty *tp; 1382 int signo; 1383 { 1384 1385 gsignal(tp->t_pgrp, signo); 1386 } 1387