3 * Keith Bostic. All rights reserved.
5 * See the LICENSE file for redistribution information.
11 static const char sccsid
[] = "@(#)ip_read.c 8.3 (Berkeley) 9/24/96";
14 #include <sys/types.h>
15 #include <sys/queue.h>
17 #include <bitstring.h>
22 #include "../common/common.h"
23 #include "../ex/script.h"
26 extern GS
*__global_list
;
28 typedef enum { INP_OK
=0, INP_EOF
, INP_ERR
, INP_TIMEOUT
} input_t
;
30 static input_t ip_read
__P((SCR
*, IP_PRIVATE
*, struct timeval
*));
31 static int ip_resize
__P((SCR
*, size_t, size_t));
32 static int ip_trans
__P((SCR
*, IP_PRIVATE
*, EVENT
*));
36 * Return a single event.
38 * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
41 ip_event(sp
, evp
, flags
, ms
)
48 struct timeval t
, *tp
;
50 if (LF_ISSET(EC_INTERRUPT
)) { /* XXX */
51 evp
->e_event
= E_TIMEOUT
;
55 ipp
= sp
== NULL
? GIPP(__global_list
) : IPP(sp
);
57 /* Discard the last command. */
58 if (ipp
->iskip
!= 0) {
59 ipp
->iblen
-= ipp
->iskip
;
60 memmove(ipp
->ibuf
, ipp
->ibuf
+ ipp
->iskip
, ipp
->iblen
);
69 t
.tv_usec
= (ms
% 1000) * 1000;
73 /* Read input events. */
75 switch (ip_read(sp
, ipp
, tp
)) {
77 if (!ip_trans(sp
, ipp
, evp
))
87 evp
->e_event
= E_TIMEOUT
;
99 * Read characters from the input.
116 gp
= sp
== NULL
? __global_list
: sp
->gp
;
117 bp
= ipp
->ibuf
+ ipp
->iblen
;
118 blen
= sizeof(ipp
->ibuf
) - ipp
->iblen
;
121 * 1: A read with an associated timeout, e.g., trying to complete
122 * a map sequence. If input exists, we fall into #2.
128 FD_SET(ipp
->i_fd
, &rdfd
);
129 switch (select(ipp
->i_fd
+ 1,
130 &rdfd
, NULL
, NULL
, tp
== NULL
? &poll
: tp
)) {
132 return (INP_TIMEOUT
);
143 * Select on the command input and scripting window file descriptors.
144 * It's ugly that we wait on scripting file descriptors here, but it's
145 * the only way to keep from locking out scripting windows.
147 if (sp
!= NULL
&& F_ISSET(gp
, G_SCRWIN
)) {
148 loop
: FD_ZERO(&rdfd
);
149 FD_SET(ipp
->i_fd
, &rdfd
);
151 for (tsp
= gp
->dq
.cqh_first
;
152 tsp
!= (void *)&gp
->dq
; tsp
= tsp
->q
.cqe_next
)
153 if (F_ISSET(sp
, SC_SCRIPT
)) {
154 FD_SET(sp
->script
->sh_master
, &rdfd
);
155 if (sp
->script
->sh_master
> maxfd
)
156 maxfd
= sp
->script
->sh_master
;
158 switch (select(maxfd
+ 1, &rdfd
, NULL
, NULL
, NULL
)) {
166 if (!FD_ISSET(ipp
->i_fd
, &rdfd
)) {
176 switch (nr
= read(ipp
->i_fd
, bp
, blen
)) {
180 case -1: /* Error or interrupt. */
182 msgq(sp
, M_SYSERR
, "input");
184 default: /* Input characters. */
194 * Translate messages into events.
197 ip_trans(sp
, ipp
, evp
)
202 u_int32_t val1
, val2
;
204 switch (ipp
->ibuf
[0]) {
206 evp
->e_event
= E_EOF
;
207 ipp
->iskip
= IPO_CODE_LEN
;
210 evp
->e_event
= E_ERR
;
211 ipp
->iskip
= IPO_CODE_LEN
;
214 evp
->e_event
= E_INTERRUPT
;
215 ipp
->iskip
= IPO_CODE_LEN
;
218 evp
->e_event
= E_QUIT
;
219 ipp
->iskip
= IPO_CODE_LEN
;
222 if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
* 2)
224 evp
->e_event
= E_WRESIZE
;
225 memcpy(&val1
, ipp
->ibuf
+ IPO_CODE_LEN
, IPO_INT_LEN
);
228 ipp
->ibuf
+ IPO_CODE_LEN
+ IPO_INT_LEN
, IPO_INT_LEN
);
230 ip_resize(sp
, val1
, val2
);
231 ipp
->iskip
= IPO_CODE_LEN
+ IPO_INT_LEN
* 2;
234 evp
->e_event
= E_SIGHUP
;
235 ipp
->iskip
= IPO_CODE_LEN
;
238 evp
->e_event
= E_SIGTERM
;
239 ipp
->iskip
= IPO_CODE_LEN
;
242 evp
->e_event
= E_STRING
;
243 string
: if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
)
245 memcpy(&val1
, ipp
->ibuf
+ IPO_CODE_LEN
, IPO_INT_LEN
);
247 if (ipp
->iblen
< IPO_CODE_LEN
+ IPO_INT_LEN
+ val1
)
249 ipp
->iskip
= IPO_CODE_LEN
+ IPO_INT_LEN
+ val1
;
250 evp
->e_csp
= ipp
->ibuf
+ IPO_CODE_LEN
+ IPO_INT_LEN
;
254 evp
->e_event
= E_WRITE
;
255 ipp
->iskip
= IPO_CODE_LEN
;
259 * XXX: Protocol is out of sync?
268 * Reset the options for a resize event.
271 ip_resize(sp
, lines
, columns
)
273 size_t lines
, columns
;
281 * The IP screen has to know the lines and columns before anything
282 * else happens. So, we may not have a valid SCR pointer, and we
283 * have to deal with that.
287 OG_VAL(gp
, GO_LINES
) = OG_D_VAL(gp
, GO_LINES
) = lines
;
288 OG_VAL(gp
, GO_COLUMNS
) = OG_D_VAL(gp
, GO_COLUMNS
) = columns
;
298 (void)snprintf(b1
, sizeof(b1
), "lines=%lu", (u_long
)lines
);
300 if (opts_set(sp
, argv
, NULL
))
302 (void)snprintf(b1
, sizeof(b1
), "columns=%lu", (u_long
)columns
);
304 if (opts_set(sp
, argv
, NULL
))