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

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: /*
1.10    ! millert    45:  * This function gets called once, to set up the terminal.
1.8       millert    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:        }
1.10    ! millert    94:        return(TRUE);
1.8       millert    95: }
1.1       deraadt    96:
1.8       millert    97: /*
                     98:  * This function gets called just before we go back home to the shell.
                     99:  * Put all of the terminal parameters back.
                    100:  * Under UN*X this just calls ttcooked(), but the ttclose() hook is in
                    101:  * because vttidy() in display.c expects it for portability reasons.
                    102:  */
                    103: void
                    104: ttclose()
                    105: {
1.1       deraadt   106:
1.8       millert   107:        if (ttcooked() == FALSE)
                    108:                panic("");              /* ttcooked() already printf'd */
1.1       deraadt   109: }
                    110:
                    111: /*
1.8       millert   112:  * This function restores all terminal settings to their default values,
                    113:  * in anticipation of exiting or suspending the editor.
1.1       deraadt   114:  */
1.8       millert   115: int
                    116: ttcooked()
1.1       deraadt   117: {
1.8       millert   118:
1.1       deraadt   119:        ttflush();
1.8       millert   120:        if (tcsetattr(0, TCSASOFT | TCSADRAIN, &oldtty) < 0) {
                    121:                ewprintf("ttclose can't tcsetattr");
                    122:                return(FALSE);
                    123:        }
                    124:        return(TRUE);
1.1       deraadt   125: }
                    126:
                    127: /*
1.8       millert   128:  * Write character to the display.  Characters are buffered up,
                    129:  * to make things a little bit more efficient.
1.1       deraadt   130:  */
1.8       millert   131: void
1.1       deraadt   132: ttputc(c)
1.8       millert   133:        int c;
1.1       deraadt   134: {
1.5       millert   135:
1.1       deraadt   136:        if (nobuf >= NOBUF)
                    137:                ttflush();
                    138:        obuf[nobuf++] = c;
                    139: }
                    140:
                    141: /*
                    142:  * Flush output.
                    143:  */
1.8       millert   144: void
1.1       deraadt   145: ttflush()
                    146: {
1.5       millert   147:
1.1       deraadt   148:        if (nobuf != 0) {
1.8       millert   149:                if (write(1, obuf, nobuf) != nobuf)
                    150:                        panic("ttflush write failed");
1.1       deraadt   151:                nobuf = 0;
                    152:        }
                    153: }
                    154:
                    155: /*
                    156:  * Read character from terminal.
                    157:  * All 8 bits are returned, so that you can use
                    158:  * a multi-national terminal.
                    159:  */
1.8       millert   160: int
1.1       deraadt   161: ttgetc()
                    162: {
1.9       millert   163:        char    c;
1.5       millert   164:
1.9       millert   165:        while (read(0, &c, 1) != 1)
1.5       millert   166:                ;
1.9       millert   167:        return ((int) c);
1.1       deraadt   168: }
                    169:
                    170: /*
1.8       millert   171:  * Set the tty size.
                    172:  * XXX - belongs in tty.c since it uses terminfo vars.
1.1       deraadt   173:  */
1.8       millert   174: void
1.1       deraadt   175: setttysize()
                    176: {
                    177: #ifdef TIOCGWINSZ
1.8       millert   178:        struct  winsize winsize;
1.5       millert   179:
1.1       deraadt   180:        if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
1.5       millert   181:                nrow = winsize.ws_row;
                    182:                ncol = winsize.ws_col;
1.8       millert   183:        } else nrow = 0;
1.1       deraadt   184: #endif
1.8       millert   185:        if ((nrow <= 0 || ncol <= 0) &&
                    186:            ((nrow = lines) <= 0 || (ncol = columns) <= 0)) {
1.1       deraadt   187:                nrow = 24;
                    188:                ncol = 80;
                    189:        }
1.4       millert   190:
                    191:        /* Enforce maximum screen size. */
                    192:        if (nrow > NROW)
                    193:                nrow = NROW;
                    194:        if (ncol > NCOL)
1.1       deraadt   195:                ncol = NCOL;
                    196: }
                    197:
1.8       millert   198: /*
                    199:  * Returns TRUE if there are characters waiting to be read.
                    200:  */
                    201: int
                    202: typeahead()
                    203: {
                    204:        int     x;
                    205:
                    206:        return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x);
                    207: }
                    208:
                    209: /*
                    210:  * panic - just exit, as quickly as we can.
                    211:  */
                    212: void
                    213: panic(s)
                    214:        char *s;
                    215: {
                    216:
                    217:        (void) fputs("panic: ", stderr);
                    218:        (void) fputs(s, stderr);
                    219:        (void) fputc('\n', stderr);
                    220:        abort();                /* To leave a core image. */
                    221: }
                    222:
1.1       deraadt   223: #ifndef NO_DPROMPT
                    224: /*
1.8       millert   225:  * A program to return TRUE if we wait for 2 seconds without anything
                    226:  * happening, else return FALSE.  Cribbed from mod.sources xmodem.
1.1       deraadt   227:  */
1.8       millert   228: int
1.1       deraadt   229: ttwait()
                    230: {
1.8       millert   231:        fd_set          readfds;
                    232:        struct timeval  tmout;
1.5       millert   233:
1.8       millert   234:        FD_ZERO(&readfds);
1.5       millert   235:        FD_SET(0, &readfds);
                    236:
                    237:        tmout.tv_sec = 2;
                    238:        tmout.tv_usec = 0;
                    239:
                    240:        if ((select(1, &readfds, NULL, NULL, &tmout)) == 0)
1.8       millert   241:                return (TRUE);
                    242:        return (FALSE);
1.1       deraadt   243: }
1.8       millert   244: #endif /* NO_DPROMPT */