Initial revision
[nvi.git] / common / key.c
blobfaea3cec2bb424d929c470b134a56b5388814517
1 /* unix.c */
3 /* Author:
4 * Steve Kirkendall
5 * 14407 SW Teal Blvd. #C
6 * Beaverton, OR 97005
7 * kirkenda@cs.pdx.edu
8 */
11 /* This file contains the unix-specific versions the ttyread() functions.
12 * There are actually three versions of ttyread() defined here, because
13 * BSD, SysV, and V7 all need quite different implementations.
16 #include "config.h"
17 #if ANY_UNIX
18 # include "vi.h"
20 # if BSD
21 /* For BSD, we use select() to wait for characters to become available,
22 * and then do a read() to actually get the characters. We also try to
23 * handle SIGWINCH -- if the signal arrives during the select() call, then
24 * we adjust the o_columns and o_lines variables, and fake a control-L.
26 # include <sys/types.h>
27 # include <sys/time.h>
28 int ttyread(buf, len, time)
29 char *buf; /* where to store the gotten characters */
30 int len; /* maximum number of characters to read */
31 int time; /* maximum time to allow for reading */
33 fd_set rd; /* the file descriptors that we want to read from */
34 static tty; /* 'y' if reading from tty, or 'n' if not a tty */
35 int i;
36 struct timeval t;
37 struct timeval *tp;
40 /* do we know whether this is a tty or not? */
41 if (!tty)
43 tty = (isatty(0) ? 'y' : 'n');
46 /* compute the timeout value */
47 if (time)
49 t.tv_sec = time / 10;
50 t.tv_usec = (time % 10) * 100000L;
51 tp = &t;
53 else
55 tp = (struct timeval *)0;
58 /* loop until we get characters or a definite EOF */
59 for (;;)
61 if (tty == 'y')
63 /* wait until timeout or characters are available */
64 FD_ZERO(&rd);
65 FD_SET(0, &rd);
66 i = select(1, &rd, (fd_set *)0, (fd_set *)0, tp);
68 else
70 /* if reading from a file or pipe, never timeout!
71 * (This also affects the way that EOF is detected)
73 i = 1;
76 /* react accordingly... */
77 switch (i)
79 case -1: /* assume we got an EINTR because of SIGWINCH */
80 if (*o_lines != LINES || *o_columns != COLS)
82 *o_lines = LINES;
83 *o_columns = COLS;
84 if (mode != MODE_EX)
86 /* pretend the user hit ^L */
87 *buf = ctrl('L');
88 return 1;
91 break;
93 case 0: /* timeout */
94 return 0;
96 default: /* characters available */
97 return read(0, buf, len);
101 # else
103 # if M_SYSV
104 /* For System-V or Coherent, we use VMIN/VTIME to implement the timeout.
105 * For no timeout, VMIN should be 1 and VTIME should be 0; for timeout,
106 * VMIN should be 0 and VTIME should be the timeout value.
108 # include <termio.h>
109 int ttyread(buf, len, time)
110 char *buf; /* where to store the gotten characters */
111 int len; /* maximum number of characters to read */
112 int time; /* maximum time to allow for reading */
114 struct termio tio;
115 int bytes; /* number of bytes actually read */
117 /* arrange for timeout */
118 ioctl(0, TCGETA, &tio);
119 if (time)
121 tio.c_cc[VMIN] = 0;
122 tio.c_cc[VTIME] = time;
124 else
126 tio.c_cc[VMIN] = 1;
127 tio.c_cc[VTIME] = 0;
129 ioctl(0, TCSETA, &tio);
131 /* Perform the read. Loop if EINTR error happens */
134 bytes = read(0, buf, len);
135 } while (bytes < 0);
137 /* return the number of bytes read */
138 return bytes;
140 /* NOTE: The terminal may be left in a timeout-mode after this function
141 * returns. This shouldn't be a problem since Elvis *NEVER* tries to
142 * read from the keyboard except through this function.
146 # else /* any other version of UNIX, assume it is V7 compatible */
148 /* For V7 UNIX (including Minix) we set an alarm() before doing a blocking
149 * read(), and assume that the SIGALRM signal will cause the read() function
150 * to give up.
153 #include <signal.h>
154 #include <setjmp.h>
156 static jmp_buf env;
158 /*ARGSUSED*/
159 int dummy(signo)
160 int signo;
162 longjmp(env, 1);
164 int ttyread(buf, len, time)
165 char *buf; /* where to store the gotten characters */
166 int len; /* maximum number of characters to read */
167 int time; /* maximum time to allow for reading */
169 /* arrange for timeout */
170 #if __GNUC__
171 signal(SIGALRM, (void (*)()) dummy);
172 #else
173 signal(SIGALRM, dummy);
174 #endif
175 alarm(time);
177 /* perform the blocking read */
178 if (setjmp(env) == 0)
180 len = read(0, buf, len);
182 else /* I guess we timed out */
184 len = 0;
187 /* cancel the alarm */
188 signal(SIGALRM, dummy); /* <-- to work around a bug in Minix */
189 alarm(0);
191 /* return the number of bytes read */
192 if (len < 0)
193 len = 0;
194 return len;
197 # endif /* !(M_SYSV || COHERENT) */
198 # endif /* !BSD */
200 #endif /* ANY_UNIX */