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

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