Annotation of src/usr.bin/mg/ttyio.c, Revision 1.6
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:
18: #define NOBUF 512 /* Output buffer size. */
19:
20: char obuf[NOBUF]; /* Output buffer. */
21: int nobuf; /* buffer count */
22:
1.2 deraadt 23: static struct termios ot; /* entry state of the terminal */
24: static struct termios nt; /* editor's terminal state */
1.1 deraadt 25:
26: static int ttyactivep = FALSE; /* terminal in editor mode? */
27: static int ttysavedp = FALSE; /* terminal state saved? */
28:
29: int nrow; /* Terminal size, rows. */
30: int ncol; /* Terminal size, columns. */
31:
32: /*
33: * This function gets called once, to set up
34: * the terminal channel. This version turns off flow
35: * control. This may be wrong for your system, but no
36: * good solution has really been found (daveb).
37: */
38: ttopen()
39: {
40: register char *cp;
41:
42: if (ttyactivep)
43: return;
44:
45: if( !ttysavedp )
46: {
1.2 deraadt 47: if (tcgetattr(0, &ot) < 0)
1.1 deraadt 48: abort();
49: nt = ot; /* save entry state */
1.6 ! millert 50: /* Set terminal to 'raw' mode and ignore a 'break' */
! 51: nt.c_cc[VMIN] = 1;
! 52: nt.c_cc[VTIME] = 0;
1.1 deraadt 53: nt.c_iflag |= IGNBRK;
1.6 ! millert 54: nt.c_iflag &= ~(BRKINT|PARMRK|INLCR|IGNCR|ICRNL|IXON);
1.1 deraadt 55: nt.c_oflag &= ~OPOST;
1.6 ! millert 56: nt.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
1.1 deraadt 57:
58: ttysavedp = TRUE;
59: }
60:
1.6 ! millert 61: if (tcsetattr(0, TCSASOFT | TCSADRAIN, &nt) < 0)
1.1 deraadt 62: abort();
63:
64: ttyactivep = TRUE;
65: }
66:
67: /*
68: * This function gets called just
69: * before we go back home to the shell. Put all of
70: * the terminal parameters back.
71: */
72: ttclose()
73: {
74: if(!ttysavedp || !ttyactivep)
75: return;
76: ttflush();
1.6 ! millert 77: if (tcsetattr(0, TCSASOFT | TCSADRAIN, &ot) < 0)
1.1 deraadt 78: abort();
79: ttyactivep = FALSE;
80: }
81:
82: /*
83: * Write character to the display.
84: * Characters are buffered up, to make things
85: * a little bit more efficient.
86: */
87: ttputc(c)
88: {
1.5 millert 89:
1.1 deraadt 90: if (nobuf >= NOBUF)
91: ttflush();
92: obuf[nobuf++] = c;
93: }
94:
95: /*
96: * Flush output.
97: */
98: ttflush()
99: {
1.5 millert 100:
1.1 deraadt 101: if (nobuf != 0) {
102: write(1, obuf, nobuf);
103: nobuf = 0;
104: }
105: }
106:
107: /*
108: * Read character from terminal.
109: * All 8 bits are returned, so that you can use
110: * a multi-national terminal.
111: *
112: * If keyboard 'queue' already has typeahead from a typeahead() call,
113: * just return it. Otherwise, make sure we are in blocking i/o mode
114: * and read a character.
115: */
116: ttgetc()
117: {
1.5 millert 118: int c;
119:
120: while (read(0, &c, 1) != 1)
121: ;
122: return (c & 0xFF);
1.1 deraadt 123: }
124:
125: /*
1.5 millert 126: * Return TRUE if there are characters waiting to be read.
1.1 deraadt 127: */
128: typeahead()
129: {
1.5 millert 130: int x;
131:
132: return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x);
1.1 deraadt 133: }
134:
135:
136: /*
137: * panic: print error and die, leaving core file.
138: * Don't know why this is needed (daveb).
139: */
140: panic(s)
141: char *s;
142: {
1.5 millert 143:
144: (void) fputs("panic: ", stderr);
145: (void) fputs(s, stderr);
146: (void) fputc('\n', stderr);
147: abort(); /* To leave a core image. */
1.1 deraadt 148: }
149:
150:
151: /*
152: ** This should check the size of the window, and reset if needed.
153: */
154:
155: setttysize()
156: {
157: #ifdef TIOCGWINSZ
158: struct winsize winsize;
1.5 millert 159:
1.1 deraadt 160: if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
1.5 millert 161: nrow = winsize.ws_row;
162: ncol = winsize.ws_col;
1.1 deraadt 163: } else
164: #endif
1.4 millert 165: if ((nrow = lines) <= 0 || (ncol = columns) <= 0) {
1.1 deraadt 166: nrow = 24;
167: ncol = 80;
168: }
1.4 millert 169:
170: /* Enforce maximum screen size. */
171: if (nrow > NROW)
172: nrow = NROW;
173: if (ncol > NCOL)
1.1 deraadt 174: ncol = NCOL;
175: }
176:
177: #ifndef NO_DPROMPT
178: /*
179: * Return TRUE if we wait without doing anything, else return FALSE.
180: */
181: ttwait()
182: {
1.5 millert 183: fd_set readfds;
184: struct timeval tmout;
185:
186: FD_ZERO(&readfds);
187: FD_SET(0, &readfds);
188:
189: tmout.tv_sec = 2;
190: tmout.tv_usec = 0;
191:
192: if ((select(1, &readfds, NULL, NULL, &tmout)) == 0)
193: return(TRUE);
194: return(FALSE);
1.1 deraadt 195: }
196: #endif NO_DPROMPT