[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.18

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