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