1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)tty.c 7.19 (Berkeley) 11/20/89 7 */ 8 9 #include "param.h" 10 #include "systm.h" 11 #include "user.h" 12 #include "ioctl.h" 13 #define TTYDEFCHARS 14 #include "tty.h" 15 #undef TTYDEFCHARS 16 #include "proc.h" 17 #include "file.h" 18 #include "conf.h" 19 #include "dkstat.h" 20 #include "uio.h" 21 #include "kernel.h" 22 #include "vnode.h" 23 #include "syslog.h" 24 25 #include "machine/reg.h" 26 27 /* 28 * Table giving parity for characters and indicating 29 * character classes to tty driver. The 8th bit 30 * indicates parity, the 7th bit indicates the character 31 * is an alphameric or underscore (for ALTWERASE), and the 32 * low 6 bits indicate delay type. If the low 6 bits are 0 33 * then the character needs no special processing on output. 34 */ 35 36 char partab[] = { 37 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 38 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 39 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 40 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 41 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 42 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 43 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 44 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 45 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 46 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 47 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 48 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 49 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 50 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 51 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 52 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 53 /* 54 * meta chars 55 */ 56 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */ 57 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */ 58 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */ 59 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */ 60 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */ 61 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */ 62 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */ 63 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */ 64 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */ 65 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */ 66 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */ 67 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */ 68 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */ 69 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */ 70 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */ 71 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */ 72 }; 73 74 extern struct tty *constty; /* temporary virtual console */ 75 extern char partab[], maptab[]; 76 77 /* 78 * Is 'c' a line delimiter ("break" character)? 79 */ 80 #define ttbreakc(c) (c == '\n' || CCEQ(cc[VEOF], c) || \ 81 CCEQ(cc[VEOL], c) || CCEQ(cc[VEOL2], c)) 82 83 ttychars(tp) 84 struct tty *tp; 85 { 86 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars)); 87 } 88 89 /* 90 * Wait for output to drain, then flush input waiting. 91 */ 92 ttywflush(tp) 93 struct tty *tp; 94 { 95 96 ttywait(tp); 97 ttyflush(tp, FREAD); 98 } 99 100 /* 101 * Wait for output to drain. 102 */ 103 ttywait(tp) 104 register struct tty *tp; 105 { 106 int s = spltty(); 107 108 while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) && 109 (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) && 110 tp->t_oproc) { 111 (*tp->t_oproc)(tp); 112 tp->t_state |= TS_ASLEEP; 113 sleep((caddr_t)&tp->t_outq, TTOPRI); 114 } 115 splx(s); 116 } 117 118 /* 119 * Flush all TTY queues 120 */ 121 ttyflush(tp, rw) 122 register struct tty *tp; 123 { 124 register s; 125 126 s = spltty(); 127 if (rw & FREAD) { 128 while (getc(&tp->t_canq) >= 0) 129 ; 130 ttwakeup(tp); 131 } 132 if (rw & FWRITE) { 133 wakeup((caddr_t)&tp->t_outq); /* XXX? what about selwakeup? */ 134 tp->t_state &= ~TS_TTSTOP; 135 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw); 136 while (getc(&tp->t_outq) >= 0) 137 ; 138 } 139 if (rw & FREAD) { 140 while (getc(&tp->t_rawq) >= 0) 141 ; 142 tp->t_rocount = 0; 143 tp->t_rocol = 0; 144 tp->t_state &= ~TS_LOCAL; 145 } 146 splx(s); 147 } 148 149 /* 150 * Send stop character on input overflow. 151 */ 152 ttyblock(tp) 153 register struct tty *tp; 154 { 155 register x; 156 157 x = tp->t_rawq.c_cc + tp->t_canq.c_cc; 158 if (tp->t_rawq.c_cc > TTYHOG) { 159 ttyflush(tp, FREAD|FWRITE); 160 tp->t_state &= ~TS_TBLOCK; 161 } 162 /* 163 * Block further input iff: 164 * Current input > threshold AND input is available to user program 165 */ 166 if (x >= TTYHOG/2 && 167 (!(tp->t_lflag&ICANON)) || (tp->t_canq.c_cc > 0) && 168 tp->t_cc[VSTOP] != _POSIX_VDISABLE) { 169 if (putc(tp->t_cc[VSTOP], &tp->t_outq)==0) { 170 tp->t_state |= TS_TBLOCK; 171 ttstart(tp); 172 } 173 } 174 } 175 176 /* 177 * Restart typewriter output following a delay 178 * timeout. 179 * The name of the routine is passed to the timeout 180 * subroutine and it is called during a clock interrupt. 181 */ 182 ttrstrt(tp) 183 struct tty *tp; 184 { 185 186 if (tp == 0) 187 panic("ttrstrt"); 188 tp->t_state &= ~TS_TIMEOUT; 189 ttstart(tp); 190 } 191 192 /* 193 * Start output on the typewriter. It is used from the top half 194 * after some characters have been put on the output queue, 195 * from the interrupt routine to transmit the next 196 * character, and after a timeout has finished. 197 */ 198 ttstart(tp) 199 struct tty *tp; 200 { 201 202 if (tp->t_oproc) /* kludge for pty */ 203 (*tp->t_oproc)(tp); 204 } 205 206 /* 207 * Common code for tty ioctls. 208 */ 209 /*ARGSUSED*/ 210 ttioctl(tp, com, data, flag) 211 register struct tty *tp; 212 caddr_t data; 213 { 214 extern int nldisp; 215 int s, error; 216 217 /* 218 * If the ioctl involves modification, 219 * hang if in the background. 220 */ 221 switch (com) { 222 223 case TIOCSETD: 224 case TIOCFLUSH: 225 /*case TIOCSPGRP:*/ 226 case TIOCSTI: 227 case TIOCSWINSZ: 228 case TIOCSETA: 229 case TIOCSETAW: 230 case TIOCSETAF: 231 /**** these get removed **** 232 case TIOCSETAS: 233 case TIOCSETAWS: 234 case TIOCSETAFS: 235 /***************************/ 236 while (isbackground(u.u_procp, tp) && 237 u.u_procp->p_pgrp->pg_jobc && 238 (u.u_procp->p_flag&SVFORK) == 0 && 239 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 240 !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) { 241 pgsignal(u.u_procp->p_pgrp, SIGTTOU); 242 sleep((caddr_t)&lbolt, TTOPRI); 243 } 244 break; 245 } 246 247 /* 248 * Process the ioctl. 249 */ 250 switch (com) { 251 252 /* get discipline number */ 253 case TIOCGETD: 254 *(int *)data = tp->t_line; 255 break; 256 257 /* set line discipline */ 258 case TIOCSETD: { 259 register int t = *(int *)data; 260 dev_t dev = tp->t_dev; 261 int error = 0; 262 263 if ((unsigned)t >= nldisp) 264 return (ENXIO); 265 if (t != tp->t_line) { 266 s = spltty(); 267 (*linesw[tp->t_line].l_close)(tp); 268 error = (*linesw[t].l_open)(dev, tp); 269 if (error) { 270 (void)(*linesw[tp->t_line].l_open)(dev, tp); 271 splx(s); 272 return (error); 273 } 274 tp->t_line = t; 275 splx(s); 276 } 277 break; 278 } 279 280 /* prevent more opens on channel */ 281 case TIOCEXCL: 282 tp->t_state |= TS_XCLUDE; 283 break; 284 285 case TIOCNXCL: 286 tp->t_state &= ~TS_XCLUDE; 287 break; 288 289 case TIOCHPCL: 290 tp->t_cflag |= HUPCL; 291 break; 292 293 case TIOCFLUSH: { 294 register int flags = *(int *)data; 295 296 if (flags == 0) 297 flags = FREAD|FWRITE; 298 else 299 flags &= FREAD|FWRITE; 300 ttyflush(tp, flags); 301 break; 302 } 303 304 case FIOASYNC: 305 if (*(int *)data) 306 tp->t_state |= TS_ASYNC; 307 else 308 tp->t_state &= ~TS_ASYNC; 309 break; 310 311 case FIONBIO: 312 break; /* XXX remove */ 313 314 /* return number of characters immediately available */ 315 case FIONREAD: 316 *(off_t *)data = ttnread(tp); 317 break; 318 319 case TIOCOUTQ: 320 *(int *)data = tp->t_outq.c_cc; 321 break; 322 323 case TIOCSTOP: 324 s = spltty(); 325 if ((tp->t_state&TS_TTSTOP) == 0) { 326 tp->t_state |= TS_TTSTOP; 327 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 328 } 329 splx(s); 330 break; 331 332 case TIOCSTART: 333 s = spltty(); 334 if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) { 335 tp->t_state &= ~TS_TTSTOP; 336 tp->t_lflag &= ~FLUSHO; 337 ttstart(tp); 338 } 339 splx(s); 340 break; 341 342 /* 343 * Simulate typing of a character at the terminal. 344 */ 345 case TIOCSTI: 346 if (u.u_uid && (flag & FREAD) == 0) 347 return (EPERM); 348 if (u.u_uid && !isctty(u.u_procp, tp)) 349 return (EACCES); 350 (*linesw[tp->t_line].l_rint)(*(char *)data, tp); 351 break; 352 353 case TIOCGETA: { 354 struct termios *t = (struct termios *)data; 355 356 bcopy(&tp->t_termios, t, sizeof(struct termios)); 357 break; 358 } 359 360 /*** THIS ALL GETS REMOVED ***/ 361 case JUNK_TIOCSETAS: 362 case JUNK_TIOCSETAWS: 363 case JUNK_TIOCSETAFS: 364 ((struct termios *)data)->c_cflag |= CIGNORE; 365 switch(com) { 366 case JUNK_TIOCSETAS: 367 com = TIOCSETA; 368 break; 369 case JUNK_TIOCSETAWS: 370 com = TIOCSETAW; 371 break; 372 case JUNK_TIOCSETAFS: 373 com = TIOCSETAF; 374 break; 375 } 376 /*******************************/ 377 /*FALLTHROGH*/ 378 case TIOCSETA: 379 case TIOCSETAW: 380 case TIOCSETAF: { 381 register struct termios *t = (struct termios *)data; 382 s = spltty(); 383 if (com == TIOCSETAW || com == TIOCSETAF) { 384 ttywait(tp); 385 if (com == TIOCSETAF); 386 ttyflush(tp, FREAD); 387 } 388 if (!(t->c_cflag&CIGNORE)) { 389 /* 390 * set device hardware 391 */ 392 if (tp->t_param && (error = (*tp->t_param)(tp, t))) { 393 splx(s); 394 return (error); 395 } else { 396 if (!(tp->t_state&TS_CARR_ON) && 397 (tp->t_cflag&CLOCAL) && 398 !(t->c_cflag&CLOCAL)) { 399 tp->t_state &= ~TS_ISOPEN; 400 tp->t_state |= TS_WOPEN; 401 ttwakeup(tp); 402 } 403 tp->t_cflag = t->c_cflag; 404 tp->t_ispeed = t->c_ispeed; 405 tp->t_ospeed = t->c_ospeed; 406 } 407 ttsetwater(tp); 408 } 409 if (com != TIOCSETAF) { 410 if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON)) 411 if (t->c_lflag&ICANON) { 412 tp->t_lflag |= PENDIN; 413 ttwakeup(tp); 414 } 415 else { 416 struct clist tq; 417 418 catq(&tp->t_rawq, &tp->t_canq); 419 tq = tp->t_rawq; 420 tp->t_rawq = tp->t_canq; 421 tp->t_canq = tq; 422 } 423 } 424 tp->t_iflag = t->c_iflag; 425 tp->t_oflag = t->c_oflag; 426 tp->t_lflag = t->c_lflag; 427 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc)); 428 splx(s); 429 break; 430 } 431 432 /* 433 * Set controlling terminal. 434 * Session ctty vnode pointer set in vnode layer. 435 */ 436 case TIOCSCTTY: { 437 register struct proc *p = u.u_procp; 438 439 if (!SESS_LEADER(p) || 440 (p->p_session->s_ttyvp || tp->t_session) && 441 (tp->t_session != p->p_session)) 442 return (EPERM); 443 tp->t_session = p->p_session; 444 tp->t_pgrp = p->p_pgrp; 445 p->p_session->s_ttyp = tp; 446 p->p_flag |= SCTTY; 447 break; 448 } 449 450 /* 451 * Set terminal process group. 452 */ 453 case TIOCSPGRP: { 454 register struct proc *p = u.u_procp; 455 register struct pgrp *pgrp = pgfind(*(int *)data); 456 457 if (!isctty(p, tp)) 458 return (ENOTTY); 459 else if (pgrp->pg_session != p->p_session) 460 return (EPERM); 461 tp->t_pgrp = pgrp; 462 break; 463 } 464 465 case TIOCGPGRP: 466 if (!isctty(u.u_procp, tp)) 467 return (ENOTTY); 468 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0; 469 break; 470 471 case TIOCSWINSZ: 472 if (bcmp((caddr_t)&tp->t_winsize, data, 473 sizeof (struct winsize))) { 474 tp->t_winsize = *(struct winsize *)data; 475 pgsignal(tp->t_pgrp, SIGWINCH); 476 } 477 break; 478 479 case TIOCGWINSZ: 480 *(struct winsize *)data = tp->t_winsize; 481 break; 482 483 case TIOCCONS: 484 if (*(int *)data) { 485 if (constty != NULL) 486 return (EBUSY); 487 #ifndef UCONSOLE 488 if (error = suser(u.u_cred, &u.u_acflag)) 489 return (error); 490 #endif 491 constty = tp; 492 } else if (tp == constty) 493 constty = NULL; 494 break; 495 496 #ifdef COMPAT_43 497 case TIOCGETP: 498 case TIOCSETP: 499 case TIOCSETN: 500 case TIOCGETC: 501 case TIOCSETC: 502 case TIOCSLTC: 503 case TIOCGLTC: 504 case TIOCLBIS: 505 case TIOCLBIC: 506 case TIOCLSET: 507 case TIOCLGET: 508 case OTIOCGETD: 509 case OTIOCSETD: 510 return(ttcompat(tp, com, data, flag)); 511 #endif 512 513 default: 514 return (-1); 515 } 516 return (0); 517 } 518 519 ttnread(tp) 520 struct tty *tp; 521 { 522 int nread = 0; 523 524 if (tp->t_lflag & PENDIN) 525 ttypend(tp); 526 nread = tp->t_canq.c_cc; 527 if ((tp->t_lflag & ICANON) == 0) 528 nread += tp->t_rawq.c_cc; 529 return (nread); 530 } 531 532 ttselect(dev, rw) 533 dev_t dev; 534 int rw; 535 { 536 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)]; 537 int nread; 538 int s = spltty(); 539 540 switch (rw) { 541 542 case FREAD: 543 nread = ttnread(tp); 544 if (nread > 0 || 545 (!(tp->t_cflag&CLOCAL) && !(tp->t_state&TS_CARR_ON))) 546 goto win; 547 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait) 548 tp->t_state |= TS_RCOLL; 549 else 550 tp->t_rsel = u.u_procp; 551 break; 552 553 case FWRITE: 554 if (tp->t_outq.c_cc <= tp->t_lowat) 555 goto win; 556 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait) 557 tp->t_state |= TS_WCOLL; 558 else 559 tp->t_wsel = u.u_procp; 560 break; 561 } 562 splx(s); 563 return (0); 564 win: 565 splx(s); 566 return (1); 567 } 568 569 /* 570 * Initial open of tty, or (re)entry to line discipline. 571 */ 572 ttyopen(dev, tp) 573 dev_t dev; 574 register struct tty *tp; 575 { 576 577 tp->t_dev = dev; 578 579 tp->t_state &= ~TS_WOPEN; 580 if ((tp->t_state & TS_ISOPEN) == 0) { 581 tp->t_state |= TS_ISOPEN; 582 bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize)); 583 } 584 return (0); 585 } 586 587 /* 588 * "close" a line discipline 589 */ 590 ttylclose(tp) 591 register struct tty *tp; 592 { 593 594 ttywflush(tp); 595 } 596 597 /* 598 * clean tp on last close 599 */ 600 ttyclose(tp) 601 register struct tty *tp; 602 { 603 if (constty == tp) 604 constty = NULL; 605 ttyflush(tp, FREAD|FWRITE); 606 tp->t_session = NULL; 607 tp->t_pgrp = NULL; 608 tp->t_state = 0; 609 } 610 611 /* 612 * Handle modem control transition on a tty. 613 * Flag indicates new state of carrier. 614 * Returns 0 if the line should be turned off, otherwise 1. 615 */ 616 ttymodem(tp, flag) 617 register struct tty *tp; 618 { 619 620 if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag & MDMBUF)) { 621 /* 622 * MDMBUF: do flow control according to carrier flag 623 */ 624 if (flag) { 625 tp->t_state &= ~TS_TTSTOP; 626 ttstart(tp); 627 } else if ((tp->t_state&TS_TTSTOP) == 0) { 628 tp->t_state |= TS_TTSTOP; 629 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 630 } 631 } else if (flag == 0) { 632 /* 633 * Lost carrier. 634 */ 635 tp->t_state &= ~TS_CARR_ON; 636 if (tp->t_state & TS_ISOPEN) { 637 if ((tp->t_lflag & NOHANG) == 0) { 638 pgsignal(tp->t_pgrp, SIGHUP); 639 pgsignal(tp->t_pgrp, SIGCONT); 640 ttyflush(tp, FREAD|FWRITE); 641 return (0); 642 } 643 } 644 } else { 645 /* 646 * Carrier now on. 647 */ 648 tp->t_state |= TS_CARR_ON; 649 ttwakeup(tp); 650 } 651 return (1); 652 } 653 654 /* 655 * Default modem control routine (for other line disciplines). 656 * Return argument flag, to turn off device on carrier drop. 657 */ 658 nullmodem(tp, flag) 659 register struct tty *tp; 660 int flag; 661 { 662 663 if (flag) 664 tp->t_state |= TS_CARR_ON; 665 else { 666 tp->t_state &= ~TS_CARR_ON; 667 if ((tp->t_lflag & NOHANG) == 0) 668 pgsignal(tp->t_pgrp, SIGHUP); 669 } 670 return (flag); 671 } 672 673 /* 674 * reinput pending characters after state switch 675 * call at spltty(). 676 */ 677 ttypend(tp) 678 register struct tty *tp; 679 { 680 struct clist tq; 681 register c; 682 683 tp->t_lflag &= ~PENDIN; 684 tp->t_state |= TS_TYPEN; 685 tq = tp->t_rawq; 686 tp->t_rawq.c_cc = 0; 687 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0; 688 while ((c = getc(&tq)) >= 0) 689 ttyinput(c, tp); 690 tp->t_state &= ~TS_TYPEN; 691 } 692 693 /* 694 * 695 * Place a character on raw TTY input queue, 696 * putting in delimiters and waking up top 697 * half as needed. Also echo if required. 698 * The arguments are the character and the 699 * appropriate tty structure. 700 */ 701 ttyinput(c, tp) 702 register c; 703 register struct tty *tp; 704 { 705 register int iflag = tp->t_iflag; 706 register int lflag = tp->t_lflag; 707 register u_char *cc = tp->t_cc; 708 int i, err; 709 710 /* 711 * If input is pending take it first. 712 */ 713 if (lflag&PENDIN) 714 ttypend(tp); 715 /* 716 * Gather stats. 717 */ 718 tk_nin++; 719 if (lflag&ICANON) { 720 tk_cancc++; 721 tp->t_cancc++; 722 } else { 723 tk_rawcc++; 724 tp->t_rawcc++; 725 } 726 /* 727 * Handle exceptional conditions (break, parity, framing). 728 */ 729 if (err = (c&TTY_ERRORMASK)) { 730 c &= ~TTY_ERRORMASK; 731 if (err&TTY_FE && !c) { /* break */ 732 if (iflag&IGNBRK) 733 goto endcase; 734 else if (iflag&BRKINT && lflag&ISIG && 735 (cc[VINTR] != _POSIX_VDISABLE)) 736 c = cc[VINTR]; 737 else { 738 c = 0; 739 if (iflag&PARMRK) 740 goto parmrk; 741 } 742 } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) { 743 if (iflag&IGNPAR) 744 goto endcase; 745 else if (iflag&PARMRK) { 746 parmrk: 747 putc(0377|TTY_QUOTE, &tp->t_rawq); 748 putc(0|TTY_QUOTE, &tp->t_rawq); 749 putc(c|TTY_QUOTE, &tp->t_rawq); 750 goto endcase; 751 } else 752 c = 0; 753 } 754 } 755 /* 756 * In tandem mode, check high water mark. 757 */ 758 if (iflag&IXOFF) 759 ttyblock(tp); 760 if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP)) 761 c &= 0177; 762 /* 763 * Check for literal nexting very first 764 */ 765 if (tp->t_state&TS_LNCH) { 766 c |= TTY_QUOTE; 767 tp->t_state &= ~TS_LNCH; 768 } 769 /* 770 * Scan for special characters. This code 771 * is really just a big case statement with 772 * non-constant cases. The bottom of the 773 * case statement is labeled ``endcase'', so goto 774 * it after a case match, or similar. 775 */ 776 /* 777 * Control chars which aren't controlled 778 * by ICANON, ISIG, or IXON. 779 */ 780 if (lflag&IEXTEN) { 781 if (CCEQ(cc[VLNEXT],c)) { 782 if (lflag&ECHO) { 783 if (lflag&ECHOE) 784 ttyout("^\b", tp); 785 else 786 ttyecho(c, tp); 787 } 788 tp->t_state |= TS_LNCH; 789 goto endcase; 790 } 791 if (CCEQ(cc[VFLUSHO],c)) { 792 if (lflag&FLUSHO) 793 tp->t_lflag &= ~FLUSHO; 794 else { 795 ttyflush(tp, FWRITE); 796 ttyecho(c, tp); 797 if (tp->t_rawq.c_cc + tp->t_canq.c_cc) 798 ttyretype(tp); 799 tp->t_lflag |= FLUSHO; 800 } 801 goto startoutput; 802 } 803 } 804 /* 805 * Signals. 806 */ 807 if (lflag&ISIG) { 808 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 809 if ((lflag&NOFLSH) == 0) 810 ttyflush(tp, FREAD|FWRITE); 811 ttyecho(c, tp); 812 pgsignal(tp->t_pgrp, 813 CCEQ(cc[VINTR],c) ? SIGINT : SIGQUIT); 814 goto endcase; 815 } 816 if (CCEQ(cc[VSUSP],c)) { 817 if ((lflag&NOFLSH) == 0) 818 ttyflush(tp, FREAD); 819 ttyecho(c, tp); 820 pgsignal(tp->t_pgrp, SIGTSTP); 821 goto endcase; 822 } 823 if (CCEQ(cc[VINFO],c)) { 824 ttyinfo(tp); 825 goto endcase; 826 } 827 } 828 /* 829 * Handle start/stop characters. 830 */ 831 if (iflag&IXON) { 832 if (CCEQ(cc[VSTOP],c)) { 833 if ((tp->t_state&TS_TTSTOP) == 0) { 834 tp->t_state |= TS_TTSTOP; 835 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0); 836 return; 837 } 838 if (!CCEQ(cc[VSTART], c)) 839 return; 840 /* 841 * if VSTART == VSTOP then toggle 842 */ 843 goto endcase; 844 } 845 if (CCEQ(cc[VSTART], c)) 846 goto restartoutput; 847 } 848 /* 849 * IGNCR, ICRNL, & INLCR 850 */ 851 if (c == '\r') { 852 if (iflag&IGNCR) 853 goto endcase; 854 else if (iflag&ICRNL) 855 c = '\n'; 856 } 857 else if (c == '\n' && iflag&INLCR) 858 c = '\r'; 859 /* 860 * Non canonical mode; don't process line editing 861 * characters; check high water mark for wakeup. 862 * 863 */ 864 if (!(lflag&ICANON)) { 865 if (tp->t_rawq.c_cc > TTYHOG) { 866 if (iflag&IMAXBEL) { 867 if (tp->t_outq.c_cc < tp->t_hiwat) 868 (void) ttyoutput(CTRL('g'), tp); 869 } else 870 ttyflush(tp, FREAD | FWRITE); 871 } else { 872 if (putc(c, &tp->t_rawq) >= 0) { 873 ttwakeup(tp); 874 ttyecho(c, tp); 875 } 876 } 877 goto endcase; 878 } 879 /* 880 * From here on down canonical mode character 881 * processing takes place. 882 */ 883 /* 884 * erase (^H / ^?) 885 */ 886 if (CCEQ(cc[VERASE], c)) { 887 if (tp->t_rawq.c_cc) 888 ttyrub(unputc(&tp->t_rawq), tp); 889 goto endcase; 890 } 891 /* 892 * kill (^U) 893 */ 894 if (CCEQ(cc[VKILL], c)) { 895 if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount && 896 !(lflag&ECHOPRT)) { 897 while (tp->t_rawq.c_cc) 898 ttyrub(unputc(&tp->t_rawq), tp); 899 } else { 900 ttyecho(c, tp); 901 if (lflag&ECHOK || lflag&ECHOKE) 902 ttyecho('\n', tp); 903 while (getc(&tp->t_rawq) > 0) 904 ; 905 tp->t_rocount = 0; 906 } 907 tp->t_state &= ~TS_LOCAL; 908 goto endcase; 909 } 910 /* 911 * word erase (^W) 912 */ 913 if (CCEQ(cc[VWERASE], c)) { 914 int ctype; 915 916 #define CTYPE(c) ((lflag&ALTWERASE) ? (partab[(c)&TTY_CHARMASK]&0100) : 0) 917 /* 918 * erase whitespace 919 */ 920 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t') 921 ttyrub(c, tp); 922 if (c == -1) 923 goto endcase; 924 /* 925 * special case last char of token 926 */ 927 ttyrub(c, tp); 928 c = unputc(&tp->t_rawq); 929 if (c == -1 || c == ' ' || c == '\t') { 930 if (c != -1) 931 (void) putc(c, &tp->t_rawq); 932 goto endcase; 933 } 934 /* 935 * erase rest of token 936 */ 937 ctype = CTYPE(c); 938 do { 939 ttyrub(c, tp); 940 c = unputc(&tp->t_rawq); 941 if (c == -1) 942 goto endcase; 943 } while (c != ' ' && c != '\t' && CTYPE(c) == ctype); 944 (void) putc(c, &tp->t_rawq); 945 goto endcase; 946 #undef CTYPE 947 } 948 /* 949 * reprint line (^R) 950 */ 951 if (CCEQ(cc[VREPRINT], c)) { 952 ttyretype(tp); 953 goto endcase; 954 } 955 /* 956 * Check for input buffer overflow 957 */ 958 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) { 959 if (iflag&IMAXBEL) { 960 if (tp->t_outq.c_cc < tp->t_hiwat) 961 (void) ttyoutput(CTRL('g'), tp); 962 } else 963 ttyflush(tp, FREAD | FWRITE); 964 goto endcase; 965 } 966 /* 967 * Put data char in q for user and 968 * wakeup on seeing a line delimiter. 969 */ 970 if (putc(c, &tp->t_rawq) >= 0) { 971 if (ttbreakc(c)) { 972 tp->t_rocount = 0; 973 catq(&tp->t_rawq, &tp->t_canq); 974 ttwakeup(tp); 975 } else if (tp->t_rocount++ == 0) 976 tp->t_rocol = tp->t_col; 977 if (tp->t_state&TS_ERASE) { 978 /* 979 * end of prterase \.../ 980 */ 981 tp->t_state &= ~TS_ERASE; 982 (void) ttyoutput('/', tp); 983 } 984 i = tp->t_col; 985 ttyecho(c, tp); 986 if (CCEQ(cc[VEOF], c) && lflag&ECHO) { 987 /* 988 * Place the cursor over the '^' of the ^D. 989 */ 990 i = MIN(2, tp->t_col - i); 991 while (i > 0) { 992 (void) ttyoutput('\b', tp); 993 i--; 994 } 995 } 996 } 997 endcase: 998 /* 999 * IXANY means allow any character to restart output. 1000 */ 1001 if ((tp->t_state&TS_TTSTOP) && !(iflag&IXANY) 1002 && cc[VSTART] != cc[VSTOP]) 1003 return; 1004 restartoutput: 1005 tp->t_state &= ~TS_TTSTOP; 1006 tp->t_lflag &= ~FLUSHO; 1007 startoutput: 1008 ttstart(tp); 1009 } 1010 1011 /* 1012 * Put character on TTY output queue, adding delays, 1013 * expanding tabs, and handling the CR/NL bit. 1014 * This is called both from the top half for output, 1015 * and from interrupt level for echoing. 1016 * The arguments are the character and the tty structure. 1017 * Returns < 0 if putc succeeds, otherwise returns char to resend 1018 * Must be recursive. 1019 */ 1020 ttyoutput(c, tp) 1021 register c; 1022 register struct tty *tp; 1023 { 1024 register char *colp; 1025 register ctype; 1026 register long oflag = tp->t_oflag; 1027 1028 if (!(oflag&OPOST)) { 1029 if (tp->t_lflag&FLUSHO) 1030 return (-1); 1031 if (putc(c, &tp->t_outq)) 1032 return (c); 1033 tk_nout++; 1034 tp->t_outcc++; 1035 return (-1); 1036 } 1037 c &= TTY_CHARMASK; 1038 /* 1039 * Turn tabs to spaces as required 1040 */ 1041 if (c == '\t' && oflag&OXTABS ) { 1042 register int s; 1043 1044 c = 8 - (tp->t_col&7); 1045 if ((tp->t_lflag&FLUSHO) == 0) { 1046 s = spltty(); /* don't interrupt tabs */ 1047 c -= b_to_q(" ", c, &tp->t_outq); 1048 tk_nout += c; 1049 tp->t_outcc += c; 1050 splx(s); 1051 } 1052 tp->t_col += c; 1053 return (c ? -1 : '\t'); 1054 } 1055 if (c == CEOT && oflag&ONOEOT) 1056 return(-1); 1057 tk_nout++; 1058 tp->t_outcc++; 1059 /* 1060 * turn <nl> to <cr><lf> if desired. 1061 */ 1062 if (c == '\n' && (tp->t_oflag&ONLCR) && ttyoutput('\r', tp) >= 0) 1063 return (c); 1064 if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq)) 1065 return (c); 1066 /* 1067 * Calculate delays. 1068 * The numbers here represent clock ticks 1069 * and are not necessarily optimal for all terminals. 1070 * 1071 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS 1072 * 1073 * (actually, should THROW AWAY terminals which need delays) 1074 */ 1075 colp = &tp->t_col; 1076 ctype = partab[c]; 1077 c = 0; 1078 switch (ctype&077) { 1079 1080 case ORDINARY: 1081 (*colp)++; 1082 1083 case CONTROL: 1084 break; 1085 1086 case BACKSPACE: 1087 if (*colp) 1088 (*colp)--; 1089 break; 1090 1091 /* 1092 * This macro is close enough to the correct thing; 1093 * it should be replaced by real user settable delays 1094 * in any event... 1095 */ 1096 #define mstohz(ms) (((ms) * hz) >> 10) 1097 case NEWLINE: 1098 ctype = (tp->t_flags >> 8) & 03; 1099 if (ctype == 1) { /* tty 37 */ 1100 if (*colp > 0) { 1101 c = (((unsigned)*colp) >> 4) + 3; 1102 if ((unsigned)c > 6) 1103 c = 6; 1104 } 1105 } else if (ctype == 2) /* vt05 */ 1106 c = mstohz(100); 1107 *colp = 0; 1108 break; 1109 1110 case TAB: 1111 ctype = (tp->t_flags >> 10) & 03; 1112 if (ctype == 1) { /* tty 37 */ 1113 c = 1 - (*colp | ~07); 1114 if (c < 5) 1115 c = 0; 1116 } 1117 *colp |= 07; 1118 (*colp)++; 1119 break; 1120 1121 case VTAB: 1122 if (tp->t_flags&VTDELAY) /* tty 37 */ 1123 c = 0177; 1124 break; 1125 1126 case RETURN: 1127 ctype = (tp->t_flags >> 12) & 03; 1128 if (ctype == 1) /* tn 300 */ 1129 c = mstohz(83); 1130 else if (ctype == 2) /* ti 700 */ 1131 c = mstohz(166); 1132 else if (ctype == 3) { /* concept 100 */ 1133 int i; 1134 1135 if ((i = *colp) >= 0) 1136 for (; i < 9; i++) 1137 (void) putc(0177, &tp->t_outq); 1138 } 1139 *colp = 0; 1140 } 1141 if (c && (tp->t_lflag&FLUSHO) == 0) 1142 (void) putc(c|TTY_QUOTE, &tp->t_outq); 1143 return (-1); 1144 } 1145 #undef mstohz 1146 1147 /* 1148 * Called from device's read routine after it has 1149 * calculated the tty-structure given as argument. 1150 */ 1151 ttread(tp, uio, flag) 1152 register struct tty *tp; 1153 struct uio *uio; 1154 { 1155 register struct clist *qp; 1156 register int c; 1157 register long lflag = tp->t_lflag; 1158 register u_char *cc = tp->t_cc; 1159 int s, first, error = 0; 1160 1161 loop: 1162 s = spltty(); 1163 /* 1164 * take pending input first 1165 */ 1166 if (lflag&PENDIN) 1167 ttypend(tp); 1168 /* 1169 * Handle carrier. 1170 */ 1171 if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) { 1172 if (tp->t_state&TS_ISOPEN) { 1173 splx(s); 1174 return (0); /* EOF */ 1175 } else if (flag & IO_NDELAY) { 1176 splx(s); 1177 return (EWOULDBLOCK); 1178 } else { 1179 /* 1180 * sleep awaiting carrier 1181 */ 1182 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1183 splx(s); 1184 goto loop; 1185 } 1186 } 1187 splx(s); 1188 /* 1189 * Hang process if it's in the background. 1190 */ 1191 if (isbackground(u.u_procp, tp)) { 1192 if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 1193 (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 1194 u.u_procp->p_flag&SVFORK || u.u_procp->p_pgrp->pg_jobc == 0) 1195 return (EIO); 1196 pgsignal(u.u_procp->p_pgrp, SIGTTIN); 1197 sleep((caddr_t)&lbolt, TTIPRI); 1198 goto loop; 1199 } 1200 /* 1201 * If canonical, use the canonical queue, 1202 * else use the raw queue. 1203 * 1204 * XXX - should get rid of canonical queue. 1205 * (actually, should get rid of clists...) 1206 */ 1207 qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq; 1208 /* 1209 * No input, sleep on rawq awaiting hardware 1210 * receipt and notification. 1211 */ 1212 s = spltty(); 1213 if (qp->c_cc <= 0) { 1214 /** XXX ??? ask mike why TS_CARR_ON was (once) necessary here 1215 if ((tp->t_state&TS_CARR_ON) == 0 || 1216 (tp->t_state&TS_NBIO)) { 1217 splx(s); 1218 return (EWOULDBLOCK); 1219 } 1220 **/ 1221 if (flag & IO_NDELAY) { 1222 splx(s); 1223 return (EWOULDBLOCK); 1224 } 1225 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1226 splx(s); 1227 goto loop; 1228 } 1229 splx(s); 1230 /* 1231 * Input present, check for input mapping and processing. 1232 */ 1233 first = 1; 1234 while ((c = getc(qp)) >= 0) { 1235 /* 1236 * delayed suspend (^Y) 1237 */ 1238 if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) { 1239 pgsignal(tp->t_pgrp, SIGTSTP); 1240 if (first) { 1241 sleep((caddr_t)&lbolt, TTIPRI); 1242 goto loop; 1243 } 1244 break; 1245 } 1246 /* 1247 * Interpret EOF only in canonical mode. 1248 */ 1249 if (CCEQ(cc[VEOF], c) && lflag&ICANON) 1250 break; 1251 /* 1252 * Give user character. 1253 */ 1254 error = ureadc(c , uio); 1255 if (error) 1256 break; 1257 if (uio->uio_resid == 0) 1258 break; 1259 /* 1260 * In canonical mode check for a "break character" 1261 * marking the end of a "line of input". 1262 */ 1263 if (lflag&ICANON && ttbreakc(c)) { 1264 break; 1265 } 1266 first = 0; 1267 } 1268 /* 1269 * Look to unblock output now that (presumably) 1270 * the input queue has gone down. 1271 */ 1272 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 1273 if (cc[VSTART] != _POSIX_VDISABLE 1274 && putc(cc[VSTART], &tp->t_outq) == 0) { 1275 tp->t_state &= ~TS_TBLOCK; 1276 ttstart(tp); 1277 } 1278 } 1279 return (error); 1280 } 1281 1282 /* 1283 * Check the output queue on tp for space for a kernel message 1284 * (from uprintf/tprintf). Allow some space over the normal 1285 * hiwater mark so we don't lose messages due to normal flow 1286 * control, but don't let the tty run amok. 1287 * Sleeps here are not interruptible, but we return prematurely 1288 * if new signals come in. 1289 */ 1290 ttycheckoutq(tp, wait) 1291 register struct tty *tp; 1292 int wait; 1293 { 1294 int hiwat, s, oldsig; 1295 1296 hiwat = tp->t_hiwat; 1297 s = spltty(); 1298 oldsig = u.u_procp->p_sig; 1299 if (tp->t_outq.c_cc > hiwat + 200) 1300 while (tp->t_outq.c_cc > hiwat) { 1301 ttstart(tp); 1302 if (wait == 0 || u.u_procp->p_sig != oldsig) { 1303 splx(s); 1304 return (0); 1305 } 1306 timeout(wakeup, (caddr_t)&tp->t_outq, hz); 1307 tp->t_state |= TS_ASLEEP; 1308 sleep((caddr_t)&tp->t_outq, PZERO - 1); 1309 } 1310 splx(s); 1311 return (1); 1312 } 1313 1314 /* 1315 * Called from the device's write routine after it has 1316 * calculated the tty-structure given as argument. 1317 */ 1318 ttwrite(tp, uio, flag) 1319 register struct tty *tp; 1320 register struct uio *uio; 1321 { 1322 register char *cp; 1323 register int cc, ce; 1324 int i, hiwat, cnt, error, s; 1325 char obuf[OBUFSIZ]; 1326 1327 hiwat = tp->t_hiwat; 1328 cnt = uio->uio_resid; 1329 error = 0; 1330 loop: 1331 s = spltty(); 1332 if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) { 1333 if (tp->t_state&TS_ISOPEN) { 1334 splx(s); 1335 return (EIO); 1336 } else if (flag & IO_NDELAY) { 1337 splx(s); 1338 return (EWOULDBLOCK); 1339 } else { 1340 /* 1341 * sleep awaiting carrier 1342 */ 1343 sleep((caddr_t)&tp->t_rawq, TTIPRI); 1344 splx(s); 1345 goto loop; 1346 } 1347 } 1348 splx(s); 1349 /* 1350 * Hang the process if it's in the background. 1351 */ 1352 if (isbackground(u.u_procp, tp) && 1353 (tp->t_lflag&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 && 1354 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) && 1355 !(u.u_procp->p_sigmask & sigmask(SIGTTOU)) && 1356 u.u_procp->p_pgrp->pg_jobc) { 1357 pgsignal(u.u_procp->p_pgrp, SIGTTOU); 1358 sleep((caddr_t)&lbolt, TTIPRI); 1359 goto loop; 1360 } 1361 /* 1362 * Process the user's data in at most OBUFSIZ 1363 * chunks. Perform lower case simulation and 1364 * similar hacks. Keep track of high water 1365 * mark, sleep on overflow awaiting device aid 1366 * in acquiring new space. 1367 */ 1368 while (uio->uio_resid > 0) { 1369 if (tp->t_outq.c_cc > hiwat) { 1370 cc = 0; 1371 goto ovhiwat; 1372 } 1373 /* 1374 * Grab a hunk of data from the user. 1375 */ 1376 cc = uio->uio_iov->iov_len; 1377 if (cc == 0) { 1378 uio->uio_iovcnt--; 1379 uio->uio_iov++; 1380 if (uio->uio_iovcnt <= 0) 1381 panic("ttwrite"); 1382 continue; 1383 } 1384 if (cc > OBUFSIZ) 1385 cc = OBUFSIZ; 1386 cp = obuf; 1387 error = uiomove(cp, cc, uio); 1388 if (error) 1389 break; 1390 if (tp->t_lflag&FLUSHO) 1391 continue; 1392 /* 1393 * If nothing fancy need be done, grab those characters we 1394 * can handle without any of ttyoutput's processing and 1395 * just transfer them to the output q. For those chars 1396 * which require special processing (as indicated by the 1397 * bits in partab), call ttyoutput. After processing 1398 * a hunk of data, look for FLUSHO so ^O's will take effect 1399 * immediately. 1400 */ 1401 while (cc > 0) { 1402 if (!(tp->t_oflag&OPOST)) 1403 ce = cc; 1404 else { 1405 ce = cc - scanc((unsigned)cc, (u_char *)cp, 1406 (u_char *)partab, 077); 1407 /* 1408 * If ce is zero, then we're processing 1409 * a special character through ttyoutput. 1410 */ 1411 if (ce == 0) { 1412 tp->t_rocount = 0; 1413 if (ttyoutput(*cp, tp) >= 0) { 1414 /* no c-lists, wait a bit */ 1415 ttstart(tp); 1416 sleep((caddr_t)&lbolt, TTOPRI); 1417 if (cc != 0) { 1418 uio->uio_iov->iov_base -= cc; 1419 uio->uio_iov->iov_len += cc; 1420 uio->uio_resid += cc; 1421 uio->uio_offset -= cc; 1422 } 1423 goto loop; 1424 } 1425 cp++, cc--; 1426 if ((tp->t_lflag&FLUSHO) || 1427 tp->t_outq.c_cc > hiwat) 1428 goto ovhiwat; 1429 continue; 1430 } 1431 } 1432 /* 1433 * A bunch of normal characters have been found, 1434 * transfer them en masse to the output queue and 1435 * continue processing at the top of the loop. 1436 * If there are any further characters in this 1437 * <= OBUFSIZ chunk, the first should be a character 1438 * requiring special handling by ttyoutput. 1439 */ 1440 tp->t_rocount = 0; 1441 i = b_to_q(cp, ce, &tp->t_outq); 1442 ce -= i; 1443 tp->t_col += ce; 1444 cp += ce, cc -= ce, tk_nout += ce; 1445 tp->t_outcc += ce; 1446 if (i > 0) { 1447 /* out of c-lists, wait a bit */ 1448 ttstart(tp); 1449 sleep((caddr_t)&lbolt, TTOPRI); 1450 uio->uio_iov->iov_base -= cc; 1451 uio->uio_iov->iov_len += cc; 1452 uio->uio_resid += cc; 1453 uio->uio_offset -= cc; 1454 goto loop; 1455 } 1456 if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat) 1457 goto ovhiwat; 1458 } 1459 ttstart(tp); 1460 } 1461 return (error); 1462 ovhiwat: 1463 if (cc != 0) { 1464 uio->uio_iov->iov_base -= cc; 1465 uio->uio_iov->iov_len += cc; 1466 uio->uio_resid += cc; 1467 uio->uio_offset -= cc; 1468 } 1469 ttstart(tp); 1470 s = spltty(); 1471 /* 1472 * This can only occur if FLUSHO is set in t_lflag, 1473 * or if ttstart/oproc is synchronous (or very fast). 1474 */ 1475 if (tp->t_outq.c_cc <= hiwat) { 1476 splx(s); 1477 goto loop; 1478 } 1479 if (flag & IO_NDELAY) { 1480 splx(s); 1481 if (uio->uio_resid == cnt) 1482 return (EWOULDBLOCK); 1483 return (0); 1484 } 1485 tp->t_state |= TS_ASLEEP; 1486 sleep((caddr_t)&tp->t_outq, TTOPRI); 1487 splx(s); 1488 goto loop; 1489 } 1490 1491 /* 1492 * Rubout one character from the rawq of tp 1493 * as cleanly as possible. 1494 */ 1495 ttyrub(c, tp) 1496 register c; 1497 register struct tty *tp; 1498 { 1499 register char *cp; 1500 register int savecol; 1501 int s; 1502 char *nextc(); 1503 1504 if ((tp->t_lflag&ECHO) == 0) 1505 return; 1506 tp->t_lflag &= ~FLUSHO; 1507 if (tp->t_lflag&ECHOE) { 1508 if (tp->t_rocount == 0) { 1509 /* 1510 * Screwed by ttwrite; retype 1511 */ 1512 ttyretype(tp); 1513 return; 1514 } 1515 if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE)) 1516 ttyrubo(tp, 2); 1517 else switch (partab[c&=0377]&077) { 1518 1519 case ORDINARY: 1520 ttyrubo(tp, 1); 1521 break; 1522 1523 case VTAB: 1524 case BACKSPACE: 1525 case CONTROL: 1526 case RETURN: 1527 if (tp->t_lflag&ECHOCTL) 1528 ttyrubo(tp, 2); 1529 break; 1530 1531 case TAB: { 1532 int c; 1533 1534 if (tp->t_rocount < tp->t_rawq.c_cc) { 1535 ttyretype(tp); 1536 return; 1537 } 1538 s = spltty(); 1539 savecol = tp->t_col; 1540 tp->t_state |= TS_CNTTB; 1541 tp->t_lflag |= FLUSHO; 1542 tp->t_col = tp->t_rocol; 1543 cp = tp->t_rawq.c_cf; 1544 if (cp) 1545 c = *cp; /* XXX FIX NEXTC */ 1546 for (; cp; cp = nextc(&tp->t_rawq, cp, &c)) 1547 ttyecho(c, tp); 1548 tp->t_lflag &= ~FLUSHO; 1549 tp->t_state &= ~TS_CNTTB; 1550 splx(s); 1551 /* 1552 * savecol will now be length of the tab 1553 */ 1554 savecol -= tp->t_col; 1555 tp->t_col += savecol; 1556 if (savecol > 8) 1557 savecol = 8; /* overflow screw */ 1558 while (--savecol >= 0) 1559 (void) ttyoutput('\b', tp); 1560 break; 1561 } 1562 1563 default: 1564 /* XXX */ 1565 printf("ttyrub: would panic c = %d, val = %d\n", 1566 c, partab[c&=0377]&077); 1567 /*panic("ttyrub");*/ 1568 } 1569 } else if (tp->t_lflag&ECHOPRT) { 1570 if ((tp->t_state&TS_ERASE) == 0) { 1571 (void) ttyoutput('\\', tp); 1572 tp->t_state |= TS_ERASE; 1573 } 1574 ttyecho(c, tp); 1575 } else 1576 ttyecho(tp->t_cc[VERASE], tp); 1577 tp->t_rocount--; 1578 } 1579 1580 /* 1581 * Crt back over cnt chars perhaps 1582 * erasing them. 1583 */ 1584 ttyrubo(tp, cnt) 1585 register struct tty *tp; 1586 int cnt; 1587 { 1588 1589 while (--cnt >= 0) 1590 ttyout("\b \b", tp); 1591 } 1592 1593 /* 1594 * Reprint the rawq line. 1595 * We assume c_cc has already been checked. 1596 */ 1597 ttyretype(tp) 1598 register struct tty *tp; 1599 { 1600 register char *cp; 1601 char *nextc(); 1602 int s, c; 1603 1604 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE) 1605 ttyecho(tp->t_cc[VREPRINT], tp); 1606 (void) ttyoutput('\n', tp); 1607 s = spltty(); 1608 /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE 1609 BIT OF FIRST CHAR ****/ 1610 for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) { 1611 ttyecho(c, tp); 1612 } 1613 for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) { 1614 ttyecho(c, tp); 1615 } 1616 tp->t_state &= ~TS_ERASE; 1617 splx(s); 1618 tp->t_rocount = tp->t_rawq.c_cc; 1619 tp->t_rocol = 0; 1620 } 1621 1622 /* 1623 * Echo a typed character to the terminal. 1624 */ 1625 ttyecho(c, tp) 1626 register c; 1627 register struct tty *tp; 1628 { 1629 if ((tp->t_state&TS_CNTTB) == 0) 1630 tp->t_lflag &= ~FLUSHO; 1631 if ((tp->t_lflag&ECHO) == 0 && !(tp->t_lflag&ECHONL && c == '\n')) 1632 return; 1633 if (tp->t_lflag&ECHOCTL) { 1634 if ((c&TTY_CHARMASK)<=037 && c!='\t' && c!='\n' || c==0177) { 1635 (void) ttyoutput('^', tp); 1636 c &= TTY_CHARMASK; 1637 if (c == 0177) 1638 c = '?'; 1639 else 1640 c += 'A' - 1; 1641 } 1642 } 1643 (void) ttyoutput(c, tp); 1644 } 1645 1646 /* 1647 * send string cp to tp 1648 */ 1649 ttyout(cp, tp) 1650 register char *cp; 1651 register struct tty *tp; 1652 { 1653 register char c; 1654 1655 while (c = *cp++) 1656 (void) ttyoutput(c, tp); 1657 } 1658 1659 ttwakeup(tp) 1660 struct tty *tp; 1661 { 1662 1663 if (tp->t_rsel) { 1664 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL); 1665 tp->t_state &= ~TS_RCOLL; 1666 tp->t_rsel = 0; 1667 } 1668 if (tp->t_state & TS_ASYNC) 1669 pgsignal(tp->t_pgrp, SIGIO); 1670 wakeup((caddr_t)&tp->t_rawq); 1671 } 1672 1673 /* 1674 * set tty hi and low water marks 1675 * 1676 * Try to arrange the dynamics so there's about one second 1677 * from hi to low water. 1678 * 1679 */ 1680 ttsetwater(tp) 1681 struct tty *tp; 1682 { 1683 register cps = tp->t_ospeed / 10; 1684 register x; 1685 1686 #define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x)) 1687 tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT); 1688 x += cps; 1689 x = clamp(x, TTMAXHIWAT, TTMINHIWAT); 1690 tp->t_hiwat = roundup(x, CBSIZE); 1691 #undef clamp 1692 } 1693 1694 ttspeedtab(speed, table) 1695 struct speedtab table[]; 1696 { 1697 register int i; 1698 1699 for (i = 0; table[i].sp_speed != -1; i++) 1700 if (table[i].sp_speed == speed) 1701 return(table[i].sp_code); 1702 return(-1); 1703 } 1704 1705 /* 1706 * (^T) 1707 * Report on state of foreground process group. 1708 */ 1709 ttyinfo(tp) 1710 struct tty *tp; 1711 { 1712 register struct proc *p; 1713 1714 if (ttycheckoutq(tp,0) == 0) 1715 return; 1716 if (tp->t_session == NULL) 1717 ttyprintf(tp, "kernel: not a controlling terminal\n"); 1718 else if (tp->t_pgrp == NULL || 1719 (p = tp->t_pgrp->pg_mem) == NULL) 1720 ttyprintf(tp, "kernel: no foreground process group\n"); 1721 else { 1722 int i = 0; 1723 1724 for (; p != NULL; p = p->p_pgrpnxt) { 1725 ttyprintf(tp, 1726 "kernel: pid: %d state: %x wchan: %x ticks: %d\n", 1727 p->p_pid, p->p_stat, p->p_wchan, p->p_cpticks); 1728 if (++i > 6) { 1729 ttyprintf(tp, "kernel: more...\n"); 1730 break; 1731 } 1732 } 1733 } 1734 } 1735 1736 #define TOTTY 0x2 /* XXX should be in header */ 1737 /*VARARGS2*/ 1738 ttyprintf(tp, fmt, x1) 1739 struct tty *tp; 1740 char *fmt; 1741 unsigned x1; 1742 { 1743 prf(fmt, &x1, TOTTY, (caddr_t)tp); 1744 } 1745 1746 /* 1747 * Output char to tty; console putchar style. 1748 */ 1749 tputchar(c, tp) 1750 int c; 1751 struct tty *tp; 1752 { 1753 register s = spltty(); 1754 1755 if ((tp->t_state & (TS_CARR_ON | TS_ISOPEN)) 1756 == (TS_CARR_ON | TS_ISOPEN)) { 1757 if (c == '\n') 1758 (void) ttyoutput('\r', tp); 1759 (void) ttyoutput(c, tp); 1760 ttstart(tp); 1761 splx(s); 1762 return (0); 1763 } 1764 splx(s); 1765 return (-1); 1766 } 1767