Annotation of 40BSD/sys/dev/tty.c, revision 1.1

1.1     ! root        1: /*     tty.c   4.2     11/9/80 */
        !             2: 
        !             3: /*
        !             4:  * TTY subroutines common to more than one line discipline
        !             5:  */
        !             6: #include "../h/param.h"
        !             7: #include "../h/systm.h"
        !             8: #include "../h/dir.h"
        !             9: #include "../h/user.h"
        !            10: #include "../h/tty.h"
        !            11: #include "../h/proc.h"
        !            12: #include "../h/mx.h"
        !            13: #include "../h/inode.h"
        !            14: #include "../h/file.h"
        !            15: #include "../h/reg.h"
        !            16: #include "../h/conf.h"
        !            17: #include "../h/buf.h"
        !            18: #include "../h/dk.h"
        !            19: 
        !            20: char   partab[];
        !            21: 
        !            22: /*
        !            23:  * When running dz's using only SAE (silo alarm) on input
        !            24:  * it is necessary to call dzrint() at clock interrupt time.
        !            25:  * This is unsafe unless spl5()s in tty code are changed to
        !            26:  * spl6()s to block clock interrupts.  Note that the dh driver
        !            27:  * currently in use works the same way as the dz, even though
        !            28:  * we could try to more intelligently manage its silo.
        !            29:  * Thus don't take this out if you have no dz's unless you
        !            30:  * change clock.c and dhtimer().
        !            31:  */
        !            32: #define        spl5    spl6
        !            33: 
        !            34: /*
        !            35:  * Input mapping table-- if an entry is non-zero, when the
        !            36:  * corresponding character is typed preceded by "\" the escape
        !            37:  * sequence is replaced by the table value.  Mostly used for
        !            38:  * upper-case only terminals.
        !            39:  */
        !            40: 
        !            41: char   maptab[] ={
        !            42:        000,000,000,000,000,000,000,000,
        !            43:        000,000,000,000,000,000,000,000,
        !            44:        000,000,000,000,000,000,000,000,
        !            45:        000,000,000,000,000,000,000,000,
        !            46:        000,'|',000,000,000,000,000,'`',
        !            47:        '{','}',000,000,000,000,000,000,
        !            48:        000,000,000,000,000,000,000,000,
        !            49:        000,000,000,000,000,000,000,000,
        !            50:        000,000,000,000,000,000,000,000,
        !            51:        000,000,000,000,000,000,000,000,
        !            52:        000,000,000,000,000,000,000,000,
        !            53:        000,000,000,000,000,000,'~',000,
        !            54:        000,'A','B','C','D','E','F','G',
        !            55:        'H','I','J','K','L','M','N','O',
        !            56:        'P','Q','R','S','T','U','V','W',
        !            57:        'X','Y','Z',000,000,000,000,000,
        !            58: };
        !            59: 
        !            60: short  tthiwat[16] =
        !            61:    { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,650,650 };
        !            62: short  ttlowat[16] =
        !            63:    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125,125,125 };
        !            64: 
        !            65: #define        OBUFSIZ 100
        !            66: 
        !            67: /*
        !            68:  * set default control characters.
        !            69:  */
        !            70: ttychars(tp)
        !            71: register struct tty *tp;
        !            72: {
        !            73: 
        !            74:        tun.t_intrc = CINTR;
        !            75:        tun.t_quitc = CQUIT;
        !            76:        tun.t_startc = CSTART;
        !            77:        tun.t_stopc = CSTOP;
        !            78:        tun.t_eofc = CEOT;
        !            79:        tun.t_brkc = CBRK;
        !            80:        tp->t_erase = CERASE;
        !            81:        tp->t_kill = CKILL;
        !            82: /* begin local */
        !            83:        tlun.t_suspc = CTRL(z);
        !            84:        tlun.t_dsuspc = CTRL(y);
        !            85:        tlun.t_rprntc = CTRL(r);
        !            86:        tlun.t_flushc = CTRL(o);
        !            87:        tlun.t_werasc = CTRL(w);
        !            88:        tlun.t_lnextc = CTRL(v);
        !            89:        tp->t_local = 0;
        !            90:        tp->t_lstate = 0;
        !            91: /* end local */
        !            92: }
        !            93: 
        !            94: /*
        !            95:  * Wait for output to drain, then flush input waiting.
        !            96:  */
        !            97: wflushtty(tp)
        !            98: register struct tty *tp;
        !            99: {
        !           100: 
        !           101:        (void) spl5();
        !           102:        while (tp->t_outq.c_cc && tp->t_state&CARR_ON) {
        !           103:                (*tp->t_oproc)(tp);
        !           104:                tp->t_state |= ASLEEP;
        !           105:                sleep((caddr_t)&tp->t_outq, TTOPRI);
        !           106:        }
        !           107:        flushtty(tp, FREAD|FWRITE);
        !           108:        (void) spl0();
        !           109: }
        !           110: 
        !           111: /*
        !           112:  * flush all TTY queues
        !           113:  */
        !           114: flushtty(tp, rw)
        !           115: register struct tty *tp;
        !           116: {
        !           117:        register s;
        !           118: 
        !           119:        if (tp->t_line == NETLDISC)
        !           120:                return;
        !           121:        s = spl6();
        !           122:        if (rw & FREAD) {
        !           123:                while (getc(&tp->t_canq) >= 0)
        !           124:                        ;
        !           125:                wakeup((caddr_t)&tp->t_rawq);
        !           126:        }
        !           127:        if (rw & FWRITE) {
        !           128:                wakeup((caddr_t)&tp->t_outq);
        !           129:                tp->t_state &= ~TTSTOP;
        !           130:                (*cdevsw[major(tp->t_dev)].d_stop)(tp);
        !           131:                while (getc(&tp->t_outq) >= 0)
        !           132:                        ;
        !           133:        }
        !           134:        if (rw & FREAD) {
        !           135:                while (getc(&tp->t_rawq) >= 0)
        !           136:                        ;
        !           137:                tp->t_delct = 0;
        !           138:                tp->t_rocount = 0;              /* local */
        !           139:                tp->t_rocol = 0;
        !           140:                tp->t_lstate = 0;
        !           141:        }
        !           142:        splx(s);
        !           143: }
        !           144: 
        !           145: /*
        !           146:  * Send stop character on input overflow.
        !           147:  */
        !           148: ttyblock(tp)
        !           149: register struct tty *tp;
        !           150: {
        !           151:        register x;
        !           152:        x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
        !           153:        if (tp->t_rawq.c_cc > TTYHOG) {
        !           154:                flushtty(tp, FREAD|FWRITE);
        !           155:                tp->t_state &= ~TBLOCK;
        !           156:        }
        !           157:        if (x >= TTYHOG/2) {
        !           158:                if (putc(tun.t_stopc, &tp->t_outq)==0) {
        !           159:                        tp->t_state |= TBLOCK;
        !           160:                        tp->t_char++;
        !           161:                        ttstart(tp);
        !           162:                }
        !           163:        }
        !           164: }
        !           165: 
        !           166: /*
        !           167:  * Restart typewriter output following a delay
        !           168:  * timeout.
        !           169:  * The name of the routine is passed to the timeout
        !           170:  * subroutine and it is called during a clock interrupt.
        !           171:  */
        !           172: ttrstrt(tp)
        !           173: register struct tty *tp;
        !           174: {
        !           175: 
        !           176:        tp->t_state &= ~TIMEOUT;
        !           177:        ttstart(tp);
        !           178: }
        !           179: 
        !           180: /*
        !           181:  * Start output on the typewriter. It is used from the top half
        !           182:  * after some characters have been put on the output queue,
        !           183:  * from the interrupt routine to transmit the next
        !           184:  * character, and after a timeout has finished.
        !           185:  */
        !           186: ttstart(tp)
        !           187: register struct tty *tp;
        !           188: {
        !           189:        register s;
        !           190: 
        !           191:        s = spl5();
        !           192:        if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0)
        !           193:                (*tp->t_oproc)(tp);
        !           194:        splx(s);
        !           195: }
        !           196: 
        !           197: /*
        !           198:  * Common code for tty ioctls.
        !           199:  */
        !           200: /*ARGSUSED*/
        !           201: ttioctl(com, tp, addr, dev, flag)
        !           202: register struct tty *tp;
        !           203: caddr_t addr;
        !           204: {
        !           205:        unsigned t;
        !           206:        struct sgttyb iocb;
        !           207:        struct clist tq;
        !           208:        extern int nldisp;
        !           209:        register c;
        !           210:        int temp;
        !           211: 
        !           212:        /*
        !           213:         * This is especially so that isatty() will
        !           214:         * fail when carrier is gone.
        !           215:         */
        !           216:        if ((tp->t_state&CARR_ON) == 0) {
        !           217:                u.u_error = EBADF;
        !           218:                return (1);
        !           219:        }
        !           220: 
        !           221:        /*
        !           222:         * If the ioctl involves modification,
        !           223:         * insist on being able to write the device,
        !           224:         * and hang if in the background.
        !           225:         */
        !           226:        switch(com) {
        !           227: 
        !           228:        case TIOCSETD:
        !           229:        case TIOCSETP:
        !           230:        case TIOCSETN:
        !           231:        case TIOCFLUSH:
        !           232:        case TIOCSETC:
        !           233:        case TIOCSLTC:
        !           234:        case TIOCSPGRP:
        !           235:        case TIOCLBIS:
        !           236:        case TIOCLBIC:
        !           237:        case TIOCLSET:
        !           238:        case TIOCSTI:
        !           239: /* this is reasonable, but impractical... 
        !           240:                if ((flag & FWRITE) == 0) {
        !           241:                        u.u_error = EBADF;
        !           242:                        return (1);
        !           243:                }
        !           244:  */
        !           245:                while (tp->t_line == NTTYDISC &&
        !           246:                   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
        !           247:                   (u.u_procp->p_flag&SVFORK) == 0 &&
        !           248:                   u.u_signal[SIGTTOU] != SIG_IGN &&
        !           249:                   u.u_signal[SIGTTOU] != SIG_HOLD &&
        !           250:                   (u.u_procp->p_flag&SDETACH)==0) {
        !           251:                        gsignal(u.u_procp->p_pgrp, SIGTTOU);
        !           252:                        sleep((caddr_t)&lbolt, TTOPRI);
        !           253:                }
        !           254:                break;
        !           255:        }
        !           256: 
        !           257:        /*
        !           258:         * Process the ioctl.
        !           259:         */
        !           260:        switch(com) {
        !           261: 
        !           262:        /*
        !           263:         * Get discipline number
        !           264:         */
        !           265:        case TIOCGETD:
        !           266:                t = tp->t_line;
        !           267:                if (copyout((caddr_t)&t, addr, sizeof(t)))
        !           268:                        u.u_error = EFAULT;
        !           269:                break;
        !           270: 
        !           271:        /*
        !           272:         * Set line discipline
        !           273:         */
        !           274:        case TIOCSETD:
        !           275:                if (copyin(addr, (caddr_t)&t, sizeof(t))) {
        !           276:                        u.u_error = EFAULT;
        !           277:                        break;
        !           278:                }
        !           279:                if (t >= nldisp) {
        !           280:                        u.u_error = ENXIO;
        !           281:                        break;
        !           282:                }
        !           283:                (void) spl5();
        !           284:                if (tp->t_line)
        !           285:                        (*linesw[tp->t_line].l_close)(tp);
        !           286:                if (t)
        !           287:                        (*linesw[t].l_open)(dev, tp, addr);
        !           288:                if (u.u_error==0)
        !           289:                        tp->t_line = t;
        !           290:                (void) spl0();
        !           291:                break;
        !           292: 
        !           293:        /*
        !           294:         * Prevent more opens on channel
        !           295:         */
        !           296:        case TIOCEXCL:
        !           297:                tp->t_state |= XCLUDE;
        !           298:                break;
        !           299: 
        !           300:        case TIOCNXCL:
        !           301:                tp->t_state &= ~XCLUDE;
        !           302:                break;
        !           303: 
        !           304:        /*
        !           305:         * Set new parameters
        !           306:         */
        !           307:        case TIOCSETP:
        !           308:        case TIOCSETN:
        !           309:                if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
        !           310:                        u.u_error = EFAULT;
        !           311:                        return(1);
        !           312:                }
        !           313:                (void) spl5();
        !           314:                if (tp->t_line == 0) {
        !           315:                        if (com == TIOCSETP)
        !           316:                                wflushtty(tp);
        !           317:                        while (canon(tp)>=0) 
        !           318:                                ;
        !           319: #ifdef notdef
        !           320:                        wakeup((caddr_t)&tp->t_rawq);
        !           321: #endif
        !           322:                } else if (tp->t_line == NTTYDISC) {
        !           323:                        if (tp->t_flags&RAW || iocb.sg_flags&RAW ||
        !           324:                            com == TIOCSETP)
        !           325:                                wflushtty(tp);
        !           326:                        else if ((tp->t_flags&CBREAK) != (iocb.sg_flags&CBREAK)) {
        !           327:                                if (iocb.sg_flags & CBREAK) {
        !           328:                                        catq(&tp->t_rawq, &tp->t_canq);
        !           329:                                        tq = tp->t_rawq;
        !           330:                                        tp->t_rawq = tp->t_canq;
        !           331:                                        tp->t_canq = tq;
        !           332:                                } else {
        !           333:                                        tp->t_local |= LPENDIN;
        !           334:                                        if (tp->t_canq.c_cc)
        !           335:                                                panic("ioccom canq");
        !           336: #ifdef notdef
        !           337:                                        if (tp->t_chan)
        !           338:                                                (void) sdata(tp->t_chan);
        !           339:                                        else
        !           340: #endif
        !           341:                                                wakeup((caddr_t)&tp->t_rawq);
        !           342:                                }
        !           343:                        }
        !           344:                }
        !           345:                if ((tp->t_state&SPEEDS)==0) {
        !           346:                        tp->t_ispeed = iocb.sg_ispeed;
        !           347:                        tp->t_ospeed = iocb.sg_ospeed;
        !           348:                }
        !           349:                tp->t_erase = iocb.sg_erase;
        !           350:                tp->t_kill = iocb.sg_kill;
        !           351:                tp->t_flags = iocb.sg_flags;
        !           352:                (void) spl0();
        !           353:                break;
        !           354: 
        !           355:        /*
        !           356:         * Send current parameters to user
        !           357:         */
        !           358:        case TIOCGETP:
        !           359:                iocb.sg_ispeed = tp->t_ispeed;
        !           360:                iocb.sg_ospeed = tp->t_ospeed;
        !           361:                iocb.sg_erase = tp->t_erase;
        !           362:                iocb.sg_kill = tp->t_kill;
        !           363:                iocb.sg_flags = tp->t_flags;
        !           364:                if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
        !           365:                        u.u_error = EFAULT;
        !           366:                break;
        !           367: 
        !           368:        /*
        !           369:         * Hang up line on last close
        !           370:         */
        !           371:        case TIOCHPCL:
        !           372:                tp->t_state |= HUPCLS;
        !           373:                break;
        !           374: 
        !           375:        case TIOCFLUSH:
        !           376:                flushtty(tp, FREAD|FWRITE);
        !           377:                break;
        !           378: 
        !           379:        /*
        !           380:         * Ioctl entries to line discipline
        !           381:         */
        !           382:        case DIOCSETP:
        !           383:        case DIOCGETP:
        !           384:                if ((*linesw[tp->t_line].l_ioctl)(com, tp, addr))
        !           385:                        u.u_error = ENOTTY;
        !           386:                break;
        !           387: 
        !           388:        /*
        !           389:         * Set and fetch special characters
        !           390:         */
        !           391:        case TIOCSETC:
        !           392:                if (copyin(addr, (caddr_t)&tun, sizeof(struct tchars)))
        !           393:                        u.u_error = EFAULT;
        !           394:                break;
        !           395: 
        !           396:        case TIOCGETC:
        !           397:                if (copyout((caddr_t)&tun, addr, sizeof(struct tchars)))
        !           398:                        u.u_error = EFAULT;
        !           399:                break;
        !           400: 
        !           401: /* local ioctls */
        !           402:        /*
        !           403:         * Set/get local special characters.
        !           404:         */
        !           405:        case TIOCSLTC:
        !           406:                if (copyin(addr, (caddr_t)&tlun, sizeof (struct ltchars)))
        !           407:                        u.u_error = EFAULT;
        !           408:                break;
        !           409: 
        !           410:        case TIOCGLTC:
        !           411:                if (copyout((caddr_t)&tlun, addr, sizeof (struct ltchars)))
        !           412:                        u.u_error = EFAULT;
        !           413:                break;
        !           414: 
        !           415:        /*
        !           416:         * Return number of characters immediately available.
        !           417:         */
        !           418:        case FIONREAD: {
        !           419:                off_t nread;
        !           420: 
        !           421:                switch (tp->t_line) {
        !           422: 
        !           423:                case NETLDISC:
        !           424:                        nread = tp->t_rec ? tp->t_inbuf : 0;
        !           425:                        break;
        !           426: 
        !           427:                case 0:
        !           428:                        (void) spl5();
        !           429:                        while (canon(tp)>=0)
        !           430:                                ;
        !           431:                        (void) spl0();
        !           432:                        /* fall into ... */
        !           433: 
        !           434:                case NTTYDISC:
        !           435:                        nread = tp->t_canq.c_cc;
        !           436:                        if (tp->t_flags & (RAW|CBREAK))
        !           437:                                nread += tp->t_rawq.c_cc;
        !           438:                        break;
        !           439: 
        !           440:                }
        !           441:                if (copyout((caddr_t)&nread, addr, sizeof (off_t)))
        !           442:                        u.u_error = EFAULT;
        !           443:                break;
        !           444:                }
        !           445: 
        !           446:        /*
        !           447:         * Should allow SPGRP and GPGRP only if tty open for reading.
        !           448:         */
        !           449:        case TIOCSPGRP:
        !           450:                if (copyin(addr, (caddr_t)&tp->t_pgrp, sizeof (tp->t_pgrp)))
        !           451:                        u.u_error = EFAULT;
        !           452:                break;
        !           453: 
        !           454:        case TIOCGPGRP:
        !           455:                if (copyout((caddr_t)&tp->t_pgrp, addr, sizeof(tp->t_pgrp)))
        !           456:                        u.u_error = EFAULT;
        !           457:                break;
        !           458: 
        !           459:        /*
        !           460:         * Modify local mode word.
        !           461:         */
        !           462:        case TIOCLBIS:
        !           463:                if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
        !           464:                        u.u_error = EFAULT;
        !           465:                else
        !           466:                        tp->t_local |= temp;
        !           467:                break;
        !           468: 
        !           469:        case TIOCLBIC:
        !           470:                if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
        !           471:                        u.u_error = EFAULT;
        !           472:                else
        !           473:                        tp->t_local &= ~temp;
        !           474:                break;
        !           475: 
        !           476:        case TIOCLSET:
        !           477:                if (copyin(addr, (caddr_t)&temp, sizeof (tp->t_local)))
        !           478:                        u.u_error = EFAULT;
        !           479:                else
        !           480:                        tp->t_local = temp;
        !           481:                break;
        !           482: 
        !           483:        case TIOCLGET:
        !           484:                if (copyout((caddr_t)&tp->t_local, addr, sizeof(tp->t_local)))
        !           485:                        u.u_error = EFAULT;
        !           486:                break;
        !           487: 
        !           488:        /*
        !           489:         * Return number of characters in
        !           490:         * the output.
        !           491:         */
        !           492:        case TIOCOUTQ:
        !           493:                if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc)))
        !           494:                        u.u_error = EFAULT;
        !           495:                break;
        !           496: 
        !           497:        /*
        !           498:         * Simulate typing of a character at the terminal.
        !           499:         */
        !           500:        case TIOCSTI:
        !           501:                c = fubyte(addr);
        !           502:                if (u.u_uid && u.u_ttyp != tp || c < 0)
        !           503:                        u.u_error = EFAULT;
        !           504:                else
        !           505:                        (*linesw[tp->t_line].l_rint)(c, tp);
        !           506:                break;
        !           507: /* end of locals */
        !           508: 
        !           509:        default:
        !           510:                return(0);
        !           511:        }
        !           512:        return(1);
        !           513: }

unix.superglobalmegacorp.com

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