*** empty log message ***
[nvi.git] / ipc / ip_trans.c
blob7354e8a99765c6e50afbf93863dd20f772178405
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.15 1997/08/02 16:49:33 bostic Exp $ (Berkeley) $Date: 1997/08/02 16:49:33 $";
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((int));
42 int
43 vi_input(fd)
44 int fd;
46 ssize_t nr;
48 /* Read waiting vi messages and translate to X calls. */
49 switch (nr = read(fd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
50 case 0:
51 return (0);
52 case -1:
53 return (-1);
54 default:
55 break;
57 ibuf_len += nr;
59 /* Parse to data end or partial message. */
60 (void)vi_translate(ibuf, &ibuf_len, NULL);
62 return (ibuf_len > 0);
66 * vi_wsend --
67 * Construct and send an IP buffer, and wait for an answer.
69 * PUBLIC: int vi_wsend __P((char *, IP_BUF *));
71 int
72 vi_wsend(fmt, ipbp)
73 char *fmt;
74 IP_BUF *ipbp;
76 fd_set rdfd;
77 ssize_t nr;
79 if (vi_send(fmt, ipbp))
80 return (1);
82 FD_ZERO(&rdfd);
83 ipbp->code = CODE_OOB;
85 for (;;) {
86 FD_SET(vi_ifd, &rdfd);
87 if (select(vi_ifd + 1, &rdfd, NULL, NULL, NULL) != 0)
88 return (-1);
90 /* Read waiting vi messages and translate to X calls. */
91 switch (nr =
92 read(vi_ifd, ibuf + ibuf_len, sizeof(ibuf) - ibuf_len)) {
93 case 0:
94 return (0);
95 case -1:
96 return (-1);
97 default:
98 break;
100 ibuf_len += nr;
102 /* Parse to data end or partial message. */
103 (void)vi_translate(ibuf, &ibuf_len, ipbp);
105 if (ipbp->code != CODE_OOB)
106 break;
108 return (0);
112 * vi_translate --
113 * Translate vi messages into function calls.
115 * PUBLIC: int vi_translate __P((char *, size_t *, IP_BUF *));
118 vi_translate(bp, lenp, ipbp)
119 char *bp;
120 size_t *lenp;
121 IP_BUF *ipbp;
123 extern int (*__vi_iplist[SI_EVENT_MAX - 1]) __P((IP_BUF *));
124 IP_BUF ipb;
125 size_t len, needlen;
126 u_int32_t *vp;
127 char *fmt, *p, *s_bp, **vsp;
129 for (s_bp = bp, len = *lenp; len > 0;) {
130 switch (ipb.code = bp[0]) {
131 case SI_ADDSTR:
132 case SI_BUSY_ON:
133 case SI_RENAME:
134 case SI_SELECT:
135 fmt = "a";
136 break;
137 case SI_ATTRIBUTE:
138 case SI_MOVE:
139 fmt = "12";
140 break;
141 case SI_EDITOPT:
142 fmt = "ab1";
143 break;
144 case SI_REPLY:
145 fmt = "1a";
146 break;
147 case SI_REWRITE:
148 fmt = "1";
149 break;
150 case SI_SCROLLBAR:
151 fmt = "123";
152 break;
153 default:
154 fmt = "";
157 p = bp + IPO_CODE_LEN;
158 needlen = IPO_CODE_LEN;
159 for (; *fmt != '\0'; ++fmt)
160 switch (*fmt) {
161 case '1': /* Value #1. */
162 vp = &ipb.val1;
163 goto value;
164 case '2': /* Value #2. */
165 vp = &ipb.val2;
166 goto value;
167 case '3': /* Value #3. */
168 vp = &ipb.val3;
169 value: needlen += IPO_INT_LEN;
170 if (len < needlen)
171 goto partial;
172 memcpy(vp, p, IPO_INT_LEN);
173 *vp = ntohl(*vp);
174 p += IPO_INT_LEN;
175 break;
176 case 'a': /* String #1. */
177 vp = &ipb.len1;
178 vsp = &ipb.str1;
179 goto string;
180 case 'b': /* String #2. */
181 vp = &ipb.len2;
182 vsp = &ipb.str2;
183 string: needlen += IPO_INT_LEN;
184 if (len < needlen)
185 goto partial;
186 memcpy(vp, p, IPO_INT_LEN);
187 *vp = ntohl(*vp);
188 p += IPO_INT_LEN;
189 needlen += *vp;
190 if (len < needlen)
191 goto partial;
192 *vsp = p;
193 p += *vp;
194 break;
196 bp += needlen;
197 len -= needlen;
200 * XXX
201 * Protocol error!?!?
203 if (ipb.code > SI_EVENT_MAX) {
204 len = 0;
205 break;
209 * If we're waiting for a reply and we got it, return it, and
210 * leave any unprocessed data in the buffer. If we got a reply
211 * and we're not waiting for one, discard it -- callers wait
212 * for responses.
214 if (ipb.code == SI_REPLY) {
215 if (ipbp == NULL)
216 continue;
217 *ipbp = ipb;
218 break;
221 /* Call the underlying routine. */
222 if (__vi_iplist[ipb.code - 1](&ipb))
223 break;
225 partial:
226 if ((*lenp = len) != 0)
227 memmove(s_bp, bp, len);
228 return (0);