Annotation of 41BSD/4.0.upgrade/sys/dev/tty.c, revision 1.1

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

unix.superglobalmegacorp.com

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