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