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

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.9     ! millert   162:        char    c;
1.5       millert   163:
1.9     ! millert   164:        while (read(0, &c, 1) != 1)
1.5       millert   165:                ;
1.9     ! millert   166:        return ((int) c);
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 */