/*
 * Copyright (c) 2002-2005 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.
 *
 * $Id: t-rcb-sr.c,v 1.14 2005/04/14 17:14:02 ca Exp $
 */

/*
**  STDIN2RCB -- read rcb data from stdin
**
**	Parameters:
**		rcb -- RCB
**
**	Returns:
**		usual sm_error code
**
**  This is a hack: it reads an "RCB" from stdin in the following format:
**	I int
**	S string
*/

sm_ret_T
stdin2rcb(sm_rcb_P rcb)
{
	int c;
	sm_ret_T ret;

	ret = sm_rcb_open_enc(rcb, -1);
	SM_TEST(sm_is_success(ret));

	/* just a place holder for the size */
	ret = sm_rcb_putuint32(rcb, 0);
	SM_TEST(sm_is_success(ret));

	while ((c = getchar()) != EOF)
	{
		if (c == 'I')
		{
			ret = addint(rcb);
			SM_TEST(ret == SM_SUCCESS);
		}
		else if (c == 'S')
		{
			ret = addstr(rcb);
			SM_TEST(ret == SM_SUCCESS);
		}
		else
		{
			ret = sm_rcb_close_enc(rcb);
			SM_TEST(ret == SM_SUCCESS);
			if (sm_is_err(ret))
				break;
		}
		if (sm_is_err(ret))
		{
			(void) sm_rcb_close_enc(rcb);
			break;
		}
	}
	if (c == EOF && sm_is_success(ret))
	{
		(void) sm_rcb_close_enc(rcb);
		ret = EOF;
	}
	return ret;
}

/*
**  WRITERCB -- send rcb
**
**	Parameters:
**		rcb -- RCB
**		fd -- fd
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
writercb(sm_rcb_P rcb, rcb_fd_T fd)
{
	int res;
	sm_ret_T ret;

	if (Verbose > 1)
		fprintf(stderr, "write: %d\n", (int) sm_rcb_getlen(rcb));

	ret = sm_rcb_open_snd(rcb);
	SM_TEST(sm_is_success(ret));
	do
	{
		res = sm_rcb_snd(fd, rcb TMO);
		SM_TEST(res >= 0);
	} while (res > 0);
	ret = sm_rcb_close_snd(rcb);
	if (res != 0)
	{
		fprintf(stderr, "clt: write_fd failed=%d, len=%d, errno=%d\n",
			res, (int) sm_rcb_getlen(rcb), errno);
		ret = sm_err_perm(EIO);
	}
	return ret;
}

/*
**  SENDRCB -- send rcb
**
**	Parameters:
**		rcb -- RCB
**		fd -- fd
**
**	Returns:
**		usual sm_error code
**
**  This is a hack: it reads an "RCB" from stdin in the following format:
**	I int
**	S string
*/

sm_ret_T
sendrcb(sm_rcb_P rcb, rcb_fd_T fd)
{
	int res, c;
	sm_ret_T ret;

	ret = sm_rcb_open_enc(rcb, -1);
	SM_TEST(sm_is_success(ret));

	/* just a place holder for the size */
	ret = sm_rcb_putuint32(rcb, 0);
	SM_TEST(sm_is_success(ret));

	while ((c = getchar()) != EOF)
	{
		if (c == 'I')
		{
			ret = addint(rcb);
			SM_TEST(ret == SM_SUCCESS);
		}
		else if (c == 'S')
		{
			ret = addstr(rcb);
			SM_TEST(ret == SM_SUCCESS);
		}
		else
		{
			ret = sm_rcb_close_enc(rcb);
			SM_TEST(ret == SM_SUCCESS);
			if (sm_is_err(ret))
			{
				if (Verbose > 1)
					fprintf(stderr, "sm_rcb_close_enc=%#X\n"
						, ret);
				break;
			}

			if (Verbose > 1)
				fprintf(stderr, "write: %d\n",
					(int) sm_rcb_getlen(rcb));

			ret = sm_rcb_open_snd(rcb);
			SM_TEST(sm_is_success(ret));
			do
			{
				res = sm_rcb_snd(fd, rcb TMO);
				SM_TEST(res >= 0);
			} while (res > 0);
			ret = sm_rcb_close_snd(rcb);
			if (res != 0)
			{
				fprintf(stderr,
					"clt: write_fd failed=%d, len=%d, errno=%d\n",
					res, (int) sm_rcb_getlen(rcb), errno);
				ret = sm_err_perm(EIO);
			}
			else
				break;
		}
		if (sm_is_err(ret))
		{
			(void) sm_rcb_close_enc(rcb);
			break;
		}
	}
	if (c == EOF && sm_is_success(ret))
	{
		(void) sm_rcb_close_enc(rcb);
		ret = EOF;
	}
	return ret;
}

/*
**  RCVRCB -- rcv rcb
**
**	Parameters:
**		rcb -- RCB
**		fd -- fd
**		full -- read the entire RCB at once (block if necessary)
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
rcvrcb(sm_rcb_P rcb, rcb_fd_T fd, bool full)
{
	sm_ret_T ret;
	uint32_t val, len;
	char buf[SM_BIGRCBSIZE];

	if (full)
	{
		ret = sm_rcb_open_rcv(rcb);
		SM_TEST(sm_is_success(ret));
	}

	ret = SM_SUCCESS;
	val = 0;
	len = 0;
	do
	{
		ret = sm_rcb_rcv(fd, rcb, 16 TMO);
		if (Verbose > 2)
			fprintf(stderr, "rcb_rcv: ret=%x\n", ret);
	} while (full && ret > 0);
	if (ret < 0)
		return ret;
	if (ret > 0 && !full)
		return ret;
	ret = sm_rcb_close_rcv(rcb);
	SM_TEST(ret == SM_SUCCESS);

	ret = sm_rcb_open_dec(rcb);
	SM_TEST(sm_is_success(ret));
	if (!sm_is_success(ret))
		return ret;

	ret = sm_rcb_getuint32(rcb, &val);
	SM_TEST(sm_is_success(ret));
	if (!sm_is_success(ret))
		return ret;
	if (Verbose > 1)
		fprintf(stderr, "srv: total length=%d\n", val);

	/* have to agree on record types with sender ... */
	do
	{
		if (Verbose > 2)
			fprintf(stderr, "srv: rd=%d\n", rcb->sm_rcb_rw);

		ret = sm_rcb_getuint32(rcb, &len);
		SM_TEST(sm_is_success(ret));
		if (!sm_is_success(ret))
			break;
		if (Verbose > 1)
			fprintf(stderr, "srv: got length=%d\n", len);

		ret = sm_rcb_getuint32(rcb, &val);
		SM_TEST(sm_is_success(ret));
		if (!sm_is_success(ret))
			break;
		if (Verbose > 1)
			fprintf(stderr, "srv: got rectype=%x\n", val);

		/* bit 1: set: int */
		if (val & 0x01)
		{
			ret = sm_rcb_getuint32(rcb, &val);
			SM_TEST(sm_is_success(ret));
			if (!sm_is_success(ret))
				break;
			if (Verbose > 1)
				fprintf(stderr, "srv: got val=%d\n",
					val);
			fprintf(stderr, "I=%d\n", val);
		}
		else if (len < sizeof(buf) - 1)
		{
			sm_memzero(buf, sizeof(buf));
			ret = sm_rcb_getn(rcb, (uchar *) buf, len);
			SM_TEST(sm_is_success(ret));
			if (!sm_is_success(ret))
				break;
			if (Verbose > 1)
				fprintf(stderr, "srv: got buf=%d\n",
					buf[0]);
			fprintf(stderr, "S=");
			prtbuf(stderr, buf, len);
			fputc('\n', stderr);
		}
		else
			break;
		if (Verbose > 2)
			fprintf(stderr, "srv: next: rd=%d, len=%d\n",
				rcb->sm_rcb_rw, (int) rcb->sm_rcb_len);
	} while (rcb->sm_rcb_rw < (int) rcb->sm_rcb_len);
	ret = sm_rcb_close_dec(rcb);
	SM_TEST(ret == SM_SUCCESS);
	return ret;
}


syntax highlighted by Code2HTML, v. 0.9.1