eliminate i_fd and o_fd global vars
[nvi.git] / ipc / ip_trans.c
blob88e588e552a26c9d8d8d62b4ad15f4811b5437a6
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[] = "$Id: ip_trans.c,v 8.16 2000/06/28 20:20:39 skimo Exp $ (Berkeley) $Date: 2000/06/28 20:20:39 $";
12 #endif /* not lint */
14 #include <sys/types.h>
15 #include <sys/queue.h>
16 #ifdef HAVE_SYS_SELECT_H
17 #include <sys/select.h>
18 #endif
20 #include <bitstring.h>
21 #include <stdio.h>
22 #include <string.h>
24 #ifdef __STDC__
25 #include <stdarg.h>
26 #else
27 #include <varargs.h>
28 #endif
30 #include "../common/common.h"
31 #include "ip.h"
33 static char ibuf[2048]; /* Input buffer. */
34 static size_t ibuf_len; /* Length of current input. */
37 * vi_input --
38 * Read from the vi message queue.
40 * PUBLIC: int vi_input __P((IPVIWIN *, int));
42 int
43 vi_input(ipviwin, fd)
44 IPVIWIN *ipviwin;
45 int fd;
47 ssize_t nr;
49 /* Read waiting vi messages and translate to X calls. */
50 switch (nr = read(fd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
51 case 0:
52 return (0);
53 case -1:
54 return (-1);
55 default:
56 break;
58 ibuf_len += nr;
60 /* Parse to data end or partial message. */
61 (void)vi_translate(ipviwin, ibuf, &ibuf_len, NULL);
63 return (ibuf_len > 0);
67 * vi_wsend --
68 * Construct and send an IP buffer, and wait for an answer.
70 * PUBLIC: int vi_wsend __P((IPVIWIN*, char *, IP_BUF *));
72 int
73 vi_wsend(ipviwin, fmt, ipbp)
74 IPVIWIN *ipviwin;
75 char *fmt;
76 IP_BUF *ipbp;
78 fd_set rdfd;
79 ssize_t nr;
81 if (vi_send(ipviwin->ofd, fmt, ipbp))
82 return (1);
84 FD_ZERO(&rdfd);
85 ipbp->code = CODE_OOB;
87 for (;;) {
88 FD_SET(ipviwin->ifd, &rdfd);
89 if (select(ipviwin->ifd + 1, &rdfd, NULL, NULL, NULL) != 0)
90 return (-1);
92 /* Read waiting vi messages and translate to X calls. */
93 switch (nr =
94 read(ipviwin->ifd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
95 case 0:
96 return (0);
97 case -1:
98 return (-1);
99 default:
100 break;
102 ibuf_len += nr;
104 /* Parse to data end or partial message. */
105 (void)vi_translate(ipviwin, ibuf, &ibuf_len, ipbp);
107 if (ipbp->code != CODE_OOB)
108 break;
110 return (0);
114 * vi_translate --
115 * Translate vi messages into function calls.
117 * PUBLIC: int vi_translate __P((IPVIWIN *, char *, size_t *, IP_BUF *));
120 vi_translate(ipviwin, bp, lenp, ipbp)
121 IPVIWIN *ipviwin;
122 char *bp;
123 size_t *lenp;
124 IP_BUF *ipbp;
126 extern int (*__vi_iplist[SI_EVENT_MAX - 1]) __P((IP_BUF *));
127 IP_BUF ipb;
128 size_t len, needlen;
129 u_int32_t *vp;
130 char *fmt, *p, *s_bp;
131 const char **vsp;
133 for (s_bp = bp, len = *lenp; len > 0;) {
134 switch (ipb.code = bp[0]) {
135 case SI_ADDSTR:
136 case SI_BUSY_ON:
137 case SI_RENAME:
138 case SI_SELECT:
139 fmt = "a";
140 break;
141 case SI_ATTRIBUTE:
142 case SI_MOVE:
143 fmt = "12";
144 break;
145 case SI_EDITOPT:
146 fmt = "ab1";
147 break;
148 case SI_REPLY:
149 fmt = "1a";
150 break;
151 case SI_REWRITE:
152 fmt = "1";
153 break;
154 case SI_SCROLLBAR:
155 fmt = "123";
156 break;
157 default:
158 fmt = "";
161 p = bp + IPO_CODE_LEN;
162 needlen = IPO_CODE_LEN;
163 for (; *fmt != '\0'; ++fmt)
164 switch (*fmt) {
165 case '1': /* Value #1. */
166 vp = &ipb.val1;
167 goto value;
168 case '2': /* Value #2. */
169 vp = &ipb.val2;
170 goto value;
171 case '3': /* Value #3. */
172 vp = &ipb.val3;
173 value: needlen += IPO_INT_LEN;
174 if (len < needlen)
175 goto partial;
176 memcpy(vp, p, IPO_INT_LEN);
177 *vp = ntohl(*vp);
178 p += IPO_INT_LEN;
179 break;
180 case 'a': /* String #1. */
181 vp = &ipb.len1;
182 vsp = &ipb.str1;
183 goto string;
184 case 'b': /* String #2. */
185 vp = &ipb.len2;
186 vsp = &ipb.str2;
187 string: needlen += IPO_INT_LEN;
188 if (len < needlen)
189 goto partial;
190 memcpy(vp, p, IPO_INT_LEN);
191 *vp = ntohl(*vp);
192 p += IPO_INT_LEN;
193 needlen += *vp;
194 if (len < needlen)
195 goto partial;
196 *vsp = p;
197 p += *vp;
198 break;
200 bp += needlen;
201 len -= needlen;
204 * XXX
205 * Protocol error!?!?
207 if (ipb.code > SI_EVENT_MAX) {
208 len = 0;
209 break;
213 * If we're waiting for a reply and we got it, return it, and
214 * leave any unprocessed data in the buffer. If we got a reply
215 * and we're not waiting for one, discard it -- callers wait
216 * for responses.
218 if (ipb.code == SI_REPLY) {
219 if (ipbp == NULL)
220 continue;
221 *ipbp = ipb;
222 break;
225 /* Call the underlying routine. */
226 if (__vi_iplist[ipb.code - 1](&ipb))
227 break;
229 partial:
230 if ((*lenp = len) != 0)
231 memmove(s_bp, bp, len);
232 return (0);