Switch from bioq_insert_tail() to bioqdisksort(). When the kernel is
[dragonfly.git] / contrib / nvi / ip / ip_read.c
blob9fd977774173f6814f77d1450ff8a569dc83f0b4
1 /*-
2 * Copyright (c) 1996
3 * Keith Bostic. All rights reserved.
5 * See the LICENSE file for redistribution information.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char sccsid[] = "@(#)ip_read.c 8.3 (Berkeley) 9/24/96";
12 #endif /* not lint */
14 #include <sys/types.h>
15 #include <sys/queue.h>
17 #include <bitstring.h>
18 #include <stdio.h>
19 #include <termios.h>
20 #include <time.h>
22 #include "../common/common.h"
23 #include "../ex/script.h"
24 #include "ip.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 *));
35 * ip_event --
36 * Return a single event.
38 * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
40 int
41 ip_event(sp, evp, flags, ms)
42 SCR *sp;
43 EVENT *evp;
44 u_int32_t flags;
45 int ms;
47 IP_PRIVATE *ipp;
48 struct timeval t, *tp;
50 if (LF_ISSET(EC_INTERRUPT)) { /* XXX */
51 evp->e_event = E_TIMEOUT;
52 return (0);
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);
61 ipp->iskip = 0;
64 /* Set timer. */
65 if (ms == 0)
66 tp = NULL;
67 else {
68 t.tv_sec = ms / 1000;
69 t.tv_usec = (ms % 1000) * 1000;
70 tp = &t;
73 /* Read input events. */
74 for (;;) {
75 switch (ip_read(sp, ipp, tp)) {
76 case INP_OK:
77 if (!ip_trans(sp, ipp, evp))
78 continue;
79 break;
80 case INP_EOF:
81 evp->e_event = E_EOF;
82 break;
83 case INP_ERR:
84 evp->e_event = E_ERR;
85 break;
86 case INP_TIMEOUT:
87 evp->e_event = E_TIMEOUT;
88 break;
89 default:
90 abort();
92 break;
94 return (0);
98 * ip_read --
99 * Read characters from the input.
101 static input_t
102 ip_read(sp, ipp, tp)
103 SCR *sp;
104 IP_PRIVATE *ipp;
105 struct timeval *tp;
107 struct timeval poll;
108 GS *gp;
109 SCR *tsp;
110 fd_set rdfd;
111 input_t rval;
112 size_t blen;
113 int maxfd, nr;
114 char *bp;
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.
124 FD_ZERO(&rdfd);
125 poll.tv_sec = 0;
126 poll.tv_usec = 0;
127 if (tp != NULL) {
128 FD_SET(ipp->i_fd, &rdfd);
129 switch (select(ipp->i_fd + 1,
130 &rdfd, NULL, NULL, tp == NULL ? &poll : tp)) {
131 case 0:
132 return (INP_TIMEOUT);
133 case -1:
134 goto err;
135 default:
136 break;
141 * 2: Wait for input.
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);
150 maxfd = ipp->i_fd;
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)) {
159 case 0:
160 abort();
161 case -1:
162 goto err;
163 default:
164 break;
166 if (!FD_ISSET(ipp->i_fd, &rdfd)) {
167 if (sscr_input(sp))
168 return (INP_ERR);
169 goto loop;
174 * 3: Read the input.
176 switch (nr = read(ipp->i_fd, bp, blen)) {
177 case 0: /* EOF. */
178 rval = INP_EOF;
179 break;
180 case -1: /* Error or interrupt. */
181 err: rval = INP_ERR;
182 msgq(sp, M_SYSERR, "input");
183 break;
184 default: /* Input characters. */
185 ipp->iblen += nr;
186 rval = INP_OK;
187 break;
189 return (rval);
193 * ip_trans --
194 * Translate messages into events.
196 static int
197 ip_trans(sp, ipp, evp)
198 SCR *sp;
199 IP_PRIVATE *ipp;
200 EVENT *evp;
202 u_int32_t val1, val2;
204 switch (ipp->ibuf[0]) {
205 case IPO_EOF:
206 evp->e_event = E_EOF;
207 ipp->iskip = IPO_CODE_LEN;
208 return (1);
209 case IPO_ERR:
210 evp->e_event = E_ERR;
211 ipp->iskip = IPO_CODE_LEN;
212 return (1);
213 case IPO_INTERRUPT:
214 evp->e_event = E_INTERRUPT;
215 ipp->iskip = IPO_CODE_LEN;
216 return (1);
217 case IPO_QUIT:
218 evp->e_event = E_QUIT;
219 ipp->iskip = IPO_CODE_LEN;
220 return (1);
221 case IPO_RESIZE:
222 if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN * 2)
223 return (0);
224 evp->e_event = E_WRESIZE;
225 memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
226 val1 = ntohl(val1);
227 memcpy(&val2,
228 ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN, IPO_INT_LEN);
229 val2 = ntohl(val2);
230 ip_resize(sp, val1, val2);
231 ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN * 2;
232 return (1);
233 case IPO_SIGHUP:
234 evp->e_event = E_SIGHUP;
235 ipp->iskip = IPO_CODE_LEN;
236 return (1);
237 case IPO_SIGTERM:
238 evp->e_event = E_SIGTERM;
239 ipp->iskip = IPO_CODE_LEN;
240 return (1);
241 case IPO_STRING:
242 evp->e_event = E_STRING;
243 string: if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN)
244 return (0);
245 memcpy(&val1, ipp->ibuf + IPO_CODE_LEN, IPO_INT_LEN);
246 val1 = ntohl(val1);
247 if (ipp->iblen < IPO_CODE_LEN + IPO_INT_LEN + val1)
248 return (0);
249 ipp->iskip = IPO_CODE_LEN + IPO_INT_LEN + val1;
250 evp->e_csp = ipp->ibuf + IPO_CODE_LEN + IPO_INT_LEN;
251 evp->e_len = val1;
252 return (1);
253 case IPO_WRITE:
254 evp->e_event = E_WRITE;
255 ipp->iskip = IPO_CODE_LEN;
256 return (1);
257 default:
259 * XXX: Protocol is out of sync?
261 abort();
263 /* NOTREACHED */
267 * ip_resize --
268 * Reset the options for a resize event.
270 static int
271 ip_resize(sp, lines, columns)
272 SCR *sp;
273 size_t lines, columns;
275 GS *gp;
276 ARGS *argv[2], a, b;
277 char b1[1024];
280 * XXX
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.
285 if (sp == NULL) {
286 gp = __global_list;
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;
289 return (0);
292 a.bp = b1;
293 b.bp = NULL;
294 a.len = b.len = 0;
295 argv[0] = &a;
296 argv[1] = &b;
298 (void)snprintf(b1, sizeof(b1), "lines=%lu", (u_long)lines);
299 a.len = strlen(b1);
300 if (opts_set(sp, argv, NULL))
301 return (1);
302 (void)snprintf(b1, sizeof(b1), "columns=%lu", (u_long)columns);
303 a.len = strlen(b1);
304 if (opts_set(sp, argv, NULL))
305 return (1);
306 return (0);