Sync usage with man page.
[netbsd-mini2440.git] / dist / nvi / ipc / ip_trans.c
blob5a53da3e45b22072d931bfb83700d42469c92f34
1 /* $NetBSD$ */
3 /*-
4 * Copyright (c) 1996
5 * Keith Bostic. All rights reserved.
7 * See the LICENSE file for redistribution information.
8 */
10 #include "config.h"
12 #ifndef lint
13 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";
14 #endif /* not lint */
16 #include <sys/types.h>
17 #include <sys/queue.h>
18 #ifdef HAVE_SYS_SELECT_H
19 #include <sys/select.h>
20 #endif
22 #include <bitstring.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <netinet/in.h>
28 #ifdef __STDC__
29 #include <stdarg.h>
30 #else
31 #include <varargs.h>
32 #endif
34 #include "../common/common.h"
35 #include "ip.h"
36 #include "ipc_def.h"
38 static char ibuf[2048]; /* Input buffer. */
39 static size_t ibuf_len; /* Length of current input. */
41 extern IPFUNLIST const ipfuns[];
44 * vi_input --
45 * Read from the vi message queue.
47 * PUBLIC: int vi_input __P((IPVIWIN *, int));
49 int
50 vi_input(IPVIWIN *ipviwin, 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 *ipviwin, char *fmt, IP_BUF *ipbp)
80 fd_set rdfd;
81 ssize_t nr;
83 if (vi_send(ipviwin->ofd, fmt, ipbp))
84 return (1);
86 FD_ZERO(&rdfd);
87 ipbp->code = CODE_OOB;
89 for (;;) {
90 FD_SET(ipviwin->ifd, &rdfd);
91 if (select(ipviwin->ifd + 1, &rdfd, NULL, NULL, NULL) != 0)
92 return (-1);
94 /* Read waiting vi messages and translate to X calls. */
95 switch (nr =
96 read(ipviwin->ifd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
97 case 0:
98 return (0);
99 case -1:
100 return (-1);
101 default:
102 break;
104 ibuf_len += nr;
106 /* Parse to data end or partial message. */
107 (void)vi_translate(ipviwin, ibuf, &ibuf_len, ipbp);
109 if (ipbp->code != CODE_OOB)
110 break;
112 return (0);
116 * vi_translate --
117 * Translate vi messages into function calls.
119 * PUBLIC: int vi_translate __P((IPVIWIN *, char *, size_t *, IP_BUF *));
122 vi_translate(IPVIWIN *ipviwin, char *bp, size_t *lenp, IP_BUF *ipbp)
124 IP_BUF ipb;
125 size_t len, needlen;
126 u_int32_t *vp;
127 char *fmt, *p, *s_bp;
128 const char **vsp;
129 IPFunc fun;
131 for (s_bp = bp, len = *lenp; len > 0;) {
132 fmt = ipfuns[(ipb.code = bp[0])-1].format;
134 p = bp + IPO_CODE_LEN;
135 needlen = IPO_CODE_LEN;
136 for (; *fmt != '\0'; ++fmt)
137 switch (*fmt) {
138 case '1': /* Value #1. */
139 vp = &ipb.val1;
140 goto value;
141 case '2': /* Value #2. */
142 vp = &ipb.val2;
143 goto value;
144 case '3': /* Value #3. */
145 vp = &ipb.val3;
146 value: needlen += IPO_INT_LEN;
147 if (len < needlen)
148 goto partial;
149 memcpy(vp, p, IPO_INT_LEN);
150 *vp = ntohl(*vp);
151 p += IPO_INT_LEN;
152 break;
153 case 'a': /* String #1. */
154 vp = &ipb.len1;
155 vsp = &ipb.str1;
156 goto string;
157 case 'b': /* String #2. */
158 vp = &ipb.len2;
159 vsp = &ipb.str2;
160 string: needlen += IPO_INT_LEN;
161 if (len < needlen)
162 goto partial;
163 memcpy(vp, p, IPO_INT_LEN);
164 *vp = ntohl(*vp);
165 p += IPO_INT_LEN;
166 needlen += *vp;
167 if (len < needlen)
168 goto partial;
169 *vsp = p;
170 p += *vp;
171 break;
173 bp += needlen;
174 len -= needlen;
177 * XXX
178 * Protocol error!?!?
180 if (ipb.code >= SI_EVENT_SUP) {
181 len = 0;
182 break;
186 * If we're waiting for a reply and we got it, return it, and
187 * leave any unprocessed data in the buffer. If we got a reply
188 * and we're not waiting for one, discard it -- callers wait
189 * for responses.
191 if (ipb.code == SI_REPLY) {
192 if (ipbp == NULL)
193 continue;
194 *ipbp = ipb;
195 break;
198 /* Call the underlying routine. */
199 fun = *(IPFunc *)
200 (((char *)ipviwin->si_ops)+ipfuns[ipb.code - 1].offset);
201 if (fun != NULL &&
202 ipfuns[ipb.code - 1].unmarshall(ipviwin, &ipb, fun))
203 break;
205 partial:
206 if ((*lenp = len) != 0)
207 memmove(s_bp, bp, len);
208 return (0);