Annotation of researchv10no/sys/io/nttyld.c, revision 1.1.1.1

1.1       root        1: #include "sys/param.h"
                      2: #include "sys/stream.h"
                      3: #include "sys/ttyio.h"
                      4: #include "sys/nttyio.h"
                      5: #include "sys/ttyld.h"
                      6: #include "sys/nttyld.h"
                      7: #include "sys/conf.h"
                      8: #include "sys/file.h"
                      9: 
                     10: extern char    maptab[],       /* see dev/ttyld.c */
                     11:                partab[];       /* see sys/partab.c */
                     12: 
                     13: 
                     14: extern struct nttyld ntty[];
                     15: extern int nttycnt;
                     16: 
                     17: int    ntclose(),      /* queue close routine */
                     18:        ntin(),         /* reader queue put routine */
                     19:        ntinsrv(),      /* reader queue service routine */
                     20:        ntout(),        /* writer queue put routine */
                     21:        ntoutsrv();     /* writer queue service routine */
                     22: long   ntopen();       /* queue open routine */
                     23: 
                     24: static struct qinit    rinit = { ntin, ntinsrv, ntopen, ntclose, 300, 0 },
                     25:                        winit = { ntout, ntoutsrv, ntopen, ntclose, 300, 200 };
                     26: struct streamtab       nttystream = { &rinit, &winit };
                     27: 
                     28: #define        CANBSIZ 256     /* why not NT_NIN? */
                     29: 
                     30: /*
                     31:  * Backspace over "n" characters, perhaps erasing them.
                     32:  * Called from ntrubout().
                     33:  */
                     34: 
                     35: ntbs (nt, n)
                     36:        register struct nttyld  *nt;
                     37:        register int            n;
                     38: {
                     39:        while (--n >= 0)
                     40:                if (putd (putq, nt->nt_outq, '\b')) {
                     41:                        nt->nt_state |= NT_ECHO;
                     42:                        if (nt->nt_local & LCRTERA) {
                     43:                                (void) putd (putq, nt->nt_outq, ' ');
                     44:                                (void) putd (putq, nt->nt_outq, '\b');
                     45:                        }
                     46:                }
                     47:        return;
                     48: }
                     49: 
                     50: 
                     51: /*
                     52:  * Set default control characters.
                     53:  * Called by ntopen().
                     54:  */
                     55: 
                     56: ntchars (nt)
                     57:        register struct nttyld  *nt;
                     58: {
                     59:        static struct tchars    tchars = { CINTR, CQUIT, CSTART, CSTOP, CEOT, 
                     60:                                    0377 };
                     61:        static struct ltchars   ltchars = { CSUSP, CDSUSP, CRPRNT, CFLUSH,
                     62:                                    CWERAS, CLNEXT };
                     63: 
                     64:        nt->nt_erase = CERASE;
                     65:        nt->nt_kill = CKILL;
                     66:        nt->nt_tchr = tchars;
                     67:        nt->nt_ltchr = ltchars;
                     68:        return;
                     69: }
                     70: 
                     71: 
                     72: ntclose (q)
                     73:        register struct queue   *q;
                     74: {
                     75:        register struct nttyld  *nt = (struct nttyld *) q->ptr;
                     76: 
                     77:        nt->nt_state = 0;
                     78:        return;
                     79: }
                     80: 
                     81: 
                     82: /*
                     83:  * Put input buffer on read queue followed by a delimiter.
                     84:  * Called from ntinc() when a line break character is read,
                     85:  * and from ntioctl() when switching from cooked to raw or cbreak mode.
                     86:  */
                     87: 
                     88: ntcooked (nt)
                     89:        register struct nttyld  *nt;
                     90: {
                     91:        register char           *s, *t;
                     92:        register struct block   *b;
                     93:        register struct queue   *q = RD (nt->nt_outq);
                     94: 
                     95:        if (!(q->flag & QFULL) && (b = allocb (1))) {
                     96:                for (t = (s = nt->nt_in) + nt->nt_nin; s < t; s++)
                     97:                        (void) putd (putq, q, *s);
                     98:                b->class |= S_DELIM;
                     99:                putq (q, b);
                    100:                nt->nt_delct++;
                    101:        }
                    102:        qenable (q);
                    103:        nt->nt_nin = 0;
                    104:        nt->nt_trash = 0;
                    105:        return;
                    106: }
                    107: 
                    108: 
                    109: /*
                    110:  * Echo a typed character to a terminal.
                    111:  */
                    112: 
                    113: ntecho (c, nt)
                    114:        register int            c;
                    115:        register struct nttyld  *nt;
                    116: {
                    117:        register struct queue   *echoq = nt->nt_outq;
                    118: 
                    119:        nt->nt_local &= ~LFLUSHO;
                    120:        if (!(nt->nt_flags & ECHO) || echoq->flag & QFULL)
                    121:                return;
                    122:        c &= 0377;
                    123:        if (nt->nt_flags & RAW)
                    124:                goto out;
                    125:        if (c == '\r' && nt->nt_flags & CRMOD)
                    126:                c = '\n';
                    127:        if (c != '\n' && c != '\t' && nt->nt_local & LCTLECH)
                    128:                if ((c &= 0177) <= 037 || c == 0177) {
                    129:                        (void) putd (putq, echoq, '^');
                    130:                        if (c == 0177)
                    131:                                c = '?';
                    132:                        else if (nt->nt_flags & LCASE)
                    133:                                c += 'a' - 1;
                    134:                        else    c += 'A' - 1;
                    135:                        goto out;
                    136:                }
                    137: 
                    138:        if ((c &= 0177) == CEOT)        /* terminals don't like it */
                    139:                return;
                    140: 
                    141: out:
                    142:        if (putd (putq, echoq, c))
                    143:                nt->nt_state |= NT_ECHO;
                    144:        return;
                    145: }
                    146: 
                    147: 
                    148: /*
                    149:  * Flush all input and/or all output tty queues.
                    150:  */
                    151: 
                    152: ntflush (nt, rw)
                    153:        struct nttyld   *nt;
                    154:        int             rw;
                    155: {
                    156:        struct queue    *wrq = nt->nt_outq, 
                    157:                        *rdq = RD (wrq);
                    158: 
                    159:        if (rw & FREAD) {
                    160:                flushq (rdq, 0);
                    161:                (void) putctl (rdq->next, M_FLUSH);
                    162:                nt->nt_delct = 0;
                    163:                nt->nt_nin = 0;
                    164:                nt->nt_trash = 0;
                    165:                nt->nt_lstate = 0;
                    166:        }
                    167:        if (rw & FWRITE) {
                    168:                flushq (wrq, 0);
                    169:                (void) putctl (wrq->next, M_FLUSH);
                    170:        }
                    171:        return;
                    172: }
                    173: 
                    174: 
                    175: /*
                    176:  * Reader queue (input from tty) put routine.
                    177:  */
                    178: 
                    179: ntin (q, b)
                    180:        struct queue            *q;
                    181:        register struct block   *b;
                    182: {
                    183:        register struct nttyld  *nt = (struct nttyld *) q->ptr;
                    184: 
                    185:        switch (b->type) {
                    186:        case M_DATA:
                    187:                if (nt->nt_flags & RAW && !(nt->nt_flags & ECHO))
                    188:                        break;
                    189:                nt->nt_state &= ~NT_ECHO;
                    190:                while (b->rptr < b->wptr)
                    191:                        ntinc ((int) *b->rptr++, nt);
                    192:                freeb (b);
                    193:                if (nt->nt_state & NT_ECHO && nt->nt_outq->next->flag & QDELIM)
                    194:                        (void) qpctld (nt->nt_outq, M_DATA);
                    195:                return;
                    196:        case M_BREAK:
                    197:                if (nt->nt_flags & RAW) {               /* speed-change hack */
                    198:                        b->type = M_DATA;
                    199:                        if (b->wptr < b->lim)
                    200:                                *b->wptr++ = '\0';
                    201:                        break;
                    202:                }
                    203:                (void) putctl1 (q->next, M_SIGNAL, SIGINT);
                    204:                ntflush (nt, FREAD | FWRITE);
                    205:                freeb (b);
                    206:                return;
                    207:        case M_HANGUP:
                    208:                (*q->next->qinfo->putp)(q->next, b);
                    209:                return;
                    210:        }
                    211: 
                    212:        if (q->next->flag & QFULL)
                    213:                freeb (b);
                    214:        else    (*q->next->qinfo->putp)(q->next, b);
                    215:        return;
                    216: }
                    217: 
                    218: 
                    219: /*
                    220:  * Process a single input character.
                    221:  * Called (at interrupt level) by ntin().
                    222:  */
                    223: 
                    224: ntinc (c, nt)
                    225:        register                c;
                    226:        register struct nttyld  *nt;
                    227: {
                    228:        register int    t_flags;
                    229: 
                    230:        c &= 0377;
                    231:        t_flags = nt->nt_flags;
                    232: 
                    233:        if (t_flags & RAW) {
                    234:                if (!(nt->nt_readq->next->flag & QFULL))
                    235:                        if (putd (nt->nt_readq->next->qinfo->putp, nt->nt_readq->next, c))
                    236:                                ntecho (c, nt);
                    237:                return;
                    238:        }
                    239: 
                    240:        if (!(nt->nt_lstate & LSTYPEN))
                    241:                c &= 0177;
                    242: 
                    243:        /*
                    244:         * Interpret literal-next-character control character (^V).
                    245:         */
                    246:        if (nt->nt_lstate & LSLNCH) {
                    247:                c |= 0200;
                    248:                nt->nt_lstate &= ~LSLNCH;
                    249:        }
                    250:        if (c == nt->nt_lnextc) {
                    251:                nt->nt_lstate |= LSLNCH;
                    252:                if (nt->nt_flags & ECHO)
                    253:                        if (putd (putq, nt->nt_outq, '^')) {
                    254:                                nt->nt_state |= NT_ECHO;
                    255:                                (void) putd (putq, nt->nt_outq, '\b');
                    256:                        }
                    257:                return;
                    258:        }
                    259: 
                    260:        if (ntstst (c, nt) ||           /* start, stop */
                    261:            ntoflush (c, nt) ||         /* flush output */
                    262:            ntsigc (c, nt))             /* interrupt/quit/stop */
                    263:                return;
                    264: 
                    265:        if (c == '\r' && t_flags & CRMOD)
                    266:                c = '\n';
                    267:        if (t_flags & LCASE && c >= 'A' && c <= 'Z')
                    268:                c += 'a' - 'A';
                    269: 
                    270:        if (t_flags & CBREAK) {
                    271:                if (nt->nt_readq->next->flag & QFULL) {
                    272:                        if (putd (putq, nt->nt_outq, CTRL('g')))
                    273:                                nt->nt_state |= NT_ECHO;
                    274:                }
                    275: #ifdef notdef
                    276:                else if (c == nt->nt_dsuspc)
                    277:                        (void) putctl1 (nt->nt_readq->next, M_SSIGNAL, SIGTSTP);
                    278: #endif
                    279:                else if (putd (nt->nt_readq->next->qinfo->putp, nt->nt_readq->next, c&0177))
                    280:                        ntecho (c, nt);
                    281:                return;
                    282:        }
                    283: 
                    284:        if (nt->nt_lstate & LSQUOT) {
                    285:                nt->nt_lstate &= ~LSQUOT;
                    286:                if (c == nt->nt_erase || c == nt->nt_kill) {
                    287:                        c |= 0200;
                    288:                        ntrubout (nt);
                    289:                }
                    290:        }
                    291:        if (c == '\\')
                    292:                nt->nt_lstate |= LSQUOT;
                    293: 
                    294:        if (c == nt->nt_erase)
                    295:                ntrubout (nt);          /* erase character */
                    296:        else if (c == nt->nt_kill)
                    297:                ntkill (nt);            /* erase line */
                    298:        else if (c == nt->nt_werasc)
                    299:                ntwerase (nt);          /* erase word */
                    300:        else if (c == nt->nt_rprntc)
                    301:                ntreprint (nt);         /* reprint line */
                    302:        else {
                    303:                if (nt->nt_nin < NT_NIN) {
                    304:                        if (nt->nt_nin == 0)
                    305:                                nt->nt_rocol = nt->nt_col;
                    306:                        nt->nt_in[nt->nt_nin++] = c;
                    307:                }
                    308:                else {
                    309:                        if (putd (putq, nt->nt_outq, CTRL('g')))
                    310:                                nt->nt_state |= NT_ECHO;
                    311:                        return;
                    312:                }
                    313: 
                    314:                if (c == '\n' || c == nt->nt_eofc || c == nt->nt_brkc ||
                    315:                    c == '\r' && (nt->nt_flags & CRMOD))
                    316:                        ntcooked (nt);
                    317: 
                    318:                if (nt->nt_lstate & LSERASE) {
                    319:                        nt->nt_lstate &= ~LSERASE;
                    320:                        if (putd (putq, nt->nt_outq, '/'))
                    321:                                nt->nt_state |= NT_ECHO;
                    322:                }
                    323: 
                    324:                ntecho (c, nt);
                    325:                if (c == nt->nt_eofc && nt->nt_flags & ECHO && 
                    326:                    nt->nt_local & LCTLECH)
                    327:                        if (putd (putq, nt->nt_outq, '\b')) {
                    328:                                nt->nt_state |= NT_ECHO;
                    329:                                (void) putd (putq, nt->nt_outq, '\b');
                    330:                        }
                    331:        }
                    332:        return;
                    333: }
                    334: 
                    335: 
                    336: /*
                    337:  * Reader queue (tty input) service routine.
                    338:  * Only cooked mode data and delimiters come through here, via ntcooked().
                    339:  */
                    340: 
                    341: ntinsrv (q)
                    342:        register struct queue   *q;
                    343: {
                    344:        register struct nttyld  *nt;
                    345:        register struct block   *b;
                    346:        register char           *op;
                    347:        register int            c;
                    348:        static char             canonb[CANBSIZ];
                    349: 
                    350:        if (q->next->flag & QFULL)
                    351:                return;
                    352:        nt = (struct nttyld *) q->ptr;
                    353:        op = canonb;
                    354:        while (nt->nt_delct) {
                    355:                b = getq(q);
                    356:                if (b == NULL) {
                    357:                        if (op > canonb)
                    358:                                putcpy (q->next, canonb, op - canonb);
                    359:                        return;
                    360:                }
                    361:                while (b->rptr < b->wptr) {
                    362:                        c = *b->rptr++;
                    363:                        if (c & 0200) {         /* escaped */
                    364:                                c &= 0177;
                    365:                                if (nt->nt_flags & LCASE && maptab[c])
                    366:                                        c = maptab[c];
                    367:                                else if (c != nt->nt_erase &&
                    368:                                       c != nt->nt_kill && c != nt->nt_eofc)
                    369:                                        *op++ = '\\';
                    370:                        }
                    371:                        else {
                    372: #ifdef notdef
                    373:                                /*
                    374:                                 * Interpret delayed stop process
                    375:                                 * control character (^Y).
                    376:                                 */
                    377:                                if (c == nt->nt_dsuspc) {
                    378:                                        putcpy (q->next, canonb, op - canonb);
                    379:                                        op = canonb;
                    380:                                        (void) putctl1 (q->next, M_SSIGNAL, 
                    381:                                            SIGTSTP);
                    382:                                        continue;
                    383:                                }
                    384: #endif
                    385:                                if (c == nt->nt_eofc)
                    386:                                        continue;
                    387:                        }
                    388:                        *op++ = c;
                    389:                        if (op >= &canonb[CANBSIZ-1]) {
                    390:                                putcpy (q->next, canonb, op - canonb);
                    391:                                op = canonb;
                    392:                        }
                    393:                }
                    394:                if ((b->class & S_DELIM) == 0)
                    395:                        freeb(b);
                    396:                else {          /* end of line */
                    397:                        if (op > canonb)
                    398:                                putcpy(q->next, canonb, op - canonb);
                    399:                        (*q->next->qinfo->putp)(q->next, b);    /* empty S_DELIM */
                    400:                        nt->nt_delct--;
                    401:                        op = canonb;
                    402:                }
                    403:        }
                    404: 
                    405:        return;
                    406: }
                    407: 
                    408: 
                    409: /*
                    410:  * Acknowledge ioctl message.
                    411:  * Called by ntioctl().
                    412:  */
                    413: 
                    414: ntiocack (q, b, n)
                    415:        register struct queue   *q;
                    416:        register struct block   *b;
                    417:        register int            n;
                    418: {
                    419:        if (n > 0)
                    420:                n += sizeof (int);      /* for ioctl command */
                    421:        b->wptr = b->rptr + n;
                    422:        b->type = M_IOCACK;
                    423:        qreply (q, b);
                    424:        return;
                    425: }
                    426: 
                    427: 
                    428: /*
                    429:  * Terminal I/O control operations.
                    430:  * Called by ntoutsrv().
                    431:  */
                    432: 
                    433: ntioctl (q, b)
                    434:        register struct queue   *q;
                    435:        register struct block   *b;
                    436: {
                    437:        register struct nttyld  *nt = (struct nttyld *) q->ptr;
                    438:        register struct ntioc   *ioc = (struct ntioc *) b->rptr;
                    439:        int                     s;
                    440: 
                    441:        switch (ioc->command) {
                    442: 
                    443:        /*
                    444:         * Set new parameters
                    445:         */
                    446:        case TIOCSETP:
                    447:        case TIOCSETN:
                    448:                s = spl6();
                    449:                if (ioc->arg.sg.sg_flags & (RAW|CBREAK) &&
                    450:                    !(nt->nt_flags & (RAW|CBREAK))) {
                    451:                        /*
                    452:                         * Before leaving cooked mode, push through
                    453:                         * any characters that made it to ntin().
                    454:                         */
                    455:                        if (nt->nt_nin > 0)
                    456:                                ntcooked (nt);
                    457:                        ntinsrv (RD (nt->nt_outq));
                    458:                }
                    459:                nt->nt_erase = ioc->arg.sg.sg_erase;
                    460:                nt->nt_kill = ioc->arg.sg.sg_kill;
                    461:                nt->nt_flags = ioc->arg.sg.sg_flags;
                    462:                nt->nt_readq->flag &= ~QDELIM;
                    463:                if ((nt->nt_flags & (RAW|CBREAK))==0)
                    464:                        nt->nt_readq->flag |= QDELIM;
                    465:                splx (s);
                    466: 
                    467:                ntiocack (q, b, 0);
                    468:                break;
                    469: 
                    470:        /*
                    471:         * Send current parameters to user
                    472:         */
                    473:        case TIOCGETP:
                    474:                ioc->arg.sg.sg_erase = nt->nt_erase;
                    475:                ioc->arg.sg.sg_kill = nt->nt_kill;
                    476:                ioc->arg.sg.sg_flags = nt->nt_flags;
                    477:                ioc->arg.sg.sg_ispeed =
                    478:                 ioc->arg.sg.sg_ospeed = B9600;
                    479: 
                    480:                b->wptr = b->rptr + sizeof (int) + sizeof (struct sgttyb);
                    481:                b->wptr = 2 + b->rptr + sizeof (int) + sizeof (struct sgttyb);
                    482:                ntiocack (q, b, sizeof (struct sgttyb));
                    483:                break;
                    484: 
                    485:        /*
                    486:         * Set/get special characters
                    487:         */
                    488:        case TIOCSETC:
                    489:                nt->nt_tchr = ioc->arg.tchr;
                    490:                ntiocack (q, b, 0);
                    491:                break;
                    492: 
                    493:        case TIOCGETC:
                    494:                ioc->arg.tchr = nt->nt_tchr;
                    495:                ntiocack (q, b, sizeof (struct tchars));
                    496:                break;
                    497: 
                    498:        /*
                    499:         * Set/get local special characters.
                    500:         */
                    501:        case TIOCSLTC:
                    502:                nt->nt_ltchr = ioc->arg.ltchr;
                    503:                ntiocack (q, b, 0);
                    504:                break;
                    505: 
                    506:        case TIOCGLTC:
                    507:                ioc->arg.ltchr = nt->nt_ltchr;
                    508:                ntiocack (q, b, sizeof (struct ltchars));
                    509:                break;
                    510: 
                    511:        /*
                    512:         * Modify local mode word.
                    513:         */
                    514:        case TIOCLBIS:
                    515:                nt->nt_local |= ioc->arg.local;
                    516:                ntiocack (q, b, 0);
                    517:                break;
                    518: 
                    519:        case TIOCLBIC:
                    520:                nt->nt_local &= ~ioc->arg.local;
                    521:                ntiocack (q, b, 0);
                    522:                break;
                    523: 
                    524:        case TIOCLSET:
                    525:                nt->nt_local = ioc->arg.local;
                    526:                ntiocack (q, b, 0);
                    527:                break;
                    528: 
                    529:        case TIOCLGET:
                    530:                ioc->arg.local = nt->nt_local;
                    531:                ntiocack (q, b, sizeof (short));
                    532:                break;
                    533: 
                    534:        /*
                    535:         * Return number of characters in the output.
                    536:         */
                    537:        case TIOCOUTQ:
                    538: 
                    539:        default:
                    540:                (*q->next->qinfo->putp)(q->next, b);
                    541:                break;
                    542:        }
                    543: 
                    544:        return;
                    545: }
                    546: 
                    547: 
                    548: /*
                    549:  * Erase entire input buffer.
                    550:  * Called by ntinc().
                    551:  */
                    552: 
                    553: ntkill (nt)
                    554:        register struct nttyld  *nt;
                    555: {
                    556:        if (nt->nt_local & LCRTKIL && !nt->nt_trash) {
                    557:                while (nt->nt_nin > 0)
                    558:                        ntrubout (nt);
                    559:        }
                    560:        else {
                    561:                ntecho (nt->nt_kill, nt);
                    562:                ntecho ('\n', nt);
                    563:                nt->nt_nin = 0;
                    564:                nt->nt_trash = 0;
                    565:        }
                    566:        nt->nt_lstate = 0;
                    567:        return;
                    568: }
                    569: 
                    570: 
                    571: /*
                    572:  * Interpret the flush-output (^O) control character.
                    573:  * Called by ntinc().
                    574:  */
                    575: 
                    576: int
                    577: ntoflush (c, nt)
                    578:        register int            c;
                    579:        register struct nttyld  *nt;
                    580: {
                    581:        if (nt->nt_local & LFLUSHO) {
                    582:                nt->nt_local &= ~LFLUSHO;
                    583:                if (c == nt->nt_flushc)
                    584:                        return (1);
                    585:        }
                    586:        else    if (c == nt->nt_flushc) {
                    587:                        ntflush (nt, FWRITE);
                    588:                        ntecho (c, nt);
                    589:                        ntreprint (nt);
                    590:                        nt->nt_local |= LFLUSHO;
                    591:                        return (1);
                    592:                }
                    593: 
                    594:        return (0);
                    595: }
                    596: 
                    597: 
                    598: /*ARGSUSED*/
                    599: 
                    600: long
                    601: ntopen (q, dev)
                    602:        register struct queue   *q;
                    603:        int                     dev;
                    604: {
                    605:        register struct nttyld  *nt;
                    606: 
                    607:        if (q->ptr)
                    608:                return (1);             /* already attached */
                    609: 
                    610:        for (nt = ntty; nt->nt_state & NT_USE; nt++)
                    611:                if (nt >= &ntty[nttycnt-1])
                    612:                        return (0);
                    613: 
                    614:        WR (q)->ptr = q->ptr = (caddr_t) nt;
                    615:        nt->nt_outq = WR (q);
                    616:        nt->nt_readq = q;
                    617:        nt->nt_nin = 0;
                    618:        nt->nt_state = NT_USE;
                    619:        nt->nt_flags = ECHO | CRMOD;
                    620:        nt->nt_col = 0;
                    621:        nt->nt_delct = 0;
                    622:        ntchars (nt);                   /* set default control characters */
                    623:        nt->nt_trash = 0;
                    624:        nt->nt_local = 0;
                    625:        nt->nt_lstate = 0;
                    626:        q->flag |= QDELIM;
                    627:        return (1);
                    628: }
                    629: 
                    630: 
                    631: /*
                    632:  * Writer queue (output to tty) put routine.
                    633:  */
                    634: 
                    635: ntout (wrq, b)
                    636:        register struct queue   *wrq;
                    637:        register struct block   *b;
                    638: {
                    639:        if (b->type == M_DATA)
                    640:                b->type = M_CTL;                /* see ntoutsrv() */
                    641:        putq (wrq, b);
                    642:        return;
                    643: }
                    644: 
                    645: 
                    646: /*
                    647:  * Output a block of data to a terminal.
                    648:  * Handle tab expansion, case conversion, turning CR to CRLF, delays, etc.
                    649:  * Called from ntoutsrv().
                    650:  */
                    651: 
                    652: ntoutb (nt, ib)
                    653:        register struct nttyld  *nt;
                    654:        register struct block   *ib;
                    655: {
                    656:        register struct block   *ob = 0;
                    657:        register struct queue   *q = nt->nt_outq;
                    658:        register int            c, delay, ctype;
                    659:        char                    *colp;
                    660: 
                    661:        while (ib->rptr < ib->wptr) {
                    662:                if (!ob || ob->wptr >= ob->lim) {
                    663:                        if (ob) {
                    664:                                if (nt->nt_local & LFLUSHO)
                    665:                                        break;
                    666:                                (*q->next->qinfo->putp)(q->next, ob);
                    667:                        }
                    668:                        if (q->next->flag & QFULL || !(ob = allocb (QBSIZE))) {
                    669:                                putbq (q, ib);
                    670:                                return;
                    671:                        }
                    672:                }
                    673: 
                    674:                switch (c = *ib->rptr++ & 0177) {
                    675:                case '\t':
                    676:                        if ((nt->nt_flags & TBDELAY) != XTABS)
                    677:                                break;
                    678: 
                    679:                        /*
                    680:                         * Expand tabs to spaces.
                    681:                         */
                    682:                        for (;;) {
                    683:                                *ob->wptr++ = ' ';
                    684:                                nt->nt_col++;
                    685:                                if ((nt->nt_col & 07) == 0)     /* every 8 */
                    686:                                        break;
                    687:                                if (ob->wptr >= ob->lim) {
                    688:                                        ib->rptr--;
                    689:                                        break;
                    690:                                }
                    691:                        }
                    692:                        continue;
                    693:                case '\n':
                    694:                        if (!(nt->nt_flags & CRMOD))
                    695:                                break;
                    696: 
                    697:                        /*
                    698:                         * Turn <nl> to <cr><lf>.
                    699:                         */
                    700:                        if (nt->nt_state & NT_CR)
                    701:                                nt->nt_state &= ~NT_CR;
                    702:                        else {
                    703:                                nt->nt_state |= NT_CR;
                    704:                                c = '\r';
                    705:                                ib->rptr--;
                    706:                        }
                    707:                        break;
                    708:                case '~':
                    709:                        if (nt->nt_local & LTILDE)
                    710:                                c = '`';
                    711:                        /* no break */
                    712:                default:
                    713:                        if (!(nt->nt_flags & LCASE))
                    714:                                break;
                    715: 
                    716:                        /*
                    717:                         * Generate escapes for upper-case-only terminals.
                    718:                         */
                    719:                        if (nt->nt_state & NT_CASE) {
                    720:                                nt->nt_state &= ~NT_CASE;
                    721:                                break;
                    722:                        }
                    723: 
                    724:                        for (colp = "{(})|!~^`'"; *colp && c != *colp; 
                    725:                            colp += 2);
                    726: 
                    727:                        if (*colp || c >= 'A' && c <= 'Z') {
                    728:                                *--ib->rptr = *colp ? colp[1] : c;
                    729:                                nt->nt_state |= NT_CASE;
                    730:                                c = '\\';
                    731:                        }
                    732:                        else if (c >= 'a' && c <= 'z')
                    733:                                c += 'A' - 'a';
                    734:                        break;
                    735:                }
                    736: 
                    737:                /*
                    738:                 * Store character.
                    739:                 */
                    740:                *ob->wptr++ = c;
                    741: 
                    742:                /*
                    743:                 * Calculate delays and column movement.
                    744:                 * The delay values are in clock ticks and aren't
                    745:                 * necessarily optimal for all terminals.
                    746:                 */
                    747:                delay = 0;
                    748: 
                    749:                switch (ctype = partab[c] & 077) {
                    750:                case ORDINARY:
                    751:                        nt->nt_col++;
                    752:                        break;
                    753:                case CONTROL:
                    754:                        break;
                    755:                case BACKSPACE:
                    756:                        if (nt->nt_col)
                    757:                                nt->nt_col--;
                    758:                        break;
                    759:                case NEWLINE:
                    760:                        ctype = (nt->nt_flags >> 8) & 03;
                    761:                        if (ctype == 1) {       /* tty 37 */
                    762:                                if (nt->nt_col)
                    763:                                        if ((delay = nt->nt_col >> 4) < 6)
                    764:                                                delay = 6;
                    765:                        }
                    766:                        else if (ctype == 2)    /* vt05 */
                    767:                                delay = 6;
                    768:                        if (!(nt->nt_flags & CRMOD))
                    769:                                nt->nt_col = 0;
                    770:                        break;
                    771:                case TAB:
                    772:                        ctype = (nt->nt_flags >> 10) & 03;
                    773:                        if (ctype == 1)         /* tty 37 */
                    774:                                if ((delay = 1 - (nt->nt_col | ~07)) < 5)
                    775:                                        delay = 0;
                    776:                        nt->nt_col |= 07;
                    777:                        nt->nt_col++;
                    778:                        break;
                    779:                case VTAB:
                    780:                        if (nt->nt_flags & VTDELAY)
                    781:                                delay = 127;
                    782:                        break;
                    783:                case RETURN:
                    784:                        ctype = (nt->nt_flags >> 12) & 03;
                    785:                        if (ctype == 1)          /* tn 300 */
                    786:                                delay = 5;
                    787:                        else if (ctype == 2)    /* ti 700 */
                    788:                                delay = 10;
                    789:                        else if (ctype == 3)    /* concept 100 */
                    790:                                if ((delay = 9 - nt->nt_col) < 0)
                    791:                                        delay = 0;
                    792:                        nt->nt_col = 0;
                    793:                        break;
                    794:                }
                    795: 
                    796:                if (delay) {
                    797:                        if (nt->nt_local & LFLUSHO)
                    798:                                break;
                    799:                        (*q->next->qinfo->putp)(q->next, ob);
                    800:                        if (ob = allocb(1)) {
                    801:                                ob->type = M_DELAY;
                    802:                                *ob->wptr++ = delay;
                    803:                                (*q->next->qinfo->putp)(q->next, ob);
                    804:                        }
                    805:                        ob = 0;
                    806:                }
                    807:        }
                    808: 
                    809:        if (ib->class & S_DELIM) {
                    810:                if (ob == NULL)
                    811:                        ob = allocb(0);
                    812:                if (ob)
                    813:                        ob->class |= S_DELIM;
                    814:        }
                    815:        freeb(ib);
                    816:        if (ob) {
                    817:                if (nt->nt_local & LFLUSHO)
                    818:                        freeb(ob);
                    819:                else
                    820:                        (*q->next->qinfo->putp)(q->next, ob);
                    821:        }
                    822: }
                    823: 
                    824: 
                    825: /*
                    826:  * Writer queue (tty output) service routine.
                    827:  * All tty output comes through here.  Upstream data comes in M_CTL
                    828:  * blocks via ntout(); echoed data comes in M_DATA blocks.
                    829:  */
                    830: 
                    831: ntoutsrv (q)
                    832:        register struct queue   *q;
                    833: {
                    834:        register struct nttyld  *nt = (struct nttyld *) q->ptr;
                    835:        register struct block   *b;
                    836: 
                    837:        while (b = getq (q))
                    838:                switch (b->type) {
                    839:                default:
                    840:                        freeb (b);
                    841:                        continue;
                    842:                case M_BREAK:
                    843:                        if (q->next->flag & QFULL) {
                    844:                                putbq (q, b);
                    845:                                return;
                    846:                        }
                    847:                        (*q->next->qinfo->putp)(q->next, b);
                    848:                        continue;
                    849:                case M_IOCTL:
                    850:                        if (q->next->flag & QFULL) {
                    851:                                putbq (q, b);
                    852:                                return;
                    853:                        }
                    854:                        ntioctl (q, b);
                    855:                        continue;
                    856:                case M_FLUSH:
                    857:                        flushq (q, 0);
                    858:                        /* no break */
                    859:                case M_IOCNAK:
                    860:                case M_IOCACK:
                    861:                        (*q->next->qinfo->putp)(q->next, b);
                    862:                        continue;
                    863:                case M_CTL:
                    864:                case M_DATA:
                    865:                        if (nt->nt_local & LFLUSHO) {
                    866:                                freeb (b);
                    867:                                continue;
                    868:                        }
                    869:                        if (q->next->flag & QFULL) {
                    870:                                putbq (q, b);
                    871:                                return;
                    872:                        }
                    873:                        if (b->type == M_CTL) {
                    874:                                b->type = M_DATA;
                    875:                                nt->nt_trash = nt->nt_nin;
                    876:                        }
                    877:                        if (nt->nt_flags & RAW || nt->nt_local & LLITOUT) {
                    878:                                (*q->next->qinfo->putp)(q->next, b);
                    879:                        }
                    880:                        else    ntoutb (nt, b);
                    881:                        continue;
                    882:                }
                    883: 
                    884:        return;
                    885: }
                    886: 
                    887: 
                    888: /*
                    889:  * Reprint input buffer.
                    890:  */
                    891: 
                    892: ntreprint (nt)
                    893:        register struct nttyld  *nt;
                    894: {
                    895:        register char   *in;
                    896:        register int    nin;
                    897: 
                    898:        if (nt->nt_rprntc != 0377)
                    899:                ntecho ((int) nt->nt_rprntc, nt);
                    900:        (void) putd (putq, nt->nt_outq, '\n');
                    901:        for (in = nt->nt_in, nin = nt->nt_nin; nin > 0; in++, nin--)
                    902:                ntecho (*in, nt);
                    903:        nt->nt_lstate &= ~LSERASE;
                    904:        nt->nt_trash = 0;
                    905:        return;
                    906: }
                    907: 
                    908: 
                    909: /*
                    910:  * Rubout the last character of the input buffer.
                    911:  */
                    912: 
                    913: ntrubout (nt)
                    914:        register struct nttyld  *nt;
                    915: {
                    916:        register int    c, cc, col, i;
                    917: 
                    918:        if (nt->nt_nin <= 0)
                    919:                return;
                    920:        c = nt->nt_in[--nt->nt_nin];
                    921: 
                    922:        if (!(nt->nt_flags & ECHO))
                    923:                return;
                    924: 
                    925:        nt->nt_local &= ~LFLUSHO;
                    926: 
                    927:        if (nt->nt_local & LPRTERA) {
                    928:                if (!(nt->nt_lstate & LSERASE)) {
                    929:                        (void) putd (putq, nt->nt_outq, '\\');
                    930:                        nt->nt_lstate |= LSERASE;
                    931:                }
                    932:                ntecho (c, nt);
                    933:                return;
                    934:        }
                    935: 
                    936:        if (!(nt->nt_local & LCRTBS)) {
                    937:                ntecho (nt->nt_erase, nt);
                    938:                return;
                    939:        }
                    940: 
                    941:        if (nt->nt_trash > nt->nt_nin) {
                    942:                ntreprint (nt);
                    943:                return;
                    944:        }
                    945: 
                    946:        if (c == ('\t'|0200) || c == ('\n'|0200)) {
                    947:                ntbs (nt, 2);
                    948:                return;
                    949:        }
                    950: 
                    951:        switch (partab[c&=0177] & 0177) {
                    952:        case ORDINARY:
                    953:                if (nt->nt_flags&LCASE && c >= 'A' && c <= 'Z')
                    954:                        ntbs (nt, 2);
                    955:                else    ntbs (nt, 1);
                    956:                break;
                    957:        case TAB:
                    958:                for (col = nt->nt_rocol, i = 0; i < nt->nt_nin; i++) {
                    959:                        cc = nt->nt_in[i];
                    960:                        if (cc == ('\t'|0200) || cc == ('\n'|0200)) {
                    961:                                col += 2;
                    962:                                continue;
                    963:                        }
                    964:                        switch (partab[cc&=0177] & 0177) {
                    965:                        case ORDINARY:
                    966:                                if (nt->nt_flags&LCASE && cc>='A' && cc<='Z')
                    967:                                        col += 2;
                    968:                                else    col++;
                    969:                                break;
                    970:                        case TAB:
                    971:                                col = (col + 8) & ~7;
                    972:                                break;
                    973:                        default:
                    974:                                if (nt->nt_local & LCTLECH)
                    975:                                        col += 2;
                    976:                                break;
                    977:                        }
                    978:                }
                    979:                ntbs (nt, 8 - (col & 7));
                    980:                break;
                    981:        default:
                    982:                if (nt->nt_local & LCTLECH)
                    983:                        ntbs (nt, 2);
                    984:                break;
                    985:        }
                    986: 
                    987:        return;
                    988: }
                    989: 
                    990: 
                    991: /*
                    992:  * Interpret the control characters that cause signals to be generated
                    993:  * immediately: interrupt (^?), quit (^\), stop (^Z).
                    994:  * Called from ntinc().
                    995:  */
                    996: 
                    997: int
                    998: ntsigc (c, nt)
                    999:        register                c;
                   1000:        register struct nttyld  *nt;
                   1001: {
                   1002:        if (c == nt->nt_intrc) {
                   1003:                ntflush (nt, FREAD | FWRITE);
                   1004:                (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGINT);
                   1005:        }
                   1006:        else if (c == nt->nt_quitc) {
                   1007:                ntflush (nt, FREAD | FWRITE);
                   1008:                (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGQUIT);
                   1009:        }
                   1010:        else if (c == nt->nt_suspc) {
                   1011:                ntflush (nt, FREAD);
                   1012:                (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGTSTP);
                   1013:        }
                   1014:        else    return (0);
                   1015: 
                   1016:        ntecho (c, nt);
                   1017:        return (1);
                   1018: }
                   1019: 
                   1020: 
                   1021: /*
                   1022:  * Interpret the start (^S) and stop (^Q) control characters.
                   1023:  * Called from ntinc().
                   1024:  */
                   1025: 
                   1026: int
                   1027: ntstst (c, nt)
                   1028:        register int            c;
                   1029:        register struct nttyld  *nt;
                   1030: {
                   1031:        if (nt->nt_state & NT_STOP) {
                   1032:                if (c == nt->nt_startc || 
                   1033:                    !(nt->nt_local & LDECCTQ) &&
                   1034:                    (c != nt->nt_stopc || nt->nt_stopc == nt->nt_startc)) {
                   1035:                        if (putctl (nt->nt_outq->next, M_START))
                   1036:                                nt->nt_state &= ~NT_STOP;
                   1037:                }
                   1038:        }
                   1039:        else    if (c == nt->nt_stopc) {
                   1040:                        if (putctl (nt->nt_outq->next, M_STOP))
                   1041:                                nt->nt_state |= NT_STOP;
                   1042:                }
                   1043: 
                   1044:        return (c == nt->nt_startc || c == nt->nt_stopc);
                   1045: }
                   1046: 
                   1047: 
                   1048: /*
                   1049:  * Erase the last word of the input buffer.
                   1050:  * Called from ntinc().
                   1051:  */
                   1052: 
                   1053: ntwerase (nt)
                   1054:        register struct nttyld  *nt;
                   1055: {
                   1056:        register char   *s;
                   1057: 
                   1058:        for (s = nt->nt_in + nt->nt_nin - 1; s >= nt->nt_in; s--)
                   1059:                if (*s == ' ' || *s == '\t')
                   1060:                        ntrubout (nt);
                   1061:                else    break;
                   1062: 
                   1063:        for (; s >= nt->nt_in; s--)
                   1064:                if (*s == ' ' || *s == '\t')
                   1065:                        break;
                   1066:                else    ntrubout (nt);
                   1067: 
                   1068:        return;
                   1069: }

unix.superglobalmegacorp.com

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