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