Annotation of coherent/b/kernel/io.386/tty.c, revision 1.1.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.