(failed ?) attempt at cleaner ip interface
[nvi.git] / ipc / ip_trans.c
blobb03eb18dd7712f52b9c0b0565fac1c2273ed489e
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.17 2000/07/05 11:33:17 skimo Exp $ (Berkeley) $Date: 2000/07/05 11:33:17 $";
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>
23 #include <unistd.h>
24 #include <netinet/in.h>
26 #ifdef __STDC__
27 #include <stdarg.h>
28 #else
29 #include <varargs.h>
30 #endif
32 #include "../common/common.h"
33 #include "ip.h"
34 #include "ipc_def.h"
36 static char ibuf[2048]; /* Input buffer. */
37 static size_t ibuf_len; /* Length of current input. */
39 extern IPFUNLIST const ipfuns[];
42 * vi_input --
43 * Read from the vi message queue.
45 * PUBLIC: int vi_input __P((IPVIWIN *, int));
47 int
48 vi_input(ipviwin, fd)
49 IPVIWIN *ipviwin;
50 int fd;
52 ssize_t nr;
54 /* Read waiting vi messages and translate to X calls. */
55 switch (nr = read(fd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
56 case 0:
57 return (0);
58 case -1:
59 return (-1);
60 default:
61 break;
63 ibuf_len += nr;
65 /* Parse to data end or partial message. */
66 (void)vi_translate(ipviwin, ibuf, &ibuf_len, NULL);
68 return (ibuf_len > 0);
72 * vi_wsend --
73 * Construct and send an IP buffer, and wait for an answer.
75 * PUBLIC: int vi_wsend __P((IPVIWIN*, char *, IP_BUF *));
77 int
78 vi_wsend(ipviwin, fmt, ipbp)
79 IPVIWIN *ipviwin;
80 char *fmt;
81 IP_BUF *ipbp;
83 fd_set rdfd;
84 ssize_t nr;
86 if (vi_send(ipviwin->ofd, fmt, ipbp))
87 return (1);
89 FD_ZERO(&rdfd);
90 ipbp->code = CODE_OOB;
92 for (;;) {
93 FD_SET(ipviwin->ifd, &rdfd);
94 if (select(ipviwin->ifd + 1, &rdfd, NULL, NULL, NULL) != 0)
95 return (-1);
97 /* Read waiting vi messages and translate to X calls. */
98 switch (nr =
99 read(ipviwin->ifd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
100 case 0:
101 return (0);
102 case -1:
103 return (-1);
104 default:
105 break;
107 ibuf_len += nr;
109 /* Parse to data end or partial message. */
110 (void)vi_translate(ipviwin, ibuf, &ibuf_len, ipbp);
112 if (ipbp->code != CODE_OOB)
113 break;
115 return (0);
119 * vi_translate --
120 * Translate vi messages into function calls.
122 * PUBLIC: int vi_translate __P((IPVIWIN *, char *, size_t *, IP_BUF *));
125 vi_translate(ipviwin, bp, lenp, ipbp)
126 IPVIWIN *ipviwin;
127 char *bp;
128 size_t *lenp;
129 IP_BUF *ipbp;
131 IP_BUF ipb;
132 size_t len, needlen;
133 u_int32_t *vp;
134 char *fmt, *p, *s_bp;
135 const char **vsp;
136 IPFunc fun;
138 for (s_bp = bp, len = *lenp; len > 0;) {
139 fmt = ipfuns[(ipb.code = bp[0])-1].format;
141 p = bp + IPO_CODE_LEN;
142 needlen = IPO_CODE_LEN;
143 for (; *fmt != '\0'; ++fmt)
144 switch (*fmt) {
145 case '1': /* Value #1. */
146 vp = &ipb.val1;
147 goto value;
148 case '2': /* Value #2. */
149 vp = &ipb.val2;
150 goto value;
151 case '3': /* Value #3. */
152 vp = &ipb.val3;
153 value: needlen += IPO_INT_LEN;
154 if (len < needlen)
155 goto partial;
156 memcpy(vp, p, IPO_INT_LEN);
157 *vp = ntohl(*vp);
158 p += IPO_INT_LEN;
159 break;
160 case 'a': /* String #1. */
161 vp = &ipb.len1;
162 vsp = &ipb.str1;
163 goto string;
164 case 'b': /* String #2. */
165 vp = &ipb.len2;
166 vsp = &ipb.str2;
167 string: needlen += IPO_INT_LEN;
168 if (len < needlen)
169 goto partial;
170 memcpy(vp, p, IPO_INT_LEN);
171 *vp = ntohl(*vp);
172 p += IPO_INT_LEN;
173 needlen += *vp;
174 if (len < needlen)
175 goto partial;
176 *vsp = p;
177 p += *vp;
178 break;
180 bp += needlen;
181 len -= needlen;
184 * XXX
185 * Protocol error!?!?
187 if (ipb.code >= SI_EVENT_SUP) {
188 len = 0;
189 break;
193 * If we're waiting for a reply and we got it, return it, and
194 * leave any unprocessed data in the buffer. If we got a reply
195 * and we're not waiting for one, discard it -- callers wait
196 * for responses.
198 if (ipb.code == SI_REPLY) {
199 if (ipbp == NULL)
200 continue;
201 *ipbp = ipb;
202 break;
205 /* Call the underlying routine. */
206 fun = *(IPFunc *)
207 (((char *)ipviwin->si_ops)+ipfuns[ipb.code - 1].offset);
208 if (fun != NULL &&
209 ipfuns[ipb.code - 1].unmarshall(ipviwin, &ipb, fun))
210 break;
212 partial:
213 if ((*lenp = len) != 0)
214 memmove(s_bp, bp, len);
215 return (0);