Annotation of 41BSD/4.0.upgrade/sys/dev/tty.c, revision 1.1.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.