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

unix.superglobalmegacorp.com

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