⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comm.c

📁 < linux网络编程工具>>配套源码
💻 C
字号:
/*
 *  Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 */

#ifndef lint
static char id[] = "@(#)$Id: comm.c,v 8.30.4.5 2000/08/14 09:04:47 gshapiro Exp $";
#endif /* ! lint */

#if _FFR_MILTER
#include "libmilter.h"

#define FD_Z	FD_ZERO(&readset);	\
		FD_SET((u_int) sd, &readset);	\
		FD_ZERO(&excset);	\
		FD_SET((u_int) sd, &excset)

/*
**  MI_RD_CMD -- read a command
**
**	Parameters:
**		sd -- socket descriptor
**		timeout -- maximum time to wait
**		cmd -- single character command read from sd
**		rlen -- pointer to length of result
**		name -- name of milter
**
**	Returns:
**		buffer with rest of command
**		(malloc()ed here, should be free()d)
**		hack: encode error in cmd
*/

char *
mi_rd_cmd(sd, timeout, cmd, rlen, name)
	socket_t sd;
	struct timeval *timeout;
	char *cmd;
	size_t *rlen;
	char *name;
{
	ssize_t len;
	mi_int32 expl;
	ssize_t i;
	fd_set readset, excset;
	int ret;
	int save_errno;
	char *buf;
	char data[MILTER_LEN_BYTES + 1];

	*cmd = '\0';
	*rlen = 0;
	if (sd >= FD_SETSIZE)
	{
		smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d",
			name, sd, FD_SETSIZE);
		*cmd = SMFIC_SELECT;
		return NULL;
	}
	FD_Z;
	i = 0;
	while ((ret = select(sd + 1, &readset, NULL, &excset, timeout)) >= 1)
	{
		if (FD_ISSET(sd, &excset))
		{
			*cmd = SMFIC_SELECT;
			return NULL;
		}
		if ((len = MI_SOCK_READ(sd, data + i, sizeof data - i)) < 0)
		{
			smi_log(SMI_LOG_ERR,
				"%s, mi_rd_cmd: read returned %d: %s",
				name, len, strerror(errno));
			*cmd = SMFIC_RECVERR;
			return NULL;
		}
		if (len == 0)
		{
			*cmd = SMFIC_EOF;
			return NULL;
		}
		if (len >= (ssize_t) sizeof data - i)
			break;
		i += len;
		FD_Z;
	}
	if (ret == 0)
	{
		*cmd = SMFIC_TIMEOUT;
		return NULL;
	}
	else if (ret < 0)
	{
		smi_log(SMI_LOG_ERR,
			"%s: mi_rd_cmd: select returned %d: %s",
			name, ret, strerror(errno));
		*cmd = SMFIC_RECVERR;
		return NULL;
	}

	*cmd = data[MILTER_LEN_BYTES];
	data[MILTER_LEN_BYTES] = '\0';
	(void) memcpy((void *) &expl, (void *) &(data[0]), MILTER_LEN_BYTES);
	expl = ntohl(expl) - 1;
	if (expl <= 0)
		return NULL;
	if (expl > MILTER_CHUNK_SIZE)
	{
		*cmd = SMFIC_TOOBIG;
		return NULL;
	}
	buf = malloc(expl);
	if (buf == NULL)
	{
		*cmd = SMFIC_MALLOC;
		return NULL;
	}

	i = 0;
	FD_Z;
	while ((ret = select(sd + 1, &readset, NULL, &excset, timeout)) == 1)
	{
		if (FD_ISSET(sd, &excset))
		{
			*cmd = SMFIC_SELECT;
			free(buf);
			return NULL;
		}
		if ((len = MI_SOCK_READ(sd, buf + i, expl - i)) < 0)
		{
			smi_log(SMI_LOG_ERR,
				"%s: mi_rd_cmd: read returned %d: %s",
				name, len, strerror(errno));
			ret = -1;
			break;
		}
		if (len == 0)
		{
			*cmd = SMFIC_EOF;
			free(buf);
			return NULL;
		}
		if (len > expl - i)
		{
			*cmd = SMFIC_RECVERR;
			free(buf);
			return NULL;
		}
		if (len >= expl - i)
		{
			*rlen = expl;
			return buf;
		}
		i += len;
		FD_Z;
	}

	save_errno = errno;
	free(buf);

	/* select returned 0 (timeout) or < 0 (error) */
	if (ret == 0)
	{
		*cmd = SMFIC_TIMEOUT;
		return NULL;
	}
	if (ret < 0)
	{
		smi_log(SMI_LOG_ERR,
			"%s: mi_rd_cmd: select returned %d: %s",
			name, ret, strerror(save_errno));
		*cmd = SMFIC_RECVERR;
		return NULL;
	}
	*cmd = SMFIC_UNKNERR;
	return NULL;
}
/*
**  MI_WR_CMD -- write a cmd to sd
**
**	Parameters:
**		sd -- socket descriptor
**		timeout -- maximum time to wait (currently unused)
**		cmd -- single character command to write
**		buf -- buffer with further data
**		len -- length of buffer (without cmd!)
**
**	Returns:
**		MI_SUCCESS/MI_FAILURE
*/

int
mi_wr_cmd(sd, timeout, cmd, buf, len)
	socket_t sd;
	struct timeval *timeout;
	int cmd;
	char *buf;
	size_t len;
{
	size_t sl, i;
	ssize_t l;
	mi_int32 nl;
	int ret;
	fd_set wrtset;
	char data[MILTER_LEN_BYTES + 1];

	if (len > MILTER_CHUNK_SIZE)
		return MI_FAILURE;
	nl = htonl(len + 1);	/* add 1 for the cmd char */
	(void) memcpy(data, (void *) &nl, MILTER_LEN_BYTES);
	data[MILTER_LEN_BYTES] = (char) cmd;
	i = 0;
	sl = MILTER_LEN_BYTES + 1;

	do
	{
		FD_ZERO(&wrtset);
		FD_SET((u_int) sd, &wrtset);
		if ((ret = select(sd + 1, NULL, &wrtset, NULL, timeout)) == 0)
			return MI_FAILURE;
	} while (ret < 0 && errno == EINTR);
	if (ret < 0)
		return MI_FAILURE;

	/* use writev() instead to send the whole stuff at once? */
	while ((l = MI_SOCK_WRITE(sd, (void *) (data + i),
				  sl - i)) < (ssize_t) sl)
	{
		if (l < 0)
			return MI_FAILURE;
		i += l;
		sl -= l;
	}

	if (len > 0 && buf == NULL)
		return MI_FAILURE;
	if (len == 0 || buf == NULL)
		return MI_SUCCESS;
	i = 0;
	sl = len;
	do
	{
		FD_ZERO(&wrtset);
		FD_SET((u_int) sd, &wrtset);
		if ((ret = select(sd + 1, NULL, &wrtset, NULL, timeout)) == 0)
			return MI_FAILURE;
	} while (ret < 0 && errno == EINTR);
	if (ret < 0)
		return MI_FAILURE;
	while ((l = MI_SOCK_WRITE(sd, (void *) (buf + i),
				  sl - i)) < (ssize_t) sl)
	{
		if (l < 0)
			return MI_FAILURE;
		i += l;
		sl -= l;
	}
	return MI_SUCCESS;
}
#endif /* _FFR_MILTER */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -