add db.1.85
[nvi.git] / ipc / ip_trans.c
blobc1182a85aba6d047fa8f23ebcc37493098023f91
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.18 2001/06/25 15:19:25 skimo Exp $ (Berkeley) $Date: 2001/06/25 15:19:25 $";
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 *ipviwin, int fd)
50 ssize_t nr;
52 /* Read waiting vi messages and translate to X calls. */
53 switch (nr = read(fd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
54 case 0:
55 return (0);
56 case -1:
57 return (-1);
58 default:
59 break;
61 ibuf_len += nr;
63 /* Parse to data end or partial message. */
64 (void)vi_translate(ipviwin, ibuf, &ibuf_len, NULL);
66 return (ibuf_len > 0);
70 * vi_wsend --
71 * Construct and send an IP buffer, and wait for an answer.
73 * PUBLIC: int vi_wsend __P((IPVIWIN*, char *, IP_BUF *));
75 int
76 vi_wsend(IPVIWIN *ipviwin, char *fmt, 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 *ipviwin, char *bp, size_t *lenp, IP_BUF *ipbp)
122 IP_BUF ipb;
123 size_t len, needlen;
124 u_int32_t *vp;
125 char *fmt, *p, *s_bp;
126 const char **vsp;
127 IPFunc fun;
129 for (s_bp = bp, len = *lenp; len > 0;) {
130 fmt = ipfuns[(ipb.code = bp[0])-1].format;
132 p = bp + IPO_CODE_LEN;
133 needlen = IPO_CODE_LEN;
134 for (; *fmt != '\0'; ++fmt)
135 switch (*fmt) {
136 case '1': /* Value #1. */
137 vp = &ipb.val1;
138 goto value;
139 case '2': /* Value #2. */
140 vp = &ipb.val2;
141 goto value;
142 case '3': /* Value #3. */
143 vp = &ipb.val3;
144 value: needlen += IPO_INT_LEN;
145 if (len < needlen)
146 goto partial;
147 memcpy(vp, p, IPO_INT_LEN);
148 *vp = ntohl(*vp);
149 p += IPO_INT_LEN;
150 break;
151 case 'a': /* String #1. */
152 vp = &ipb.len1;
153 vsp = &ipb.str1;
154 goto string;
155 case 'b': /* String #2. */
156 vp = &ipb.len2;
157 vsp = &ipb.str2;
158 string: needlen += IPO_INT_LEN;
159 if (len < needlen)
160 goto partial;
161 memcpy(vp, p, IPO_INT_LEN);
162 *vp = ntohl(*vp);
163 p += IPO_INT_LEN;
164 needlen += *vp;
165 if (len < needlen)
166 goto partial;
167 *vsp = p;
168 p += *vp;
169 break;
171 bp += needlen;
172 len -= needlen;
175 * XXX
176 * Protocol error!?!?
178 if (ipb.code >= SI_EVENT_SUP) {
179 len = 0;
180 break;
184 * If we're waiting for a reply and we got it, return it, and
185 * leave any unprocessed data in the buffer. If we got a reply
186 * and we're not waiting for one, discard it -- callers wait
187 * for responses.
189 if (ipb.code == SI_REPLY) {
190 if (ipbp == NULL)
191 continue;
192 *ipbp = ipb;
193 break;
196 /* Call the underlying routine. */
197 fun = *(IPFunc *)
198 (((char *)ipviwin->si_ops)+ipfuns[ipb.code - 1].offset);
199 if (fun != NULL &&
200 ipfuns[ipb.code - 1].unmarshall(ipviwin, &ipb, fun))
201 break;
203 partial:
204 if ((*lenp = len) != 0)
205 memmove(s_bp, bp, len);
206 return (0);