Deleted Added
full compact
comm.c (111823) comm.c (132943)
1/*
1/*
2 * Copyright (c) 1999-2003 Sendmail, Inc. and its suppliers.
2 * Copyright (c) 1999-2004 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11#include <sm/gen.h>
3 * All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11#include <sm/gen.h>
12SM_RCSID("@(#)$Id: comm.c,v 8.54.2.6 2003/01/03 22:14:40 ca Exp $")
12SM_RCSID("@(#)$Id: comm.c,v 8.65 2004/07/07 21:41:30 ca Exp $")
13
14#include "libmilter.h"
15#include <sm/errstring.h>
13
14#include "libmilter.h"
15#include <sm/errstring.h>
16#include <sys/uio.h>
16
17
18static size_t Maxdatasize = MILTER_MAX_DATA_SIZE;
19
20#if _FFR_MAXDATASIZE
17/*
21/*
22** SMFI_SETMAXDATASIZE -- set limit for milter data read/write.
23**
24** Parameters:
25** sz -- new limit.
26**
27** Returns:
28** old limit
29*/
30
31size_t
32smfi_setmaxdatasize(sz)
33 size_t sz;
34{
35 size_t old;
36
37 old = Maxdatasize;
38 Maxdatasize = sz;
39 return old;
40}
41#endif /* _FFR_MAXDATASIZE */
42
43/*
18** MI_RD_CMD -- read a command
19**
20** Parameters:
21** sd -- socket descriptor
22** timeout -- maximum time to wait
23** cmd -- single character command read from sd
24** rlen -- pointer to length of result
25** name -- name of milter

--- 76 unchanged lines hidden (view full) ---

102 }
103
104 *cmd = data[MILTER_LEN_BYTES];
105 data[MILTER_LEN_BYTES] = '\0';
106 (void) memcpy((void *) &expl, (void *) &(data[0]), MILTER_LEN_BYTES);
107 expl = ntohl(expl) - 1;
108 if (expl <= 0)
109 return NULL;
44** MI_RD_CMD -- read a command
45**
46** Parameters:
47** sd -- socket descriptor
48** timeout -- maximum time to wait
49** cmd -- single character command read from sd
50** rlen -- pointer to length of result
51** name -- name of milter

--- 76 unchanged lines hidden (view full) ---

128 }
129
130 *cmd = data[MILTER_LEN_BYTES];
131 data[MILTER_LEN_BYTES] = '\0';
132 (void) memcpy((void *) &expl, (void *) &(data[0]), MILTER_LEN_BYTES);
133 expl = ntohl(expl) - 1;
134 if (expl <= 0)
135 return NULL;
110 if (expl > MILTER_CHUNK_SIZE)
136 if (expl > Maxdatasize)
111 {
112 *cmd = SMFIC_TOOBIG;
113 return NULL;
114 }
115#if _FFR_ADD_NULL
116 buf = malloc(expl + 1);
117#else /* _FFR_ADD_NULL */
118 buf = malloc(expl);

--- 71 unchanged lines hidden (view full) ---

190 "%s: mi_rd_cmd: select returned %d: %s",
191 name, ret, sm_errstring(save_errno));
192 *cmd = SMFIC_RECVERR;
193 return NULL;
194 }
195 *cmd = SMFIC_UNKNERR;
196 return NULL;
197}
137 {
138 *cmd = SMFIC_TOOBIG;
139 return NULL;
140 }
141#if _FFR_ADD_NULL
142 buf = malloc(expl + 1);
143#else /* _FFR_ADD_NULL */
144 buf = malloc(expl);

--- 71 unchanged lines hidden (view full) ---

216 "%s: mi_rd_cmd: select returned %d: %s",
217 name, ret, sm_errstring(save_errno));
218 *cmd = SMFIC_RECVERR;
219 return NULL;
220 }
221 *cmd = SMFIC_UNKNERR;
222 return NULL;
223}
224
198/*
225/*
226** RETRY_WRITEV -- Keep calling the writev() system call
227** until all the data is written out or an error occurs.
228**
229** Parameters:
230** fd -- socket descriptor
231** iov -- io vector
232** iovcnt -- number of elements in io vector
233** must NOT exceed UIO_MAXIOV.
234** timeout -- maximum time to wait
235**
236** Returns:
237** success: number of bytes written
238** otherwise: MI_FAILURE
239*/
240
241static ssize_t
242retry_writev(fd, iov, iovcnt, timeout)
243 socket_t fd;
244 struct iovec *iov;
245 int iovcnt;
246 struct timeval *timeout;
247{
248 int i;
249 ssize_t n, written;
250 FD_WR_VAR(wrs);
251
252 written = 0;
253 for (;;)
254 {
255 while (iovcnt > 0 && iov[0].iov_len == 0)
256 {
257 iov++;
258 iovcnt--;
259 }
260 if (iovcnt <= 0)
261 return written;
262
263 /*
264 ** We don't care much about the timeout here,
265 ** it's very long anyway; correct solution would be
266 ** to take the time before the loop and reduce the
267 ** timeout after each invocation.
268 ** FD_SETSIZE is checked when socket is created.
269 */
270
271 FD_WR_INIT(fd, wrs);
272 i = FD_WR_READY(fd, wrs, timeout);
273 if (i == 0)
274 return MI_FAILURE;
275 if (i < 0)
276 {
277 if (errno == EINTR || errno == EAGAIN)
278 continue;
279 return MI_FAILURE;
280 }
281 n = writev(fd, iov, iovcnt);
282 if (n == -1)
283 {
284 if (errno == EINTR || errno == EAGAIN)
285 continue;
286 return MI_FAILURE;
287 }
288
289 written += n;
290 for (i = 0; i < iovcnt; i++)
291 {
292 if (iov[i].iov_len > (unsigned int) n)
293 {
294 iov[i].iov_base = (char *)iov[i].iov_base + n;
295 iov[i].iov_len -= (unsigned int) n;
296 break;
297 }
298 n -= (int) iov[i].iov_len;
299 iov[i].iov_len = 0;
300 }
301 if (i == iovcnt)
302 return written;
303 }
304}
305
306/*
199** MI_WR_CMD -- write a cmd to sd
200**
201** Parameters:
202** sd -- socket descriptor
307** MI_WR_CMD -- write a cmd to sd
308**
309** Parameters:
310** sd -- socket descriptor
203** timeout -- maximum time to wait (currently unused)
311** timeout -- maximum time to wait
204** cmd -- single character command to write
205** buf -- buffer with further data
206** len -- length of buffer (without cmd!)
207**
208** Returns:
209** MI_SUCCESS/MI_FAILURE
210*/
211
312** cmd -- single character command to write
313** buf -- buffer with further data
314** len -- length of buffer (without cmd!)
315**
316** Returns:
317** MI_SUCCESS/MI_FAILURE
318*/
319
212/*
213** we don't care much about the timeout here, it's very long anyway
214** FD_SETSIZE is checked when socket is created.
215** XXX l == 0 ?
216*/
217
218#define MI_WR(data) \
219 while (sl > 0) \
220 { \
221 FD_WR_INIT(sd, wrs); \
222 ret = FD_WR_READY(sd, wrs, timeout); \
223 if (ret == 0) \
224 return MI_FAILURE; \
225 if (ret < 0) \
226 { \
227 if (errno == EINTR) \
228 continue; \
229 else \
230 return MI_FAILURE; \
231 } \
232 l = MI_SOCK_WRITE(sd, (void *) ((data) + i), sl); \
233 if (l < 0) \
234 { \
235 if (errno == EINTR) \
236 continue; \
237 else \
238 return MI_FAILURE; \
239 } \
240 i += l; \
241 sl -= l; \
242 }
243
244int
245mi_wr_cmd(sd, timeout, cmd, buf, len)
246 socket_t sd;
247 struct timeval *timeout;
248 int cmd;
249 char *buf;
250 size_t len;
251{
252 size_t sl, i;
253 ssize_t l;
254 mi_int32 nl;
320int
321mi_wr_cmd(sd, timeout, cmd, buf, len)
322 socket_t sd;
323 struct timeval *timeout;
324 int cmd;
325 char *buf;
326 size_t len;
327{
328 size_t sl, i;
329 ssize_t l;
330 mi_int32 nl;
255 int ret;
256 FD_WR_VAR(wrs);
331 int iovcnt;
332 struct iovec iov[2];
257 char data[MILTER_LEN_BYTES + 1];
258
333 char data[MILTER_LEN_BYTES + 1];
334
259 if (len > MILTER_CHUNK_SIZE)
335 if (len > Maxdatasize || (len > 0 && buf == NULL))
260 return MI_FAILURE;
336 return MI_FAILURE;
337
261 nl = htonl(len + 1); /* add 1 for the cmd char */
262 (void) memcpy(data, (void *) &nl, MILTER_LEN_BYTES);
263 data[MILTER_LEN_BYTES] = (char) cmd;
264 i = 0;
265 sl = MILTER_LEN_BYTES + 1;
266
338 nl = htonl(len + 1); /* add 1 for the cmd char */
339 (void) memcpy(data, (void *) &nl, MILTER_LEN_BYTES);
340 data[MILTER_LEN_BYTES] = (char) cmd;
341 i = 0;
342 sl = MILTER_LEN_BYTES + 1;
343
267 /* use writev() instead to send the whole stuff at once? */
268
269 MI_WR(data);
270 if (len > 0 && buf == NULL)
344 /* set up the vector for the size / command */
345 iov[0].iov_base = (void *) data;
346 iov[0].iov_len = sl;
347 iovcnt = 1;
348 if (len >= 0 && buf != NULL)
349 {
350 iov[1].iov_base = (void *) buf;
351 iov[1].iov_len = len;
352 iovcnt = 2;
353 }
354
355 l = retry_writev(sd, iov, iovcnt, timeout);
356 if (l == MI_FAILURE)
271 return MI_FAILURE;
357 return MI_FAILURE;
272 if (len == 0 || buf == NULL)
273 return MI_SUCCESS;
274 i = 0;
275 sl = len;
276 MI_WR(buf);
277 return MI_SUCCESS;
278}
358 return MI_SUCCESS;
359}