Annotation of coherent/b/kernel/io.386/tty.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.