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

unix.superglobalmegacorp.com

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