Annotation of coherent/d/286_KERNEL/USRSRC/io/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:  * $Log:       tty.c,v $
                     10:  * Revision 1.15  92/01/13  08:58:40  bin
                     11:  * update by hal for 321 kernel (looks like just additions of debug stuff)
                     12:  * 
                     13:  * Revision 1.15  92/01/13  08:36:53  hal
                     14:  * Add a few DEBUG lines.
                     15:  * 
                     16:  * Revision 1.14  92/01/09  09:42:31  hal
                     17:  * Add debug conditionals for sleeps.
                     18:  * Fix process group logic, including TIOCSETG hack.
                     19:  * 
                     20:  * Revision 1.13  91/12/10  17:01:56  hal
                     21:  * Don't wait for drain on TIOCFLUSH.
                     22:  * 
                     23:  * Revision 1.12  91/11/14  14:28:51  hal
                     24:  * Move flow control out of tty.c.
                     25:  * Make ttin() run at hi priority.
                     26:  *
                     27:  * Revision 1.11  91/09/16  18:11:08  hal
                     28:  * Update t_flags in ttstart() at high priority.
                     29:  * Document that ttstash() is local.
                     30:  *
                     31:  * Revision 1.10  91/09/16  15:58:26  hal
                     32:  * Mask interrrupts when modifying tp->t_flags as some IRQ handlers change this.
                     33:  *
                     34:  * Revision 1.9  91/09/16  10:27:47  hal
                     35:  * Explain T_ISTOP/T_TSTOP/T_STOP.
                     36:  * Add check for TANDEM before sending t_startc.
                     37:  *
                     38:  * Revision 1.8  91/09/13  18:01:39  piggy
                     39:  * Only do XON/XOFF flow control if TANDEM is set.
                     40:  *
                     41:  * Revision 1.7  91/09/13  17:58:00  hal
                     42:  * Drop 3rd arg (was writing PSW directly from it!) for ttread/ttwrite.
                     43:  * General face lift.
                     44:  *
                     45:  * Bug: no support for 8-bit characters.
                     46:  * Fix: don't strip keyboard input. 01/22/91.  (norm)
                     47:  *
                     48:  * Bug:        Switching modes between cooked and CBREAK/RAW left buffered input
                     49:  *     in the input buffer until returning to cooked mode. 05/13/91 norm
                     50:  *
                     51:  * Bug: setting speed to default in ttopen() was conditioned to
                     52:  *      use hard constants.  90/08/28.  hws
                     53:  *
                     54:  * Revision 1.5  91/06/06  18:28:53  norm
                     55:  * Restore 8-bit fix.
                     56:  *
                     57:  * Revision 1.2        89/07/17  11:51:20      src
                     58:  * Bug:        Terminal could lock up when setting it to RAWIN mode, if
                     59:  *     output was suspended due to X-OFF, and output data was present.
                     60:  * Fix:        Setting terminal to RAWIN mode now clears X-OFF, starts output
                     61:  *     BEFORE waiting for output to drain.  Received signals now cause
                     62:  *     operation to complete without waiting for drain. (ABC)
                     63:  *
                     64:  * Revision 1.1        88/03/24  16:18:12      src
                     65:  * Initial revision
                     66:  *
                     67:  * 86/12/12    Allan Cornish           /usr/src/sys/drv/tty.c
                     68:  * Added 3rd argument to ttpoll() to support non-blocking polls.
                     69:  *
                     70:  * 86/11/19    Allan Cornish           /usr/src/sys/drv/tty.c
                     71:  * Made ttread() and ttwrite() recognize the IONDLY flag in iop->io_flag.
                     72:  * wakeup() and pollwake() now have delayed invocation by defer().
                     73:  * Added poll [System V.3] capability.
                     74:  *
                     75:  * 85/06/28    Allan Cornish
                     76:  * made ttioctl() clear T_STOP flag if ISRIN.
                     77:  *
                     78:  * 85/03/04    Allan Cornish
                     79:  * made ttread()  interruptible.
                     80:  *
                     81:  * 85/03/01    Allan Cornish
                     82:  * made ttclose() interruptible.
                     83:  */
                     84: 
                     85: /*
                     86:  * About STOP flag bits:
                     87:  *     T_ISTOP is set when the tty module's input queue is in danger of
                     88:  *             overflow.  It is up to the device driver to check this flag
                     89:  *             and do something about it.  If ttin() is called with a
                     90:  *             character from the device while T_ISTOP is set, the  character
                     91:  *             is discarded.  T_ISTOP is cleared when the input queue is
                     92:  *             sufficiently empty.  The device driver can monitor this bit for
                     93:  *             hardware flow control.
                     94:  *     T_TSTOP is the "Tandem" flow control flag for input.  If TANDEM is set
                     95:  *             and the input queue is in danger of overflow, t_stopc is sent
                     96:  *             and T_TSTOP is set.  When the input queue is empty enough,
                     97:  *             t_startc is sent and T_TSTOP is cleared.
                     98:  *     T_STOP is the flow control bit for output.  No output will be
                     99:  *             written to the output queue while this bit is true.
                    100:  *             Except for initialization of flags in the TTY struct, by
                    101:  *             ttopen(), this bit is not written by tty.c.
                    102:  *     91/09/15 - hal
                    103:  */
                    104: 
                    105: /*
                    106:  * Includes.
                    107:  */
                    108: #include <sys/clist.h>
                    109: #include <sys/coherent.h>
                    110: #include <sys/con.h>
                    111: #include <sys/deftty.h>
                    112: #include <sys/io.h>
                    113: #include <sys/proc.h>
                    114: #include <sys/sched.h>
                    115: #include <sys/stat.h>
                    116: #include <sys/tty.h>
                    117: #include <sys/uproc.h>
                    118: #include <errno.h>
                    119: 
                    120: /*
                    121:  * Definitions.
                    122:  *     Constants.
                    123:  *     Macros with argument lists.
                    124:  *     Typedefs.
                    125:  *     Enums.
                    126:  */
                    127: 
                    128: /* NEAR_OR_FAR_CALL is for invoking t_param and t_start */
                    129: #define         NEAR_OR_FAR_CALL(tp_fn)  {\
                    130:        if (tp->t_cs_sel) \
                    131:                ld_call(tp->t_cs_sel, tp->tp_fn, tp); \
                    132:        else \
                    133:                (*tp->tp_fn)(tp); }
                    134: 
                    135: /*
                    136:  * Functions.
                    137:  *     Import Functions.
                    138:  *     Export Functions.
                    139:  *     Local Functions.
                    140:  */
                    141: void ttclose();
                    142: void ttflush();
                    143: void tthup();
                    144: void ttin();
                    145: void ttioctl();
                    146: void ttopen();
                    147: int  ttout();
                    148: int  ttpoll();
                    149: void ttread();
                    150: void ttsetgrp();
                    151: void ttsignal();
                    152: void ttstart();
                    153: void ttwrite();
                    154: 
                    155: static void ttstash();
                    156: 
                    157: /*
                    158:  * Global Data.
                    159:  *     Import Variables.
                    160:  *     Export Variables.
                    161:  *     Local Variables.
                    162:  */
                    163: extern int     wakeup();
                    164: extern void    pollwake();
                    165: 
                    166: /*
                    167:  * ttopen()
                    168:  *
                    169:  *     Called by driver on first open.
                    170:  *     Set up defaults.
                    171:  */
                    172: void ttopen(tp)
                    173: register TTY *tp;
                    174: {
                    175:        tp->t_escape = 0;
                    176:        tp->t_sgttyb.sg_ispeed = tp->t_dispeed;
                    177:        tp->t_sgttyb.sg_ospeed = tp->t_dospeed;
                    178:        tp->t_sgttyb.sg_erase  = DEF_SG_ERASE;
                    179:        tp->t_sgttyb.sg_kill   = DEF_SG_KILL;
                    180:        tp->t_sgttyb.sg_flags  = DEF_SG_FLAGS;
                    181:        tp->t_tchars.t_intrc   = DEF_T_INTRC;
                    182:        tp->t_tchars.t_quitc   = DEF_T_QUITC;
                    183:        tp->t_tchars.t_startc  = DEF_T_STARTC;
                    184:        tp->t_tchars.t_stopc   = DEF_T_STOPC;
                    185:        tp->t_tchars.t_eofc    = DEF_T_EOFC;
                    186:        tp->t_tchars.t_brkc    = DEF_T_BRKC;
                    187:        if (tp->t_param != NULL) {
                    188:                NEAR_OR_FAR_CALL(t_param)
                    189:        }
                    190: }
                    191: 
                    192: /*
                    193:  * ttsetgrp()
                    194:  *
                    195:  *     If process is a group leader without a control terminal,
                    196:  *     make its control terminal this device.
                    197:  *
                    198:  *     If process is a group leader and this device does not have
                    199:  *     a process group, give it the group of the current process.
                    200:  */
                    201: void ttsetgrp(tp, ctdev)
                    202: register TTY *tp;
                    203: dev_t ctdev;
                    204: {
                    205:        register PROC *pp;
                    206: 
                    207:        pp = SELF;
                    208: #if DEBUG
                    209: printf("ttsetgrp dev=%x pid=%d pg=%d ", ctdev, pp->p_pid, pp->p_group);
                    210: printf("old_ct=%x old_tg=%d ", pp->p_ttdev, tp->t_group);
                    211: #endif
                    212:        if (pp->p_group == pp->p_pid) {
                    213:                if (pp->p_ttdev == NODEV)
                    214:                        pp->p_ttdev = ctdev;
                    215:                if (tp->t_group == 0)
                    216:                        tp->t_group = pp->p_pid;
                    217:        }
                    218: #if DEBUG
                    219: printf("new_ct=%x new_tg=%d\n", pp->p_ttdev, tp->t_group);
                    220: #endif
                    221: }
                    222: 
                    223: /*
                    224:  * ttyclose()
                    225:  *
                    226:  *     Called by driver on the last close.
                    227:  *     Wait for all pending output to go out.
                    228:  *     Kill input.
                    229:  */
                    230: void ttclose(tp)
                    231: register TTY *tp;
                    232: {
                    233:        register int s;
                    234: 
                    235:        while (tp->t_oq.cq_cc != 0) {
                    236:                s = sphi();
                    237:                if (tp->t_oq.cq_cc != 0) {
                    238:                        tp->t_flags |= T_DRAIN;
                    239: #if DEBUG
                    240: printf("T1 ");
                    241: #endif
                    242:                        sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
                    243: #if DEBUG
                    244: printf("z ");
                    245: #endif
                    246:                }
                    247:                spl(s);
                    248:                if (SELF->p_ssig && nondsig())
                    249:                        break;
                    250:        }
                    251:        ttflush(tp);
                    252:        tp->t_flags = tp->t_group = 0;
                    253: }
                    254: 
                    255: /*
                    256:  * ttread()
                    257:  *
                    258:  *     The read routine for a tty device driver will call this function.
                    259:  *
                    260:  *     Move data from tp->t_iq to io segment iop.
                    261:  *     Number of characters to copy is in iop->ioc.
                    262:  *
                    263:  *     In cooked mode, copy up to the first newline or break character, or
                    264:  *     until the count runs out.
                    265:  *     In CBREAK or RAW modes, return when count runs out or when input clist
                    266:  *     is empty and we're returning at least one byte.
                    267:  */
                    268: void ttread(tp, iop)
                    269: register TTY *tp;
                    270: register IO *iop;
                    271: {
                    272:        register c;
                    273:        int o;
                    274:        int sioc = iop->io_ioc;  /* number of bytes to read */
                    275: 
                    276:        while (iop->io_ioc) {
                    277:                o = sphi();
                    278:                while ((c = getq(&tp->t_iq)) < 0) {
                    279:                        if ((tp->t_flags & T_CARR) == 0) {
                    280:                           u.u_error = EIO;  /* error since no carrier */
                    281:                           spl(o);
                    282:                           return;
                    283:                        }
                    284: 
                    285:                        /* If we're in CBREAK or RAW mode, and we don't */
                    286:                        /* have the special "blocking read" bit set for */
                    287:                        /* these modes, and we read at least one byte   */
                    288:                        /* of input, return immediately, since we have  */
                    289:                        /* run out of characters from the clist.        */
                    290: 
                    291:                        if (ISBBYB && ((tp->t_flags & T_BRD) == 0)
                    292:                           && iop->io_ioc < sioc) {
                    293:                           spl(o);
                    294:                           return;
                    295:                        }
                    296: 
                    297:                        /*
                    298:                         * Non-blocking reads.
                    299:                         * Tell user process to try again later.
                    300:                         */
                    301:                        if (iop->io_flag & IONDLY) {
                    302:                                u.u_error = EAGAIN;
                    303:                                spl(o);
                    304:                                return;
                    305:                        }
                    306: 
                    307:                        tp->t_flags |= T_INPUT;  /* wait for more data */
                    308: #if DEBUG
                    309: printf("T2 ");
                    310: #endif
                    311:                        sleep((char *)&tp->t_iq, CVTTIN, IVTTIN, SVTTIN);
                    312: #if DEBUG
                    313: printf("z ");
                    314: #endif
                    315: 
                    316:                        if (SELF->p_ssig && nondsig()) {
                    317:                                if (iop->io_ioc == sioc)
                    318:                                        u.u_error = EINTR;
                    319:                                spl(o);
                    320:                                return;
                    321:                        }
                    322:                }
                    323:                /*
                    324:                 * Flow control - can we turn on input from the driver yet?
                    325:                 */
                    326:                if (tp->t_iq.cq_cc <= ILOLIM) {
                    327:                        if ((tp->t_flags&T_ISTOP) != 0)
                    328:                                tp->t_flags &= ~T_ISTOP;
                    329:                        if (ISTAND && (tp->t_flags&T_TSTOP) != 0) {
                    330:                                tp->t_flags &= ~T_TSTOP;
                    331:                                while (putq(&tp->t_oq, startc) < 0) {
                    332:                                        ttstart(tp);
                    333:                                        waitq();
                    334:                                }
                    335:                                ttstart(tp);
                    336:                        }
                    337:                }
                    338:                spl(o);
                    339:                if (!ISBBYB && ISEOF)
                    340:                        return;
                    341:                if (ioputc(c, iop) < 0)
                    342:                        return;
                    343:                if (!ISBBYB && (c=='\n' || ISBRK))
                    344:                        return;
                    345:        }
                    346: }
                    347: 
                    348: /*
                    349:  * ttwrite()
                    350:  *
                    351:  *     Write routine.
                    352:  *     Transfer stuff to the character list.
                    353:  */
                    354: void ttwrite(tp, iop)
                    355: register TTY *tp;
                    356: register IO *iop;
                    357: {
                    358:        register c;
                    359:        int o;
                    360: 
                    361:        /*
                    362:         * Non-blocking writes which can fit.
                    363:         * NOTE: exhaustion of clists can still cause blocking writes.
                    364:         */
                    365:        if ((iop->io_flag & IONDLY) && (OHILIM >= iop->io_ioc)) {
                    366: 
                    367:                /*
                    368:                 * No room.
                    369:                 */
                    370:                if (tp->t_oq.cq_cc >= OHILIM-iop->io_ioc) {
                    371:                        u.u_error = EAGAIN;
                    372:                        return;
                    373:                }
                    374:        }
                    375: 
                    376:        while ((c = iogetc(iop)) >= 0) {
                    377:                if ((tp->t_flags & T_CARR) == 0) {
                    378:                        u.u_error = EIO;  /* error since no carrier */
                    379:                        return;
                    380:                }
                    381:                o = sphi();
                    382:                while (tp->t_oq.cq_cc >= OHILIM) {
                    383:                        ttstart(tp);
                    384:                        if (tp->t_oq.cq_cc < OHILIM)
                    385:                                break;
                    386:                        tp->t_flags |= T_HILIM;
                    387: #if DEBUG
                    388: printf("T3 ");
                    389: #endif
                    390:                        sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
                    391: #if DEBUG
                    392: printf("z ");
                    393: #endif
                    394:                        if (SELF->p_ssig && nondsig()) {
                    395:                                u.u_error = EINTR;
                    396:                                spl(o);
                    397:                                return;
                    398:                        }
                    399:                }
                    400:                while (putq(&tp->t_oq, c) < 0) {
                    401:                        ttstart(tp);
                    402:                        waitq();
                    403:                }
                    404:                spl(o);
                    405:        }
                    406:        o = sphi();
                    407:        ttstart(tp);
                    408:        spl(o);
                    409: }
                    410: 
                    411: /*
                    412:  * ttioctl()
                    413:  *
                    414:  *     This routine handles common typewriter ioctl functions.
                    415:  *     Note that flushing the stream now means drain the output
                    416:  *     and clear the input.
                    417:  */
                    418: void ttioctl(tp, com, vec)
                    419: register TTY *tp;
                    420: register struct sgttyb *vec;
                    421: {
                    422:        register int    flush = 0;
                    423:        register int    drain = 0;
                    424:        register char   *p1, *p2;
                    425:        int s;
                    426:        int rload = 0;
                    427:        int was_bbyb = 0;
                    428: 
                    429:        switch (com) {
                    430:        case TIOCQUERY:
                    431:                kucopy(&tp->t_iq.cq_cc, vec, sizeof(int));
                    432:                break;
                    433:        case TIOCGETP:
                    434:                kucopy(&tp->t_sgttyb, vec, sizeof (struct sgttyb));
                    435:                break;
                    436:        case TIOCSETP:
                    437:                ++flush;          /* flush input */
                    438:                ++drain;          /* delay for output */
                    439:                ++rload;
                    440:                ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb));
                    441:                break;
                    442:        case TIOCSETN:
                    443:                was_bbyb = ISBBYB;      /* previous mode */
                    444:                ++rload;
                    445:                ukcopy(vec, &tp->t_sgttyb, sizeof (struct sgttyb));
                    446:                if (!was_bbyb && ISBBYB && tp->t_ibx != 0) {
                    447:                        p1 = &tp->t_ib[0];
                    448:                        p2 = &tp->t_ib[tp->t_ibx];
                    449:                        while (p1 < p2)
                    450: #if NOT_8_BIT
                    451:                                putq(&tp->t_iq, (*p1++) & 0177);
                    452: #else
                    453:                                putq(&tp->t_iq, (*p1++));
                    454: #endif
                    455:                        tp->t_ibx = 0;
                    456:                }
                    457:                break;
                    458:        case TIOCGETC:
                    459:                kucopy(&tp->t_tchars, vec, sizeof (struct tchars));
                    460:                break;
                    461:        case TIOCSETC:
                    462:                ++rload;
                    463:                ++drain;
                    464:                ukcopy(vec, &tp->t_tchars, sizeof (struct tchars));
                    465:                break;
                    466:        case TIOCEXCL:
                    467:                s = sphi();
                    468:                tp->t_flags |= T_EXCL;
                    469:                spl(s);
                    470:                break;
                    471:        case TIOCNXCL:
                    472:                s = sphi();
                    473:                tp->t_flags &= ~T_EXCL;
                    474:                spl(s);
                    475:                break;
                    476:        case TIOCHPCL:          /* set hangup on last close */
                    477:                s = sphi();
                    478:                tp->t_flags |= T_HPCL;
                    479:                spl(s);
                    480:                break;
                    481:        case TIOCCHPCL:         /* don't hangup on last close */
                    482:                if (!super())   /* only superuser may do this */
                    483:                        u.u_error = EPERM;        /* not su */
                    484:                else {
                    485:                        s = sphi();
                    486:                        tp->t_flags &= ~T_HPCL;   /* turn off hangup bit */
                    487:                        spl(s);
                    488:                }
                    489:                break;
                    490:        case TIOCGETTF:         /* get tty flag word */
                    491:                kucopy(&tp->t_flags, (unsigned *) vec, sizeof(unsigned));
                    492:                break;
                    493:        case TIOCFLUSH:
                    494:                ++flush;        /* flush both input and output */
                    495: /*             ++drain;        Why? - hws - 91/11/22   */
                    496:                break;
                    497:        case TIOCBREAD:         /* blocking read for CBREAK/RAW mode */
                    498:                s = sphi();
                    499:                tp->t_flags |= T_BRD;
                    500:                spl(s);
                    501:                break;
                    502:        case TIOCCBREAD:        /* turn off CBREAK/RAW blocking read mode */
                    503:                s = sphi();
                    504:                tp->t_flags &= ~T_BRD;
                    505:                spl(s);
                    506:                break;
                    507:        /*
                    508:         * The following is a hack so that the process group for /dev/console
                    509:         * contains the current login shell running on it.
                    510:         * Only expect /etc/init to use this ugliness.
                    511:         */
                    512:        case TIOCSETG:
                    513:                if (super())
                    514:                        tp->t_group = SELF->p_group;
                    515:                break;
                    516:        default:
                    517:                u.u_error = EINVAL;
                    518:        }
                    519: 
                    520:        /*
                    521:         * Wait for output to drain, or signal to arrive.
                    522:         */
                    523:        if (drain != 0) {
                    524: 
                    525:                /*
                    526:                 * Ensure output is enabled BEFORE waiting for output to drain.
                    527:                 */
                    528:                if (ISRIN && (tp->t_flags & T_STOP)) {
                    529:                        s = sphi();
                    530:                        tp->t_flags &= ~T_STOP;
                    531:                        ttstart(tp);
                    532:                        spl(s);
                    533:                }
                    534: 
                    535:                while (tp->t_oq.cq_cc != 0) {
                    536:                        s = sphi();
                    537:                        tp->t_flags |= T_DRAIN;
                    538:                        spl(s);
                    539: #if DEBUG
                    540: printf("T4 ");
                    541: #endif
                    542:                        sleep((char *)&tp->t_oq, CVTTOUT, IVTTOUT, SVTTOUT);
                    543: #if DEBUG
                    544: printf("z ");
                    545: #endif
                    546:                        if (SELF->p_ssig && nondsig())
                    547:                                break;
                    548:                }
                    549:        }
                    550: 
                    551:        /*
                    552:         * Flush input.
                    553:         */
                    554:        if (flush != 0)
                    555:                ttflush(tp);
                    556: 
                    557:        /*
                    558:         * Re-initialize hardware.
                    559:         */
                    560:        if ((rload != 0) && (tp->t_param != NULL))
                    561:                NEAR_OR_FAR_CALL(t_param)
                    562: }
                    563: 
                    564: /*
                    565:  * ttpoll()
                    566:  *
                    567:  *     Polling routine.
                    568:  *     [System V.3 Compatible]
                    569:  */
                    570: int ttpoll(tp, ev, msec)
                    571: register TTY * tp;
                    572: int ev;
                    573: int msec;
                    574: {
                    575:        /*
                    576:         * Priority polls not supported.
                    577:         */
                    578:        ev &= ~POLLPRI;
                    579: 
                    580:        /*
                    581:         * Input poll with no data present.
                    582:         */
                    583:        if ((ev & POLLIN) && (tp->t_iq.cq_cc == 0)) {
                    584: 
                    585:                /*
                    586:                 * Blocking input poll.
                    587:                 */
                    588:                if (msec != 0)
                    589:                        pollopen(&tp->t_ipolls);
                    590: 
                    591:                /*
                    592:                 * Second look to avoid interrupt race.
                    593:                 */
                    594:                if (tp->t_iq.cq_cc == 0)
                    595:                        ev &= ~POLLIN;
                    596:        }
                    597: 
                    598:        /*
                    599:         * Output poll with no space.
                    600:         */
                    601:        if ((ev & POLLOUT) && (tp->t_oq.cq_cc >= OLOLIM)) {
                    602: 
                    603:                /*
                    604:                 * Blocking output poll.
                    605:                 */
                    606:                if (msec != 0)
                    607:                        pollopen(&tp->t_opolls);
                    608: 
                    609:                /*
                    610:                 * Second look to avoid interrupt race.
                    611:                 */
                    612:                if (tp->t_oq.cq_cc >= OLOLIM)
                    613:                        ev &= ~POLLIN;
                    614:        }
                    615: 
                    616:        if (((ev & POLLIN) == 0) && ((tp->t_flags & T_CARR) == 0))
                    617:                ev |= POLLHUP;
                    618: 
                    619:        return ev;
                    620: }
                    621: 
                    622: /*
                    623:  * ttout()
                    624:  *
                    625:  *     Pull a character from the output queues of the typewriter.
                    626:  *     Doing fills, newline insert, tab expansion, etc.
                    627:  *
                    628:  *     If the stream is empty return a -1.
                    629:  *     Called at high priority.
                    630:  */
                    631: int ttout(tp)
                    632: register TTY *tp;
                    633: {
                    634:        register c;
                    635: 
                    636:        if (tp->t_nfill) {
                    637:                --tp->t_nfill;
                    638:                c = tp->t_fillb;
                    639:        } else if ((tp->t_flags&T_INL) != 0) {
                    640:                tp->t_flags &= ~T_INL;
                    641:                c = '\n';
                    642:        } else {
                    643:                if ((c=getq(&tp->t_oq)) < 0)
                    644:                        return -1;
                    645:                if (!ISROUT) {
                    646:                        if (c=='\n' && ISCRMOD) {
                    647:                                tp->t_flags |= T_INL;
                    648:                                c = '\r';
                    649:                        } else if (c=='\t' && ISXTABS) {
                    650:                                tp->t_nfill = ~(tp->t_hpos|~07);
                    651:                                tp->t_fillb = ' ';
                    652:                                c = ' ';
                    653:                        }
                    654:                }
                    655:        }
                    656:        if (!ISROUT) {
                    657:                if (c == '\b') {
                    658:                        if (tp->t_hpos)
                    659:                                --tp->t_hpos;
                    660:                } else if (c == '\r')
                    661:                        tp->t_hpos = 0;
                    662:                else if (c == '\t')
                    663:                        tp->t_hpos = (tp->t_hpos|07) + 1;
                    664: #if NOT_8_BIT
                    665:                else if (c >= ' ' && c <= '~')
                    666: #else
                    667:                else if ((c >= ' ' && c <= '~') || (c >= 0200 && c <= 0376))
                    668: #endif
                    669:                        ++tp->t_hpos;
                    670:        }
                    671:        return c;
                    672: }
                    673: 
                    674: /*
                    675:  * ttin()
                    676:  *
                    677:  *     Pass a character to the device independent typewriter routines.
                    678:  *     Handle erase and kill, tandem flow control, and other magic.
                    679:  *     Often called at high priority from the driver's interrupt routine.
                    680:  */
                    681: void ttin(tp, c)
                    682: register TTY *tp;
                    683: register c;
                    684: {
                    685:        int dc, i, n;
                    686:        int s;
                    687: 
                    688:        if (!ISRIN) {
                    689: #if NOT_8_BIT
                    690:                c &= 0177;
                    691: #endif
                    692:                if (ISINTR) {
                    693:                        ttsignal(tp, SIGINT);
                    694:                        goto ttin_ret;
                    695:                }
                    696:                if (ISQUIT) {
                    697:                        ttsignal(tp, SIGQUIT);
                    698:                        goto ttin_ret;
                    699:                }
                    700:        }
                    701:        if ((tp->t_flags&T_ISTOP) != 0)
                    702:                goto ttin_ret;
                    703:        if (!ISRIN) {
                    704:                if (c=='\r' && ISCRMOD)
                    705:                        c = '\n';
                    706:                if (tp->t_escape != 0) {
                    707:                        if (c == ESC)
                    708:                                ++tp->t_escape;
                    709:                        else {
                    710:                                if (ISERASE || ISKILL) {
                    711:                                        c |= 0200;
                    712:                                        --tp->t_escape;
                    713:                                }
                    714:                                while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) {
                    715:                                        tp->t_ib[tp->t_ibx++] = ESC;
                    716:                                        --tp->t_escape;
                    717:                                }
                    718:                                ttstash(tp, c);
                    719:                        }
                    720:                        if (ISECHO) {
                    721: #if NOT_8_BIT
                    722:                                putq(&tp->t_oq, c&0177);
                    723: #else
                    724:                                putq(&tp->t_oq, c); /* no strip for 8-bit */
                    725: #endif
                    726:                                ttstart(tp);
                    727:                        }
                    728:                        goto ttin_ret;
                    729:                }
                    730:                if (ISERASE && !ISCBRK) {
                    731:                        while (tp->t_escape!=0 && tp->t_ibx<NCIB-1) {
                    732:                                tp->t_ib[tp->t_ibx++] = ESC;
                    733:                                --tp->t_escape;
                    734:                        }
                    735:                        if (tp->t_ibx == 0)
                    736:                                goto ttin_ret;
                    737:                        dc = tp->t_ib[--tp->t_ibx];
                    738:                        if (ISECHO) {
                    739:                                if (!ISCRT)
                    740:                                        putq(&tp->t_oq, c);
                    741:                                /* don't erase for bell, null, or rubout */
                    742: #if NOT_8_BIT
                    743:                                else if (((c = dc&0177) == '\007')
                    744:                                        || c == 0 || c == 0177)
                    745: #else
                    746:                                else if (((c = dc) == '\007')
                    747:                                        || c == 0 || c == 0177 || c == 0377)
                    748: #endif
                    749:                                        goto ttin_ret;
                    750:                                else if (c != '\b' && c != '\t') {
                    751:                                        putq(&tp->t_oq, '\b');
                    752:                                        putq(&tp->t_oq,  ' ');
                    753:                                        putq(&tp->t_oq, '\b');
                    754:                                } else if (c == '\t') {
                    755:                                        n = tp->t_opos + tp->t_escape;
                    756:                                        for (i=0; i<tp->t_ibx; ++i) {
                    757:                                                c = tp->t_ib[i];
                    758: #if NOT_8_BIT
                    759:                                                if ((c&0200) != 0) {
                    760:                                                        ++n;
                    761:                                                        c &= 0177;
                    762:                                                }
                    763: #endif
                    764:                                                if (c == '\b')
                    765:                                                        --n;
                    766:                                                else {
                    767:                                                        if (c == '\t')
                    768:                                                                n |= 07;
                    769:                                                        ++n;
                    770:                                                }
                    771:                                        }
                    772:                                        while (n++ < tp->t_hpos)
                    773:                                                putq(&tp->t_oq, '\b');
                    774:                                }
                    775: #if NOT_8_BIT
                    776:                                if ((dc&0200) != 0) {
                    777:                                        if ((dc&0177) != '\b')
                    778:                                                putq(&tp->t_oq, '\b');
                    779:                                        putq(&tp->t_oq,  ' ');
                    780:                                        putq(&tp->t_oq, '\b');
                    781:                                }
                    782: #endif
                    783:                                ttstart(tp);
                    784:                        }
                    785:                        goto ttin_ret;
                    786:                }
                    787:                if (ISKILL && !ISCBRK) {
                    788:                        tp->t_ibx = 0;
                    789:                        tp->t_escape = 0;
                    790:                        if (ISECHO) {
                    791:                                if (c < 0x20) {
                    792:                                        putq(&tp->t_oq, '^');
                    793:                                        c += 0x40;
                    794:                                }
                    795:                                putq(&tp->t_oq, c);
                    796:                                putq(&tp->t_oq, '\n');
                    797:                                ttstart(tp);
                    798:                        }
                    799:                        goto ttin_ret;
                    800:                }
                    801:        }
                    802:        if (ISBBYB) {
                    803:                putq(&tp->t_iq, c);
                    804:                if ((tp->t_flags&T_INPUT) != 0) {
                    805:                        s = sphi();
                    806:                        tp->t_flags &= ~T_INPUT;
                    807:                        spl(s);
                    808:                        defer(wakeup, (char *) &tp->t_iq);
                    809:                }
                    810:                if (tp->t_ipolls.e_procp) {
                    811:                        tp->t_ipolls.e_procp = 0;
                    812:                        defer(pollwake, (char *) &tp->t_ipolls);
                    813:                }
                    814:        } else {
                    815:                if (tp->t_ibx == 0)
                    816:                        tp->t_opos = tp->t_hpos;
                    817:                if (c == ESC)
                    818:                        ++tp->t_escape;
                    819:                else
                    820:                        ttstash(tp, c);
                    821:        }
                    822:        if (ISECHO) {
                    823:                if (ISRIN || !ISEOF) {
                    824:                        putq(&tp->t_oq, c);
                    825:                        ttstart(tp);
                    826:                }
                    827:        }
                    828:        if ((n=tp->t_iq.cq_cc)>=IHILIM) {
                    829:                s = sphi();
                    830:                tp->t_flags |= T_ISTOP;
                    831:                spl(s);
                    832:        } else if (ISTAND && (tp->t_flags&T_TSTOP)==0 && n>=ITSLIM) {
                    833:                s = sphi();
                    834:                tp->t_flags |= T_TSTOP;
                    835:                spl(s);
                    836:                putq(&tp->t_oq, stopc);
                    837:                ttstart(tp);
                    838:        }
                    839: 
                    840: ttin_ret:
                    841:        return;
                    842: }
                    843: 
                    844: /*
                    845:  * ttstash()
                    846:  *
                    847:  *     Cooked mode.
                    848:  *     Put character in the buffer and check for end of line.
                    849:  *     Only a legal end of line can take the last character position.
                    850:  *
                    851:  *     Only called from ttin(), and ttin() is called at high priority.
                    852:  */
                    853: static void ttstash(tp, c)
                    854: register TTY *tp;
                    855: {
                    856:        register char *p1, *p2;
                    857: 
                    858:        if (c=='\n' || ISEOF || ISBRK) {
                    859:                p1 = &tp->t_ib[0];
                    860:                p2 = &tp->t_ib[tp->t_ibx];
                    861:                *p2++ = c;                      /* Always room */
                    862:                while (p1 < p2)
                    863: #if NOT_8_BIT
                    864:                        putq(&tp->t_iq, (*p1++)&0177);
                    865: #else
                    866:                        putq(&tp->t_iq, (*p1++));
                    867: #endif
                    868:                tp->t_ibx = 0;
                    869:                tp->t_escape = 0;
                    870: 
                    871:                if (tp->t_flags & T_INPUT) {
                    872:                        tp->t_flags &= ~T_INPUT;
                    873:                        defer(wakeup, (char *) &tp->t_iq);
                    874:                }
                    875: 
                    876:                if (tp->t_ipolls.e_procp) {
                    877:                        tp->t_ipolls.e_procp = 0;
                    878:                        defer(pollwake, (char *) &tp->t_ipolls);
                    879:                }
                    880: 
                    881:        } else if (tp->t_ibx < NCIB-1)
                    882:                tp->t_ib[tp->t_ibx++] = c;
                    883: }
                    884: 
                    885: /*
                    886:  * ttstart()
                    887:  *
                    888:  *     Start output on a tty.
                    889:  *     Duck out if stopped.  Do wakeups.
                    890:  */
                    891: void ttstart(tp)
                    892: register TTY *tp;
                    893: {
                    894:        register int n;
                    895:        int s;
                    896: 
                    897:        n = tp->t_flags;
                    898:        if (n & T_STOP)
                    899:                goto stdone;
                    900: 
                    901:        if ((n&T_DRAIN)!=0 && tp->t_oq.cq_cc==0
                    902:           && (n&T_INL)==0 && tp->t_nfill==0) {
                    903:                s = sphi();
                    904:                tp->t_flags &= ~T_DRAIN;
                    905:                spl(s);
                    906:                defer(wakeup, (char *) &tp->t_oq);
                    907:                goto stdone;
                    908:        }
                    909: 
                    910:        NEAR_OR_FAR_CALL(t_start)
                    911: 
                    912:        if (tp->t_oq.cq_cc > OLOLIM)
                    913:                goto stdone;
                    914: 
                    915:        if (n & T_HILIM) {
                    916:                s = sphi();
                    917:                tp->t_flags &= ~T_HILIM;
                    918:                spl(s);
                    919:                defer(wakeup, (char *) &tp->t_oq);
                    920:        }
                    921: 
                    922:        if (tp->t_opolls.e_procp) {
                    923:                tp->t_opolls.e_procp = 0;
                    924:                defer(pollwake, (char *) &tp->t_opolls);
                    925:        }
                    926: stdone:
                    927:        return;
                    928: }
                    929: 
                    930: /*
                    931:  * ttflush()
                    932:  *
                    933:  *     Flush a tty.
                    934:  *     Called to clear out queues.
                    935:  */
                    936: void ttflush(tp)
                    937: register TTY *tp;
                    938: {
                    939:        int s;
                    940: 
                    941:        clrq(&tp->t_iq);
                    942:        clrq(&tp->t_oq);
                    943: 
                    944:        if (tp->t_flags & T_INPUT)
                    945:                defer(wakeup, (char *) &tp->t_iq);
                    946: 
                    947:        if (tp->t_flags & (T_DRAIN|T_HILIM))
                    948:                defer(wakeup, (char *) &tp->t_oq);
                    949: 
                    950:        if (tp->t_ipolls.e_procp != 0) {
                    951:                tp->t_ipolls.e_procp = 0;
                    952:                defer(pollwake, (char *) &tp->t_ipolls);
                    953:        }
                    954: 
                    955:        if (tp->t_opolls.e_procp != 0) {
                    956:                tp->t_opolls.e_procp = 0;
                    957:                defer(pollwake, (char *) &tp->t_opolls);
                    958:        }
                    959: 
                    960:        tp->t_ibx = 0;
                    961:        tp->t_escape = 0;
                    962:        s = sphi();
                    963:        tp->t_flags &= T_SAVE;  /* reset most flag bits */
                    964:        spl(s);
                    965: }
                    966: 
                    967: /*
                    968:  * ttsignal()
                    969:  *
                    970:  *     Send a signal to every process in the given process group.
                    971:  */
                    972: void ttsignal(tp, sig)
                    973: TTY *tp;
                    974: int sig;
                    975: {
                    976:        register int g;
                    977:        register PROC *pp;
                    978: 
                    979:        g = tp->t_group;
                    980: #if DEBUG
                    981: printf("ttsignal sig=%d gp=%d\n", sig, g);     
                    982: #endif
                    983:        if (g == 0)
                    984:                goto sigdone;
                    985:        ttflush(tp);
                    986:        pp = &procq;
                    987:        while ((pp=pp->p_nforw) != &procq)
                    988:                if (pp->p_group == g) {
                    989:                        sendsig(sig, pp);
                    990:                }
                    991: sigdone:
                    992:        return;
                    993: }
                    994: 
                    995: /*
                    996:  * tthup()
                    997:  *
                    998:  *     Flag hangup internally to force errors on tty read/write, flush tty,
                    999:  *     then send hangup signal.
                   1000:  */
                   1001: void tthup(tp)
                   1002: register TTY *tp;
                   1003: {
                   1004:        ttflush(tp);
                   1005:        ttsignal(tp, SIGHUP);
                   1006: }

unix.superglobalmegacorp.com

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