|
|
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: */ ! 10: ! 11: /* ! 12: * About STOP flag bits: ! 13: * T_ISTOP is set when the tty module's input queue is in danger of ! 14: * overflow. It is up to the device driver to check this flag ! 15: * and do something about it. If ttin() is called with a ! 16: * character from the device while T_ISTOP is set, the character ! 17: * is discarded. T_ISTOP is cleared when the input queue is ! 18: * sufficiently empty. The device driver can monitor this bit for ! 19: * hardware flow control. ! 20: * T_TSTOP is the "Tandem" flow control flag for input. If TANDEM is set ! 21: * and the input queue is in danger of overflow, t_stopc is sent ! 22: * and T_TSTOP is set. When the input queue is empty enough, ! 23: * t_startc is sent and T_TSTOP is cleared. ! 24: * T_STOP is the flow control bit for output. No output will be ! 25: * written to the output queue while this bit is true. ! 26: * Except for initialization of flags in the TTY struct, by ! 27: * ttopen(), this bit is not written by tty.c. ! 28: * 91/09/15 - hal ! 29: */ ! 30: /* ! 31: * About VMIN and VTIME: ! 32: * These parameters only apply when ICANON is zero. ! 33: * If VMIN > 0 and VTIME = 0, block until VMIN characters are received. ! 34: * If VMIN > 0 and VTIME > 0, block until the first character is received, ! 35: * then return after VMIN characters are received or VTIME/10 seconds ! 36: * have elapsed since last character, whichever comes first. ! 37: * If VMIN = 0, return after first character or after VTIME/10 seconds. ! 38: * (may return with read count of zero - but will return one character ! 39: * if it is available, even if VTIME is zero). ! 40: */ ! 41: ! 42: /* ! 43: * Includes. ! 44: */ ! 45: #include <kernel/v_types.h> ! 46: ! 47: #include <sys/coherent.h> ! 48: #include <sys/clist.h> ! 49: #include <sys/con.h> ! 50: #include <sys/deftty.h> ! 51: #include <sys/io.h> ! 52: #include <sys/proc.h> ! 53: #include <sys/sched.h> ! 54: #include <sys/stat.h> ! 55: #include <sys/tty.h> ! 56: #include <sys/errno.h> ! 57: #ifdef _I386 ! 58: #include <termio.h> ! 59: #include <sys/file.h> ! 60: #else ! 61: #define kucopyS(k, u, n) kucopy(k, u, n) ! 62: #define ukcopyS(u, k, n) ukcopy(u, k, n) ! 63: #endif ! 64: ! 65: #ifdef TRACER ! 66: #define DUMPSGTTY(sp) dumpsgtty(sp) ! 67: ! 68: static void dumpsgtty(sp) ! 69: struct sgttyb * sp; ! 70: { ! 71: T_HAL(2, printf("S:%x:%x ", sp->sg_ispeed, sp->sg_flags)); ! 72: } ! 73: #else ! 74: #define DUMPSGTTY(sp) ! 75: #endif ! 76: ! 77: /* ! 78: * Definitions. ! 79: * Constants. ! 80: * Macros with argument lists. ! 81: * Typedefs. ! 82: * Enums. ! 83: */ ! 84: ! 85: #define SGTTY_CPY_LEN (sizeof (struct sgttyb)) ! 86: ! 87: /* NEAR_OR_FAR_CALL is for invoking t_param and t_start */ ! 88: #ifdef _I386 ! 89: #define NEAR_OR_FAR_CALL(tp_fn) { (*tp->tp_fn)(tp); } ! 90: #define SET_HPCL { \ ! 91: if (tp->t_termio.c_cflag & HUPCL) \ ! 92: tp->t_flags |= T_HPCL; \ ! 93: else \ ! 94: tp->t_flags &= ~T_HPCL; } ! 95: #else ! 96: #define NEAR_OR_FAR_CALL(tp_fn) {\ ! 97: if (tp->t_cs_sel) \ ! 98: ld_call(tp->t_cs_sel, tp->tp_fn, tp); \ ! 99: else \ ! 100: (*tp->tp_fn)(tp); } ! 101: #define SET_HPCL ! 102: #endif ! 103: ! 104: /* ! 105: * Functions. ! 106: * Import Functions. ! 107: * Export Functions. ! 108: * Local Functions. ! 109: */ ! 110: void ttclose(); ! 111: void ttflush(); ! 112: void tthup(); ! 113: void ttin(); ! 114: void ttinflush(); ! 115: int ttinp(); ! 116: void ttioctl(); ! 117: void ttopen(); ! 118: int ttout(); ! 119: void ttoutflush(); ! 120: int ttoutp(); ! 121: int ttpoll(); ! 122: void ttread(); ! 123: void ttread0(); ! 124: void ttsetgrp(); ! 125: void ttsignal(); ! 126: void ttstart(); ! 127: void ttwrite(); ! 128: void ttwrite0(); ! 129: ! 130: static void ttstash(); ! 131: static void ttrtp(); ! 132: ! 133: #ifdef _I386 ! 134: static void make_termio(); ! 135: static void make_sg(); ! 136: #else ! 137: #define make_termio(a1,a2,a3) ! 138: #define make_sg(a1,a2,a3) ! 139: #endif ! 140: ! 141: /* ! 142: * Global Data. ! 143: * Import Variables. ! 144: * Export Variables. ! 145: * Local Variables. ! 146: */ ! 147: extern int wakeup(); ! 148: extern void pollwake(); ! 149: ! 150: /* ! 151: * ttopen() ! 152: * ! 153: * Called by driver on first open. ! 154: * Set up defaults. ! 155: */ ! 156: void ! 157: ttopen(tp) ! 158: register TTY *tp; ! 159: { ! 160: tp->t_escape = 0; ! 161: tp->t_sgttyb.sg_ispeed = tp->t_dispeed; ! 162: tp->t_sgttyb.sg_ospeed = tp->t_dospeed; ! 163: tp->t_sgttyb.sg_erase = DEF_SG_ERASE; ! 164: tp->t_sgttyb.sg_kill = DEF_SG_KILL; ! 165: tp->t_sgttyb.sg_flags = DEF_SG_FLAGS; ! 166: tp->t_tchars.t_intrc = DEF_T_INTRC; ! 167: tp->t_tchars.t_quitc = DEF_T_QUITC; ! 168: tp->t_tchars.t_startc = DEF_T_STARTC; ! 169: tp->t_tchars.t_stopc = DEF_T_STOPC; ! 170: tp->t_tchars.t_eofc = DEF_T_EOFC; ! 171: tp->t_tchars.t_brkc = DEF_T_BRKC; ! 172: ! 173: #ifdef _I386 ! 174: tp->t_termio.c_lflag |= ICANON; ! 175: tp->t_termio.c_cc[VEOL] = '\n'; ! 176: tp->t_termio.c_cc[VEOF] = __CTRL ('D'); ! 177: make_termio(&tp->t_sgttyb, &tp->t_tchars, &tp->t_termio); ! 178: if (tp->t_flags & T_HPCL) ! 179: tp->t_termio.c_cflag |= HUPCL; ! 180: else ! 181: tp->t_termio.c_cflag &= ~HUPCL; ! 182: tp->t_termio.c_cflag |= (CS8|CREAD); ! 183: #endif ! 184: ! 185: if (tp->t_param) ! 186: NEAR_OR_FAR_CALL(t_param) ! 187: } ! 188: ! 189: /* ! 190: * ttsetgrp() ! 191: * ! 192: * If process is a group leader without a control terminal, ! 193: * make its control terminal this device. ! 194: * ! 195: * If process is a group leader and this device does not have ! 196: * a process group, give it the group of the current process. ! 197: */ ! 198: void ttsetgrp(tp, ctdev, mode) ! 199: register TTY *tp; ! 200: dev_t ctdev; ! 201: int mode; ! 202: { ! 203: register PROC *pp; ! 204: ! 205: pp = SELF; ! 206: #ifdef _I386 ! 207: if (pp->p_group == pp->p_pid && 0 == (mode & IPNOCTTY)) { ! 208: #else ! 209: if (pp->p_group == pp->p_pid) { ! 210: #endif ! 211: if (pp->p_ttdev == NODEV) ! 212: pp->p_ttdev = ctdev; ! 213: if (tp->t_group == 0) ! 214: tp->t_group = pp->p_pid; ! 215: } ! 216: } ! 217: ! 218: /* ! 219: * ttyclose() ! 220: * ! 221: * Called by driver on the last close. ! 222: * Wait for all pending output to go out. ! 223: * Kill input. ! 224: */ ! 225: void ttclose(tp) ! 226: register TTY *tp; ! 227: { ! 228: register int s; ! 229: ! 230: while (tp->t_oq.cq_cc) { ! 231: s = sphi(); ! 232: if (tp->t_oq.cq_cc) { ! 233: tp->t_flags |= T_DRAIN; ! 234: /* The line discipline is waiting for the tty to drain. */ ! 235: #ifdef _I386 ! 236: if (x_sleep ((char *) & tp->t_oq, pritty, ! 237: slpriSigCatch, "ttydrain") ! 238: == PROCESS_SIGNALLED) { ! 239: #else ! 240: v_sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT, ! 241: "ttydrain"); ! 242: if (nondsig ()) { ! 243: #endif ! 244: spl (s); ! 245: break; ! 246: } ! 247: } ! 248: spl(s); ! 249: } ! 250: ttflush(tp); ! 251: tp->t_flags = tp->t_group = 0; ! 252: } ! 253: ! 254: /* ! 255: * ttread() ! 256: * ! 257: * The read routine for a tty device driver will call this function. ! 258: * ! 259: * Move data from tp->t_iq to io segment iop. ! 260: * Number of characters to copy is in iop->ioc. ! 261: * ! 262: * In cooked mode, copy up to the first newline or break character, or ! 263: * until the count runs out. ! 264: * In CBREAK or RAW modes, return when count runs out or when input clist ! 265: * is empty and we're returning at least one byte. ! 266: */ ! 267: ! 268: void ttread(tp, iop) ! 269: register TTY *tp; ! 270: register IO *iop; ! 271: { ! 272: ttread0(tp, iop, 0, 0, 0, 0); ! 273: } ! 274: ! 275: /* VTIME value is in 10ths of a second */ ! 276: /* VTICKS is number of cpu ticks per VTIME unit */ ! 277: #define VTICKS (HZ/10) ! 278: ! 279: /* ! 280: * ttread0() ! 281: * ! 282: * Move data from user (in IO struct) to clists. ! 283: * Do wakeups on functions supplied when read is blocked or completed. ! 284: */ ! 285: void ttread0(tp, iop, func1, arg1, func2, arg2) ! 286: register TTY *tp; ! 287: register IO *iop; ! 288: int (*func1)(), arg1, (*func2)(), arg2; ! 289: { ! 290: register int c; ! 291: int sioc = iop->io_ioc; /* number of bytes to read */ ! 292: #ifdef _I386 ! 293: int time0 = lbolt; ! 294: int timing = 0; /* a boolean flag */ ! 295: int got_ch = 0; /* a boolean flag */ ! 296: unsigned char vtime = tp->t_termio.c_cc[VTIME]; ! 297: unsigned char vmin = tp->t_termio.c_cc[VMIN]; ! 298: #endif ! 299: ! 300: while (iop->io_ioc) { ! 301: pl_t prev_pl; ! 302: #ifdef _I386 ! 303: /* ! 304: * Start VTIME timer if we got a character or vmin is zero. ! 305: */ ! 306: if (! _IS_CANON_MODE (tp) && vtime) { ! 307: if (got_ch || vmin == 0) { ! 308: timing = 1; ! 309: time0 = lbolt; ! 310: timeout(&tp->t_vtime, vtime*VTICKS, wakeup, ! 311: &tp->t_iq); ! 312: } ! 313: } ! 314: #endif ! 315: ! 316: prev_pl = sphi(); ! 317: while ((c = cltgetq (& tp->t_iq)) < 0) { ! 318: if ((tp->t_flags & T_CARR) == 0) { ! 319: u.u_error = EIO; /* error since no carrier */ ! 320: spl (prev_pl); ! 321: goto read_done; ! 322: } ! 323: ! 324: #ifdef _I386 ! 325: /* ! 326: * [T_BRD handling in COH 286 is replaced by ! 327: * VMIN/VTIME handling in COH 386.] ! 328: * ! 329: * If vmin is nonzero, and at least vmin characters ! 330: * have been received, return. ! 331: * ! 332: * If vmin is zero and vtime is zero, return ! 333: * whether characters have been received or not. ! 334: * ! 335: * If vmin is zero, and we got a char, return. ! 336: * ! 337: * If vtime is nonzero, and vtime 10th seconds have ! 338: * elapsed, return. ! 339: * ! 340: * Otherwise, go to sleep until more input arrives. ! 341: */ ! 342: if (! _IS_CANON_MODE (tp)) { ! 343: if (vmin) { ! 344: /* received vmin or more characters? */ ! 345: if ((sioc - iop->io_ioc) >= vmin) { ! 346: spl (prev_pl); ! 347: goto read_done; ! 348: } ! 349: } else { ! 350: if (got_ch || vtime == 0) { ! 351: spl (prev_pl); ! 352: goto read_done; ! 353: } ! 354: } ! 355: } ! 356: if (timing && ((lbolt - time0)/VTICKS) >= vtime) { ! 357: spl (prev_pl); ! 358: goto read_done; ! 359: } ! 360: #else ! 361: /* If we're in CBREAK or RAW mode, and we don't */ ! 362: /* have the special "blocking read" bit set for */ ! 363: /* these modes, and we read at least one byte */ ! 364: /* of input, return immediately, since we have */ ! 365: /* run out of characters from the clist. */ ! 366: ! 367: if (! _IS_CANON_MODE (tp) && ! 368: (tp->t_flags & T_BRD) == 0 && ! 369: iop->io_ioc < sioc) { ! 370: spl (prev_pl); ! 371: goto read_done; ! 372: } ! 373: #endif ! 374: /* ! 375: * Non-blocking reads. ! 376: * Tell user process to try again later. ! 377: * How do we tell if we are a terminal or not? Check ! 378: * to see if we have a process group, for now. ! 379: */ ! 380: if (iop->io_flag & (IONDLY | IONONBLOCK)) { ! 381: if (tp->t_group == 0 || ! 382: (iop->io_flag & IONONBLOCK) != 0) ! 383: u.u_error = EAGAIN; ! 384: spl (prev_pl); ! 385: goto read_done; ! 386: } ! 387: ! 388: tp->t_flags |= T_INPUT; /* wait for more data */ ! 389: if (func1) ! 390: (*func1)(arg1); ! 391: if (func2) ! 392: (*func2)(arg2); ! 393: /* The line discipline is waiting for more data. */ ! 394: #ifdef _I386 ! 395: if (x_sleep ((char *) & tp->t_iq, pritty, ! 396: slpriSigLjmp, "ttywait") ! 397: == PROCESS_SIGNALLED) { ! 398: #else ! 399: v_sleep((char *)&tp->t_iq, CVTTIN, IVTTIN, SVTTIN, ! 400: "ttywait"); ! 401: if (nondsig ()) { ! 402: #endif ! 403: if (iop->io_ioc == sioc) ! 404: u.u_error = EINTR; ! 405: spl (prev_pl); ! 406: goto read_done; ! 407: } ! 408: } ! 409: ! 410: /* Got a character "c" from the input queue. */ ! 411: got_ch = 1; ! 412: ! 413: /* ! 414: * Flow control - can we turn on input from the driver yet? ! 415: */ ! 416: if (tp->t_iq.cq_cc <= ILOLIM) { ! 417: if (tp->t_flags & T_ISTOP) ! 418: tp->t_flags &= ~ T_ISTOP; ! 419: if (_IS_TANDEM_MODE (tp) && ! 420: (tp->t_flags & T_TSTOP) != 0) { ! 421: tp->t_flags &= ~ T_TSTOP; ! 422: while (cltputq (& tp->t_oq, ! 423: tp->t_tchars.t_startc) < 0) { ! 424: ttstart (tp); ! 425: waitq (); ! 426: } ! 427: ttstart (tp); ! 428: } ! 429: } ! 430: spl (prev_pl); ! 431: if (_IS_CANON_MODE (tp) && _IS_EOF_CHAR (tp, c)) ! 432: goto read_done; ! 433: if (ioputc (c, iop) < 0) ! 434: goto read_done; ! 435: if (_IS_CANON_MODE (tp) && ! 436: (c == '\n' || _IS_BREAK_CHAR (tp, c))) ! 437: goto read_done; ! 438: #ifdef _I386 ! 439: if (! _IS_CANON_MODE (tp) && vtime) ! 440: timing = 1; ! 441: #endif ! 442: } ! 443: ! 444: read_done: ! 445: ! 446: #ifdef _I386 ! 447: if (timing) /* turn off the VTIME timer */ ! 448: timeout(&tp->t_vtime, 0, 0, 0); ! 449: #endif ! 450: ! 451: if (func1) ! 452: (*func1)(arg1); ! 453: if (func2) ! 454: (*func2)(arg2); ! 455: return; ! 456: } ! 457: ! 458: /* ! 459: * ttwrite() ! 460: * ! 461: * Write routine. ! 462: */ ! 463: void ! 464: ttwrite(tp, iop) ! 465: register TTY *tp; ! 466: register IO *iop; ! 467: { ! 468: ttwrite0(tp, iop, 0, 0, 0, 0); ! 469: } ! 470: ! 471: /* ! 472: * ttwrite0() ! 473: * ! 474: * Move data from user (in IO struct) to clists. ! 475: * Do wakeups on functions supplied when write is blocked or completed. ! 476: */ ! 477: void ! 478: ttwrite0(tp, iop, func1, arg1, func2, arg2) ! 479: register TTY *tp; ! 480: register IO *iop; ! 481: int (*func1)(), arg1, (*func2)(), arg2; ! 482: { ! 483: register int c; ! 484: ! 485: /* ! 486: * Non-blocking writes which can fit. ! 487: * NOTE: exhaustion of clists can still cause blocking writes. ! 488: */ ! 489: if ((iop->io_flag & (IONDLY | IONONBLOCK)) && ! 490: (OHILIM >= iop->io_ioc)) { ! 491: ! 492: /* ! 493: * No room. ! 494: */ ! 495: if (tp->t_oq.cq_cc >= OHILIM-iop->io_ioc) { ! 496: u.u_error = EAGAIN; ! 497: return; ! 498: } ! 499: } ! 500: ! 501: while ((c = iogetc(iop)) >= 0) { ! 502: pl_t prev_pl; ! 503: ! 504: if ((tp->t_flags & T_CARR) == 0) { ! 505: u.u_error = EIO; /* error since no carrier */ ! 506: return; ! 507: } ! 508: ! 509: prev_pl = sphi(); ! 510: ! 511: while (tp->t_oq.cq_cc >= OHILIM) { ! 512: ttstart (tp); ! 513: if (tp->t_oq.cq_cc < OHILIM) ! 514: break; ! 515: tp->t_flags |= T_HILIM; ! 516: if (func1) ! 517: (*func1)(arg1); ! 518: if (func2) ! 519: (*func2)(arg2); ! 520: /* ! 521: * The line discipline is waiting for an output ! 522: * queue to drain. ! 523: */ ! 524: #ifdef _I386 ! 525: if (x_sleep ((char *) & tp->t_oq, pritty, ! 526: slpriSigCatch, "ttyoq") ! 527: == PROCESS_SIGNALLED) { ! 528: #else ! 529: v_sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT, ! 530: "ttyoq"); ! 531: if (nondsig ()) { ! 532: #endif ! 533: u.u_error = EINTR; ! 534: spl (prev_pl); ! 535: return; ! 536: } ! 537: } ! 538: while (cltputq (& tp->t_oq, c) < 0) { ! 539: ttstart (tp); ! 540: waitq (); ! 541: } ! 542: spl (prev_pl); ! 543: } ! 544: ! 545: ttstart (tp); ! 546: ! 547: if (func1) ! 548: (*func1)(arg1); ! 549: if (func2) ! 550: (*func2)(arg2); ! 551: } ! 552: ! 553: /* ! 554: * ttioctl() ! 555: * ! 556: * This routine handles common typewriter ioctl functions. ! 557: * Note that flushing the stream now means drain the output ! 558: * and clear the input. ! 559: */ ! 560: void ! 561: ttioctl(tp, com, vec) ! 562: register TTY *tp; ! 563: int com; ! 564: register struct sgttyb *vec; ! 565: { ! 566: register int outDrain = 0; ! 567: int rload = 0; ! 568: int was_bbyb; ! 569: int inFlush = 0, outFlush = 0; ! 570: pl_t prev_pl; ! 571: ! 572: /* ! 573: * Keep sgttyb, t_chars, AND termio structs for each tty device. ! 574: * ! 575: * TCSET* writes a new termio and converts so as to update ! 576: * sgttyb and t_chars as well. ! 577: * ! 578: * TIOCSET[NP] writes new sgttyb and converts so as to update termio. ! 579: * ! 580: * TIOCSETC writes new t_chars and converts so as to update termio. ! 581: */ ! 582: switch (com) { ! 583: #if _I386 ! 584: case TCGETA: ! 585: if (! kucopyS (& tp->t_termio, vec, sizeof (struct termio))) ! 586: return; ! 587: break; ! 588: ! 589: case TCSETA: ! 590: was_bbyb = ! _IS_CANON_MODE (tp); /* previous mode */ ! 591: if (! ukcopyS (vec, & tp->t_termio, sizeof (struct termio))) ! 592: return; ! 593: make_sg (vec, & tp->t_sgttyb, & tp->t_tchars); ! 594: SET_HPCL; ! 595: ++ rload; ! 596: if (! was_bbyb && ! _IS_CANON_MODE (tp)) ! 597: ttrtp (tp); ! 598: break; ! 599: ! 600: case TCSETAW: ! 601: was_bbyb = ! _IS_CANON_MODE (tp); /* previous mode */ ! 602: if (! ukcopyS (vec, & tp->t_termio, sizeof (struct termio))) ! 603: return; ! 604: make_sg (vec, & tp->t_sgttyb, & tp->t_tchars); ! 605: SET_HPCL; ! 606: ++ outDrain; /* delay for output */ ! 607: ++ rload; ! 608: if (! was_bbyb && ! _IS_CANON_MODE (tp)) ! 609: ttrtp (tp); ! 610: break; ! 611: ! 612: case TCSETAF: ! 613: if (! ukcopyS (vec, & tp->t_termio, sizeof (struct termio))) ! 614: return; ! 615: make_sg (vec, & tp->t_sgttyb, & tp->t_tchars); ! 616: SET_HPCL; ! 617: ++ inFlush; /* flush input */ ! 618: ++ outDrain; /* delay for output */ ! 619: ++ rload; ! 620: break; ! 621: #endif ! 622: ! 623: case TIOCQUERY: ! 624: kucopyS (& tp->t_iq.cq_cc, vec, sizeof (int)); ! 625: break; ! 626: ! 627: case TIOCGETP: ! 628: /* ! 629: * The addressability checking for this is carried out at ! 630: * a higher level in order to support i286 Coherent binaries. ! 631: */ ! 632: kucopy (& tp->t_sgttyb, vec, SGTTY_CPY_LEN); ! 633: break; ! 634: ! 635: case TIOCSETP: ! 636: DUMPSGTTY (& tp->t_sgttyb); ! 637: ++ inFlush; /* flush input */ ! 638: ++ outDrain; /* delay for output */ ! 639: ++ rload; ! 640: ! 641: /* ! 642: * The addressability checking for this is carried out at ! 643: * a higher level in order to support i286 Coherent binaries. ! 644: */ ! 645: ! 646: ukcopy (vec, & tp->t_sgttyb, SGTTY_CPY_LEN); ! 647: make_termio (& tp->t_sgttyb, & tp->t_tchars, & tp->t_termio); ! 648: break; ! 649: ! 650: case TIOCSETN: ! 651: was_bbyb = ! _IS_CANON_MODE (tp); /* previous mode */ ! 652: DUMPSGTTY (& tp->t_sgttyb); ! 653: ++ rload; ! 654: ! 655: /* ! 656: * The addressability checking for this is carried out at ! 657: * a higher level in order to support i286 Coherent binaries. ! 658: */ ! 659: ! 660: ukcopy(vec, & tp->t_sgttyb, SGTTY_CPY_LEN); ! 661: make_termio (& tp->t_sgttyb, & tp->t_tchars, & tp->t_termio); ! 662: ! 663: if (! was_bbyb && ! _IS_CANON_MODE (tp)) ! 664: ttrtp (tp); ! 665: break; ! 666: ! 667: case TIOCGETC: ! 668: kucopyS (& tp->t_tchars, vec, sizeof (struct tchars)); ! 669: break; ! 670: ! 671: case TIOCSETC: ! 672: ++ rload; ! 673: ++ outDrain; ! 674: if (! ukcopyS (vec, & tp->t_tchars, sizeof (struct tchars))) ! 675: return; ! 676: make_termio (& tp->t_sgttyb, & tp->t_tchars, & tp->t_termio); ! 677: break; ! 678: ! 679: case TIOCEXCL: ! 680: prev_pl = sphi (); ! 681: tp->t_flags |= T_EXCL; ! 682: spl (prev_pl); ! 683: break; ! 684: ! 685: case TIOCNXCL: ! 686: prev_pl = sphi (); ! 687: tp->t_flags &= ~T_EXCL; ! 688: spl (prev_pl); ! 689: break; ! 690: ! 691: case TIOCHPCL: /* set hangup on last close */ ! 692: prev_pl = sphi (); ! 693: tp->t_flags |= T_HPCL; ! 694: spl (prev_pl); ! 695: #ifdef _I386 ! 696: tp->t_termio.c_cflag |= HUPCL; ! 697: #endif ! 698: break; ! 699: ! 700: case TIOCCHPCL: /* don't hangup on last close */ ! 701: if (! super ()) /* only superuser may do this */ ! 702: u.u_error = EPERM; /* not su */ ! 703: else { ! 704: prev_pl = sphi (); ! 705: tp->t_flags &= ~T_HPCL; /* turn off hangup bit */ ! 706: spl (prev_pl); ! 707: #ifdef _I386 ! 708: tp->t_termio.c_cflag &= ~HUPCL; ! 709: #endif ! 710: } ! 711: break; ! 712: ! 713: case TIOCGETTF: /* get tty flag word */ ! 714: kucopyS (& tp->t_flags, (unsigned *) vec, sizeof (unsigned)); ! 715: break; ! 716: ! 717: #ifdef _I386 ! 718: case TCFLSH: ! 719: switch ((int) vec) { ! 720: case 0: inFlush ++; break; ! 721: case 1: outFlush ++; break; ! 722: case 2: inFlush ++; outFlush ++; break; ! 723: default: u.u_error = EINVAL; ! 724: } ! 725: break; ! 726: ! 727: case TCSBRK: ! 728: ++ outDrain; ! 729: break; ! 730: ! 731: #endif ! 732: case TIOCFLUSH: ! 733: ++ inFlush; /* flush both input and output */ ! 734: ++ outFlush; ! 735: /* ++ outDrain; Why? - hws - 91/11/22 */ ! 736: break; ! 737: ! 738: #ifndef _I386 ! 739: case TIOCBREAD: /* blocking read for CBREAK/RAW mode */ ! 740: prev_pl = sphi (); ! 741: tp->t_flags |= T_BRD; ! 742: spl (prev_pl); ! 743: break; ! 744: ! 745: case TIOCCBREAD: /* turn off CBREAK/RAW blocking read mode */ ! 746: prev_pl = sphi (); ! 747: tp->t_flags &= ~ T_BRD; ! 748: spl (prev_pl); ! 749: break; ! 750: #endif ! 751: /* ! 752: * The following is a hack so that the process group for /dev/console ! 753: * contains the current login shell running on it. ! 754: * Only expect /etc/init to use this ugliness. ! 755: */ ! 756: case TIOCSETG: ! 757: if (super ()) ! 758: tp->t_group = SELF->p_group; ! 759: break; ! 760: default: ! 761: u.u_error = EINVAL; ! 762: } ! 763: ! 764: /* ! 765: * T_STOP is set under two conditions: ! 766: * - a modem control device is awaiting carrier ! 767: * - a stopc (usually Ctrl-S) character was received. ! 768: * ! 769: * If ioctl just put device into RAWIN mode, make sure device ! 770: * is not still waiting for startc. ! 771: */ ! 772: #if _I386 ! 773: /* Is XON/XOFF flow control off *and* we are waiting for startc? */ ! 774: if (! _IS_IXON_MODE (tp) && (tp->t_flags & T_XSTOP) != 0) { ! 775: prev_pl = sphi (); ! 776: tp->t_flags &= ~ (T_STOP | T_XSTOP); ! 777: spl (prev_pl); ! 778: ! 779: ttstart (tp); ! 780: } ! 781: #else ! 782: if (! _IS_IXON_MODE (tp)) && (tp->t_flags & T_STOP) != 0 && ! 783: (tp->t_flags & T_HOPEN) == 0) { ! 784: prev_pl = sphi (); ! 785: tp->t_flags &= ~ T_STOP; ! 786: spl (prev_pl); ! 787: ! 788: ttstart (tp); ! 789: } ! 790: #endif ! 791: ! 792: /* ! 793: * Wait for output to drain, or signal to arrive. ! 794: * ! 795: * NOTE: This stuff is properly done within the device driver, ! 796: * *before* ttioctl() is called. This paragraph should disappear ! 797: * from tty.c, with maybe an entry point added for the driver to ! 798: * drain the queue while draining the peripheral device. -hws- ! 799: */ ! 800: ! 801: if (outDrain) { ! 802: while (tp->t_oq.cq_cc) { ! 803: prev_pl = sphi (); ! 804: tp->t_flags |= T_DRAIN; ! 805: spl (prev_pl); ! 806: /* A TIOC has asked for tty output to drain. */ ! 807: #ifdef _I386 ! 808: if (x_sleep ((char *) & tp->t_oq, pritty, ! 809: slpriSigCatch, "ttyiodrn") ! 810: == PROCESS_SIGNALLED) { ! 811: #else ! 812: v_sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT, ! 813: "ttyiodrn"); ! 814: if (nondsig ()) { ! 815: #endif ! 816: break; ! 817: } ! 818: } ! 819: } ! 820: ! 821: /* ! 822: * Flush. ! 823: */ ! 824: if (inFlush) ! 825: ttinflush(tp); ! 826: if (outFlush) ! 827: ttoutflush(tp); ! 828: ! 829: /* ! 830: * Re-initialize hardware. ! 831: */ ! 832: if (rload) { ! 833: if (tp->t_param) ! 834: NEAR_OR_FAR_CALL(t_param) ! 835: } ! 836: } ! 837: ! 838: /* ! 839: * ttpoll() ! 840: * ! 841: * Polling routine. ! 842: * [System V.3 Compatible] ! 843: */ ! 844: int ttpoll(tp, ev, msec) ! 845: register TTY * tp; ! 846: int ev; ! 847: int msec; ! 848: { ! 849: /* ! 850: * Priority polls not supported. ! 851: */ ! 852: ev &= ~POLLPRI; ! 853: ! 854: /* ! 855: * Input poll with no data present. ! 856: */ ! 857: if ((ev & POLLIN) && (tp->t_iq.cq_cc == 0)) { ! 858: ! 859: /* ! 860: * Blocking input poll. ! 861: */ ! 862: if (msec) ! 863: pollopen(&tp->t_ipolls); ! 864: ! 865: /* ! 866: * Second look to avoid interrupt race. ! 867: */ ! 868: if (tp->t_iq.cq_cc == 0) ! 869: ev &= ~POLLIN; ! 870: } ! 871: ! 872: /* ! 873: * Output poll with no space. ! 874: */ ! 875: if ((ev & POLLOUT) && (tp->t_oq.cq_cc >= OLOLIM)) { ! 876: ! 877: /* ! 878: * Blocking output poll. ! 879: */ ! 880: if (msec) ! 881: pollopen(&tp->t_opolls); ! 882: ! 883: /* ! 884: * Second look to avoid interrupt race. ! 885: */ ! 886: if (tp->t_oq.cq_cc >= OLOLIM) ! 887: ev &= ~POLLOUT; ! 888: } ! 889: ! 890: if (((ev & POLLIN) == 0) && ((tp->t_flags & T_CARR) == 0)) ! 891: ev |= POLLHUP; ! 892: ! 893: return ev; ! 894: } ! 895: ! 896: /* ! 897: * ttout() ! 898: * ! 899: * Pull a character from the output queues of the typewriter. ! 900: * Doing fills, newline insert, tab expansion, etc. ! 901: * ! 902: * If the stream is empty return a -1. ! 903: * Called at high priority. ! 904: */ ! 905: int ttout(tp) ! 906: register TTY *tp; ! 907: { ! 908: register int c; ! 909: ! 910: if (tp->t_nfill) { ! 911: --tp->t_nfill; ! 912: c = tp->t_fillb; ! 913: } else if (tp->t_flags & T_INL) { ! 914: tp->t_flags &= ~T_INL; ! 915: c = '\n'; ! 916: } else { ! 917: if ((c=cltgetq(&tp->t_oq)) < 0) ! 918: return -1; ! 919: if (! _IS_RAW_OUT_MODE (tp)) { ! 920: if (c == '\n' && _IS_ONLCR_MODE (tp)) { ! 921: tp->t_flags |= T_INL; ! 922: c = '\r'; ! 923: } else if (c == '\r' && _IS_OCRNL_MODE (tp)) { ! 924: c = '\n'; ! 925: } else if (c == '\t' && _IS_XTABS_MODE (tp)) { ! 926: tp->t_nfill = ~ (tp->t_hpos | ~ 7); ! 927: tp->t_fillb = ' '; ! 928: c = ' '; ! 929: } ! 930: } ! 931: } ! 932: if (! _IS_RAW_OUT_MODE (tp)) { ! 933: if (c == '\b') { ! 934: if (tp->t_hpos) ! 935: -- tp->t_hpos; ! 936: } else if (c == '\r') ! 937: tp->t_hpos = 0; ! 938: else if (c == '\t') ! 939: tp->t_hpos = (tp->t_hpos | 7) + 1; ! 940: #if NOT_8_BIT ! 941: else if (c >= ' ' && c <= '~') ! 942: #else ! 943: else if ((c >= ' ' && c <= '~') || (c >= 0200 && c <= 0376)) ! 944: #endif ! 945: ++ tp->t_hpos; ! 946: } ! 947: return c; ! 948: } ! 949: ! 950: /* ! 951: * ttin() ! 952: * ! 953: * Pass a character to the device independent typewriter routines. ! 954: * Handle erase and kill, tandem flow control, and other magic. ! 955: * Often called at high priority from the driver's interrupt routine. ! 956: */ ! 957: void ! 958: ttin(tp, c) ! 959: register TTY *tp; ! 960: register int c; ! 961: { ! 962: int dc, i, n; ! 963: pl_t prev_pl; ! 964: ! 965: if (_IS_ISTRIP_MODE (tp)) ! 966: c &= 0x7F; ! 967: ! 968: if (_IS_ISIG_MODE (tp) && _IS_QUIT_CHAR (tp, c)) { ! 969: ttsignal (tp, SIGQUIT); ! 970: goto ttin_ret; ! 971: } ! 972: ! 973: if (_IS_ISIG_MODE (tp) && _IS_INTERRUPT_CHAR (tp, c)) { ! 974: ttsignal (tp, SIGINT); ! 975: goto ttin_ret; ! 976: } ! 977: ! 978: if (tp->t_flags & T_ISTOP) ! 979: goto ttin_ret; ! 980: ! 981: if (_IS_ICRNL_MODE (tp) && ! _IS_IGNCR_MODE (tp)) { ! 982: if (c == '\r') ! 983: c = '\n'; ! 984: } ! 985: ! 986: if (! _IS_RAW_INPUT_MODE (tp)) { ! 987: if (tp->t_escape) { ! 988: if (c == ESC) ! 989: ++ tp->t_escape; ! 990: else { ! 991: if (_IS_ERASE_CHAR (tp, c) || ! 992: _IS_KILL_CHAR (tp, c)) { ! 993: c |= 0x80; ! 994: -- tp->t_escape; ! 995: } ! 996: while (tp->t_escape && tp->t_ibx < NCIB - 1) { ! 997: tp->t_ib [tp->t_ibx ++] = ESC; ! 998: -- tp->t_escape; ! 999: } ! 1000: ttstash (tp, c); ! 1001: } ! 1002: if (_IS_ECHO_MODE (tp)) { ! 1003: #if NOT_8_BIT ! 1004: cltputq (& tp->t_oq, c & 0x7F); ! 1005: #else ! 1006: cltputq (& tp->t_oq, c); /* no strip for 8-bit */ ! 1007: #endif ! 1008: ttstart (tp); ! 1009: } ! 1010: goto ttin_ret; ! 1011: } ! 1012: if (_IS_ERASE_CHAR (tp, c) && _IS_CANON_MODE (tp)) { ! 1013: while (tp->t_escape && tp->t_ibx < NCIB - 1) { ! 1014: tp->t_ib [tp->t_ibx ++] = ESC; ! 1015: -- tp->t_escape; ! 1016: } ! 1017: if (tp->t_ibx == 0) ! 1018: goto ttin_ret; ! 1019: dc = tp->t_ib [-- tp->t_ibx]; ! 1020: if (_IS_ECHO_MODE (tp)) { ! 1021: if (! _IS_CRT_MODE (tp)) ! 1022: cltputq (& tp->t_oq, c); ! 1023: /* don't erase for bell, null, or rubout */ ! 1024: #if NOT_8_BIT ! 1025: else if ((c = dc & 0x7F) == '\a' || c == 0 || ! 1026: c == 0x7F) ! 1027: #else ! 1028: else if ((c = dc) == '\a' || c == 0 || ! 1029: c == 0x7F || c == 0xFF) ! 1030: #endif ! 1031: goto ttin_ret; ! 1032: else if (c != '\b' && c != '\t') { ! 1033: cltputq (& tp->t_oq, '\b'); ! 1034: cltputq (& tp->t_oq, ' '); ! 1035: cltputq (& tp->t_oq, '\b'); ! 1036: } else if (c == '\t') { ! 1037: n = tp->t_opos + tp->t_escape; ! 1038: for (i = 0 ; i < tp->t_ibx ; ++ i) { ! 1039: c = tp->t_ib [i]; ! 1040: #if NOT_8_BIT ! 1041: if (c & 0x80) { ! 1042: ++ n; ! 1043: c &= 0x7F; ! 1044: } ! 1045: #endif ! 1046: if (c == '\b') ! 1047: -- n; ! 1048: else { ! 1049: if (c == '\t') ! 1050: n |= 07; ! 1051: ++ n; ! 1052: } ! 1053: } ! 1054: while (n ++ < tp->t_hpos) ! 1055: cltputq (& tp->t_oq, '\b'); ! 1056: } ! 1057: #if NOT_8_BIT ! 1058: if (dc & 0x80) { ! 1059: if ((dc & 0x7F) != '\b') ! 1060: cltputq (& tp->t_oq, '\b'); ! 1061: cltputq (& tp->t_oq, ' '); ! 1062: cltputq (& tp->t_oq, '\b'); ! 1063: } ! 1064: #endif ! 1065: ttstart (tp); ! 1066: } ! 1067: goto ttin_ret; ! 1068: } ! 1069: if (_IS_KILL_CHAR (tp, c) && _IS_CANON_MODE (tp)) { ! 1070: tp->t_ibx = 0; ! 1071: tp->t_escape = 0; ! 1072: if (_IS_ECHO_MODE (tp)) { ! 1073: if (c < 0x20) { ! 1074: cltputq (& tp->t_oq, '^'); ! 1075: c += 0x40; ! 1076: } ! 1077: cltputq (& tp->t_oq, c); ! 1078: cltputq (& tp->t_oq, '\n'); ! 1079: ttstart (tp); ! 1080: } ! 1081: goto ttin_ret; ! 1082: } ! 1083: } ! 1084: if (! _IS_CANON_MODE (tp)) { ! 1085: cltputq (& tp->t_iq, c); ! 1086: if (tp->t_flags & T_INPUT) { ! 1087: prev_pl = sphi (); ! 1088: tp->t_flags &= ~T_INPUT; ! 1089: spl (prev_pl); ! 1090: wakeup (& tp->t_iq); ! 1091: } ! 1092: if (tp->t_ipolls.e_procp) { ! 1093: tp->t_ipolls.e_procp = 0; ! 1094: pollwake ((char *) & tp->t_ipolls); ! 1095: } ! 1096: } else { ! 1097: if (tp->t_ibx == 0) ! 1098: tp->t_opos = tp->t_hpos; ! 1099: if (c == ESC) ! 1100: ++ tp->t_escape; ! 1101: else ! 1102: ttstash(tp, c); ! 1103: } ! 1104: if (_IS_ECHO_MODE (tp)) { ! 1105: if (_IS_RAW_INPUT_MODE (tp) || ! _IS_EOF_CHAR (tp, c)) { ! 1106: cltputq (& tp->t_oq, c); ! 1107: ttstart (tp); ! 1108: } ! 1109: } ! 1110: if ((n = tp->t_iq.cq_cc) >= IHILIM) { ! 1111: prev_pl = sphi (); ! 1112: tp->t_flags |= T_ISTOP; ! 1113: spl (prev_pl); ! 1114: } else if (_IS_TANDEM_MODE (tp) && (tp->t_flags & T_TSTOP)==0 && ! 1115: n >= ITSLIM) { ! 1116: prev_pl = sphi (); ! 1117: tp->t_flags |= T_TSTOP; ! 1118: spl (prev_pl); ! 1119: cltputq (& tp->t_oq, tp->t_tchars.t_stopc); ! 1120: ttstart (tp); ! 1121: } ! 1122: ! 1123: ttin_ret: ! 1124: return; ! 1125: } ! 1126: ! 1127: /* ! 1128: * ttstash() ! 1129: * ! 1130: * Cooked mode. ! 1131: * Put character in the buffer and check for end of line. ! 1132: * Only a legal end of line can take the last character position. ! 1133: * ! 1134: * Only called from ttin(), and ttin() is called at high priority. ! 1135: */ ! 1136: static void ttstash(tp, c) ! 1137: register TTY *tp; ! 1138: { ! 1139: register char *p1, *p2; ! 1140: ! 1141: if (c == '\n' || _IS_EOF_CHAR (tp, c) || _IS_BREAK_CHAR (tp, c)) { ! 1142: p1 = & tp->t_ib [0]; ! 1143: p2 = & tp->t_ib [tp->t_ibx]; ! 1144: * p2 ++ = c; /* Always room */ ! 1145: while (p1 < p2) ! 1146: #if NOT_8_BIT ! 1147: cltputq (& tp->t_iq, (* p1 ++) & 0x7F); ! 1148: #else ! 1149: cltputq (& tp->t_iq, (* p1 ++)); ! 1150: #endif ! 1151: tp->t_ibx = 0; ! 1152: tp->t_escape = 0; ! 1153: ! 1154: if (tp->t_flags & T_INPUT) { ! 1155: tp->t_flags &= ~ T_INPUT; ! 1156: wakeup (& tp->t_iq); ! 1157: } ! 1158: ! 1159: if (tp->t_ipolls.e_procp) { ! 1160: tp->t_ipolls.e_procp = 0; ! 1161: pollwake ((char *) & tp->t_ipolls); ! 1162: } ! 1163: ! 1164: } else if (tp->t_ibx < NCIB - 1) ! 1165: tp->t_ib [tp->t_ibx ++] = c; ! 1166: } ! 1167: ! 1168: /* ! 1169: * ttstart() ! 1170: * ! 1171: * Start output on a tty. ! 1172: * Duck out if stopped. Do wakeups. ! 1173: */ ! 1174: void ttstart(tp) ! 1175: register TTY *tp; ! 1176: { ! 1177: register int n; ! 1178: pl_t prev_pl; ! 1179: ! 1180: n = tp->t_flags; ! 1181: if (n & T_STOP) ! 1182: goto stdone; ! 1183: ! 1184: if ((n & T_DRAIN) != 0 && tp->t_oq.cq_cc == 0 && (n & T_INL) == 0 && ! 1185: tp->t_nfill == 0) { ! 1186: prev_pl = sphi (); ! 1187: tp->t_flags &= ~ T_DRAIN; ! 1188: spl (prev_pl); ! 1189: wakeup (& tp->t_oq); ! 1190: goto stdone; ! 1191: } ! 1192: ! 1193: NEAR_OR_FAR_CALL(t_start) ! 1194: ! 1195: if (tp->t_oq.cq_cc > OLOLIM) ! 1196: goto stdone; ! 1197: ! 1198: if (n & T_HILIM) { ! 1199: prev_pl = sphi (); ! 1200: tp->t_flags &= ~ T_HILIM; ! 1201: spl (prev_pl); ! 1202: wakeup (& tp->t_oq); ! 1203: } ! 1204: ! 1205: if (tp->t_opolls.e_procp) { ! 1206: tp->t_opolls.e_procp = 0; ! 1207: pollwake ((char *) & tp->t_opolls); ! 1208: } ! 1209: stdone: ! 1210: return; ! 1211: } ! 1212: ! 1213: /* ! 1214: * ttflush() ! 1215: * ! 1216: * Flush tty input and output queues. ! 1217: */ ! 1218: void ! 1219: ttflush(tp) ! 1220: register TTY *tp; ! 1221: { ! 1222: ttinflush (tp); ! 1223: ttoutflush (tp); ! 1224: } ! 1225: ! 1226: /* ! 1227: * ttinflush() ! 1228: * ! 1229: * Flush input queues. ! 1230: */ ! 1231: void ! 1232: ttinflush(tp) ! 1233: register TTY *tp; ! 1234: { ! 1235: clrq (& tp->t_iq); ! 1236: ! 1237: if (tp->t_flags & T_INPUT) { ! 1238: wakeup (& tp->t_iq); ! 1239: } ! 1240: ! 1241: if (tp->t_ipolls.e_procp) { ! 1242: tp->t_ipolls.e_procp = 0; ! 1243: pollwake ((char *) & tp->t_ipolls); ! 1244: } ! 1245: ! 1246: tp->t_ibx = 0; ! 1247: tp->t_escape = 0; ! 1248: } ! 1249: ! 1250: /* ! 1251: * ttoutflush() ! 1252: * ! 1253: * Flush tty output queues. ! 1254: */ ! 1255: void ! 1256: ttoutflush(tp) ! 1257: register TTY *tp; ! 1258: { ! 1259: clrq(&tp->t_oq); ! 1260: ! 1261: if (tp->t_flags & (T_DRAIN | T_HILIM)) { ! 1262: wakeup (& tp->t_oq); ! 1263: } ! 1264: ! 1265: if (tp->t_opolls.e_procp) { ! 1266: tp->t_opolls.e_procp = 0; ! 1267: pollwake ((char *) & tp->t_opolls); ! 1268: } ! 1269: } ! 1270: ! 1271: /* ! 1272: * ttsignal() ! 1273: * ! 1274: * Send a signal to every process in the given process group. ! 1275: */ ! 1276: void ! 1277: ttsignal(tp, sig) ! 1278: TTY *tp; ! 1279: int sig; ! 1280: { ! 1281: register int g; ! 1282: register PROC *pp; ! 1283: ! 1284: g = tp->t_group; ! 1285: if (g == 0) ! 1286: goto sigdone; ! 1287: ttflush(tp); ! 1288: pp = & procq; ! 1289: while ((pp = pp->p_nforw) != & procq) { ! 1290: if (pp->p_group == g) ! 1291: sendsig(sig, pp); ! 1292: } ! 1293: sigdone: ! 1294: return; ! 1295: } ! 1296: ! 1297: /* ! 1298: * tthup() ! 1299: * ! 1300: * Flag hangup internally to force errors on tty read/write, flush tty, ! 1301: * then send hangup signal. ! 1302: */ ! 1303: void tthup(tp) ! 1304: register TTY *tp; ! 1305: { ! 1306: ttflush (tp); ! 1307: ttsignal (tp, SIGHUP); ! 1308: } ! 1309: ! 1310: #if _I386 ! 1311: /* ! 1312: * Convert from sgttyb and tchars structs to termio. ! 1313: */ ! 1314: static void ! 1315: make_termio(sgp, tcp, trp) ! 1316: struct sgttyb * sgp; ! 1317: struct tchars * tcp; ! 1318: struct termio * trp; ! 1319: { ! 1320: char vmin = 1, vtime = 0; ! 1321: char veof = 4, veol = 10; /* default to ^D, ^J */ ! 1322: ! 1323: /* ! 1324: * If VMIN/VTIME are active, save now for possible restore. ! 1325: */ ! 1326: if ((trp->c_lflag & ICANON) == 0) { ! 1327: vmin = trp->c_cc [VMIN]; ! 1328: vtime = trp->c_cc [VTIME]; ! 1329: } else { ! 1330: veol = trp->c_cc [VEOL]; ! 1331: } ! 1332: ! 1333: trp->c_cc [VINTR] = tcp->t_intrc; ! 1334: trp->c_cc [VQUIT] = tcp->t_quitc; ! 1335: veof = tcp->t_eofc; ! 1336: trp->c_cc [VERASE] = sgp->sg_erase; ! 1337: trp->c_cc [VKILL ] = sgp->sg_kill; ! 1338: ! 1339: trp->c_iflag = BRKINT | IXON | IGNPAR | INPCK; ! 1340: trp->c_oflag = OPOST; ! 1341: trp->c_cflag &= CSIZE | HUPCL | CLOCAL | CREAD; ! 1342: trp->c_lflag = ICANON | ISIG | ECHONL | ECHOK; ! 1343: ! 1344: if (sgp->sg_flags & TANDEM) ! 1345: trp->c_iflag |= IXOFF; ! 1346: ! 1347: if (sgp->sg_flags & CRMOD) { ! 1348: trp->c_iflag |= ICRNL; ! 1349: trp->c_oflag |= ONLCR; ! 1350: } ! 1351: ! 1352: if (sgp->sg_flags & LCASE) { ! 1353: trp->c_lflag |= XCASE; ! 1354: trp->c_iflag |= IUCLC; ! 1355: trp->c_oflag |= OLCUC; ! 1356: } ! 1357: ! 1358: if (sgp->sg_flags & (RAW | RAWIN)) { ! 1359: trp->c_iflag = 0; ! 1360: trp->c_cflag &= ~ (PARODD|PARENB); ! 1361: trp->c_cflag |= CS8 | CREAD; ! 1362: trp->c_lflag &= ~ (ECHONL | ISIG | ICANON); ! 1363: } ! 1364: ! 1365: if (sgp->sg_flags & (RAW|RAWOUT)) { ! 1366: trp->c_oflag &= ~ OPOST; ! 1367: trp->c_lflag &= ~ XCASE; ! 1368: } ! 1369: ! 1370: if (sgp->sg_flags & XTABS) ! 1371: trp->c_oflag |= TAB3; ! 1372: ! 1373: if (sgp->sg_flags & (EVENP | ODDP)) { ! 1374: trp->c_cflag |= PARENB; ! 1375: if (sgp->sg_flags & ODDP) ! 1376: trp->c_cflag |= PARODD; ! 1377: } ! 1378: trp->c_cflag |= sgp->sg_ispeed; ! 1379: ! 1380: if (sgp->sg_flags & CRT) ! 1381: trp->c_lflag |= ECHOE; ! 1382: ! 1383: if (sgp->sg_flags & CBREAK) ! 1384: trp->c_lflag &= ~ ICANON; ! 1385: ! 1386: if (sgp->sg_flags & ECHO) ! 1387: trp->c_lflag |= ECHO; ! 1388: ! 1389: /* ! 1390: * If not doing canonical processing, set VMIN/VTIME. ! 1391: */ ! 1392: ! 1393: if ((trp->c_lflag & ICANON) == 0) { ! 1394: trp->c_cc [VMIN] = vmin; ! 1395: trp->c_cc [VTIME] = vtime; ! 1396: } else { ! 1397: trp->c_cc [VEOF] = veof; ! 1398: trp->c_cc [VEOL] = veol; ! 1399: } ! 1400: } ! 1401: ! 1402: /* ! 1403: * Convert from termio struct to sgttyb and tchars. ! 1404: */ ! 1405: static void ! 1406: make_sg(trp, sgp, tcp) ! 1407: struct termio * trp; ! 1408: struct sgttyb * sgp; ! 1409: struct tchars * tcp; ! 1410: { ! 1411: T_HAL(1, printf("T:%x:%x:%x:%x ", trp->c_iflag, trp->c_oflag, ! 1412: trp->c_cflag, trp->c_lflag)); ! 1413: tcp->t_intrc = trp->c_cc [VINTR]; ! 1414: tcp->t_quitc = trp->c_cc [VQUIT]; ! 1415: tcp->t_startc= __CTRL ('Q'); ! 1416: tcp->t_stopc = __CTRL ('S'); ! 1417: tcp->t_eofc = trp->c_cc [VEOF]; ! 1418: tcp->t_brkc = -1; ! 1419: ! 1420: sgp->sg_erase = trp->c_cc [VERASE]; ! 1421: sgp->sg_kill = trp->c_cc [VKILL]; ! 1422: sgp->sg_ispeed = trp->c_cflag & CBAUD; ! 1423: sgp->sg_ospeed = sgp->sg_ispeed; ! 1424: sgp->sg_flags = RAWIN | RAWOUT | CBREAK; ! 1425: ! 1426: if (trp->c_lflag & ECHO) ! 1427: sgp->sg_flags |= ECHO; ! 1428: ! 1429: if (trp->c_lflag & ECHOE) ! 1430: sgp->sg_flags |= CRT; ! 1431: ! 1432: if ((trp->c_lflag & XCASE) != 0 || (trp->c_oflag & OLCUC) != 0 || ! 1433: (trp->c_iflag & IUCLC) != 0) ! 1434: sgp->sg_flags |= LCASE; ! 1435: ! 1436: if (trp->c_iflag & IXOFF) ! 1437: sgp->sg_flags |= TANDEM; ! 1438: ! 1439: if (trp->c_iflag & ICRNL) ! 1440: sgp->sg_flags |= CRMOD; ! 1441: ! 1442: if (trp->c_oflag & ONLCR) ! 1443: sgp->sg_flags |= CRMOD; ! 1444: ! 1445: if (trp->c_oflag & OPOST) ! 1446: sgp->sg_flags &= ~ RAWOUT; ! 1447: ! 1448: if ((trp->c_oflag & TABDLY) == TAB3) ! 1449: sgp->sg_flags |= XTABS; ! 1450: ! 1451: if (trp->c_cflag & PARENB) { ! 1452: if (trp->c_cflag & PARODD) ! 1453: sgp->sg_flags |= ODDP; ! 1454: else ! 1455: sgp->sg_flags |= EVENP; ! 1456: } ! 1457: ! 1458: if (trp->c_lflag & ISIG) ! 1459: sgp->sg_flags &= ~ RAWIN; ! 1460: ! 1461: if (trp->c_lflag & ICANON) ! 1462: sgp->sg_flags &= ~ CBREAK; ! 1463: } ! 1464: #endif ! 1465: ! 1466: /* ! 1467: * ttrtp() ! 1468: * ! 1469: * Recover contents of typeahead when changing modes. ! 1470: * Called for ioctls of TIOCSETP and TCSETA, ! 1471: * when going from not byte-by-byte input to BBYB. ! 1472: */ ! 1473: static void ! 1474: ttrtp(tp) ! 1475: TTY * tp; ! 1476: { ! 1477: register char *p1, *p2; ! 1478: ! 1479: if (tp->t_ibx) { ! 1480: p1 = & tp->t_ib [0]; ! 1481: p2 = & tp->t_ib [tp->t_ibx]; ! 1482: while (p1 < p2) { ! 1483: #if NOT_8_BIT ! 1484: cltputq (& tp->t_iq, (* p1 ++) & 0x7F); ! 1485: #else ! 1486: cltputq (& tp->t_iq, (* p1 ++)); ! 1487: #endif ! 1488: } ! 1489: tp->t_ibx = 0; ! 1490: } ! 1491: } ! 1492: ! 1493: /* ! 1494: * ttinp() ! 1495: * ! 1496: * Return nonzero if ttin() may be called to send data for pickup by ttread(), ! 1497: * or 0 if not. ! 1498: */ ! 1499: ! 1500: int ! 1501: ttinp(tp) ! 1502: TTY * tp; ! 1503: { ! 1504: return (tp->t_flags & T_ISTOP) == 0; ! 1505: } ! 1506: ! 1507: /* ! 1508: * ttoutp() ! 1509: * ! 1510: * Return nonzero if ttout() may be called to fetch data stored by ttwrite(), ! 1511: * or 0 if not. ! 1512: */ ! 1513: ! 1514: int ! 1515: ttoutp(tp) ! 1516: TTY * tp; ! 1517: { ! 1518: return tp->t_nfill || (tp->t_flags & T_INL) != 0 || tp->t_oq.cq_cc; ! 1519: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.