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 */