|
|
1.1 ! root 1: /* ! 2: * File: $USRSRC/ttydrv/tty.c ! 3: * ! 4: * Purpose: COHERENT line discipline module. ! 5: * This is the common part of typewriter service. It handles all device- ! 6: * independent aspects of a typewriter, including tandem flow control, ! 7: * erase and kill, stop and start, and common ioctl functions. ! 8: * ! 9: * $Log: tty.c,v $ ! 10: * Revision 1.9 91/09/17 06:06:42 bin ! 11: * updated by hal ! 12: * ! 13: * Revision 1.8 91/09/13 18:01:39 piggy ! 14: * Only do XON/XOFF flow control if TANDEM is set. ! 15: * ! 16: * Revision 1.7 91/09/13 17:58:00 hal ! 17: * Drop 3rd arg (was writing PSW directly from it!) for ttread/ttwrite. ! 18: * General face lift. ! 19: * ! 20: * ! 21: * Bug: no support for 8-bit characters. ! 22: * Fix: don't strip keyboard input. 01/22/91. (norm) ! 23: * ! 24: * Bug: Switching modes between cooked and CBREAK/RAW left buffered input ! 25: * in the input buffer until returning to cooked mode. 05/13/91 norm ! 26: * ! 27: * Bug: setting speed to default in ttopen() was conditioned to ! 28: * use hard constants. 90/08/28. hws ! 29: * ! 30: * Revision 1.5 91/06/06 18:28:53 norm ! 31: * Restore 8-bit fix. ! 32: * ! 33: * Revision 1.2 89/07/17 11:51:20 src ! 34: * Bug: Terminal could lock up when setting it to RAWIN mode, if ! 35: * output was suspended due to X-OFF, and output data was present. ! 36: * Fix: Setting terminal to RAWIN mode now clears X-OFF, starts output ! 37: * BEFORE waiting for output to drain. Received signals now cause ! 38: * operation to complete without waiting for drain. (ABC) ! 39: * ! 40: * Revision 1.1 88/03/24 16:18:12 src ! 41: * Initial revision ! 42: * ! 43: * 86/12/12 Allan Cornish /usr/src/sys/drv/tty.c ! 44: * Added 3rd argument to ttpoll() to support non-blocking polls. ! 45: * ! 46: * 86/11/19 Allan Cornish /usr/src/sys/drv/tty.c ! 47: * Made ttread() and ttwrite() recognize the IONDLY flag in iop->io_flag. ! 48: * wakeup() and pollwake() now have delayed invocation by defer(). ! 49: * Added poll [System V.3] capability. ! 50: * ! 51: * 85/06/28 Allan Cornish ! 52: * made ttioctl() clear T_STOP flag if ISRIN. ! 53: * ! 54: * 85/03/04 Allan Cornish ! 55: * made ttread() interruptible. ! 56: * ! 57: * 85/03/01 Allan Cornish ! 58: * made ttclose() interruptible. ! 59: */ ! 60: ! 61: /* ! 62: * Includes. ! 63: */ ! 64: #include <sys/clist.h> ! 65: #include <sys/coherent.h> ! 66: #include <sys/con.h> ! 67: #include <sys/deftty.h> ! 68: #include <sys/io.h> ! 69: #include <sys/proc.h> ! 70: #include <sys/sched.h> ! 71: #include <sys/stat.h> ! 72: #include <sys/tty.h> ! 73: #include <sys/uproc.h> ! 74: #include <errno.h> ! 75: ! 76: /* ! 77: * Definitions. ! 78: * Constants. ! 79: * Macros with argument lists. ! 80: * Typedefs. ! 81: * Enums. ! 82: */ ! 83: ! 84: /* NEAR_OR_FAR_CALL is for invoking t_param and t_start */ ! 85: #define NEAR_OR_FAR_CALL(tp_fn) {\ ! 86: if (tp->t_cs_sel) \ ! 87: ld_call(tp->t_cs_sel, tp->tp_fn, tp); \ ! 88: else \ ! 89: (*tp->tp_fn)(tp); } ! 90: ! 91: /* ! 92: * Functions. ! 93: * Import Functions. ! 94: * Export Functions. ! 95: * Local Functions. ! 96: */ ! 97: void ttclose(); ! 98: void ttflush(); ! 99: void tthup(); ! 100: void ttin(); ! 101: void ttioctl(); ! 102: void ttopen(); ! 103: int ttout(); ! 104: int ttpoll(); ! 105: void ttread(); ! 106: void ttsetgrp(); ! 107: void ttsignal(); ! 108: void ttstart(); ! 109: void ttstash(); ! 110: void ttwrite(); ! 111: ! 112: /* ! 113: * Global Data. ! 114: * Import Variables. ! 115: * Export Variables. ! 116: * Local Variables. ! 117: */ ! 118: extern int wakeup(); ! 119: extern void pollwake(); ! 120: ! 121: /* ! 122: * ttopen() ! 123: * ! 124: * Called by driver on first open. ! 125: * Set up defaults. ! 126: */ ! 127: void ttopen(tp) ! 128: register TTY *tp; ! 129: { ! 130: tp->t_escape = 0; ! 131: tp->t_sgttyb.sg_ispeed = tp->t_dispeed; ! 132: tp->t_sgttyb.sg_ospeed = tp->t_dospeed; ! 133: tp->t_sgttyb.sg_erase = DEF_SG_ERASE; ! 134: tp->t_sgttyb.sg_kill = DEF_SG_KILL; ! 135: tp->t_sgttyb.sg_flags = DEF_SG_FLAGS; ! 136: tp->t_tchars.t_intrc = DEF_T_INTRC; ! 137: tp->t_tchars.t_quitc = DEF_T_QUITC; ! 138: tp->t_tchars.t_startc = DEF_T_STARTC; ! 139: tp->t_tchars.t_stopc = DEF_T_STOPC; ! 140: tp->t_tchars.t_eofc = DEF_T_EOFC; ! 141: tp->t_tchars.t_brkc = DEF_T_BRKC; ! 142: if (tp->t_param != NULL) { ! 143: NEAR_OR_FAR_CALL(t_param) ! 144: } ! 145: } ! 146: ! 147: /* ! 148: * ttsetgrp() ! 149: * ! 150: * Set process group when process does not have one. ! 151: * Also set up process's controlling terminal. ! 152: */ ! 153: void ttsetgrp(tp, ctdev) ! 154: register TTY *tp; ! 155: dev_t ctdev; ! 156: { ! 157: register PROC *pp; ! 158: ! 159: pp = SELF; ! 160: if (pp->p_group == 0) { ! 161: if (tp->t_group == 0) ! 162: tp->t_group = pp->p_pid; ! 163: pp->p_group = tp->t_group; ! 164: } ! 165: if (pp->p_ttdev == NODEV) ! 166: pp->p_ttdev = ctdev; ! 167: } ! 168: ! 169: /* ! 170: * ttyclose() ! 171: * ! 172: * Called by driver on the last close. ! 173: * Wait for all pending output to go out. ! 174: * Kill input. ! 175: */ ! 176: void ttclose(tp) ! 177: register TTY *tp; ! 178: { ! 179: register int s; ! 180: ! 181: while (tp->t_oq.cq_cc != 0) { ! 182: s = sphi(); ! 183: if (tp->t_oq.cq_cc != 0) { ! 184: tp->t_flags |= T_DRAIN; ! 185: sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT); ! 186: } ! 187: spl(s); ! 188: if (SELF->p_ssig && nondsig()) ! 189: break; ! 190: } ! 191: ttflush(tp); ! 192: tp->t_flags = tp->t_group = 0; ! 193: } ! 194: ! 195: /* ! 196: * ttread() ! 197: * ! 198: * The read routine for a tty device driver will call this function. ! 199: * ! 200: * Move data from tp->t_iq to io segment iop. ! 201: * Number of characters to copy is in iop->ioc. ! 202: * ! 203: * In cooked mode, copy up to the first newline or break character, or ! 204: * until the count runs out. ! 205: * In CBREAK or RAW modes, return when count runs out or when input clist ! 206: * is empty and we're returning at least one byte. ! 207: */ ! 208: void ttread(tp, iop) ! 209: register TTY *tp; ! 210: register IO *iop; ! 211: { ! 212: register c; ! 213: int o; ! 214: int sioc = iop->io_ioc; /* number of bytes to read */ ! 215: ! 216: while (iop->io_ioc) { ! 217: o = sphi(); ! 218: while ((c = getq(&tp->t_iq)) < 0) { ! 219: if ((tp->t_flags & T_CARR) == 0) { ! 220: u.u_error = EIO; /* error since no carrier */ ! 221: spl(o); ! 222: return; ! 223: } ! 224: ! 225: /* If we're in CBREAK or RAW mode, and we don't */ ! 226: /* have the special "blocking read" bit set for */ ! 227: /* these modes, and we read at least one byte */ ! 228: /* of input, return immediately, since we have */ ! 229: /* run out of characters from the clist. */ ! 230: ! 231: if (ISBBYB && ((tp->t_flags & T_BRD) == 0) ! 232: && iop->io_ioc < sioc) { ! 233: spl(o); ! 234: return; ! 235: } ! 236: ! 237: /* ! 238: * Non-blocking reads. ! 239: * Tell user process to try again later. ! 240: */ ! 241: if ( iop->io_flag & IONDLY ) { ! 242: u.u_error = EAGAIN; ! 243: spl(o); ! 244: return; ! 245: } ! 246: ! 247: tp->t_flags |= T_INPUT; /* wait for more data */ ! 248: sleep((char *)&tp->t_iq, CVTTIN, IVTTIN, SVTTIN); ! 249: ! 250: if (SELF->p_ssig && nondsig()) { ! 251: if (iop->io_ioc == sioc) ! 252: u.u_error = EINTR; ! 253: spl(o); ! 254: return; ! 255: } ! 256: } ! 257: /* ! 258: * Flow control - can we turn on input from the driver yet? ! 259: */ ! 260: if (tp->t_iq.cq_cc <= ILOLIM) { ! 261: if ((tp->t_flags&T_ISTOP) != 0) ! 262: tp->t_flags &= ~T_ISTOP; ! 263: if ((tp->t_flags&T_TSTOP) != 0) { ! 264: tp->t_flags &= ~T_TSTOP; ! 265: while (putq(&tp->t_oq, startc) < 0) { ! 266: ttstart(tp); ! 267: waitq(); ! 268: } ! 269: ttstart(tp); ! 270: } ! 271: } ! 272: spl(o); ! 273: if (!ISBBYB && ISEOF) ! 274: return; ! 275: if (ioputc(c, iop) < 0) ! 276: return; ! 277: if (!ISBBYB && (c=='\n' || ISBRK)) ! 278: return; ! 279: } ! 280: } ! 281: ! 282: /* ! 283: * ttwrite() ! 284: * ! 285: * Write routine. ! 286: * Transfer stuff to the character list. ! 287: */ ! 288: void ttwrite(tp, iop) ! 289: register TTY *tp; ! 290: register IO *iop; ! 291: { ! 292: register c; ! 293: int o; ! 294: ! 295: /* ! 296: * Non-blocking writes which can fit. ! 297: * NOTE: exhaustion of clists can still cause blocking writes. ! 298: */ ! 299: if ( (iop->io_flag & IONDLY) && (OHILIM >= iop->io_ioc) ) { ! 300: ! 301: /* ! 302: * No room. ! 303: */ ! 304: if ( tp->t_oq.cq_cc >= OHILIM-iop->io_ioc ) { ! 305: u.u_error = EAGAIN; ! 306: return; ! 307: } ! 308: } ! 309: ! 310: while ((c = iogetc(iop)) >= 0) { ! 311: if ((tp->t_flags & T_CARR) == 0) { ! 312: u.u_error = EIO; /* error since no carrier */ ! 313: return; ! 314: } ! 315: o = sphi(); ! 316: while (tp->t_oq.cq_cc >= OHILIM) { ! 317: ttstart(tp); ! 318: if (tp->t_oq.cq_cc < OHILIM) ! 319: break; ! 320: tp->t_flags |= T_HILIM; ! 321: sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT); ! 322: if (SELF->p_ssig && nondsig()) { ! 323: u.u_error = EINTR; ! 324: spl(o); ! 325: return; ! 326: } ! 327: } ! 328: while (putq(&tp->t_oq, c) < 0) { ! 329: ttstart(tp); ! 330: waitq(); ! 331: } ! 332: spl(o); ! 333: } ! 334: o = sphi(); ! 335: ttstart(tp); ! 336: spl(o); ! 337: } ! 338: ! 339: /* ! 340: * ttioctl() ! 341: * ! 342: * This routine handles common typewriter ioctl functions. ! 343: * Note that flushing the stream now means drain the output ! 344: * and clear the input. ! 345: */ ! 346: void ttioctl(tp, com, vec) ! 347: register TTY *tp; ! 348: register struct sgttyb *vec; ! 349: { ! 350: register int flush = 0; ! 351: register int drain = 0; ! 352: register char *p1, *p2; ! 353: int rload = 0; ! 354: int was_bbyb = 0; ! 355: ! 356: switch (com) { ! 357: case TIOCQUERY: ! 358: kucopy(&tp->t_iq.cq_cc, vec, sizeof(int)); ! 359: break; ! 360: case TIOCGETP: ! 361: kucopy(&tp->t_sgttyb, vec, sizeof (struct sgttyb)); ! 362: break; ! 363: case TIOCSETP: ! 364: ++flush; /* flush input */ ! 365: ++drain; /* delay for output */ ! 366: ++rload; ! 367: ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb)); ! 368: break; ! 369: case TIOCSETN: ! 370: was_bbyb = ISBBYB; /* previous mode */ ! 371: ++rload; ! 372: ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb)); ! 373: if (!was_bbyb && ISBBYB && tp->t_ibx != 0) { ! 374: p1 = &tp->t_ib[0]; ! 375: p2 = &tp->t_ib[tp->t_ibx]; ! 376: while (p1 < p2) ! 377: #if NOT_8_BIT ! 378: putq(&tp->t_iq, (*p1++) & 0177); ! 379: #else ! 380: putq(&tp->t_iq, (*p1++)); ! 381: #endif ! 382: tp->t_ibx = 0; ! 383: } ! 384: break; ! 385: case TIOCGETC: ! 386: kucopy(&tp->t_tchars, vec, sizeof (struct tchars)); ! 387: break; ! 388: case TIOCSETC: ! 389: ++rload; ! 390: ++drain; ! 391: ukcopy(vec, &tp->t_tchars, sizeof (struct tchars)); ! 392: break; ! 393: case TIOCEXCL: ! 394: tp->t_flags |= T_EXCL; ! 395: break; ! 396: case TIOCNXCL: ! 397: tp->t_flags &= ~T_EXCL; ! 398: break; ! 399: case TIOCHPCL: /* set hangup on last close */ ! 400: tp->t_flags |= T_HPCL; ! 401: break; ! 402: case TIOCCHPCL: /* don't hangup on last close */ ! 403: if (!super()) /* only superuser may do this */ ! 404: u.u_error = EPERM; /* not su */ ! 405: else ! 406: tp->t_flags &= ~T_HPCL; /* turn off hangup bit */ ! 407: break; ! 408: case TIOCGETTF: /* get tty flag word */ ! 409: kucopy(&tp->t_flags, (unsigned *) vec, sizeof(unsigned)); ! 410: break; ! 411: case TIOCFLUSH: ! 412: ++flush; /* flush both input and output */ ! 413: ++drain; ! 414: break; ! 415: case TIOCBREAD: /* blocking read for CBREAK/RAW mode */ ! 416: tp->t_flags |= T_BRD; ! 417: break; ! 418: case TIOCCBREAD: /* turn off CBREAK/RAW blocking read mode */ ! 419: tp->t_flags &= ~T_BRD; ! 420: break; ! 421: default: ! 422: u.u_error = EINVAL; ! 423: } ! 424: ! 425: /* ! 426: * Ensure output is enabled BEFORE waiting for output to drain. ! 427: */ ! 428: if ( (ISRIN) && (tp->t_flags & T_STOP) ) { ! 429: tp->t_flags &= ~T_STOP; ! 430: ttstart( tp ); ! 431: } ! 432: ! 433: /* ! 434: * Wait for output to drain, or signal to arrive. ! 435: */ ! 436: if (drain != 0) { ! 437: while (tp->t_oq.cq_cc != 0) { ! 438: tp->t_flags |= T_DRAIN; ! 439: sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT); ! 440: if (SELF->p_ssig && nondsig()) ! 441: break; ! 442: } ! 443: } ! 444: ! 445: /* ! 446: * Flush input. ! 447: */ ! 448: if (flush != 0) ! 449: ttflush(tp); ! 450: ! 451: /* ! 452: * Re-initialize hardware. ! 453: */ ! 454: if ( (rload != 0) && (tp->t_param != NULL) ) ! 455: NEAR_OR_FAR_CALL(t_param) ! 456: } ! 457: ! 458: /* ! 459: * ttpoll() ! 460: * ! 461: * Polling routine. ! 462: * [System V.3 Compatible] ! 463: */ ! 464: int ttpoll( tp, ev, msec ) ! 465: register TTY * tp; ! 466: int ev; ! 467: int msec; ! 468: { ! 469: /* ! 470: * Priority polls not supported. ! 471: */ ! 472: ev &= ~POLLPRI; ! 473: ! 474: /* ! 475: * Input poll with no data present. ! 476: */ ! 477: if ( (ev & POLLIN) && (tp->t_iq.cq_cc == 0) ) { ! 478: ! 479: /* ! 480: * Blocking input poll. ! 481: */ ! 482: if ( msec != 0 ) ! 483: pollopen( &tp->t_ipolls ); ! 484: ! 485: /* ! 486: * Second look to avoid interrupt race. ! 487: */ ! 488: if ( tp->t_iq.cq_cc == 0 ) ! 489: ev &= ~POLLIN; ! 490: } ! 491: ! 492: /* ! 493: * Output poll with no space. ! 494: */ ! 495: if ( (ev & POLLOUT) && (tp->t_oq.cq_cc >= OLOLIM) ) { ! 496: ! 497: /* ! 498: * Blocking output poll. ! 499: */ ! 500: if ( msec != 0 ) ! 501: pollopen( &tp->t_opolls ); ! 502: ! 503: /* ! 504: * Second look to avoid interrupt race. ! 505: */ ! 506: if ( tp->t_oq.cq_cc >= OLOLIM ) ! 507: ev &= ~POLLIN; ! 508: } ! 509: ! 510: if ( ((ev & POLLIN) == 0) && ((tp->t_flags & T_CARR) == 0) ) ! 511: ev |= POLLHUP; ! 512: ! 513: return ev; ! 514: } ! 515: ! 516: /* ! 517: * ttout() ! 518: * ! 519: * Pull a character from the output queues of the typewriter. ! 520: * Doing fills, newline insert, tab expansion, etc. ! 521: * ! 522: * If the stream is empty return a -1. ! 523: * Called at high priority. ! 524: */ ! 525: int ttout(tp) ! 526: register TTY *tp; ! 527: { ! 528: register c; ! 529: ! 530: if (tp->t_nfill) { ! 531: --tp->t_nfill; ! 532: c = tp->t_fillb; ! 533: } else if ((tp->t_flags&T_INL) != 0) { ! 534: tp->t_flags &= ~T_INL; ! 535: c = '\n'; ! 536: } else { ! 537: if ((c=getq(&tp->t_oq)) < 0) ! 538: return -1; ! 539: if (!ISROUT) { ! 540: if (c=='\n' && ISCRMOD) { ! 541: tp->t_flags |= T_INL; ! 542: c = '\r'; ! 543: } else if (c=='\t' && ISXTABS) { ! 544: tp->t_nfill = ~(tp->t_hpos|~07); ! 545: tp->t_fillb = ' '; ! 546: c = ' '; ! 547: } ! 548: } ! 549: } ! 550: if (!ISROUT) { ! 551: if (c == '\b') { ! 552: if (tp->t_hpos) ! 553: --tp->t_hpos; ! 554: } else if (c == '\r') ! 555: tp->t_hpos = 0; ! 556: else if (c == '\t') ! 557: tp->t_hpos = (tp->t_hpos|07) + 1; ! 558: #if NOT_8_BIT ! 559: else if (c >= ' ' && c <= '~') ! 560: #else ! 561: else if ((c >= ' ' && c <= '~') || (c >= 0200 && c <= 0376)) ! 562: #endif ! 563: ++tp->t_hpos; ! 564: } ! 565: return c; ! 566: } ! 567: ! 568: /* ! 569: * ttin() ! 570: * ! 571: * Pass a character to the device independent typewriter routines. ! 572: * Handle erase and kill, tandem flow control, and other magic. ! 573: * Called at high priority from the driver's interrupt processor. ! 574: */ ! 575: void ttin(tp, c) ! 576: register TTY *tp; ! 577: register c; ! 578: { ! 579: int dc, i, n; ! 580: ! 581: if (!ISRIN) { ! 582: #if NOT_8_BIT ! 583: c &= 0177; ! 584: #endif ! 585: if (ISINTR) { ! 586: ttsignal(tp, SIGINT); ! 587: return; ! 588: } ! 589: if (ISQUIT) { ! 590: ttsignal(tp, SIGQUIT); ! 591: return; ! 592: } ! 593: ! 594: /* ! 595: * Only do flow control if TANDEM is set. ! 596: */ ! 597: if (ISTAND) { ! 598: if (ISSTOP) { ! 599: if ((tp->t_flags&T_STOP) == 0) ! 600: tp->t_flags |= T_STOP; ! 601: return; ! 602: } ! 603: if (ISSTART) { ! 604: tp->t_flags &= ~T_STOP; ! 605: ttstart(tp); ! 606: return; ! 607: } ! 608: } ! 609: } ! 610: if ((tp->t_flags&T_ISTOP) != 0) ! 611: return; ! 612: if (!ISRIN) { ! 613: if (c=='\r' && ISCRMOD) ! 614: c = '\n'; ! 615: if (tp->t_escape != 0) { ! 616: if (c == ESC) ! 617: ++tp->t_escape; ! 618: else { ! 619: if (ISERASE || ISKILL) { ! 620: c |= 0200; ! 621: --tp->t_escape; ! 622: } ! 623: while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) { ! 624: tp->t_ib[tp->t_ibx++] = ESC; ! 625: --tp->t_escape; ! 626: } ! 627: ttstash(tp, c); ! 628: } ! 629: if (ISECHO) { ! 630: #if NOT_8_BIT ! 631: putq(&tp->t_oq, c&0177); ! 632: #else ! 633: putq(&tp->t_oq, c); /* no strip for 8-bit */ ! 634: #endif ! 635: ttstart(tp); ! 636: } ! 637: return; ! 638: } ! 639: if (ISERASE && !ISCBRK) { ! 640: while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) { ! 641: tp->t_ib[tp->t_ibx++] = ESC; ! 642: --tp->t_escape; ! 643: } ! 644: if (tp->t_ibx == 0) ! 645: return; ! 646: dc = tp->t_ib[--tp->t_ibx]; ! 647: if (ISECHO) { ! 648: if (!ISCRT) ! 649: putq(&tp->t_oq, c); ! 650: /* don't erase for bell, null, or rubout */ ! 651: #if NOT_8_BIT ! 652: else if (((c = dc&0177) == '\007') ! 653: || c == 0 || c == 0177) ! 654: #else ! 655: else if (((c = dc) == '\007') ! 656: || c == 0 || c == 0177 || c == 0377) ! 657: #endif ! 658: return; ! 659: else if (c != '\b' && c != '\t') { ! 660: putq(&tp->t_oq, '\b'); ! 661: putq(&tp->t_oq, ' '); ! 662: putq(&tp->t_oq, '\b'); ! 663: } else if (c == '\t') { ! 664: n = tp->t_opos + tp->t_escape; ! 665: for (i=0; i<tp->t_ibx; ++i) { ! 666: c = tp->t_ib[i]; ! 667: #if NOT_8_BIT ! 668: if ((c&0200) != 0) { ! 669: ++n; ! 670: c &= 0177; ! 671: } ! 672: #endif ! 673: if (c == '\b') ! 674: --n; ! 675: else { ! 676: if (c == '\t') ! 677: n |= 07; ! 678: ++n; ! 679: } ! 680: } ! 681: while (n++ < tp->t_hpos) ! 682: putq(&tp->t_oq, '\b'); ! 683: } ! 684: #if NOT_8_BIT ! 685: if ((dc&0200) != 0) { ! 686: if ((dc&0177) != '\b') ! 687: putq(&tp->t_oq, '\b'); ! 688: putq(&tp->t_oq, ' '); ! 689: putq(&tp->t_oq, '\b'); ! 690: } ! 691: #endif ! 692: ttstart(tp); ! 693: } ! 694: return; ! 695: } ! 696: if (ISKILL && !ISCBRK) { ! 697: tp->t_ibx = 0; ! 698: tp->t_escape = 0; ! 699: if (ISECHO) { ! 700: if (c < 0x20) { ! 701: putq(&tp->t_oq, '^'); ! 702: c += 0x40; ! 703: } ! 704: putq(&tp->t_oq, c); ! 705: putq(&tp->t_oq, '\n'); ! 706: ttstart(tp); ! 707: } ! 708: return; ! 709: } ! 710: } ! 711: if (ISBBYB) { ! 712: putq(&tp->t_iq, c); ! 713: if ((tp->t_flags&T_INPUT) != 0) { ! 714: tp->t_flags &= ~T_INPUT; ! 715: defer( wakeup, (char *) &tp->t_iq ); ! 716: } ! 717: if ( tp->t_ipolls.e_procp ) { ! 718: tp->t_ipolls.e_procp = 0; ! 719: defer( pollwake, (char *) &tp->t_ipolls ); ! 720: } ! 721: } else { ! 722: if (tp->t_ibx == 0) ! 723: tp->t_opos = tp->t_hpos; ! 724: if (c == ESC) ! 725: ++tp->t_escape; ! 726: else ! 727: ttstash(tp, c); ! 728: } ! 729: if (ISECHO) { ! 730: if (ISRIN || !ISEOF) { ! 731: putq(&tp->t_oq, c); ! 732: ttstart(tp); ! 733: } ! 734: } ! 735: if ((n=tp->t_iq.cq_cc)>=IHILIM) ! 736: tp->t_flags |= T_ISTOP; ! 737: else if (ISTAND && (tp->t_flags&T_TSTOP)==0 && n>=ITSLIM) { ! 738: tp->t_flags |= T_TSTOP; ! 739: putq(&tp->t_oq, stopc); ! 740: ttstart(tp); ! 741: } ! 742: } ! 743: ! 744: /* ! 745: * ttstash() ! 746: * ! 747: * Cooked mode. ! 748: * Put character in the buffer and check for end of line. ! 749: * Only a legal end of line can take the last character position. ! 750: */ ! 751: void ttstash(tp, c) ! 752: register TTY *tp; ! 753: { ! 754: register char *p1, *p2; ! 755: ! 756: if (c=='\n' || ISEOF || ISBRK) { ! 757: p1 = &tp->t_ib[0]; ! 758: p2 = &tp->t_ib[tp->t_ibx]; ! 759: *p2++ = c; /* Always room */ ! 760: while (p1 < p2) ! 761: #if NOT_8_BIT ! 762: putq(&tp->t_iq, (*p1++)&0177); ! 763: #else ! 764: putq(&tp->t_iq, (*p1++)); ! 765: #endif ! 766: tp->t_ibx = 0; ! 767: tp->t_escape = 0; ! 768: ! 769: if ( tp->t_flags & T_INPUT ) { ! 770: tp->t_flags &= ~T_INPUT; ! 771: defer( wakeup, (char *) &tp->t_iq ); ! 772: } ! 773: ! 774: if ( tp->t_ipolls.e_procp ) { ! 775: tp->t_ipolls.e_procp = 0; ! 776: defer( pollwake, (char *) &tp->t_ipolls ); ! 777: } ! 778: ! 779: } else if (tp->t_ibx < NCIB-1) ! 780: tp->t_ib[tp->t_ibx++] = c; ! 781: } ! 782: ! 783: /* ! 784: * ttstart() ! 785: * ! 786: * Start output on a tty. ! 787: * Duck out if stopped. Do wakeups. ! 788: */ ! 789: void ttstart(tp) ! 790: register TTY *tp; ! 791: { ! 792: register int n; ! 793: ! 794: n = tp->t_flags; ! 795: if ( n & T_STOP ) ! 796: return; ! 797: ! 798: if ((n&T_DRAIN)!=0 && tp->t_oq.cq_cc==0 ! 799: && (n&T_INL)==0 && tp->t_nfill==0) ! 800: { tp->t_flags &= ~T_DRAIN; ! 801: defer( wakeup, (char *) &tp->t_oq ); ! 802: return; ! 803: } ! 804: ! 805: NEAR_OR_FAR_CALL(t_start) ! 806: ! 807: if ( tp->t_oq.cq_cc > OLOLIM ) ! 808: return; ! 809: ! 810: if ( n & T_HILIM ) { ! 811: tp->t_flags &= ~T_HILIM; ! 812: defer( wakeup, (char *) &tp->t_oq ); ! 813: } ! 814: ! 815: if ( tp->t_opolls.e_procp ) { ! 816: tp->t_opolls.e_procp = 0; ! 817: defer( pollwake, (char *) &tp->t_opolls ); ! 818: } ! 819: } ! 820: ! 821: /* ! 822: * ttflush() ! 823: * ! 824: * Flush a tty. ! 825: * Called to clear out queues. ! 826: */ ! 827: void ttflush(tp) ! 828: register TTY *tp; ! 829: { ! 830: clrq(&tp->t_iq); ! 831: clrq(&tp->t_oq); ! 832: ! 833: if ( tp->t_flags & T_INPUT ) ! 834: defer( wakeup, (char *) &tp->t_iq ); ! 835: ! 836: if ( tp->t_flags & (T_DRAIN|T_HILIM) ) ! 837: defer( wakeup, (char *) &tp->t_oq ); ! 838: ! 839: if ( tp->t_ipolls.e_procp != 0 ) { ! 840: tp->t_ipolls.e_procp = 0; ! 841: defer( pollwake, (char *) &tp->t_ipolls ); ! 842: } ! 843: ! 844: if ( tp->t_opolls.e_procp != 0 ) { ! 845: tp->t_opolls.e_procp = 0; ! 846: defer( pollwake, (char *) &tp->t_opolls ); ! 847: } ! 848: ! 849: tp->t_ibx = 0; ! 850: tp->t_escape = 0; ! 851: tp->t_flags &= T_SAVE; /* reset most flag bits */ ! 852: } ! 853: ! 854: /* ! 855: * ttsignal() ! 856: * ! 857: * Send a signal to every process in the given process group. ! 858: */ ! 859: void ttsignal(tp, sig) ! 860: TTY *tp; ! 861: int sig; ! 862: { ! 863: register int g; ! 864: register PROC *pp; ! 865: ! 866: g = tp->t_group; ! 867: if (g == 0) ! 868: return; ! 869: ttflush(tp); ! 870: pp = &procq; ! 871: while ((pp=pp->p_nforw) != &procq) ! 872: if (pp->p_group == g) ! 873: sendsig(sig, pp); ! 874: } ! 875: ! 876: /* ! 877: * tthup() ! 878: * ! 879: * Flag hangup internally to force errors on tty read/write, flush tty, ! 880: * then send hangup signal. ! 881: */ ! 882: void tthup(tp) ! 883: register TTY *tp; ! 884: { ! 885: tp->t_flags &= ~T_CARR; /* indicate no carrier */ ! 886: ttflush(tp); ! 887: ttsignal(tp, SIGHUP); ! 888: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.