1 /* $OpenBSD: ttyio.c,v 1.32 2008/02/05 12:53:38 reyk Exp $ */
3 /* This file is in the public domain. */
8 * The functions in this file negotiate with the operating system for
9 * keyboard characters, and write characters to the display in a barely
14 #include <sys/types.h>
16 #include <sys/ioctl.h>
21 #define NOBUF 512 /* Output buffer size. */
28 char obuf[NOBUF]; /* Output buffer. */
29 size_t nobuf; /* Buffer count. */
30 struct termios oldtty; /* POSIX tty settings. */
31 struct termios newtty;
32 int nrow; /* Terminal size, rows. */
33 int ncol; /* Terminal size, columns. */
36 * This function gets called once, to set up the terminal.
37 * On systems w/o TCSASOFT we turn off off flow control,
38 * which isn't really the right thing to do.
43 if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO))
44 panic("standard input and output must be a terminal");
47 panic("aborting due to terminal initialize failure");
51 * This function sets the terminal to RAW mode, as defined for the current
52 * shell. This is called both by ttopen() above and by spawncli() to
53 * get the current terminal settings and then change them to what
54 * mg expects. Thus, tty changes done while spawncli() is in effect
55 * will be reflected in mg.
60 if (tcgetattr(0, &oldtty) < 0) {
61 ewprintf("ttopen can't get terminal attributes");
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);
75 * If we don't have TCSASOFT, force terminal to
78 newtty.c_iflag &= ~ISTRIP;
79 newtty.c_cflag &= ~(CSIZE | PARENB);
80 newtty.c_cflag |= CS8;
82 if (tcsetattr(0, TCSASOFT | TCSADRAIN, &newtty) < 0) {
83 ewprintf("ttopen can't tcsetattr");
92 * This function gets called just before we go back home to the shell.
93 * Put all of the terminal parameters back.
94 * Under UN*X this just calls ttcooked(), but the ttclose() hook is in
95 * because vttidy() in display.c expects it for portability reasons.
101 if (ttcooked() == FALSE)
102 panic(""); /* ttcooked() already printf'd */
108 * This function restores all terminal settings to their default values,
109 * in anticipation of exiting or suspending the editor.
115 if (tcsetattr(0, TCSASOFT | TCSADRAIN, &oldtty) < 0) {
116 ewprintf("ttclose can't tcsetattr");
123 * Write character to the display. Characters are buffered up,
124 * to make things a little bit more efficient.
147 while ((written = write(fileno(stdout), buf, nobuf)) != nobuf) {
151 panic("ttflush write failed");
160 * Read character from terminal. All 8 bits are returned, so that you
161 * can use a multi-national terminal.
170 ret = read(STDIN_FILENO, &c, 1);
171 if (ret == -1 && errno == EINTR) {
179 return ((int) c) & 0xFF;
183 * Returns TRUE if there are characters waiting to be read.
190 return ((ioctl(0, FIONREAD, &x) < 0) ? 0 : x);
194 * panic - just exit, as quickly as we can.
200 (void) fputs("panic: ", stderr);
201 (void) fputs(s, stderr);
202 (void) fputc('\n', stderr);
207 * This function returns FALSE if any characters have showed up on the
208 * tty before 'msec' milliseconds.
214 struct timeval tmout;
219 tmout.tv_sec = msec/1000;
220 tmout.tv_usec = msec - tmout.tv_sec * 1000;
222 if ((select(1, &readfds, NULL, NULL, &tmout)) == 0)