Annotation of coherent/b/STREAMS/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 <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.