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

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