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