[BACK]Return to ttyio.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/ttyio.c, Revision 1.8

1.1       deraadt     1: /*
1.5       millert     2:  * POSIX terminal I/O.
1.1       deraadt     3:  *
                      4:  * The functions in this file
                      5:  * negotiate with the operating system for
                      6:  * keyboard characters, and write characters to
                      7:  * the display in a barely buffered fashion.
                      8:  */
                      9: #include       "def.h"
                     10:
                     11: #include       <sys/types.h>
1.5       millert    12: #include       <sys/time.h>
                     13: #include       <sys/ioctl.h>
1.1       deraadt    14: #include       <fcntl.h>
1.2       deraadt    15: #include       <termios.h>
1.4       millert    16: #include       <term.h>
1.1       deraadt    17:
1.8     ! millert    18: #define NOBUF  512                     /* Output buffer size.          */
1.1       deraadt    19:
1.7       millert    20: #ifndef TCSASOFT
                     21: #define TCSASOFT       0
                     22: #endif
                     23:
1.1       deraadt    24: char   obuf[NOBUF];                    /* Output buffer.               */
1.8     ! millert    25: int    nobuf;                          /* Buffer count.                */
        !            26: struct termios oldtty;                 /* POSIX tty settings.          */
        !            27: struct termios newtty;
1.1       deraadt    28: int    nrow;                           /* Terminal size, rows.         */
                     29: int    ncol;                           /* Terminal size, columns.      */
                     30:
1.8     ! millert    31: /* XXX - move most of these to def.h? */
        !            32: void ttopen __P((void));
        !            33: int ttraw __P((void));
        !            34: void ttclose __P((void));
        !            35: int ttcooked __P((void));
        !            36: void ttputc __P((int));
        !            37: void ttflush __P((void));
        !            38: int ttgetc __P((void));
        !            39: void setttysize __P((void));
        !            40: int typeahead __P((void));
        !            41: void panic __P((char *));
        !            42: int ttwait __P((void));
        !            43:
        !            44: /*
        !            45:  * This function gets called once, to set up the terminal
        !            46:  * On systems w/o TCSASOFT we turn off off flow control,
        !            47:  * which isn't really the right thing to do.
1.1       deraadt    48:  */
1.8     ! millert    49: void
1.1       deraadt    50: ttopen()
                     51: {
                     52:
1.8     ! millert    53:        if (ttraw() == FALSE)
        !            54:                panic("aborting due to terminal initialize failure");
        !            55: }
1.1       deraadt    56:
1.8     ! millert    57: /*
        !            58:  * This function sets the terminal to RAW mode, as defined for the current
        !            59:  * shell.  This is called both by ttopen() above and by spawncli() to
        !            60:  * get the current terminal settings and then change them to what
        !            61:  * mg expects. Thus, tty changes done while spawncli() is in effect
        !            62:  * will be reflected in mg.
        !            63:  */
        !            64: int
        !            65: ttraw()
        !            66: {
        !            67:
        !            68:        if (tcgetattr(0, &oldtty) < 0) {
        !            69:                ewprintf("ttopen can't get terminal attributes");
        !            70:                return(FALSE);
        !            71:        }
        !            72:        (void)memcpy(&newtty, &oldtty, sizeof(newtty));
        !            73:        /* Set terminal to 'raw' mode and ignore a 'break' */
        !            74:        newtty.c_cc[VMIN] = 1;
        !            75:        newtty.c_cc[VTIME] = 0;
        !            76:        newtty.c_iflag |= IGNBRK;
        !            77:        newtty.c_iflag &= ~(BRKINT | PARMRK | INLCR | IGNCR | ICRNL | IXON);
        !            78:        newtty.c_oflag &= ~OPOST;
        !            79:        newtty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
1.7       millert    80:
                     81: #if !TCSASOFT
1.8     ! millert    82:        /*
        !            83:         * If we don't have TCSASOFT, force terminal to
        !            84:         * 8 bits, no parity.
        !            85:         */
        !            86:        newtty.c_iflag &= ~ISTRIP;
        !            87:        newtty.c_cflag &= ~(CSIZE | PARENB);
        !            88:        newtty.c_cflag |= CS8;
1.7       millert    89: #endif
1.8     ! millert    90:        if (tcsetattr(0, TCSASOFT | TCSADRAIN, &newtty) < 0) {
        !            91:                ewprintf("ttopen can't tcsetattr");
        !            92:                return(FALSE);
        !            93:        }
        !            94: }
1.1       deraadt    95:
1.8     ! millert    96: /*
        !            97:  * This function gets called just before we go back home to the shell.
        !            98:  * Put all of the terminal parameters back.
        !            99:  * Under UN*X this just calls ttcooked(), but the ttclose() hook is in
        !           100:  * because vttidy() in display.c expects it for portability reasons.
        !           101:  */
        !           102: void
        !           103: ttclose()
        !           104: {
1.1       deraadt   105:
1.8     ! millert   106:        if (ttcooked() == FALSE)
        !           107:                panic("");              /* ttcooked() already printf'd */
1.1       deraadt   108: }
                    109:
                    110: /*
1.8     ! millert   111:  * This function restores all terminal settings to their default values,
        !           112:  * in anticipation of exiting or suspending the editor.
1.1       deraadt   113:  */
1.8     ! millert   114: int
        !           115: ttcooked()
1.1       deraadt   116: {
1.8     ! millert   117:
1.1       deraadt   118:        ttflush();
1.8     ! millert   119:        if (tcsetattr(0, TCSASOFT | TCSADRAIN, &oldtty) < 0) {
        !           120:                ewprintf("ttclose can't tcsetattr");
        !           121:                return(FALSE);
        !           122:        }
        !           123:        return(TRUE);
1.1       deraadt   124: }
                    125:
                    126: /*
1.8     ! millert   127:  * Write character to the display.  Characters are buffered up,
        !           128:  * to make things a little bit more efficient.
1.1       deraadt   129:  */
1.8     ! millert   130: void
1.1       deraadt   131: ttputc(c)
1.8     ! millert   132:        int c;
1.1       deraadt   133: {
1.5       millert   134:
1.1       deraadt   135:        if (nobuf >= NOBUF)
                    136:                ttflush();
                    137:        obuf[nobuf++] = c;
                    138: }
                    139:
                    140: /*
                    141:  * Flush output.
                    142:  */
1.8     ! millert   143: void
1.1       deraadt   144: ttflush()
                    145: {
1.5       millert   146:
1.1       deraadt   147:        if (nobuf != 0) {
1.8     ! millert   148:                if (write(1, obuf, nobuf) != nobuf)
        !           149:                        panic("ttflush write failed");
1.1       deraadt   150:                nobuf = 0;
                    151:        }
                    152: }
                    153:
                    154: /*
                    155:  * Read character from terminal.
                    156:  * All 8 bits are returned, so that you can use
                    157:  * a multi-national terminal.
                    158:  */
1.8     ! millert   159: int
1.1       deraadt   160: ttgetc()
                    161: {
1.8     ! millert   162:        char    buf[1];
1.5       millert   163:
1.8     ! millert   164:        while (read(0, &buf[0], 1) != 1)
1.5       millert   165:                ;
1.8     ! millert   166:        return (buf[0] & 0xFF);
1.1       deraadt   167: }
                    168:
                    169: /*
1.8     ! millert   170:  * Set the tty size.
        !           171:  * XXX - belongs in tty.c since it uses terminfo vars.
1.1       deraadt   172:  */
1.8     ! millert   173: void
1.1       deraadt   174: setttysize()
                    175: {
                    176: #ifdef TIOCGWINSZ
1.8     ! millert   177:        struct  winsize winsize;
1.5       millert   178:
1.1       deraadt   179:        if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
1.5       millert   180:                nrow = winsize.ws_row;
                    181:                ncol = winsize.ws_col;
1.8     ! millert   182:        } else nrow = 0;
1.1       deraadt   183: #endif
1.8     ! millert   184:        if ((nrow <= 0 || ncol <= 0) &&
        !           185:            ((nrow = lines) <= 0 || (ncol = columns) <= 0)) {
1.1       deraadt   186:                nrow = 24;
                    187:                ncol = 80;
                    188:        }
1.4       millert   189:
                    190:        /* Enforce maximum screen size. */
                    191:        if (nrow > NROW)
                    192:                nrow = NROW;
                    193:        if (ncol > NCOL)
1.1       deraadt   194:                ncol = NCOL;
                    195: }
                    196:
1.8     ! millert   197: /*
        !           198:  * Returns TRUE if there are characters waiting to be read.
        !           199:  */
        !           200: int
        !           201: typeahead()
        !           202: {
        !           203:        int     x;
        !           204:
        !           205:        return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x);
        !           206: }
        !           207:
        !           208: /*
        !           209:  * panic - just exit, as quickly as we can.
        !           210:  */
        !           211: void
        !           212: panic(s)
        !           213:        char *s;
        !           214: {
        !           215:
        !           216:        (void) fputs("panic: ", stderr);
        !           217:        (void) fputs(s, stderr);
        !           218:        (void) fputc('\n', stderr);
        !           219:        abort();                /* To leave a core image. */
        !           220: }
        !           221:
1.1       deraadt   222: #ifndef NO_DPROMPT
                    223: /*
1.8     ! millert   224:  * A program to return TRUE if we wait for 2 seconds without anything
        !           225:  * happening, else return FALSE.  Cribbed from mod.sources xmodem.
1.1       deraadt   226:  */
1.8     ! millert   227: int
1.1       deraadt   228: ttwait()
                    229: {
1.8     ! millert   230:        fd_set          readfds;
        !           231:        struct timeval  tmout;
1.5       millert   232:
1.8     ! millert   233:        FD_ZERO(&readfds);
1.5       millert   234:        FD_SET(0, &readfds);
                    235:
                    236:        tmout.tv_sec = 2;
                    237:        tmout.tv_usec = 0;
                    238:
                    239:        if ((select(1, &readfds, NULL, NULL, &tmout)) == 0)
1.8     ! millert   240:                return (TRUE);
        !           241:        return (FALSE);
1.1       deraadt   242: }
1.8     ! millert   243: #endif /* NO_DPROMPT */