source: trunk/third/nvi/ip/ip_read.c @ 14302

Revision 14302, 6.1 KB checked in by ghudson, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14301, which included commits to RCS files with non-trunk default branches.
Line 
1/*-
2 * Copyright (c) 1996
3 *      Keith Bostic.  All rights reserved.
4 *
5 * See the LICENSE file for redistribution information.
6 */
7
8#include "config.h"
9
10#ifndef lint
11static const char sccsid[] = "@(#)ip_read.c     8.3 (Berkeley) 9/24/96";
12#endif /* not lint */
13
14#include <sys/types.h>
15#include <sys/queue.h>
16
17#include <bitstring.h>
18#include <stdio.h>
19#include <termios.h>
20#include <time.h>
21 
22#include "../common/common.h"
23#include "../ex/script.h"
24#include "ip.h"
25
26extern GS *__global_list;
27
28typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_TIMEOUT } input_t;
29
30static input_t  ip_read __P((SCR *, IP_PRIVATE *, struct timeval *));
31static int      ip_resize __P((SCR *, size_t, size_t));
32static int      ip_trans __P((SCR *, IP_PRIVATE *, EVENT *));
33
34/*
35 * ip_event --
36 *      Return a single event.
37 *
38 * PUBLIC: int ip_event __P((SCR *, EVENT *, u_int32_t, int));
39 */
40int
41ip_event(sp, evp, flags, ms)
42        SCR *sp;
43        EVENT *evp;
44        u_int32_t flags;
45        int ms;
46{
47        IP_PRIVATE *ipp;
48        struct timeval t, *tp;
49
50        if (LF_ISSET(EC_INTERRUPT)) {           /* XXX */
51                evp->e_event = E_TIMEOUT;
52                return (0);
53        }
54
55        ipp = sp == NULL ? GIPP(__global_list) : IPP(sp);
56
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;
62        }
63
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;
71        }
72
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();
91                }
92                break;
93        }
94        return (0);
95}
96
97/*
98 * ip_read --
99 *      Read characters from the input.
100 */
101static input_t
102ip_read(sp, ipp, tp)
103        SCR *sp;
104        IP_PRIVATE *ipp;
105        struct timeval *tp;
106{
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;
115
116        gp = sp == NULL ? __global_list : sp->gp;
117        bp = ipp->ibuf + ipp->iblen;
118        blen = sizeof(ipp->ibuf) - ipp->iblen;
119
120        /*
121         * 1: A read with an associated timeout, e.g., trying to complete
122         *    a map sequence.  If input exists, we fall into #2.
123         */
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;
137                }
138        }
139       
140        /*
141         * 2: Wait for input.
142         *
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.
146         */
147        if (sp != NULL && F_ISSET(gp, G_SCRWIN)) {
148loop:           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;
157                        }
158                switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) {
159                case 0:
160                        abort();
161                case -1:
162                        goto err;
163                default:
164                        break;
165                }
166                if (!FD_ISSET(ipp->i_fd, &rdfd)) {
167                        if (sscr_input(sp))
168                                return (INP_ERR);
169                        goto loop;
170                }
171        }
172
173        /*
174         * 3: Read the input.
175         */
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. */
181err:            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;
188        }
189        return (rval);
190}
191
192/*
193 * ip_trans --
194 *      Translate messages into events.
195 */
196static int
197ip_trans(sp, ipp, evp)
198        SCR *sp;
199        IP_PRIVATE *ipp;
200        EVENT *evp;
201{
202        u_int32_t val1, val2;
203
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;
243string:         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:
258                /*
259                 * XXX: Protocol is out of sync?
260                 */
261                abort();
262        }
263        /* NOTREACHED */
264}
265
266/*
267 * ip_resize --
268 *      Reset the options for a resize event.
269 */
270static int
271ip_resize(sp, lines, columns)
272        SCR *sp;
273        size_t lines, columns;
274{
275        GS *gp;
276        ARGS *argv[2], a, b;
277        char b1[1024];
278
279        /*
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.
284         */
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);
290        }
291
292        a.bp = b1;
293        b.bp = NULL;
294        a.len = b.len = 0;
295        argv[0] = &a;
296        argv[1] = &b;
297
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);
307}
Note: See TracBrowser for help on using the repository browser.