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