Annotation of researchv9/sys/dev/nttyld.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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