2 * Copyright (c) 1999-2003 Sendmail, Inc. and its suppliers.
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.
12 SM_RCSID("@(#)$Id: comm.c,v 8.54.2.6 2003/01/03 22:14:40 ca Exp $")
14 #include "libmilter.h"
15 #include <sm/errstring.h>
18 ** MI_RD_CMD -- read a command
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
28 ** buffer with rest of command
29 ** (malloc()ed here, should be free()d)
30 ** hack: encode error in cmd
34 mi_rd_cmd(sd, timeout, cmd, rlen, name)
36 struct timeval *timeout;
48 char data[MILTER_LEN_BYTES + 1];
56 FD_RD_INIT(sd, rds, excs);
57 ret = FD_RD_READY(sd, rds, excs, timeout);
66 if (FD_IS_RD_EXC(sd, rds, excs))
72 len = MI_SOCK_READ(sd, data + i, sizeof data - i);
73 if (MI_SOCK_READ_FAIL(len))
76 "%s, mi_rd_cmd: read returned %d: %s",
77 name, (int) len, sm_errstring(errno));
86 if (len >= (ssize_t) sizeof data - i)
98 "%s: mi_rd_cmd: select returned %d: %s",
99 name, ret, sm_errstring(errno));
100 *cmd = SMFIC_RECVERR;
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;
110 if (expl > MILTER_CHUNK_SIZE)
116 buf = malloc(expl + 1);
117 #else /* _FFR_ADD_NULL */
119 #endif /* _FFR_ADD_NULL */
129 FD_RD_INIT(sd, rds, excs);
130 ret = FD_RD_READY(sd, rds, excs, timeout);
139 if (FD_IS_RD_EXC(sd, rds, excs))
145 len = MI_SOCK_READ(sd, buf + i, expl - i);
146 if (MI_SOCK_READ_FAIL(len))
149 "%s: mi_rd_cmd: read returned %d: %s",
150 name, (int) len, sm_errstring(errno));
162 *cmd = SMFIC_RECVERR;
170 /* makes life simpler for common string routines */
172 #endif /* _FFR_ADD_NULL */
181 /* select returned 0 (timeout) or < 0 (error) */
184 *cmd = SMFIC_TIMEOUT;
190 "%s: mi_rd_cmd: select returned %d: %s",
191 name, ret, sm_errstring(save_errno));
192 *cmd = SMFIC_RECVERR;
195 *cmd = SMFIC_UNKNERR;
199 ** MI_WR_CMD -- write a cmd to sd
202 ** sd -- socket descriptor
203 ** timeout -- maximum time to wait (currently unused)
204 ** cmd -- single character command to write
205 ** buf -- buffer with further data
206 ** len -- length of buffer (without cmd!)
209 ** MI_SUCCESS/MI_FAILURE
213 ** we don't care much about the timeout here, it's very long anyway
214 ** FD_SETSIZE is checked when socket is created.
218 #define MI_WR(data) \
221 FD_WR_INIT(sd, wrs); \
222 ret = FD_WR_READY(sd, wrs, timeout); \
227 if (errno == EINTR) \
232 l = MI_SOCK_WRITE(sd, (void *) ((data) + i), sl); \
235 if (errno == EINTR) \
245 mi_wr_cmd(sd, timeout, cmd, buf, len)
247 struct timeval *timeout;
257 char data[MILTER_LEN_BYTES + 1];
259 if (len > MILTER_CHUNK_SIZE)
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;
265 sl = MILTER_LEN_BYTES + 1;
267 /* use writev() instead to send the whole stuff at once? */
270 if (len > 0 && buf == NULL)
272 if (len == 0 || buf == NULL)