Annotation of 41BSD/4.0.upgrade/sys/dev/ttynew.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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