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

1.1       root        1: #include "ntty.h"
                      2: #if NNTTY > 0
                      3: #include "../h/param.h"
                      4: #include "../h/stream.h"
                      5: #include "../h/ioctl.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:                (*q->next->qinfo->putp)(q->next, b);    /* send it on down */
                    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: 
                    482:                b->wptr = b->rptr + sizeof (int) + sizeof (struct sgttyb);
                    483:                b->wptr = 2 + b->rptr + sizeof (int) + sizeof (struct sgttyb);
                    484:                (*q->next->qinfo->putp)(q->next, b);
                    485:                break;
                    486: 
                    487:        /*
                    488:         * Set/get special characters
                    489:         */
                    490:        case TIOCSETC:
                    491:                nt->nt_tchr = ioc->arg.tchr;
                    492:                ntiocack (q, b, 0);
                    493:                break;
                    494: 
                    495:        case TIOCGETC:
                    496:                ioc->arg.tchr = nt->nt_tchr;
                    497:                ntiocack (q, b, sizeof (struct tchars));
                    498:                break;
                    499: 
                    500:        /*
                    501:         * Set/get local special characters.
                    502:         */
                    503:        case TIOCSLTC:
                    504:                nt->nt_ltchr = ioc->arg.ltchr;
                    505:                ntiocack (q, b, 0);
                    506:                break;
                    507: 
                    508:        case TIOCGLTC:
                    509:                ioc->arg.ltchr = nt->nt_ltchr;
                    510:                ntiocack (q, b, sizeof (struct ltchars));
                    511:                break;
                    512: 
                    513:        /*
                    514:         * Modify local mode word.
                    515:         */
                    516:        case TIOCLBIS:
                    517:                nt->nt_local |= ioc->arg.local;
                    518:                ntiocack (q, b, 0);
                    519:                break;
                    520: 
                    521:        case TIOCLBIC:
                    522:                nt->nt_local &= ~ioc->arg.local;
                    523:                ntiocack (q, b, 0);
                    524:                break;
                    525: 
                    526:        case TIOCLSET:
                    527:                nt->nt_local = ioc->arg.local;
                    528:                ntiocack (q, b, 0);
                    529:                break;
                    530: 
                    531:        case TIOCLGET:
                    532:                ioc->arg.local = nt->nt_local;
                    533:                ntiocack (q, b, sizeof (short));
                    534:                break;
                    535: 
                    536:        /*
                    537:         * Return number of characters in the output.
                    538:         */
                    539:        case TIOCOUTQ:
                    540: 
                    541:        default:
                    542:                (*q->next->qinfo->putp)(q->next, b);
                    543:                break;
                    544:        }
                    545: 
                    546:        return;
                    547: }
                    548: 
                    549: 
                    550: /*
                    551:  * Erase entire input buffer.
                    552:  * Called by ntinc().
                    553:  */
                    554: 
                    555: ntkill (nt)
                    556:        register struct nttyld  *nt;
                    557: {
                    558:        if (nt->nt_local & LCRTKIL && !nt->nt_trash) {
                    559:                while (nt->nt_nin > 0)
                    560:                        ntrubout (nt);
                    561:        }
                    562:        else {
                    563:                ntecho (nt->nt_kill, nt);
                    564:                ntecho ('\n', nt);
                    565:                nt->nt_nin = 0;
                    566:                nt->nt_trash = 0;
                    567:        }
                    568:        nt->nt_lstate = 0;
                    569:        return;
                    570: }
                    571: 
                    572: 
                    573: /*
                    574:  * Interpret the flush-output (^O) control character.
                    575:  * Called by ntinc().
                    576:  */
                    577: 
                    578: int
                    579: ntoflush (c, nt)
                    580:        register int            c;
                    581:        register struct nttyld  *nt;
                    582: {
                    583:        if (nt->nt_local & LFLUSHO) {
                    584:                nt->nt_local &= ~LFLUSHO;
                    585:                if (c == nt->nt_flushc)
                    586:                        return (1);
                    587:        }
                    588:        else    if (c == nt->nt_flushc) {
                    589:                        ntflush (nt, FWRITE);
                    590:                        ntecho (c, nt);
                    591:                        ntreprint (nt);
                    592:                        nt->nt_local |= LFLUSHO;
                    593:                        return (1);
                    594:                }
                    595: 
                    596:        return (0);
                    597: }
                    598: 
                    599: 
                    600: /*ARGSUSED*/
                    601: 
                    602: int
                    603: ntopen (q, dev)
                    604:        register struct queue   *q;
                    605:        int                     dev;
                    606: {
                    607:        register struct nttyld  *nt;
                    608: 
                    609:        if (q->ptr)
                    610:                return (1);             /* already attached */
                    611: 
                    612:        for (nt = ntty; nt->nt_state & NT_USE; nt++)
                    613:                if (nt >= &ntty[NNTTY-1])
                    614:                        return (0);
                    615: 
                    616:        WR (q)->ptr = q->ptr = (caddr_t) nt;
                    617:        nt->nt_outq = WR (q);
                    618:        nt->nt_readq = q;
                    619:        nt->nt_nin = 0;
                    620:        nt->nt_state = NT_USE;
                    621:        nt->nt_flags = ECHO | CRMOD;
                    622:        nt->nt_col = 0;
                    623:        nt->nt_delct = 0;
                    624:        ntchars (nt);                   /* set default control characters */
                    625:        nt->nt_trash = 0;
                    626:        nt->nt_local = 0;
                    627:        nt->nt_lstate = 0;
                    628:        q->flag |= QDELIM;
                    629:        return (1);
                    630: }
                    631: 
                    632: 
                    633: /*
                    634:  * Writer queue (output to tty) put routine.
                    635:  */
                    636: 
                    637: ntout (wrq, b)
                    638:        register struct queue   *wrq;
                    639:        register struct block   *b;
                    640: {
                    641:        if (b->type == M_DATA)
                    642:                b->type = M_CTL;                /* see ntoutsrv() */
                    643:        putq (wrq, b);
                    644:        return;
                    645: }
                    646: 
                    647: 
                    648: /*
                    649:  * Output a block of data to a terminal.
                    650:  * Handle tab expansion, case conversion, turning CR to CRLF, delays, etc.
                    651:  * Called from ntoutsrv().
                    652:  */
                    653: 
                    654: ntoutb (nt, ib)
                    655:        register struct nttyld  *nt;
                    656:        register struct block   *ib;
                    657: {
                    658:        register struct block   *ob = 0;
                    659:        register struct queue   *q = nt->nt_outq;
                    660:        register int            c, delay, ctype;
                    661:        char                    *colp;
                    662: 
                    663:        while (ib->rptr < ib->wptr) {
                    664:                if (!ob || ob->wptr >= ob->lim) {
                    665:                        if (ob) {
                    666:                                if (nt->nt_local & LFLUSHO)
                    667:                                        break;
                    668:                                tk_nout += ob->wptr - ob->rptr;
                    669:                                (*q->next->qinfo->putp)(q->next, ob);
                    670:                        }
                    671:                        if (q->next->flag & QFULL || !(ob = allocb (QBSIZE))) {
                    672:                                putbq (q, ib);
                    673:                                return;
                    674:                        }
                    675:                }
                    676: 
                    677:                switch (c = *ib->rptr++ & 0177) {
                    678:                case '\t':
                    679:                        if ((nt->nt_flags & TBDELAY) != XTABS)
                    680:                                break;
                    681: 
                    682:                        /*
                    683:                         * Expand tabs to spaces.
                    684:                         */
                    685:                        for (;;) {
                    686:                                *ob->wptr++ = ' ';
                    687:                                nt->nt_col++;
                    688:                                if ((nt->nt_col & 07) == 0)     /* every 8 */
                    689:                                        break;
                    690:                                if (ob->wptr >= ob->lim) {
                    691:                                        ib->rptr--;
                    692:                                        break;
                    693:                                }
                    694:                        }
                    695:                        continue;
                    696:                case '\n':
                    697:                        if (!(nt->nt_flags & CRMOD))
                    698:                                break;
                    699: 
                    700:                        /*
                    701:                         * Turn <nl> to <cr><lf>.
                    702:                         */
                    703:                        if (nt->nt_state & NT_CR)
                    704:                                nt->nt_state &= ~NT_CR;
                    705:                        else {
                    706:                                nt->nt_state |= NT_CR;
                    707:                                c = '\r';
                    708:                                ib->rptr--;
                    709:                        }
                    710:                        break;
                    711:                case '~':
                    712:                        if (nt->nt_local & LTILDE)
                    713:                                c = '`';
                    714:                        /* no break */
                    715:                default:
                    716:                        if (!(nt->nt_flags & LCASE))
                    717:                                break;
                    718: 
                    719:                        /*
                    720:                         * Generate escapes for upper-case-only terminals.
                    721:                         */
                    722:                        if (nt->nt_state & NT_CASE) {
                    723:                                nt->nt_state &= ~NT_CASE;
                    724:                                break;
                    725:                        }
                    726: 
                    727:                        for (colp = "{(})|!~^`'"; *colp && c != *colp; 
                    728:                            colp += 2);
                    729: 
                    730:                        if (*colp || c >= 'A' && c <= 'Z') {
                    731:                                *--ib->rptr = *colp ? colp[1] : c;
                    732:                                nt->nt_state |= NT_CASE;
                    733:                                c = '\\';
                    734:                        }
                    735:                        else if (c >= 'a' && c <= 'z')
                    736:                                c += 'A' - 'a';
                    737:                        break;
                    738:                }
                    739: 
                    740:                /*
                    741:                 * Store character.
                    742:                 */
                    743:                *ob->wptr++ = c;
                    744: 
                    745:                /*
                    746:                 * Calculate delays and column movement.
                    747:                 * The delay values are in clock ticks and aren't
                    748:                 * necessarily optimal for all terminals.
                    749:                 */
                    750:                delay = 0;
                    751: 
                    752:                switch (ctype = partab[c] & 077) {
                    753:                case ORDINARY:
                    754:                        nt->nt_col++;
                    755:                        break;
                    756:                case CONTROL:
                    757:                        break;
                    758:                case BACKSPACE:
                    759:                        if (nt->nt_col)
                    760:                                nt->nt_col--;
                    761:                        break;
                    762:                case NEWLINE:
                    763:                        ctype = (nt->nt_flags >> 8) & 03;
                    764:                        if (ctype == 1) {       /* tty 37 */
                    765:                                if (nt->nt_col)
                    766:                                        if ((delay = nt->nt_col >> 4) < 6)
                    767:                                                delay = 6;
                    768:                        }
                    769:                        else if (ctype == 2)    /* vt05 */
                    770:                                delay = 6;
                    771:                        if (!(nt->nt_flags & CRMOD))
                    772:                                nt->nt_col = 0;
                    773:                        break;
                    774:                case TAB:
                    775:                        ctype = (nt->nt_flags >> 10) & 03;
                    776:                        if (ctype == 1)         /* tty 37 */
                    777:                                if ((delay = 1 - (nt->nt_col | ~07)) < 5)
                    778:                                        delay = 0;
                    779:                        nt->nt_col |= 07;
                    780:                        nt->nt_col++;
                    781:                        break;
                    782:                case VTAB:
                    783:                        if (nt->nt_flags & VTDELAY)
                    784:                                delay = 127;
                    785:                        break;
                    786:                case RETURN:
                    787:                        ctype = (nt->nt_flags >> 12) & 03;
                    788:                        if (ctype == 1)          /* tn 300 */
                    789:                                delay = 5;
                    790:                        else if (ctype == 2)    /* ti 700 */
                    791:                                delay = 10;
                    792:                        else if (ctype == 3)    /* concept 100 */
                    793:                                if ((delay = 9 - nt->nt_col) < 0)
                    794:                                        delay = 0;
                    795:                        nt->nt_col = 0;
                    796:                        break;
                    797:                }
                    798: 
                    799:                if (delay) {
                    800:                        if (nt->nt_local & LFLUSHO)
                    801:                                break;
                    802:                        tk_nout += ob->wptr - ob->rptr;
                    803:                        (*q->next->qinfo->putp)(q->next, ob);
                    804:                        if (ob = allocb(1)) {
                    805:                                ob->type = M_DELAY;
                    806:                                *ob->wptr++ = delay;
                    807:                                (*q->next->qinfo->putp)(q->next, ob);
                    808:                        }
                    809:                        ob = 0;
                    810:                }
                    811:        }
                    812: 
                    813:        freeb (ib);
                    814:        if (ob)
                    815:                if (nt->nt_local & LFLUSHO)
                    816:                        freeb (ob);
                    817:                else {
                    818:                        tk_nout += ob->wptr - ob->rptr;
                    819:                        (*q->next->qinfo->putp)(q->next, ob);
                    820:                }
                    821:        return;
                    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_DELIM:
                    850:                        if (!(q->next->flag & QDELIM)) {
                    851:                                freeb (b);
                    852:                                continue;
                    853:                        }
                    854:                        if (nt->nt_local & LFLUSHO) {
                    855:                                freeb (b);
                    856:                                continue;
                    857:                        }
                    858:                        if (q->next->flag & QFULL) {
                    859:                                putbq (q, b);
                    860:                                return;
                    861:                        }
                    862:                        (*q->next->qinfo->putp)(q->next, b);
                    863:                        continue;
                    864:                case M_IOCTL:
                    865:                        if (q->next->flag & QFULL) {
                    866:                                putbq (q, b);
                    867:                                return;
                    868:                        }
                    869:                        ntioctl (q, b);
                    870:                        continue;
                    871:                case M_FLUSH:
                    872:                        flushq (q, 0);
                    873:                        /* no break */
                    874:                case M_IOCNAK:
                    875:                case M_IOCACK:
                    876:                        (*q->next->qinfo->putp)(q->next, b);
                    877:                        continue;
                    878:                case M_CTL:
                    879:                case M_DATA:
                    880:                        if (nt->nt_local & LFLUSHO) {
                    881:                                freeb (b);
                    882:                                continue;
                    883:                        }
                    884:                        if (q->next->flag & QFULL) {
                    885:                                putbq (q, b);
                    886:                                return;
                    887:                        }
                    888:                        if (b->type == M_CTL) {
                    889:                                b->type = M_DATA;
                    890:                                nt->nt_trash = nt->nt_nin;
                    891:                        }
                    892:                        if (nt->nt_flags & RAW || nt->nt_local & LLITOUT) {
                    893:                                tk_nout += b->wptr - b->rptr;
                    894:                                (*q->next->qinfo->putp)(q->next, b);
                    895:                        }
                    896:                        else    ntoutb (nt, b);
                    897:                        continue;
                    898:                }
                    899: 
                    900:        return;
                    901: }
                    902: 
                    903: 
                    904: /*
                    905:  * Reprint input buffer.
                    906:  */
                    907: 
                    908: ntreprint (nt)
                    909:        register struct nttyld  *nt;
                    910: {
                    911:        register char   *in;
                    912:        register int    nin;
                    913: 
                    914:        if (nt->nt_rprntc != 0377)
                    915:                ntecho ((int) nt->nt_rprntc, nt);
                    916:        (void) putd (putq, nt->nt_outq, '\n');
                    917:        for (in = nt->nt_in, nin = nt->nt_nin; nin > 0; in++, nin--)
                    918:                ntecho (*in, nt);
                    919:        nt->nt_lstate &= ~LSERASE;
                    920:        nt->nt_trash = 0;
                    921:        return;
                    922: }
                    923: 
                    924: 
                    925: /*
                    926:  * Rubout the last character of the input buffer.
                    927:  */
                    928: 
                    929: ntrubout (nt)
                    930:        register struct nttyld  *nt;
                    931: {
                    932:        register int    c, cc, col, i;
                    933: 
                    934:        if (nt->nt_nin <= 0)
                    935:                return;
                    936:        c = nt->nt_in[--nt->nt_nin];
                    937: 
                    938:        if (!(nt->nt_flags & ECHO))
                    939:                return;
                    940: 
                    941:        nt->nt_local &= ~LFLUSHO;
                    942: 
                    943:        if (nt->nt_local & LPRTERA) {
                    944:                if (!(nt->nt_lstate & LSERASE)) {
                    945:                        (void) putd (putq, nt->nt_outq, '\\');
                    946:                        nt->nt_lstate |= LSERASE;
                    947:                }
                    948:                ntecho (c, nt);
                    949:                return;
                    950:        }
                    951: 
                    952:        if (!(nt->nt_local & LCRTBS)) {
                    953:                ntecho (nt->nt_erase, nt);
                    954:                return;
                    955:        }
                    956: 
                    957:        if (nt->nt_trash > nt->nt_nin) {
                    958:                ntreprint (nt);
                    959:                return;
                    960:        }
                    961: 
                    962:        if (c == ('\t'|0200) || c == ('\n'|0200)) {
                    963:                ntbs (nt, 2);
                    964:                return;
                    965:        }
                    966: 
                    967:        switch (partab[c&=0177] & 0177) {
                    968:        case ORDINARY:
                    969:                if (nt->nt_flags&LCASE && c >= 'A' && c <= 'Z')
                    970:                        ntbs (nt, 2);
                    971:                else    ntbs (nt, 1);
                    972:                break;
                    973:        case TAB:
                    974:                for (col = nt->nt_rocol, i = 0; i < nt->nt_nin; i++) {
                    975:                        cc = nt->nt_in[i];
                    976:                        if (cc == ('\t'|0200) || cc == ('\n'|0200)) {
                    977:                                col += 2;
                    978:                                continue;
                    979:                        }
                    980:                        switch (partab[cc&=0177] & 0177) {
                    981:                        case ORDINARY:
                    982:                                if (nt->nt_flags&LCASE && cc>='A' && cc<='Z')
                    983:                                        col += 2;
                    984:                                else    col++;
                    985:                                break;
                    986:                        case TAB:
                    987:                                col = (col + 8) & ~7;
                    988:                                break;
                    989:                        default:
                    990:                                if (nt->nt_local & LCTLECH)
                    991:                                        col += 2;
                    992:                                break;
                    993:                        }
                    994:                }
                    995:                ntbs (nt, 8 - (col & 7));
                    996:                break;
                    997:        default:
                    998:                if (nt->nt_local & LCTLECH)
                    999:                        ntbs (nt, 2);
                   1000:                break;
                   1001:        }
                   1002: 
                   1003:        return;
                   1004: }
                   1005: 
                   1006: 
                   1007: /*
                   1008:  * Interpret the control characters that cause signals to be generated
                   1009:  * immediately: interrupt (^?), quit (^\), stop (^Z).
                   1010:  * Called from ntinc().
                   1011:  */
                   1012: 
                   1013: int
                   1014: ntsigc (c, nt)
                   1015:        register                c;
                   1016:        register struct nttyld  *nt;
                   1017: {
                   1018:        if (c == nt->nt_intrc) {
                   1019:                ntflush (nt, FREAD | FWRITE);
                   1020:                (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGINT);
                   1021:        }
                   1022:        else if (c == nt->nt_quitc) {
                   1023:                ntflush (nt, FREAD | FWRITE);
                   1024:                (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGQUIT);
                   1025:        }
                   1026:        else if (c == nt->nt_suspc) {
                   1027:                ntflush (nt, FREAD);
                   1028:                (void) putctl1 (nt->nt_readq->next, M_SIGNAL, SIGTSTP);
                   1029:        }
                   1030:        else    return (0);
                   1031: 
                   1032:        ntecho (c, nt);
                   1033:        return (1);
                   1034: }
                   1035: 
                   1036: 
                   1037: /*
                   1038:  * Interpret the start (^S) and stop (^Q) control characters.
                   1039:  * Called from ntinc().
                   1040:  */
                   1041: 
                   1042: int
                   1043: ntstst (c, nt)
                   1044:        register int            c;
                   1045:        register struct nttyld  *nt;
                   1046: {
                   1047:        if (nt->nt_state & NT_STOP) {
                   1048:                if (c == nt->nt_startc || 
                   1049:                    !(nt->nt_local & LDECCTQ) &&
                   1050:                    (c != nt->nt_stopc || nt->nt_stopc == nt->nt_startc)) {
                   1051:                        if (putctl (nt->nt_outq->next, M_START))
                   1052:                                nt->nt_state &= ~NT_STOP;
                   1053:                }
                   1054:        }
                   1055:        else    if (c == nt->nt_stopc) {
                   1056:                        if (putctl (nt->nt_outq->next, M_STOP))
                   1057:                                nt->nt_state |= NT_STOP;
                   1058:                }
                   1059: 
                   1060:        return (c == nt->nt_startc || c == nt->nt_stopc);
                   1061: }
                   1062: 
                   1063: 
                   1064: /*
                   1065:  * Erase the last word of the input buffer.
                   1066:  * Called from ntinc().
                   1067:  */
                   1068: 
                   1069: ntwerase (nt)
                   1070:        register struct nttyld  *nt;
                   1071: {
                   1072:        register char   *s;
                   1073: 
                   1074:        for (s = nt->nt_in + nt->nt_nin - 1; s >= nt->nt_in; s--)
                   1075:                if (*s == ' ' || *s == '\t')
                   1076:                        ntrubout (nt);
                   1077:                else    break;
                   1078: 
                   1079:        for (; s >= nt->nt_in; s--)
                   1080:                if (*s == ' ' || *s == '\t')
                   1081:                        break;
                   1082:                else    ntrubout (nt);
                   1083: 
                   1084:        return;
                   1085: }

unix.superglobalmegacorp.com

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