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