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