Annotation of coherent/d/286_KERNEL/USRSRC/io/tty.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * File:       $USRSRC/ttydrv/tty.c
        !             3:  *
        !             4:  * Purpose:    COHERENT line discipline module.
        !             5:  *     This is the common part of typewriter service. It handles all device-
        !             6:  *     independent aspects of a typewriter, including tandem flow control,
        !             7:  *     erase and kill, stop and start, and common ioctl functions.
        !             8:  *
        !             9:  * $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.