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} |