Annotation of 40BSD/sys/dev/ttynew.c, revision 1.1.1.1

1.1       root        1: /*     ttynew.c        4.3     11/9/80 */
                      2: 
                      3: /*
                      4:  * New version of tty driver, supported
                      5:  * as NTTYDISC.  Adapted from a tty.c written
                      6:  * by J.E.Kulp of IIASA, Austria (jekulp@mc)
                      7:  */
                      8: #include "../h/param.h"
                      9: #include "../h/systm.h"
                     10: #include "../h/dir.h"
                     11: #include "../h/user.h"
                     12: #include "../h/tty.h"
                     13: #include "../h/proc.h"
                     14: #include "../h/mx.h"
                     15: #include "../h/inode.h"
                     16: #include "../h/file.h"
                     17: #include "../h/reg.h"
                     18: #include "../h/conf.h"
                     19: #include "../h/buf.h"
                     20: #include "../h/dk.h"
                     21: 
                     22: char   partab[];
                     23: 
                     24: /*
                     25:  * When running dz's using only SAE (silo alarm) on input
                     26:  * it is necessary to call dzrint() at clock interrupt time.
                     27:  * This is unsafe unless spl5()s in tty code are changed to
                     28:  * spl6()s to block clock interrupts.  Note that the dh driver
                     29:  * currently in use works the same way as the dz, even though
                     30:  * we could try to more intelligently manage its silo.
                     31:  * Thus don't take this out if you have no dz's unless you
                     32:  * change clock.c and dhtimer().
                     33:  */
                     34: #define        spl5    spl6
                     35: 
                     36: /*
                     37:  * Input mapping table-- if an entry is non-zero, when the
                     38:  * corresponding character is typed preceded by "\" the escape
                     39:  * sequence is replaced by the table value.  Mostly used for
                     40:  * upper-case only terminals.
                     41:  */
                     42: 
                     43: char   maptab[];               /* see tty.c */
                     44: 
                     45: /*
                     46:  * shorthand
                     47:  */
                     48: #define        q1      tp->t_rawq
                     49: #define        q2      tp->t_canq
                     50: #define        q3      tp->t_outq
                     51: #define        q4      tp->t_un.t_ctlq
                     52: 
                     53: #define        OBUFSIZ 100
                     54: 
                     55: /*
                     56:  * routine called on opens while tp->t_line == NTTYDISC
                     57:  * establishes a process group for distribution of
                     58:  * quits and interrupts from the tty.
                     59:  * (actually, pp->p_pgrp can't be 0 when this routine
                     60:  * is called since NTTYDISC is not the default discipline)
                     61:  */
                     62: ntyopen(dev, tp)
                     63: dev_t dev;
                     64: register struct tty *tp;
                     65: {
                     66:        register struct proc *pp;
                     67: 
                     68:        pp = u.u_procp;
                     69:        tp->t_dev = dev;
                     70:        if(pp->p_pgrp == 0) {
                     71:                u.u_ttyp = tp;
                     72:                u.u_ttyd = dev;
                     73:                if (tp->t_pgrp == 0)
                     74:                        tp->t_pgrp = pp->p_pid;
                     75:                pp->p_pgrp = tp->t_pgrp;
                     76:        }
                     77:        tp->t_state &= ~WOPEN;
                     78:        tp->t_state |= ISOPEN;
                     79:        if (tp->t_line != NTTYDISC)
                     80:                wflushtty(tp);
                     81: }
                     82: 
                     83: /*
                     84:  * clean tp on last close
                     85:  */
                     86: ntyclose(tp)
                     87: register struct tty *tp;
                     88: {
                     89: 
                     90:        wflushtty(tp);
                     91:        /* let ttyclose do the work if we are really closing */
                     92: }
                     93: 
                     94: /*
                     95:  * block transfer input handler.
                     96:  */
                     97: ntyrend(tp, pb, pe)
                     98: register struct tty *tp;
                     99: register char *pb, *pe;
                    100: {
                    101:        int     tandem;
                    102: 
                    103:        tandem = tp->t_flags&TANDEM;
                    104:        if (tp->t_flags&RAW) {
                    105:                (void) b_to_q(pb, pe-pb, &tp->t_rawq);
                    106:                if (tp->t_chan)
                    107:                        (void) sdata(tp->t_chan);
                    108:                else
                    109:                        wakeup((caddr_t)&tp->t_rawq);
                    110:        } else {
                    111:                tp->t_flags &= ~TANDEM;
                    112:                while (pb < pe)
                    113:                        ntyinput(*pb++, tp);
                    114:                tp->t_flags |= tandem;
                    115:        }
                    116:        if (tandem)
                    117:                ttyblock(tp);
                    118: }
                    119: 
                    120: /*
                    121:  * reinput pending characters after state switch
                    122:  * call at spl5().
                    123:  */
                    124: ntypend(tp)
                    125: register struct tty *tp;
                    126: {
                    127:        struct clist tq;
                    128:        register c;
                    129: 
                    130:        tp->t_local &= ~LPENDIN;
                    131:        tp->t_lstate |= LSTYPEN;
                    132:        tq = tp->t_rawq;
                    133:        tp->t_rawq.c_cc = 0;
                    134:        tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
                    135:        while ((c = getc(&tq)) >= 0)
                    136:                ntyinput(c, tp);
                    137:        tp->t_lstate &= ~LSTYPEN;
                    138: }
                    139: 
                    140: /*
                    141:  * Place a character on raw TTY input queue, putting in delimiters
                    142:  * and waking up top half as needed.
                    143:  * Also echo if required.
                    144:  * The arguments are the character and the appropriate
                    145:  * tty structure.
                    146:  */
                    147: ntyinput(c, tp)
                    148: register c;
                    149: register struct tty *tp;
                    150: {
                    151:        register int t_flags;
                    152:        int i;
                    153: 
                    154:        if (tp->t_local&LPENDIN)
                    155:                ntypend(tp);
                    156:        tk_nin++;
                    157:        c &= 0377;
                    158:        t_flags = tp->t_flags;
                    159:        if (t_flags&TANDEM)
                    160:                ttyblock(tp);
                    161:        if ((t_flags&RAW)==0) {
                    162:                if ((tp->t_lstate&LSTYPEN) == 0)
                    163:                        c &= 0177;
                    164:        /* check for literal nexting very first */
                    165:                if (tp->t_lstate&LSLNCH) {
                    166:                        c |= 0200;
                    167:                        tp->t_lstate &= ~LSLNCH;
                    168:                }
                    169:                if (c==tlun.t_lnextc) {
                    170:                        if (tp->t_flags&ECHO)
                    171:                                ntyout("^\b", tp);
                    172:                        tp->t_lstate |= LSLNCH;
                    173:        /* check for output control functions */
                    174:                } else if (c==tun.t_stopc) {
                    175:                        if ((tp->t_state&TTSTOP)==0) {
                    176:                                tp->t_state |= TTSTOP;
                    177:                                (*cdevsw[major(tp->t_dev)].d_stop)(tp);
                    178:                                return;
                    179:                        }
                    180:                        if (c!=tun.t_startc)
                    181:                                return;
                    182:                } else if (c==tun.t_startc)
                    183:                        ;
                    184:        /* check for input interrupts (and flushed output) */
                    185:                else if (c==tlun.t_flushc) {
                    186:                        if (tp->t_local & LFLUSHO)
                    187:                                tp->t_local &= ~LFLUSHO;
                    188:                        else {
                    189:                                flushtty(tp, FWRITE);
                    190:                                ntyecho(c, tp);
                    191:                                if (tp->t_rawq.c_cc+tp->t_canq.c_cc)
                    192:                                        ntyretype(tp);
                    193:                                tp->t_local |= LFLUSHO;
                    194:                        }
                    195:                        ttstart(tp);
                    196:                        return;
                    197:                } else if (c==tlun.t_suspc || c==tun.t_intrc ||
                    198:                           c==tun.t_quitc) {
                    199:                        flushtty(tp, c==tlun.t_suspc ? FREAD : FREAD|FWRITE);
                    200:                        ntyecho(c, tp);
                    201:                        c = c==tun.t_intrc ? SIGINT :
                    202:                                ((c==tun.t_quitc) ? SIGQUIT : SIGTSTP);
                    203:                        if (tp->t_chan)
                    204:                                scontrol(tp->t_chan, M_SIG, c);
                    205:                        else
                    206:                                gsignal(tp->t_pgrp, c);
                    207:        /* check for buffer editing functions - cooked mode */
                    208:                } else if ((t_flags&CBREAK) == 0) {
                    209:                        if ((tp->t_lstate&LSQUOT) &&
                    210:                            (c==tp->t_erase||c==tp->t_kill)) {
                    211:                                ntyrub(unputc(&tp->t_rawq), tp);
                    212:                                c |= 0200;
                    213:                        }
                    214:                        if (c==tp->t_erase) {
                    215:                                if (tp->t_rawq.c_cc)
                    216:                                        ntyrub(unputc(&tp->t_rawq), tp);
                    217:                        } else if (c==tp->t_kill) {
                    218:                                if (tp->t_local&LCRTKIL &&
                    219:                                    tp->t_rawq.c_cc == tp->t_rocount) {
                    220:                                        while (tp->t_rawq.c_cc)
                    221:                                                ntyrub(unputc(&tp->t_rawq), tp);
                    222:                                } else {
                    223:                                        ntyecho(c, tp);
                    224:                                        ntyecho('\n', tp);
                    225:                                        while (getc(&tp->t_rawq) > 0)
                    226:                                                ;
                    227:                                        tp->t_rocount = 0;
                    228:                                }
                    229:                                tp->t_lstate = 0;
                    230:                        } else if (c==tlun.t_werasc) {
                    231:                                if (tp->t_rawq.c_cc == 0)
                    232:                                        goto out;
                    233:                                do {
                    234:                                        c = unputc(&tp->t_rawq);
                    235:                                        if (c != ' ' && c != '\t')
                    236:                                                goto erasenb;
                    237:                                        ntyrub(c, tp);
                    238:                                } while (tp->t_rawq.c_cc);
                    239:                                goto out;
                    240:                            erasenb:
                    241:                                do {
                    242:                                        ntyrub(c, tp);
                    243:                                        if (tp->t_rawq.c_cc == 0)
                    244:                                                goto out;
                    245:                                        c = unputc(&tp->t_rawq);
                    246:                                } while (c != ' ' && c != '\t');
                    247:                                (void) putc(c, &tp->t_rawq);
                    248:                        } else if (c==tlun.t_rprntc) {
                    249:                                ntyretype(tp);
                    250:        /* check for cooked mode input buffer overflow */
                    251:                        } else if (tp->t_rawq.c_cc + tp->t_canq.c_cc > TTYHOG) {
                    252:                                /* we should start a timeout that flushes the
                    253:                                   buffer if it stays full - same in CBREAK */
                    254:                                if (tp->t_outq.c_cc < TTHIWAT(tp))
                    255:                                        (void) ntyoutput(CTRL(g), tp);
                    256:        /* put data char in q for user and wakeup if a break char */
                    257:                        } else if (putc(c, &tp->t_rawq) >= 0) {
                    258:                                if (!ntbreakc(c, tp)) {
                    259:                                        if (tp->t_rocount++ == 0)
                    260:                                                tp->t_rocol = tp->t_col;
                    261:                                } else {
                    262:                                        tp->t_rocount = 0;
                    263:                                        catq(&tp->t_rawq, &tp->t_canq);
                    264:                                        if (tp->t_chan)
                    265:                                                (void) sdata(tp->t_chan);
                    266:                                        else
                    267:                                                wakeup((caddr_t)&tp->t_rawq);
                    268:                                        if (tp->t_local&LINTRUP)
                    269:                                                gsignal(tp->t_pgrp, SIGTINT);
                    270:                                }
                    271:                                tp->t_lstate &= ~LSQUOT;
                    272:                                if (c == '\\')
                    273:                                        tp->t_lstate |= LSQUOT;
                    274:                                if (tp->t_lstate&LSERASE) {
                    275:                                        tp->t_lstate &= ~LSERASE;
                    276:                                        (void) ntyoutput('/', tp);
                    277:                                }
                    278:                                i = tp->t_col;
                    279:                                ntyecho(c, tp);
                    280:                                if (c==tun.t_eofc && tp->t_flags&ECHO) {
                    281:                                        i = MIN(2, tp->t_col - i);
                    282:                                        while (i > 0) {
                    283:                                                (void) ntyoutput('\b', tp);
                    284:                                                i--;
                    285:                                        }
                    286:                                }
                    287:                        }
                    288:        /* CBREAK mode */
                    289:                } else if (tp->t_rawq.c_cc > TTYHOG) {
                    290:                        if (tp->t_outq.c_cc < TTHIWAT(tp))
                    291:                                (void) ntyoutput(CTRL(g), tp);
                    292:                } else if (putc(c, &tp->t_rawq) >= 0) {
                    293:                        if (tp->t_local&LINTRUP)
                    294:                                gsignal(tp->t_pgrp, SIGTINT);
                    295:                        if (tp->t_chan)
                    296:                                (void) sdata(tp->t_chan);
                    297:                        else
                    298:                                wakeup((caddr_t)&tp->t_rawq);
                    299:                        ntyecho(c, tp);
                    300:                }
                    301:        /* RAW mode */
                    302:        } else if (tp->t_rawq.c_cc > TTYHOG) 
                    303:                flushtty(tp, FREAD|FWRITE);
                    304:        else if (putc(c, &tp->t_rawq) >= 0) {
                    305:                if (tp->t_local&LINTRUP)
                    306:                        gsignal(tp->t_pgrp, SIGTINT);
                    307:                if (tp->t_chan)
                    308:                        (void) sdata(tp->t_chan);
                    309:                else
                    310:                        wakeup((caddr_t)&tp->t_rawq);
                    311:        }
                    312: out:
                    313:        tp->t_state &= ~TTSTOP;
                    314:        tp->t_local &= ~LFLUSHO;
                    315:        ttstart(tp);
                    316: }
                    317: 
                    318: /*
                    319:  * put character on TTY output queue, adding delays,
                    320:  * expanding tabs, and handling the CR/NL bit.
                    321:  * It is called both from the top half for output, and from
                    322:  * interrupt level for echoing.
                    323:  * The arguments are the character and the tty structure.
                    324:  * Returns < 0 if putc succeeds, otherwise returns char to resend
                    325:  * Must be recursive.
                    326:  */
                    327: ntyoutput(c, tp)
                    328: register c;
                    329: register struct tty *tp;
                    330: {
                    331:        register char *colp;
                    332:        register ctype;
                    333: 
                    334:        if (tp->t_flags&RAW || tp->t_local&LLITOUT) {
                    335:                if (tp->t_local&LFLUSHO)
                    336:                        return (-1);
                    337:                if (putc(c, &tp->t_outq))
                    338:                        return(c);
                    339:                tk_nout++;
                    340:                return (-1);
                    341:        }
                    342:        /*
                    343:         * Ignore EOT in normal mode to avoid hanging up
                    344:         * certain terminals.
                    345:         */
                    346:        c &= 0177;
                    347:        if (c==CEOT && (tp->t_flags&CBREAK)==0)
                    348:                return (-1);
                    349:        /*
                    350:         * Turn tabs to spaces as required
                    351:         */
                    352:        if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
                    353:                register int s;
                    354: 
                    355:                c = 8 - (tp->t_col&7);
                    356:                if ((tp->t_local&LFLUSHO) == 0) {
                    357:                        s = spl5();             /* don't interrupt tabs */
                    358:                        c -= b_to_q("        ", c, &tp->t_outq);
                    359:                        tk_nout += c;
                    360:                        splx(s);
                    361:                }
                    362:                tp->t_col += c;
                    363:                return (c ? -1 : '\t');
                    364:        }
                    365:        tk_nout++;
                    366:        /*
                    367:         * for upper-case-only terminals,
                    368:         * generate escapes.
                    369:         */
                    370:        if (tp->t_flags&LCASE) {
                    371:                colp = "({)}!|^~'`";
                    372:                while(*colp++)
                    373:                        if(c == *colp++) {
                    374:                                if (ntyoutput('\\', tp) >= 0)
                    375:                                        return (c);
                    376:                                c = colp[-2];
                    377:                                break;
                    378:                        }
                    379:                if ('A'<=c && c<='Z') {
                    380:                        if (ntyoutput('\\', tp) >= 0)
                    381:                                return (c);
                    382:                } else if ('a'<=c && c<='z')
                    383:                        c += 'A' - 'a';
                    384:        }
                    385:        /*
                    386:         * turn <nl> to <cr><lf> if desired.
                    387:         */
                    388:        if (c=='\n' && tp->t_flags&CRMOD)
                    389:                if (ntyoutput('\r', tp) >= 0)
                    390:                        return (c);
                    391:        if (c=='~' && tp->t_local&LTILDE)
                    392:                c = '`';
                    393:        if ((tp->t_local&LFLUSHO) == 0 && putc(c, &tp->t_outq))
                    394:                return (c);
                    395:        /*
                    396:         * Calculate delays.
                    397:         * The numbers here represent clock ticks
                    398:         * and are not necessarily optimal for all terminals.
                    399:         * The delays are indicated by characters above 0200.
                    400:         * In raw mode there are no delays and the
                    401:         * transmission path is 8 bits wide.
                    402:         */
                    403:        colp = &tp->t_col;
                    404:        ctype = partab[c];
                    405:        c = 0;
                    406:        switch (ctype&077) {
                    407: 
                    408:        case ORDINARY:
                    409:                (*colp)++;
                    410: 
                    411:        case CONTROL:
                    412:                break;
                    413: 
                    414:        case BACKSPACE:
                    415:                if (*colp)
                    416:                        (*colp)--;
                    417:                break;
                    418: 
                    419:        case NEWLINE:
                    420:                ctype = (tp->t_flags >> 8) & 03;
                    421:                if(ctype == 1) { /* tty 37 */
                    422:                        if (*colp)
                    423:                                c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
                    424:                } else
                    425:                if(ctype == 2) { /* vt05 */
                    426:                        c = 6;
                    427:                }
                    428:                *colp = 0;
                    429:                break;
                    430: 
                    431:        case TAB:
                    432:                ctype = (tp->t_flags >> 10) & 03;
                    433:                if(ctype == 1) { /* tty 37 */
                    434:                        c = 1 - (*colp | ~07);
                    435:                        if(c < 5)
                    436:                                c = 0;
                    437:                }
                    438:                *colp |= 07;
                    439:                (*colp)++;
                    440:                break;
                    441: 
                    442:        case VTAB:
                    443:                if(tp->t_flags & VTDELAY) /* tty 37 */
                    444:                        c = 0177;
                    445:                break;
                    446: 
                    447:        case RETURN:
                    448:                ctype = (tp->t_flags >> 12) & 03;
                    449:                if(ctype == 1) { /* tn 300 */
                    450:                        c = 5;
                    451:                } else if(ctype == 2) { /* ti 700 */
                    452:                        c = 10;
                    453:                } else if(ctype == 3) { /* concept 100 */
                    454:                        int i;
                    455:                        if ((i = *colp) >= 0)
                    456:                                for (; i<9; i++)
                    457:                                        (void) putc(0177, &tp->t_outq);
                    458:                }
                    459:                *colp = 0;
                    460:        }
                    461:        if(c && (tp->t_local&LFLUSHO) == 0)
                    462:                (void) putc(c|0200, &tp->t_outq);
                    463:        return (-1);
                    464: }
                    465: 
                    466: /*
                    467:  * Called from device's read routine after it has
                    468:  * calculated the tty-structure given as argument.
                    469:  */
                    470: ntread(tp)
                    471: register struct tty *tp;
                    472: {
                    473:        register struct clist *qp;
                    474:        register c, first;
                    475: 
                    476:        if ((tp->t_state&CARR_ON)==0)
                    477:                return(0);
                    478: loop:
                    479:        (void) spl5();
                    480:        if (tp->t_local&LPENDIN)
                    481:                ntypend(tp);
                    482:        (void) spl0();
                    483:        while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
                    484:                if (u.u_signal[SIGTTIN] == SIG_IGN ||
                    485:                    u.u_signal[SIGTTIN] == SIG_HOLD ||
                    486:                    (u.u_procp->p_flag&SDETACH) ||
                    487:                    u.u_procp->p_flag&SVFORK)
                    488:                        return (0);
                    489:                gsignal(u.u_procp->p_pgrp, SIGTTIN);
                    490:                sleep((caddr_t)&lbolt, TTIPRI);
                    491:        }
                    492:        if (tp->t_flags&RAW) {
                    493:                (void) spl5();
                    494:                if (tp->t_rawq.c_cc <= 0) {
                    495:                        if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL) {
                    496:                                (void) spl0();
                    497:                                return (0);
                    498:                        }
                    499:                        if (tp->t_local&LINTRUP &&
                    500:                            u.u_signal[SIGTINT] != SIG_DFL) {
                    501:                                u.u_error = EIO;
                    502:                                (void) spl0();
                    503:                                return (0);
                    504:                        }
                    505:                        sleep((caddr_t)&tp->t_rawq, TTIPRI);
                    506:                        (void) spl0();
                    507:                        goto loop;
                    508:                }
                    509:                (void) spl0();
                    510:                while (tp->t_rawq.c_cc && passc(getc(&tp->t_rawq))>=0)
                    511:                        ;
                    512:                return (0);
                    513:        } else {
                    514:                qp = tp->t_flags & CBREAK ? &tp->t_rawq : &tp->t_canq;
                    515:                (void) spl5();
                    516:                if (qp->c_cc <= 0) {
                    517:                        if ((tp->t_state&CARR_ON)==0 || tp->t_chan!=NULL) {
                    518:                                (void) spl0();
                    519:                                return (0);
                    520:                        }
                    521:                        if (tp->t_local&LINTRUP &&
                    522:                            u.u_signal[SIGTINT] != SIG_DFL) {
                    523:                                u.u_error = EIO;
                    524:                                (void) spl0();
                    525:                                return (0);
                    526:                        }
                    527:                        sleep((caddr_t)&tp->t_rawq, TTIPRI);
                    528:                        (void) spl0();
                    529:                        goto loop;
                    530:                }
                    531:                (void) spl0();
                    532:                first = 1;
                    533:                while ((c = getc(qp)) >= 0) {
                    534:                        if (tp->t_flags&CRMOD && c == '\r')
                    535:                                c = '\n';
                    536:                        if (tp->t_flags&LCASE && c <= 0177)
                    537:                                if (tp->t_lstate&LSBKSL) {
                    538:                                        if (maptab[c])
                    539:                                                c = maptab[c];
                    540:                                        tp->t_lstate &= ~LSBKSL;
                    541:                                } else if (c >= 'A' && c <= 'Z')
                    542:                                        c += 'a' - 'A';
                    543:                                else if (c == '\\') {
                    544:                                        tp->t_lstate |= LSBKSL;
                    545:                                        continue;
                    546:                                }
                    547:                        if (c == tlun.t_dsuspc) {
                    548:                                gsignal(tp->t_pgrp, SIGTSTP);
                    549:                                if (first) {
                    550:                                        sleep((caddr_t)&lbolt, TTIPRI);
                    551:                                        goto loop;
                    552:                                }
                    553:                                break;
                    554:                        }
                    555:                        if (c == tun.t_eofc && (tp->t_flags&CBREAK)==0)
                    556:                                break;
                    557:                        if (passc(c & 0177) < 0)
                    558:                                break;
                    559:                        if ((tp->t_flags&CBREAK)==0 && ntbreakc(c, tp))
                    560:                                break;
                    561:                        first = 0;
                    562:                }
                    563:                tp->t_lstate &= ~LSBKSL;
                    564:        }
                    565: 
                    566:        if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
                    567:                if (putc(tun.t_startc, &tp->t_outq)==0) {
                    568:                        tp->t_state &= ~TBLOCK;
                    569:                        ttstart(tp);
                    570:                }
                    571:                tp->t_char = 0;
                    572:        }
                    573: 
                    574:        return (tp->t_rawq.c_cc + tp->t_canq.c_cc);
                    575: }
                    576: 
                    577: /*
                    578:  * Called from the device's write routine after it has
                    579:  * calculated the tty-structure given as argument.
                    580:  */
                    581: caddr_t
                    582: ntwrite(tp)
                    583: register struct tty *tp;
                    584: {
                    585: #ifdef VAX
                    586:        /*
                    587:         * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
                    588:         * AND MUST NOT BE CHANGED WITHOUT PATCHING
                    589:         * THE 'ASM' INLINES BELOW.  WATCH OUT.
                    590:         */
                    591: #endif
                    592:        register char *cp;
                    593:        register int cc, ce;
                    594:        register i;
                    595:        char obuf[OBUFSIZ];
                    596:        register c;
                    597:        int hiwat = TTHIWAT(tp);
                    598: 
                    599:        if ((tp->t_state&CARR_ON)==0)
                    600:                return (NULL);
                    601: loop:
                    602:        while (u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
                    603:            (tp->t_local&LTOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
                    604:            u.u_signal[SIGTTOU] != SIG_IGN &&
                    605:            u.u_signal[SIGTTOU] != SIG_HOLD &&
                    606:            (u.u_procp->p_flag&SDETACH)==0) {
                    607:                gsignal(u.u_procp->p_pgrp, SIGTTOU);
                    608:                sleep((caddr_t)&lbolt, TTIPRI);
                    609:        }
                    610:        while (u.u_count) {
                    611:                cc = MIN(u.u_count, OBUFSIZ);
                    612:                cp = obuf;
                    613:                iomove(cp, (unsigned)cc, B_WRITE);
                    614:                if (u.u_error)
                    615:                        break;
                    616:                if (tp->t_outq.c_cc > hiwat)
                    617:                        goto ovhiwat;
                    618:                if (tp->t_local&LFLUSHO)
                    619:                        continue;
                    620:                if (tp->t_flags&LCASE || tp->t_local&LTILDE) {
                    621:                        while (cc--) {
                    622:                                c = *cp++;
                    623:                                tp->t_rocount = 0;
                    624:                                while((c = ntyoutput(c, tp)) >= 0) {
                    625:                                        /* out of clists, wait a bit */
                    626:                                        ttstart(tp);
                    627:                                        sleep((caddr_t)&lbolt, TTOPRI);
                    628:                                        tp->t_rocount = 0;
                    629:                                }
                    630:                                if (tp->t_outq.c_cc > hiwat)
                    631:                                        goto ovhiwat;
                    632:                        }
                    633:                        continue;
                    634:                }
                    635:                while (cc) {
                    636:                        if (tp->t_flags&RAW || tp->t_local&LLITOUT)
                    637:                                ce = cc;
                    638:                        else {
                    639: #ifdef VAX
                    640:                                asm("   scanc   r9,(r10),_partab,$077");
                    641:                                asm("   subl3   r0,r9,r8");
                    642: #else
                    643:                                ce=0;
                    644:                                while(((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc))
                    645:                                        ce++;
                    646: #endif
                    647:                                if (ce==0) {
                    648:                                        tp->t_rocount = 0;
                    649:                                        if (ntyoutput(*cp, tp) >= 0) {
                    650:                                                ttstart(tp);
                    651:                                                sleep((caddr_t)&lbolt, TTOPRI);
                    652:                                                continue;
                    653:                                        }
                    654:                                        cp++;
                    655:                                        cc--;
                    656:                                        if (tp->t_outq.c_cc > hiwat)
                    657:                                                goto ovhiwat;
                    658:                                }
                    659:                        }
                    660:                        tp->t_rocount = 0;
                    661:                        i=b_to_q(cp,ce,&tp->t_outq);
                    662:                        ce-=i;
                    663:                        tk_nout+=ce;
                    664:                        tp->t_col+=ce;
                    665:                        cp+=ce;
                    666:                        cc-=ce;
                    667:                        if (i) {
                    668:                                ttstart(tp);
                    669:                                sleep((caddr_t)&lbolt, TTOPRI);
                    670:                        }
                    671:                        if (ce || tp->t_outq.c_cc > hiwat)
                    672:                                goto ovhiwat;
                    673:                }
                    674:        }
                    675:        ttstart(tp);
                    676:        return(NULL);
                    677: 
                    678: ovhiwat:
                    679:        (void) spl5();
                    680:        u.u_base -= cc;
                    681:        u.u_offset -= cc;
                    682:        u.u_count += cc;
                    683:        if (tp->t_outq.c_cc <= hiwat) {
                    684:                (void) spl0();
                    685:                goto loop;
                    686:        }
                    687:        ttstart(tp);
                    688:        tp->t_state |= ASLEEP;
                    689:        if (tp->t_chan) {
                    690:                (void) spl0();
                    691:                return ((caddr_t)&tp->t_outq);
                    692:        }
                    693:        sleep((caddr_t)&tp->t_outq, TTOPRI);
                    694:        (void) spl0();
                    695:        goto loop;
                    696: }
                    697: 
                    698: /*
                    699:  * Rubout one character from the rawq of tp
                    700:  * as cleanly as possible.
                    701:  */
                    702: ntyrub(c, tp)
                    703: register c;
                    704: register struct tty *tp;
                    705: {
                    706:        register char *cp;
                    707:        register int savecol;
                    708:        int s;
                    709:        char *nextc();
                    710: 
                    711:        if ((tp->t_flags&ECHO)==0)
                    712:                return;
                    713:        tp->t_local &= ~LFLUSHO;
                    714:        c &= 0377;
                    715:        if (tp->t_local&LCRTBS) {
                    716:                if (tp->t_rocount == 0) {
                    717:                        /*
                    718:                         * Screwed by ttwrite; retype
                    719:                         */
                    720:                        ntyretype(tp);
                    721:                        return;
                    722:                }
                    723:                if (c==('\t'|0200) || c==('\n'|0200))
                    724:                        ntyrubo(tp, 2);
                    725:                else switch(partab[c&=0177] & 0177) {
                    726: 
                    727:                case ORDINARY:
                    728:                        if (tp->t_flags&LCASE && c >= 'A' && c <= 'Z')
                    729:                                ntyrubo(tp, 2);
                    730:                        else
                    731:                                ntyrubo(tp, 1);
                    732:                        break;
                    733: 
                    734:                case VTAB:
                    735:                case BACKSPACE:
                    736:                case CONTROL:
                    737:                case RETURN:
                    738:                        if (tp->t_local & LCTLECH)
                    739:                                ntyrubo(tp, 2);
                    740:                        break;
                    741: 
                    742:                case TAB:
                    743:                        if (tp->t_rocount < tp->t_rawq.c_cc) {
                    744:                                ntyretype(tp);
                    745:                                return;
                    746:                        }
                    747:                        s = spl5();
                    748:                        savecol = tp->t_col;
                    749:                        tp->t_lstate |= LSCNTTB;
                    750:                        tp->t_local |= LFLUSHO;
                    751:                        tp->t_col = tp->t_rocol;
                    752:                        for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
                    753:                                ntyecho(*cp, tp);
                    754:                        tp->t_local &= ~LFLUSHO;
                    755:                        tp->t_lstate &= ~LSCNTTB;
                    756:                        splx(s);
                    757:                        /*
                    758:                         * savecol will now be length of the tab
                    759:                         */
                    760:                        savecol -= tp->t_col;
                    761:                        tp->t_col += savecol;
                    762:                        if (savecol > 8)
                    763:                                savecol = 8;            /* overflow screw */
                    764:                        while (--savecol >= 0)
                    765:                                (void) ntyoutput('\b', tp);
                    766:                        break;
                    767: 
                    768:                default:
                    769:                        panic("ttyrub");
                    770:                }
                    771:        } else if (tp->t_local&LPRTERA) {
                    772:                if ((tp->t_lstate&LSERASE) == 0) {
                    773:                        (void) ntyoutput('\\', tp);
                    774:                        tp->t_lstate |= LSERASE;
                    775:                }
                    776:                ntyecho(c, tp);
                    777:        } else
                    778:                ntyecho(tp->t_erase, tp);
                    779:        tp->t_rocount--;
                    780: }
                    781: 
                    782: /*
                    783:  * Crt back over cnt chars perhaps
                    784:  * erasing them.
                    785:  */
                    786: ntyrubo(tp, cnt)
                    787: register struct tty *tp;
                    788: int cnt;
                    789: {
                    790: 
                    791:        while (--cnt >= 0)
                    792:                ntyout(tp->t_local&LCRTERA ? "\b \b" : "\b", tp);
                    793: }
                    794: 
                    795: /*
                    796:  * Reprint the rawq line.
                    797:  * We assume c_cc has already been checked.
                    798:  */
                    799: ntyretype(tp)
                    800: register struct tty *tp;
                    801: {
                    802:        register char *cp;
                    803:        char *nextc();
                    804:        int s;
                    805: 
                    806:        if (tlun.t_rprntc != 0377)
                    807:                ntyecho(tlun.t_rprntc, tp);
                    808:        (void) ntyoutput('\n', tp);
                    809:        s = spl5();
                    810:        for (cp = tp->t_canq.c_cf; cp; cp = nextc(&tp->t_canq, cp))
                    811:                ntyecho(*cp, tp);
                    812:        for (cp = tp->t_rawq.c_cf; cp; cp = nextc(&tp->t_rawq, cp))
                    813:                ntyecho(*cp, tp);
                    814:        tp->t_lstate &= ~LSERASE;
                    815:        splx(s);
                    816:        tp->t_rocount = tp->t_rawq.c_cc;
                    817:        tp->t_rocol = 0;
                    818: }
                    819: 
                    820: /*
                    821:  * Echo a typed character to the terminal
                    822:  */
                    823: ntyecho(c, tp)
                    824: register c;
                    825: register struct tty *tp;
                    826: {
                    827: 
                    828:        if ((tp->t_lstate & LSCNTTB) == 0)
                    829:                tp->t_local &= ~LFLUSHO;
                    830:        c &= 0377;
                    831:        if (tp->t_flags&ECHO) {
                    832:                if (c == '\r' && tp->t_flags&CRMOD)
                    833:                        c = '\n';
                    834:                if (tp->t_local&LCTLECH) {
                    835:                        if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
                    836:                                (void) ntyoutput('^', tp);
                    837:                                c &= 0177;
                    838:                                if (c == 0177)
                    839:                                        c = '?';
                    840:                                else if (tp->t_flags&LCASE)
                    841:                                        c += 'a' - 1;
                    842:                                else
                    843:                                        c += 'A' - 1;
                    844:                        }
                    845:                }
                    846:                (void) ntyoutput(c & 0177, tp);
                    847:        }
                    848: }
                    849: 
                    850: /*
                    851:  * Is c a break char for tp?
                    852:  */
                    853: ntbreakc(c, tp)
                    854: register c;
                    855: register struct tty *tp;
                    856: {
                    857:        return (c == '\n' || c == tun.t_eofc || c == tun.t_brkc ||
                    858:                c == '\r' && (tp->t_flags&CRMOD));
                    859: }
                    860: 
                    861: /*
                    862:  * send string cp to tp
                    863:  */
                    864: ntyout(cp, tp)
                    865: register char *cp;
                    866: register struct tty *tp;
                    867: {
                    868:        register char c;
                    869: 
                    870:        while (c = *cp++)
                    871:                (void) ntyoutput(c, tp);
                    872: }

unix.superglobalmegacorp.com

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