Annotation of src/usr.bin/mg/ttyio.c, Revision 1.8
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: /*
! 45: * This function gets called once, to set up the terminal
! 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: }
! 94: }
1.1 deraadt 95:
1.8 ! millert 96: /*
! 97: * This function gets called just before we go back home to the shell.
! 98: * Put all of the terminal parameters back.
! 99: * Under UN*X this just calls ttcooked(), but the ttclose() hook is in
! 100: * because vttidy() in display.c expects it for portability reasons.
! 101: */
! 102: void
! 103: ttclose()
! 104: {
1.1 deraadt 105:
1.8 ! millert 106: if (ttcooked() == FALSE)
! 107: panic(""); /* ttcooked() already printf'd */
1.1 deraadt 108: }
109:
110: /*
1.8 ! millert 111: * This function restores all terminal settings to their default values,
! 112: * in anticipation of exiting or suspending the editor.
1.1 deraadt 113: */
1.8 ! millert 114: int
! 115: ttcooked()
1.1 deraadt 116: {
1.8 ! millert 117:
1.1 deraadt 118: ttflush();
1.8 ! millert 119: if (tcsetattr(0, TCSASOFT | TCSADRAIN, &oldtty) < 0) {
! 120: ewprintf("ttclose can't tcsetattr");
! 121: return(FALSE);
! 122: }
! 123: return(TRUE);
1.1 deraadt 124: }
125:
126: /*
1.8 ! millert 127: * Write character to the display. Characters are buffered up,
! 128: * to make things a little bit more efficient.
1.1 deraadt 129: */
1.8 ! millert 130: void
1.1 deraadt 131: ttputc(c)
1.8 ! millert 132: int c;
1.1 deraadt 133: {
1.5 millert 134:
1.1 deraadt 135: if (nobuf >= NOBUF)
136: ttflush();
137: obuf[nobuf++] = c;
138: }
139:
140: /*
141: * Flush output.
142: */
1.8 ! millert 143: void
1.1 deraadt 144: ttflush()
145: {
1.5 millert 146:
1.1 deraadt 147: if (nobuf != 0) {
1.8 ! millert 148: if (write(1, obuf, nobuf) != nobuf)
! 149: panic("ttflush write failed");
1.1 deraadt 150: nobuf = 0;
151: }
152: }
153:
154: /*
155: * Read character from terminal.
156: * All 8 bits are returned, so that you can use
157: * a multi-national terminal.
158: */
1.8 ! millert 159: int
1.1 deraadt 160: ttgetc()
161: {
1.8 ! millert 162: char buf[1];
1.5 millert 163:
1.8 ! millert 164: while (read(0, &buf[0], 1) != 1)
1.5 millert 165: ;
1.8 ! millert 166: return (buf[0] & 0xFF);
1.1 deraadt 167: }
168:
169: /*
1.8 ! millert 170: * Set the tty size.
! 171: * XXX - belongs in tty.c since it uses terminfo vars.
1.1 deraadt 172: */
1.8 ! millert 173: void
1.1 deraadt 174: setttysize()
175: {
176: #ifdef TIOCGWINSZ
1.8 ! millert 177: struct winsize winsize;
1.5 millert 178:
1.1 deraadt 179: if (ioctl(0, TIOCGWINSZ, (char *) &winsize) == 0) {
1.5 millert 180: nrow = winsize.ws_row;
181: ncol = winsize.ws_col;
1.8 ! millert 182: } else nrow = 0;
1.1 deraadt 183: #endif
1.8 ! millert 184: if ((nrow <= 0 || ncol <= 0) &&
! 185: ((nrow = lines) <= 0 || (ncol = columns) <= 0)) {
1.1 deraadt 186: nrow = 24;
187: ncol = 80;
188: }
1.4 millert 189:
190: /* Enforce maximum screen size. */
191: if (nrow > NROW)
192: nrow = NROW;
193: if (ncol > NCOL)
1.1 deraadt 194: ncol = NCOL;
195: }
196:
1.8 ! millert 197: /*
! 198: * Returns TRUE if there are characters waiting to be read.
! 199: */
! 200: int
! 201: typeahead()
! 202: {
! 203: int x;
! 204:
! 205: return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x);
! 206: }
! 207:
! 208: /*
! 209: * panic - just exit, as quickly as we can.
! 210: */
! 211: void
! 212: panic(s)
! 213: char *s;
! 214: {
! 215:
! 216: (void) fputs("panic: ", stderr);
! 217: (void) fputs(s, stderr);
! 218: (void) fputc('\n', stderr);
! 219: abort(); /* To leave a core image. */
! 220: }
! 221:
1.1 deraadt 222: #ifndef NO_DPROMPT
223: /*
1.8 ! millert 224: * A program to return TRUE if we wait for 2 seconds without anything
! 225: * happening, else return FALSE. Cribbed from mod.sources xmodem.
1.1 deraadt 226: */
1.8 ! millert 227: int
1.1 deraadt 228: ttwait()
229: {
1.8 ! millert 230: fd_set readfds;
! 231: struct timeval tmout;
1.5 millert 232:
1.8 ! millert 233: FD_ZERO(&readfds);
1.5 millert 234: FD_SET(0, &readfds);
235:
236: tmout.tv_sec = 2;
237: tmout.tv_usec = 0;
238:
239: if ((select(1, &readfds, NULL, NULL, &tmout)) == 0)
1.8 ! millert 240: return (TRUE);
! 241: return (FALSE);
1.1 deraadt 242: }
1.8 ! millert 243: #endif /* NO_DPROMPT */