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