Annotation of MiNT/src/tty.c, revision 1.1

1.1     ! root        1: /*
        !             2: 
        !             3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
        !             4: 
        !             5: */
        !             6: 
        !             7: 
        !             8: 
        !             9: /*
        !            10: 
        !            11:  * read/write routines for TTY devices
        !            12: 
        !            13:  */
        !            14: 
        !            15: 
        !            16: 
        !            17: #include "mint.h"
        !            18: 
        !            19: 
        !            20: 
        !            21: static void _erase P_((FILEPTR *, int));
        !            22: 
        !            23: static int escseq P_((struct tty *, int));
        !            24: 
        !            25: 
        !            26: 
        !            27: /* setting a special character to this value disables it */
        !            28: 
        !            29: #define UNDEF 0
        !            30: 
        !            31: 
        !            32: 
        !            33: 
        !            34: 
        !            35: /* default terminal characteristics */
        !            36: 
        !            37: 
        !            38: 
        !            39: struct tty default_tty = {
        !            40: 
        !            41:        0,                      /* process group */
        !            42: 
        !            43:        0,                      /* state */
        !            44: 
        !            45:        0,                      /* use_cnt */
        !            46: 
        !            47:        0,                      /* reserved short */
        !            48: 
        !            49:        {
        !            50: 
        !            51:        13, 13,                 /* input speed == output speed == 9600 baud */
        !            52: 
        !            53:        CTRL('H'),              /* erase */
        !            54: 
        !            55:        CTRL('U'),              /* kill */
        !            56: 
        !            57:        T_ECHO|T_CRMOD|T_TOSTOP|T_XKEY, /* flags */
        !            58: 
        !            59:        },
        !            60: 
        !            61:        {
        !            62: 
        !            63:        CTRL('C'),              /* interrupt */
        !            64: 
        !            65:        CTRL('\\'),             /* quit */
        !            66: 
        !            67:        CTRL('Q'),              /* start */
        !            68: 
        !            69:        CTRL('S'),              /* stop */
        !            70: 
        !            71:        CTRL('D'),              /* EOF */
        !            72: 
        !            73:        '\r'                    /* alternate end of line */
        !            74: 
        !            75:        },
        !            76: 
        !            77:        {
        !            78: 
        !            79:        CTRL('Z'),              /* suspend */
        !            80: 
        !            81:        CTRL('Y'),              /* suspend after read */
        !            82: 
        !            83:        CTRL('R'),              /* reprint */
        !            84: 
        !            85:        UNDEF,                  /* flush output */
        !            86: 
        !            87:        UNDEF,                  /* erase word */
        !            88: 
        !            89:        UNDEF                   /* quote next char */
        !            90: 
        !            91:        },
        !            92: 
        !            93:        {
        !            94: 
        !            95:        0, 0, 0, 0              /* window size is unknown */
        !            96: 
        !            97:        },
        !            98: 
        !            99:        0,                      /* no process is selecting us for reading */
        !           100: 
        !           101:        0,                      /* or for writing */
        !           102: 
        !           103:        0                       /* use default XKEY map */
        !           104: 
        !           105: };
        !           106: 
        !           107: 
        !           108: 
        !           109: #define _put(f, c) (tty_putchar((f), (c), RAW))
        !           110: 
        !           111: 
        !           112: 
        !           113: static void
        !           114: 
        !           115: _erase(f, c)
        !           116: 
        !           117:        FILEPTR *f;
        !           118: 
        !           119:        int c;
        !           120: 
        !           121: {
        !           122: 
        !           123:        _put(f, '\010');
        !           124: 
        !           125:        _put(f, ' ');
        !           126: 
        !           127:        _put(f, '\010');
        !           128: 
        !           129: /* watch out for control characters -- they're printed as e.g. "^C" */
        !           130: 
        !           131:        if (c >= 0 && c < ' ') {
        !           132: 
        !           133:                _put(f, '\010'); _put(f, ' '); _put(f, '\010');
        !           134: 
        !           135:        }
        !           136: 
        !           137: }
        !           138: 
        !           139: 
        !           140: 
        !           141: #define put(f, c)   { if (mode & T_ECHO) _put(f, c); }
        !           142: 
        !           143: #define erase(f, c) { if (mode & T_ECHO) _erase(f, c); }
        !           144: 
        !           145: 
        !           146: 
        !           147: long
        !           148: 
        !           149: tty_read(f, buf, nbytes)
        !           150: 
        !           151:        FILEPTR *f;
        !           152: 
        !           153:        void *buf;
        !           154: 
        !           155:        long nbytes;
        !           156: 
        !           157: {
        !           158: 
        !           159:        long r;
        !           160: 
        !           161:        long bytes_read = 0;
        !           162: 
        !           163:        unsigned char ch, *ptr;
        !           164: 
        !           165:        int rdmode, mode;
        !           166: 
        !           167:        struct tty *tty;
        !           168: 
        !           169: 
        !           170: 
        !           171:        tty = (struct tty *)f->devinfo;
        !           172: 
        !           173:        assert(tty != 0);
        !           174: 
        !           175: 
        !           176: 
        !           177:        if (f->flags & O_HEAD) {        /* pty server side? */
        !           178: 
        !           179:                rdmode = RAW;           /* yes -- always raw mode */
        !           180: 
        !           181:                mode = T_RAW;
        !           182: 
        !           183:        }
        !           184: 
        !           185:        else if (curproc->domain == DOM_MINT) { /* MiNT domain process? */
        !           186: 
        !           187:                mode = tty->sg.sg_flags;
        !           188: 
        !           189:                rdmode = COOKED|NOECHO;
        !           190: 
        !           191:                if ( mode & (T_RAW | T_CBREAK) ) {
        !           192: 
        !           193:                        rdmode = (mode & T_RAW) ? RAW : COOKED;
        !           194: 
        !           195:                }
        !           196: 
        !           197:                if (mode & T_XKEY)
        !           198: 
        !           199:                        rdmode |= ESCSEQ;
        !           200: 
        !           201:        }
        !           202: 
        !           203:        else {
        !           204: 
        !           205:                rdmode = COOKED|NOECHO;
        !           206: 
        !           207:                mode = T_TOS | T_ECHO;
        !           208: 
        !           209:        }
        !           210: 
        !           211: 
        !           212: 
        !           213:        ptr = buf;
        !           214: 
        !           215: 
        !           216: 
        !           217:        while (bytes_read < nbytes) {
        !           218: 
        !           219:                r = tty_getchar(f, rdmode);
        !           220: 
        !           221:                if (r < 0) {
        !           222: 
        !           223:                        DEBUG("tty_read: tty_getchar returned %ld", r);
        !           224: 
        !           225:                        return (bytes_read) ? bytes_read : r;
        !           226: 
        !           227:                }
        !           228: 
        !           229:                else if (r == MiNTEOF)
        !           230: 
        !           231:                        return bytes_read;
        !           232: 
        !           233:                ch = r & 0xff;
        !           234: 
        !           235: 
        !           236: 
        !           237:                if ( (mode & T_CRMOD) && (ch == '\r') )
        !           238: 
        !           239:                        ch = '\n';
        !           240: 
        !           241: 
        !           242: 
        !           243: /* 1 character reads in TOS mode are always raw */
        !           244: 
        !           245:                if (nbytes == 1 && (mode & T_TOS)) {
        !           246: 
        !           247:                        put(f, ch);
        !           248: 
        !           249:                        *ptr = ch;
        !           250: 
        !           251:                        return 1;
        !           252: 
        !           253:                }
        !           254: 
        !           255: 
        !           256: 
        !           257: /* T_CBREAK mode doesn't do erase or kill processing */
        !           258: 
        !           259: /* also note that setting a special character to UNDEF disables it */
        !           260: 
        !           261: 
        !           262: 
        !           263:                if (rdmode & COOKED && !(mode & T_CBREAK) && ch != UNDEF) {
        !           264: 
        !           265:                        if ((char)ch == tty->sg.sg_erase) {  /* backspace */
        !           266: 
        !           267:                                if (bytes_read > 0) {
        !           268: 
        !           269:                                        --ptr;
        !           270: 
        !           271:                                        erase(f, *ptr);
        !           272: 
        !           273:                                        bytes_read--;
        !           274: 
        !           275:                                }
        !           276: 
        !           277:                                continue;
        !           278: 
        !           279:                        }
        !           280: 
        !           281:                        else if (ch == CTRL('X')) {
        !           282: 
        !           283:                                while (bytes_read > 0) {
        !           284: 
        !           285:                                        --ptr;
        !           286: 
        !           287:                                        erase(f, *ptr);
        !           288: 
        !           289:                                        bytes_read--;
        !           290: 
        !           291:                                }
        !           292: 
        !           293:                                continue;
        !           294: 
        !           295:                        }
        !           296: 
        !           297:                        else if ((char)ch ==tty->ltc.t_rprntc || 
        !           298: 
        !           299:                                 (char)ch == tty->sg.sg_kill) {
        !           300: 
        !           301:                                if (mode & T_TOS)
        !           302: 
        !           303:                                        put(f, '#');
        !           304: 
        !           305:                                put(f, '\r');
        !           306: 
        !           307:                                put(f, '\n');
        !           308: 
        !           309:                                ptr = buf;
        !           310: 
        !           311:                                if ((char)ch == tty->sg.sg_kill) {
        !           312: 
        !           313:                                        bytes_read = 0;
        !           314: 
        !           315:                                }
        !           316: 
        !           317:                                else {
        !           318: 
        !           319:                                        for (r = 0; r < bytes_read; r++, ptr++)
        !           320: 
        !           321:                                                put(f, *ptr);
        !           322: 
        !           323:                                }
        !           324: 
        !           325:                                continue;
        !           326: 
        !           327:                        }
        !           328: 
        !           329:                        else if ((char)ch == tty->tc.t_eofc && !(mode & T_TOS))
        !           330: 
        !           331:                                return bytes_read;
        !           332: 
        !           333:                }
        !           334: 
        !           335: 
        !           336: 
        !           337: /* both T_CBREAK and T_COOKED modes have to do signals, though */
        !           338: 
        !           339:                if ((rdmode & COOKED) && ch != UNDEF) {
        !           340: 
        !           341:                        if ((char)ch == tty->tc.t_intrc
        !           342: 
        !           343:                                 || (char)ch == tty->tc.t_quitc
        !           344: 
        !           345:                                 || (char)ch == tty->ltc.t_dsuspc
        !           346: 
        !           347:                                 || (char)ch == tty->ltc.t_suspc
        !           348: 
        !           349:                                ) {
        !           350: 
        !           351: /* the device driver raised the appropriate signal; if we get here, the
        !           352: 
        !           353:    signal was caught by the user (or ignored). flush buffers and continue
        !           354: 
        !           355:  */
        !           356: 
        !           357:                                if (!(tty->sg.sg_flags & T_NOFLSH)) {
        !           358: 
        !           359:                                        DEBUG("tty_read: flushing input");
        !           360: 
        !           361:                                        bytes_read = 0;
        !           362: 
        !           363:                                        ptr = buf;
        !           364: 
        !           365:                                }
        !           366: 
        !           367:                                continue;
        !           368: 
        !           369:                        }
        !           370: 
        !           371:                        else if (ch == '\n' || (char)ch == tty->tc.t_brkc) {
        !           372: 
        !           373:                                put(f, '\r');
        !           374: 
        !           375:                                if (!(mode & T_TOS)) {
        !           376: 
        !           377:                                        *ptr++ = ch;
        !           378: 
        !           379:                                        put(f, '\n');
        !           380: 
        !           381:                                        bytes_read++;
        !           382: 
        !           383:                                }
        !           384: 
        !           385:                                return bytes_read;
        !           386: 
        !           387:                        }
        !           388: 
        !           389: 
        !           390: 
        !           391:                }
        !           392: 
        !           393: 
        !           394: 
        !           395: /* do the following for both RAW and COOKED mode */
        !           396: 
        !           397:                *ptr++ = ch;
        !           398: 
        !           399:                if (ch < ' ') {         /* ch is unsigned */
        !           400: 
        !           401:                        put(f, '^'); put(f, ch+'@');
        !           402: 
        !           403:                }
        !           404: 
        !           405:                else
        !           406: 
        !           407:                        put(f, ch);
        !           408: 
        !           409:                bytes_read++;
        !           410: 
        !           411: 
        !           412: 
        !           413: /* for RAW mode, if there are no more characters then break */
        !           414: 
        !           415:                if ( (mode & (T_RAW|T_CBREAK)) &&
        !           416: 
        !           417:                    !((rdmode & ESCSEQ) && (tty->state & TS_ESC))) {
        !           418: 
        !           419:                        r = 1;
        !           420: 
        !           421:                        (void)(*f->dev->ioctl)(f, FIONREAD, &r);
        !           422: 
        !           423:                        if (r <= 0) break;
        !           424: 
        !           425:                }       
        !           426: 
        !           427:        }
        !           428: 
        !           429: 
        !           430: 
        !           431:        return bytes_read;
        !           432: 
        !           433: }
        !           434: 
        !           435: 
        !           436: 
        !           437: long
        !           438: 
        !           439: tty_write(f, buf, nbytes)
        !           440: 
        !           441:        FILEPTR *f;
        !           442: 
        !           443:        const void *buf;
        !           444: 
        !           445:        long nbytes;
        !           446: 
        !           447: {
        !           448: 
        !           449:        unsigned const char *ptr;
        !           450: 
        !           451:        long c;
        !           452: 
        !           453:        long bytes_written;
        !           454: 
        !           455:        int mode, rwmode;
        !           456: 
        !           457:        struct tty *tty;
        !           458: 
        !           459:        int use_putchar = 0;
        !           460: 
        !           461:        static long cr_char = '\r';
        !           462: 
        !           463: #define LBUFSIZ 128
        !           464: 
        !           465:        long lbuf[LBUFSIZ];
        !           466: 
        !           467: 
        !           468: 
        !           469:        tty = (struct tty *)f->devinfo;
        !           470: 
        !           471:        assert(tty != 0);
        !           472: 
        !           473: 
        !           474: 
        !           475:        ptr = buf;
        !           476: 
        !           477:        if (f->flags & O_HEAD) {
        !           478: 
        !           479:                use_putchar = 1;
        !           480: 
        !           481:                mode = T_RAW;
        !           482: 
        !           483:        }
        !           484: 
        !           485:        else if (curproc->domain == DOM_TOS)
        !           486: 
        !           487: /* for TOS programs, 1 byte writes are always in raw mode */
        !           488: 
        !           489:                mode = (nbytes == 1) ? T_RAW : T_TOS;
        !           490: 
        !           491:        else
        !           492: 
        !           493:                mode = tty->sg.sg_flags;
        !           494: 
        !           495: 
        !           496: 
        !           497:        rwmode = (mode & T_RAW) ? RAW : COOKED;
        !           498: 
        !           499: 
        !           500: 
        !           501:        bytes_written = 0;
        !           502: 
        !           503: 
        !           504: 
        !           505: /*
        !           506: 
        !           507:  * "mode" can now be reduced to just T_CRMODE or not
        !           508: 
        !           509:  */
        !           510: 
        !           511:        if ((curproc->domain == DOM_MINT) && (mode & T_CRMOD) &&
        !           512: 
        !           513:            !(mode & T_RAW))
        !           514: 
        !           515:                mode = T_CRMOD;
        !           516: 
        !           517:        else
        !           518: 
        !           519:                mode = 0;
        !           520: 
        !           521: 
        !           522: 
        !           523: /*
        !           524: 
        !           525:  * we always write at least 1 byte with tty_putchar, since that takes
        !           526: 
        !           527:  * care of job control and terminal states. After that, we may be able
        !           528: 
        !           529:  * to use (*f->dev->write) directly.
        !           530: 
        !           531:  */
        !           532: 
        !           533: 
        !           534: 
        !           535: 
        !           536: 
        !           537:        if (nbytes == 0) return bytes_written;
        !           538: 
        !           539:        c = *ptr++;
        !           540: 
        !           541: 
        !           542: 
        !           543:        if (c == '\n' && mode) {        /* remember, "mode" now means CRMOD */
        !           544: 
        !           545:                tty_putchar(f, cr_char, rwmode);
        !           546: 
        !           547:        }
        !           548: 
        !           549:        tty_putchar(f, c, rwmode);
        !           550: 
        !           551:        nbytes--;
        !           552: 
        !           553:        bytes_written++;
        !           554: 
        !           555: 
        !           556: 
        !           557:        if (use_putchar) {
        !           558: 
        !           559:                while (nbytes-- > 0) {
        !           560: 
        !           561:                        c = *ptr++;
        !           562: 
        !           563:                        if (c == '\n' && mode)
        !           564: 
        !           565:                                tty_putchar(f, cr_char, rwmode);
        !           566: 
        !           567:                        tty_putchar(f, c, rwmode);
        !           568: 
        !           569:                        bytes_written++;
        !           570: 
        !           571:                }
        !           572: 
        !           573:        } else {
        !           574: 
        !           575: /* write in big chunks if possible; but never more than 1 line
        !           576: 
        !           577:  * (so that ^S/^Q can happen reasonably quickly for the user)
        !           578: 
        !           579:  */
        !           580: 
        !           581:                long bytes_to_write = 0;
        !           582: 
        !           583:                long *s = lbuf;
        !           584: 
        !           585: 
        !           586: 
        !           587:                while (nbytes-- > 0) {
        !           588: 
        !           589:                        c = *ptr++;
        !           590: 
        !           591:                        if (c == '\n') {
        !           592: 
        !           593:                                if (bytes_to_write) {
        !           594: 
        !           595:                                        (*f->dev->write)(f, (char *)lbuf,
        !           596: 
        !           597:                                                bytes_to_write);
        !           598: 
        !           599:                                        bytes_to_write = 0;
        !           600: 
        !           601:                                        s = lbuf;
        !           602: 
        !           603:                                }
        !           604: 
        !           605:                                if (mode)       /* i.e. T_CRMODE */
        !           606: 
        !           607:                                        tty_putchar(f, cr_char, rwmode);
        !           608: 
        !           609:                                tty_putchar(f, (long)c, rwmode);
        !           610: 
        !           611:                                bytes_written++;
        !           612: 
        !           613:                        } else {
        !           614: 
        !           615:                                *s++ = c;
        !           616: 
        !           617:                                bytes_written++;
        !           618: 
        !           619:                                bytes_to_write += 4;
        !           620: 
        !           621:                                if (bytes_to_write >= LBUFSIZ*4) {
        !           622: 
        !           623:                                        (*f->dev->write)(f, (char *)lbuf,
        !           624: 
        !           625:                                                         bytes_to_write);
        !           626: 
        !           627:                                        bytes_to_write = 0;
        !           628: 
        !           629:                                        s = lbuf;
        !           630: 
        !           631:                                }
        !           632: 
        !           633:                        }
        !           634: 
        !           635:                }
        !           636: 
        !           637:                if (bytes_to_write) {
        !           638: 
        !           639:                        (*f->dev->write)(f, (char *)lbuf, bytes_to_write);
        !           640: 
        !           641:                }
        !           642: 
        !           643:        }
        !           644: 
        !           645: 
        !           646: 
        !           647:        return bytes_written;
        !           648: 
        !           649: }
        !           650: 
        !           651: 
        !           652: 
        !           653: /* some notable scan codes */
        !           654: 
        !           655: #define K_INSERT       0x52
        !           656: 
        !           657: #define K_HOME         0x47
        !           658: 
        !           659: #define K_UNDO         0x61
        !           660: 
        !           661: #define K_HELP         0x62
        !           662: 
        !           663: #define CURS_UP                0x48
        !           664: 
        !           665: #define CURS_DN                0x50
        !           666: 
        !           667: #define CURS_RT                0x4d
        !           668: 
        !           669: #define CURS_LF                0x4b
        !           670: 
        !           671: #define F_1            0x3b
        !           672: 
        !           673: #define F_10           0x44
        !           674: 
        !           675: #define F_11           0x54
        !           676: 
        !           677: #define F_20           0x5d
        !           678: 
        !           679: #define ALT_1          0x78
        !           680: 
        !           681: #define ALT_0          0x81
        !           682: 
        !           683: 
        !           684: 
        !           685: /* Default function key table:
        !           686: 
        !           687:  * entries:    0-9 are F1-F10
        !           688: 
        !           689:  *             10-19 are F11-F20
        !           690: 
        !           691:  *             20-23 are cursor up, down, right, and left
        !           692: 
        !           693:  *             24-27 are help, undo, insert, and home
        !           694: 
        !           695:  *             28-31 are shift+cursor up, down, right, and left
        !           696: 
        !           697:  */
        !           698: 
        !           699: 
        !           700: 
        !           701: static char vt52xkey[256] = {
        !           702: 
        !           703: '\033', 'P', 0, 0, 0, 0, 0, 0,
        !           704: 
        !           705: '\033', 'Q', 0, 0, 0, 0, 0, 0,
        !           706: 
        !           707: '\033', 'R', 0, 0, 0, 0, 0, 0,
        !           708: 
        !           709: '\033', 'S', 0, 0, 0, 0, 0, 0,
        !           710: 
        !           711: '\033', 'T', 0, 0, 0, 0, 0, 0,
        !           712: 
        !           713: '\033', 'U', 0, 0, 0, 0, 0, 0,
        !           714: 
        !           715: '\033', 'V', 0, 0, 0, 0, 0, 0,
        !           716: 
        !           717: '\033', 'W', 0, 0, 0, 0, 0, 0,
        !           718: 
        !           719: '\033', 'X', 0, 0, 0, 0, 0, 0,
        !           720: 
        !           721: '\033', 'Y', 0, 0, 0, 0, 0, 0,
        !           722: 
        !           723: '\033', 'p', 0, 0, 0, 0, 0, 0,
        !           724: 
        !           725: '\033', 'q', 0, 0, 0, 0, 0, 0,
        !           726: 
        !           727: '\033', 'r', 0, 0, 0, 0, 0, 0,
        !           728: 
        !           729: '\033', 's', 0, 0, 0, 0, 0, 0,
        !           730: 
        !           731: '\033', 't', 0, 0, 0, 0, 0, 0,
        !           732: 
        !           733: '\033', 'u', 0, 0, 0, 0, 0, 0,
        !           734: 
        !           735: '\033', 'v', 0, 0, 0, 0, 0, 0,
        !           736: 
        !           737: '\033', 'w', 0, 0, 0, 0, 0, 0,
        !           738: 
        !           739: '\033', 'x', 0, 0, 0, 0, 0, 0,
        !           740: 
        !           741: '\033', 'y', 0, 0, 0, 0, 0, 0,
        !           742: 
        !           743: '\033', 'A', 0, 0, 0, 0, 0, 0,
        !           744: 
        !           745: '\033', 'B', 0, 0, 0, 0, 0, 0,
        !           746: 
        !           747: '\033', 'C', 0, 0, 0, 0, 0, 0,
        !           748: 
        !           749: '\033', 'D', 0, 0, 0, 0, 0, 0,
        !           750: 
        !           751: '\033', 'H', 0, 0, 0, 0, 0, 0,
        !           752: 
        !           753: '\033', 'K', 0, 0, 0, 0, 0, 0,
        !           754: 
        !           755: '\033', 'I', 0, 0, 0, 0, 0, 0,
        !           756: 
        !           757: '\033', 'E', 0, 0, 0, 0, 0, 0,
        !           758: 
        !           759: '\033', 'a', 0, 0, 0, 0, 0, 0,
        !           760: 
        !           761: '\033', 'b', 0, 0, 0, 0, 0, 0,
        !           762: 
        !           763: '\033', 'c', 0, 0, 0, 0, 0, 0,
        !           764: 
        !           765: '\033', 'd', 0, 0, 0, 0, 0, 0,
        !           766: 
        !           767: };
        !           768: 
        !           769: 
        !           770: 
        !           771: static char unxbaud P_((long));
        !           772: 
        !           773: 
        !           774: 
        !           775: /* convert a number describing the baud rate into a Unix
        !           776: 
        !           777:  * style baud rate number. Returns the Unix baud rate,
        !           778: 
        !           779:  * or 16 (EXTA) if the rate is unknown
        !           780: 
        !           781:  */
        !           782: 
        !           783: 
        !           784: 
        !           785: #define EXTA 16
        !           786: 
        !           787: 
        !           788: 
        !           789: static long ubaud[EXTA] = {
        !           790: 
        !           791: 0L, 50L, 75L, 110L, 134L, 150L, 200L, 300L,
        !           792: 
        !           793: 600L, 1200L, 1800L, 2400L, 4800L, 9600L, 19200L, 38400L
        !           794: 
        !           795: };
        !           796: 
        !           797: 
        !           798: 
        !           799: static char
        !           800: 
        !           801: unxbaud(baud)
        !           802: 
        !           803:        long baud;
        !           804: 
        !           805: {
        !           806: 
        !           807:        int i;
        !           808: 
        !           809:        for (i = 1; i < EXTA; i++) {
        !           810: 
        !           811:                if (ubaud[i] == baud)
        !           812: 
        !           813:                        break;
        !           814: 
        !           815:        }
        !           816: 
        !           817:        return i;
        !           818: 
        !           819: }
        !           820: 
        !           821: 
        !           822: 
        !           823: #define tosbaud(c) ( ((c) < 0 || (c) >= EXTA) ? -1L : ubaud[c] )
        !           824: 
        !           825: 
        !           826: 
        !           827: long
        !           828: 
        !           829: tty_ioctl(f, mode, arg)
        !           830: 
        !           831:        FILEPTR *f;
        !           832: 
        !           833:        int mode;
        !           834: 
        !           835:        void *arg;
        !           836: 
        !           837: {
        !           838: 
        !           839:        struct sgttyb *sg;
        !           840: 
        !           841:        struct tchars *tc;
        !           842: 
        !           843:        struct ltchars *ltc;
        !           844: 
        !           845:        struct tty *tty;
        !           846: 
        !           847:        struct winsize *sz;
        !           848: 
        !           849:        struct xkey *xk;
        !           850: 
        !           851:        char *xktab;
        !           852: 
        !           853:        int i;
        !           854: 
        !           855:        long baud;
        !           856: 
        !           857:        short flags;
        !           858: 
        !           859: 
        !           860: 
        !           861:        if (!is_terminal(f)) {
        !           862: 
        !           863:                DEBUG("tty_ioctl(mode %x): file is not a tty", mode);
        !           864: 
        !           865:                return EINVFN;
        !           866: 
        !           867:        }
        !           868: 
        !           869:        tty = (struct tty *)f->devinfo;
        !           870: 
        !           871:        assert(tty != 0);
        !           872: 
        !           873: 
        !           874: 
        !           875:        switch(mode) {
        !           876: 
        !           877:        case TIOCGETP:
        !           878: 
        !           879:                sg = (struct sgttyb *)arg;
        !           880: 
        !           881:        /* get input and output baud rates from the terminal device */
        !           882: 
        !           883:                baud = -1L;
        !           884: 
        !           885:                (*f->dev->ioctl)(f, TIOCIBAUD, &baud);
        !           886: 
        !           887:                tty->sg.sg_ispeed = unxbaud(baud);
        !           888: 
        !           889:                baud = -1L;
        !           890: 
        !           891:                (*f->dev->ioctl)(f, TIOCOBAUD, &baud);
        !           892: 
        !           893:                tty->sg.sg_ospeed = unxbaud(baud);
        !           894: 
        !           895:        /* get terminal flags */
        !           896: 
        !           897:                flags = 0;
        !           898: 
        !           899:                if ((*f->dev->ioctl)(f, TIOCGFLAGS, &flags) == 0) {
        !           900: 
        !           901:                        tty->sg.sg_flags &= ~TF_FLAGS;
        !           902: 
        !           903:                        tty->sg.sg_flags |= (flags & TF_FLAGS);
        !           904: 
        !           905:                }
        !           906: 
        !           907:                *sg = tty->sg;
        !           908: 
        !           909:                return 0;
        !           910: 
        !           911:        case TIOCSETP:
        !           912: 
        !           913:                sg = (struct sgttyb *)arg;
        !           914: 
        !           915:                tty->sg = *sg;
        !           916: 
        !           917:        /* set baud rates */
        !           918: 
        !           919:                baud = tosbaud(sg->sg_ispeed);
        !           920: 
        !           921:                (*f->dev->ioctl)(f, TIOCIBAUD, &baud);
        !           922: 
        !           923:                baud = tosbaud(sg->sg_ospeed);
        !           924: 
        !           925:                (*f->dev->ioctl)(f, TIOCOBAUD, &baud);
        !           926: 
        !           927:        /* set parity, etc. */
        !           928: 
        !           929:                flags = TF_8BIT;
        !           930: 
        !           931:                if (sg->sg_flags & (T_EVENP|T_ODDP)) {
        !           932: 
        !           933:                        flags = TF_7BIT;
        !           934: 
        !           935:                }
        !           936: 
        !           937:                flags |= (sg->sg_flags & TF_FLAGS);
        !           938: 
        !           939:                (*f->dev->ioctl)(f, TIOCSFLAGS, &flags);
        !           940: 
        !           941:                return 0;
        !           942: 
        !           943:        case TIOCGETC:
        !           944: 
        !           945:                tc = (struct tchars *)arg;
        !           946: 
        !           947:                *tc = tty->tc;
        !           948: 
        !           949:                return 0;
        !           950: 
        !           951:        case TIOCSETC:
        !           952: 
        !           953:                tc = (struct tchars *)arg;
        !           954: 
        !           955:                tty->tc = *tc;
        !           956: 
        !           957:                return 0;
        !           958: 
        !           959:        case TIOCGLTC:
        !           960: 
        !           961:                ltc = (struct ltchars *)arg;
        !           962: 
        !           963:                *ltc = tty->ltc;
        !           964: 
        !           965:                return 0;
        !           966: 
        !           967:        case TIOCSLTC:
        !           968: 
        !           969:                ltc = (struct ltchars *)arg;
        !           970: 
        !           971:                tty->ltc = *ltc;
        !           972: 
        !           973:                return 0;
        !           974: 
        !           975:        case TIOCGWINSZ:
        !           976: 
        !           977:                sz = (struct winsize *)arg;
        !           978: 
        !           979:                *sz = tty->wsiz;
        !           980: 
        !           981:                return 0;
        !           982: 
        !           983:        case TIOCSWINSZ:
        !           984: 
        !           985:                sz = (struct winsize *)arg;
        !           986: 
        !           987:                tty->wsiz = *sz;
        !           988: 
        !           989:                return 0;
        !           990: 
        !           991:        case TIOCGPGRP:
        !           992: 
        !           993:                *((long *)arg) = tty->pgrp;
        !           994: 
        !           995:                return 0;
        !           996: 
        !           997:        case TIOCSPGRP:
        !           998: 
        !           999:                tty->pgrp = (*((long *)arg) & 0x00007fffL);
        !          1000: 
        !          1001:                return 0;
        !          1002: 
        !          1003:        case TIOCSTART:
        !          1004: 
        !          1005:                tty->state &= ~TS_HOLD;
        !          1006: 
        !          1007:                return 0;
        !          1008: 
        !          1009:        case TIOCSTOP:
        !          1010: 
        !          1011:                tty->state |= TS_HOLD;
        !          1012: 
        !          1013:                return 0;
        !          1014: 
        !          1015:        case TIOCGXKEY:
        !          1016: 
        !          1017:                xk = (struct xkey *)arg;
        !          1018: 
        !          1019:                i = xk->xk_num;
        !          1020: 
        !          1021:                if (i < 0 || i > 31) return ERANGE;
        !          1022: 
        !          1023:                xktab = tty->xkey;
        !          1024: 
        !          1025:                if (!xktab) xktab = vt52xkey;
        !          1026: 
        !          1027:                xktab += i*8;
        !          1028: 
        !          1029:                for (i = 0; i < 8; i++)
        !          1030: 
        !          1031:                        xk->xk_def[i] = *xktab++;
        !          1032: 
        !          1033:                return 0;
        !          1034: 
        !          1035:        case TIOCSXKEY:
        !          1036: 
        !          1037:                xk = (struct xkey *)arg;
        !          1038: 
        !          1039:                xktab = tty->xkey;
        !          1040: 
        !          1041:                if (!xktab) {
        !          1042: 
        !          1043:                        xktab = kmalloc((long)256);
        !          1044: 
        !          1045:                        if (!xktab) return ENSMEM;
        !          1046: 
        !          1047:                        for (i = 0; i < 256; i++)
        !          1048: 
        !          1049:                                xktab[i] = vt52xkey[i];
        !          1050: 
        !          1051:                        tty->xkey = xktab;
        !          1052: 
        !          1053:                }
        !          1054: 
        !          1055:                i = xk->xk_num;
        !          1056: 
        !          1057:                if (i < 0 || i > 31) return ERANGE;
        !          1058: 
        !          1059:                xktab += i*8;
        !          1060: 
        !          1061:                for (i = 0; i < 7; i++)
        !          1062: 
        !          1063:                        xktab[i] = xk->xk_def[i];
        !          1064: 
        !          1065:                xktab[7] = 0;
        !          1066: 
        !          1067:                return 0;
        !          1068: 
        !          1069:        default:
        !          1070: 
        !          1071:                DEBUG("tty_ioctl: bad function call");
        !          1072: 
        !          1073:                return EINVFN;
        !          1074: 
        !          1075:        }
        !          1076: 
        !          1077: }
        !          1078: 
        !          1079: 
        !          1080: 
        !          1081: /*
        !          1082: 
        !          1083:  * function for translating extended characters (e.g. cursor keys, or
        !          1084: 
        !          1085:  * ALT+key sequences) into either escape sequences or meta characters.
        !          1086: 
        !          1087:  * for escape sequences, we return the the first character of the
        !          1088: 
        !          1089:  * sequence (normally ESC) and set the tty's state so that subsequent
        !          1090: 
        !          1091:  * calls to tty_getchar will pick up the remaining characters.
        !          1092: 
        !          1093:  * Note that escape sequences are limited to 7 characters at most.
        !          1094: 
        !          1095:  */
        !          1096: 
        !          1097: 
        !          1098: 
        !          1099: static int
        !          1100: 
        !          1101: escseq(tty, scan)
        !          1102: 
        !          1103:        struct tty *tty;
        !          1104: 
        !          1105:        int scan;
        !          1106: 
        !          1107: {
        !          1108: 
        !          1109:        char *tab;
        !          1110: 
        !          1111:        int i;
        !          1112: 
        !          1113: 
        !          1114: 
        !          1115:        switch(scan) {
        !          1116: 
        !          1117:        case CURS_UP: i = 20; break;
        !          1118: 
        !          1119:        case CURS_DN: i = 21; break;
        !          1120: 
        !          1121:        case CURS_RT: i = 22; break;
        !          1122: 
        !          1123:        case CURS_LF: i = 23; break;
        !          1124: 
        !          1125:        case K_HELP:  i = 24; break;
        !          1126: 
        !          1127:        case K_UNDO:  i = 25; break;
        !          1128: 
        !          1129:        case K_INSERT:i = 26; break;
        !          1130: 
        !          1131:        case K_HOME:  i = 27; break;
        !          1132: 
        !          1133:        case CURS_UP+0x100: i = 28; break;
        !          1134: 
        !          1135:        case CURS_DN+0x100: i = 29; break;
        !          1136: 
        !          1137:        case CURS_RT+0x100: i = 30; break;
        !          1138: 
        !          1139:        case CURS_LF+0x100: i = 31; break;
        !          1140: 
        !          1141:        default:
        !          1142: 
        !          1143:                if (scan >= F_1 && scan <= F_10) {
        !          1144: 
        !          1145:                        i = scan - F_1;
        !          1146: 
        !          1147:                } else if (scan >= F_11 && scan <= F_20) {
        !          1148: 
        !          1149:                        i = 10 + scan - F_11;
        !          1150: 
        !          1151:                } else
        !          1152: 
        !          1153:                        i = -1;
        !          1154: 
        !          1155:        }
        !          1156: 
        !          1157: 
        !          1158: 
        !          1159:        if (i >= 0) {           /* an extended escape sequence */
        !          1160: 
        !          1161:                tab = tty->xkey;
        !          1162: 
        !          1163:                if (!tab) tab = vt52xkey;
        !          1164: 
        !          1165:                i *= 8;
        !          1166: 
        !          1167:                scan = tab[i++];
        !          1168: 
        !          1169:                if (scan) {
        !          1170: 
        !          1171:                        if (tab[i] == 0) i = 0;
        !          1172: 
        !          1173:                        tty->state = (tty->state & ~TS_ESC) | i;
        !          1174: 
        !          1175:                }
        !          1176: 
        !          1177:                return scan;
        !          1178: 
        !          1179:        }
        !          1180: 
        !          1181: 
        !          1182: 
        !          1183:        if (scan >= ALT_1 && scan <= ALT_0) {
        !          1184: 
        !          1185:                scan -= (ALT_1-1);
        !          1186: 
        !          1187:                if (scan == 10) scan = 0;
        !          1188: 
        !          1189:                return (scan + '0') | 0x80;
        !          1190: 
        !          1191:        }
        !          1192: 
        !          1193: 
        !          1194: 
        !          1195:        tab = *( ((char **)Keytbl((void *)-1L, (void *)-1L, (void *)-1L)) + 2 );        /* gratuitous (void *) for Lattice */
        !          1196: 
        !          1197:        scan = tab[scan];
        !          1198: 
        !          1199:        if (scan >= 'A' && scan <= 'Z') return scan | 0x80;
        !          1200: 
        !          1201:        return 0;
        !          1202: 
        !          1203: }
        !          1204: 
        !          1205: 
        !          1206: 
        !          1207: long
        !          1208: 
        !          1209: tty_getchar(f, mode)
        !          1210: 
        !          1211:        FILEPTR *f;
        !          1212: 
        !          1213:        int mode;
        !          1214: 
        !          1215: {
        !          1216: 
        !          1217:        struct tty *tty = (struct tty *)f->devinfo;
        !          1218: 
        !          1219:        char c, *tab;
        !          1220: 
        !          1221:        long r, ret;
        !          1222: 
        !          1223:        int scan;
        !          1224: 
        !          1225:        int master = f->flags & O_HEAD;
        !          1226: 
        !          1227: 
        !          1228: 
        !          1229:        assert(tty);
        !          1230: 
        !          1231: 
        !          1232: 
        !          1233: /* pty masters never worry about job control and always read in raw mode */
        !          1234: 
        !          1235:        if (master) {
        !          1236: 
        !          1237:                ret = (*f->dev->read)(f, (char *)&r, 4L);
        !          1238: 
        !          1239:                return (ret != 4L) ? MiNTEOF : r;
        !          1240: 
        !          1241:        }
        !          1242: 
        !          1243: 
        !          1244: 
        !          1245: /* job control check */
        !          1246: 
        !          1247:        if (tty->pgrp != curproc->pgrp && tty->pgrp > 0) {
        !          1248: 
        !          1249:                TRACE("job control: tty pgrp is %d proc pgrp is %d",
        !          1250: 
        !          1251:                        tty->pgrp, curproc->pgrp);
        !          1252: 
        !          1253:                killgroup(curproc->pgrp, SIGTTIN);
        !          1254: 
        !          1255:        }
        !          1256: 
        !          1257: 
        !          1258: 
        !          1259:        if (mode & COOKED)
        !          1260: 
        !          1261:                tty->state |= TS_COOKED;
        !          1262: 
        !          1263:        else
        !          1264: 
        !          1265:                tty->state &= ~TS_COOKED;
        !          1266: 
        !          1267: 
        !          1268: 
        !          1269:        c = UNDEF+1;    /* set to UNDEF when we successfully read a character */
        !          1270: 
        !          1271: 
        !          1272: 
        !          1273: /* we may be in the middle of an escape sequence */
        !          1274: 
        !          1275:        if (scan = (tty->state & TS_ESC)) {
        !          1276: 
        !          1277:                if (mode & ESCSEQ) {
        !          1278: 
        !          1279:                        tab = tty->xkey ? tty->xkey : vt52xkey;
        !          1280: 
        !          1281:                        r = (unsigned char) tab[scan++];
        !          1282: 
        !          1283:                        if (r) {
        !          1284: 
        !          1285:                                c = UNDEF;
        !          1286: 
        !          1287:                                if (tab[scan] == 0) scan = 0;
        !          1288: 
        !          1289:                        }
        !          1290: 
        !          1291:                        else
        !          1292: 
        !          1293:                                scan = 0;
        !          1294: 
        !          1295:                        tty->state = (tty->state & ~TS_ESC) | scan;
        !          1296: 
        !          1297:                }
        !          1298: 
        !          1299:                else
        !          1300: 
        !          1301:                        tty->state &= ~TS_ESC;
        !          1302: 
        !          1303:        }
        !          1304: 
        !          1305: 
        !          1306: 
        !          1307:        while (c != UNDEF) {
        !          1308: 
        !          1309:                ret = (*f->dev->read)(f, (char *)&r, 4L);
        !          1310: 
        !          1311:                if (ret != 4L) {
        !          1312: 
        !          1313:                        DEBUG("EOF on tty device");
        !          1314: 
        !          1315:                        return MiNTEOF;
        !          1316: 
        !          1317:                }
        !          1318: 
        !          1319:                c = r & 0x00ff;
        !          1320: 
        !          1321:                scan = (r & 0x00ff0000) >> 16;
        !          1322: 
        !          1323:                if ( (c == 0) && (mode & ESCSEQ) && scan) {
        !          1324: 
        !          1325:                        c = UNDEF;
        !          1326: 
        !          1327:        /* translate cursor keys, etc. into escape sequences or
        !          1328: 
        !          1329:         * META characters
        !          1330: 
        !          1331:         */
        !          1332: 
        !          1333:                        r = escseq(tty, scan);
        !          1334: 
        !          1335:                } else if ((mode & ESCSEQ) && ((scan == CURS_UP && c == '8') ||
        !          1336: 
        !          1337:                           (scan == CURS_DN && c == '2') ||
        !          1338: 
        !          1339:                           (scan == CURS_RT && c == '6') ||
        !          1340: 
        !          1341:                           (scan == CURS_LF && c == '4'))) {
        !          1342: 
        !          1343:                        c = UNDEF;
        !          1344: 
        !          1345:                        r = escseq(tty, scan+0x100);
        !          1346: 
        !          1347:                } else if (mode & COOKED) {
        !          1348: 
        !          1349:                        if (c == UNDEF)
        !          1350: 
        !          1351:                                ;       /* do nothing */
        !          1352: 
        !          1353:                        else if (c == tty->ltc.t_dsuspc)
        !          1354: 
        !          1355:                                killgroup(curproc->pgrp, SIGTSTP);
        !          1356: 
        !          1357:                        else if (c == tty->tc.t_intrc)
        !          1358: 
        !          1359:                                killgroup(curproc->pgrp, SIGINT);
        !          1360: 
        !          1361:                        else if (c == tty->tc.t_stopc)
        !          1362: 
        !          1363:                                tty->state |= TS_HOLD;
        !          1364: 
        !          1365:                        else if (c == tty->tc.t_stopc)
        !          1366: 
        !          1367:                                tty->state &= ~TS_HOLD;
        !          1368: 
        !          1369:                        else
        !          1370: 
        !          1371:                                c = UNDEF;
        !          1372: 
        !          1373:                }
        !          1374: 
        !          1375:                else
        !          1376: 
        !          1377:                                c = UNDEF;
        !          1378: 
        !          1379:        }
        !          1380: 
        !          1381: 
        !          1382: 
        !          1383:        if (mode & ECHO)
        !          1384: 
        !          1385:                tty_putchar(f, r, mode);
        !          1386: 
        !          1387: 
        !          1388: 
        !          1389:        return r;
        !          1390: 
        !          1391: }
        !          1392: 
        !          1393: 
        !          1394: 
        !          1395: /*
        !          1396: 
        !          1397:  * tty_putchar: returns number of bytes successfully written
        !          1398: 
        !          1399:  */
        !          1400: 
        !          1401: 
        !          1402: 
        !          1403: long
        !          1404: 
        !          1405: tty_putchar(f, data, mode)
        !          1406: 
        !          1407:        FILEPTR *f;
        !          1408: 
        !          1409:        long data;
        !          1410: 
        !          1411:        int mode;
        !          1412: 
        !          1413: {
        !          1414: 
        !          1415:        struct tty *tty;
        !          1416: 
        !          1417:        int master;             /* file is pty master side */
        !          1418: 
        !          1419:        char ch;
        !          1420: 
        !          1421: 
        !          1422: 
        !          1423:        tty = (struct tty *)f->devinfo;
        !          1424: 
        !          1425: 
        !          1426: 
        !          1427:        master = f->flags & O_HEAD;
        !          1428: 
        !          1429: 
        !          1430: 
        !          1431: /* pty masters don't need to worry about job control */
        !          1432: 
        !          1433:        if (master) {
        !          1434: 
        !          1435:                ch = data & 0xff;
        !          1436: 
        !          1437: 
        !          1438: 
        !          1439:                if ( (tty->state & TS_COOKED) && ch != UNDEF) {
        !          1440: 
        !          1441: /* see if we're putting control characters into the buffer */
        !          1442: 
        !          1443:                        if (ch == tty->tc.t_intrc) {
        !          1444: 
        !          1445:                                tty->state &= ~TS_HOLD;
        !          1446: 
        !          1447:                                killgroup(tty->pgrp, SIGINT);
        !          1448: 
        !          1449:                                return 4L;
        !          1450: 
        !          1451:                        }
        !          1452: 
        !          1453:                        else if (ch == tty->tc.t_quitc) {
        !          1454: 
        !          1455:                                tty->state &= ~TS_HOLD;
        !          1456: 
        !          1457:                                killgroup(tty->pgrp, SIGQUIT);
        !          1458: 
        !          1459:                                return 4L;
        !          1460: 
        !          1461:                        }
        !          1462: 
        !          1463:                        else if (ch == tty->ltc.t_suspc) {
        !          1464: 
        !          1465:                                tty->state &= ~TS_HOLD;
        !          1466: 
        !          1467:                                killgroup(tty->pgrp, SIGTSTP);
        !          1468: 
        !          1469:                                return 4L;
        !          1470: 
        !          1471:                        }
        !          1472: 
        !          1473:                        else if (ch == tty->tc.t_stopc) {
        !          1474: 
        !          1475:                                tty->state |= TS_HOLD;
        !          1476: 
        !          1477:                                return 4L;
        !          1478: 
        !          1479:                        }
        !          1480: 
        !          1481:                        else if (ch == tty->tc.t_startc) {
        !          1482: 
        !          1483:                                tty->state &= ~TS_HOLD;
        !          1484: 
        !          1485:                                return 4L;
        !          1486: 
        !          1487:                        }
        !          1488: 
        !          1489:                        else if (tty->state & TS_HOLD) {
        !          1490: 
        !          1491:                                return 0;
        !          1492: 
        !          1493:                        }
        !          1494: 
        !          1495:                }
        !          1496: 
        !          1497:                goto do_putchar;
        !          1498: 
        !          1499:        }
        !          1500: 
        !          1501: /* job control checks */
        !          1502: 
        !          1503: /* AKP: added T_TOSTOP; don't stop BG output if T_TOSTOP is clear */
        !          1504: 
        !          1505:        if (tty->pgrp != curproc->pgrp && tty->pgrp > 0 
        !          1506: 
        !          1507:            && (tty->sg.sg_flags & T_TOSTOP)) {
        !          1508: 
        !          1509:                TRACE("job control: tty pgrp is %d proc pgrp is %d",
        !          1510: 
        !          1511:                        tty->pgrp, curproc->pgrp);
        !          1512: 
        !          1513:                killgroup(curproc->pgrp, SIGTTOU);
        !          1514: 
        !          1515:        }
        !          1516: 
        !          1517: 
        !          1518: 
        !          1519:        if (mode & COOKED) {
        !          1520: 
        !          1521:                tty->state |= TS_COOKED;
        !          1522: 
        !          1523:                while (tty->state & TS_HOLD)
        !          1524: 
        !          1525:                        nap(60);        /* sleep for 60 milliseconds */
        !          1526: 
        !          1527:        }
        !          1528: 
        !          1529:        else
        !          1530: 
        !          1531:                tty->state &= ~TS_COOKED;
        !          1532: 
        !          1533: 
        !          1534: 
        !          1535: do_putchar:
        !          1536: 
        !          1537:        return (*f->dev->write)(f, (char *)&data, 4L);
        !          1538: 
        !          1539: }
        !          1540: 

unix.superglobalmegacorp.com

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