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