/*
 * Copyright (c) 2004, 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.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: t-rcb-dec.c,v 1.6 2005/03/15 19:56:02 ca Exp $")

#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/heap.h"
#include "sm/ctype.h"
#include "sm/test.h"
#include "sm/str.h"
#include "sm/rcb.h"
#include "sm/reccom.h"

#include <stdio.h>

#define SMAXLEN	(64 * 1024)

#define PRINTIT(c)	(ISPRINT(c) ? (c) : '_')

int
dec_rcb(sm_rcb_P rcb)
{
	int r;
	uint u;
	uint32_t l, rt, v, tl;
	uchar *src;

	u = 0;
	r = sm_rcb_open_dec(rcb);
	SM_TEST(r == SM_SUCCESS);

	/* Total length of record */
	r = sm_rcb_getuint32(rcb, &tl);
	SM_TEST(!(sm_is_err(r) || tl > SMAXLEN ||
		tl > sm_rcb_getlen(rcb)));
	if (sm_is_err(r) || tl > SMAXLEN ||
	    tl > sm_rcb_getlen(rcb))
	{
		fprintf(stderr, "tl=%4u, r=0x%x\n", tl, r);
		goto error;
	}
	u += 4;
	fprintf(stdout, "tl=%4u\n", tl);

	r = sm_rcb_get3uint32(rcb, &l, &rt, &v);
	SM_TEST(r == SM_SUCCESS);
	if (sm_is_err(r))
		goto error;
	fprintf(stdout, "rt=%08X, l=%4u, v=%08X\n", rt, l, v);
	u += 12;

	SM_TEST(!(l != 4 || rt != RT_PROT_VER || v != PROT_VER_RT));
	if (l != 4 || rt != RT_PROT_VER || v != PROT_VER_RT)
	{
		r = sm_error_perm(SM_EM_Q_SC2Q, SM_E_PR_V_MISM);
	}

	while (!SM_RCB_ISEOB(rcb) && u < tl)
	{
		r = sm_rcb_get2uint32(rcb, &l, &rt);
		SM_TEST(r == SM_SUCCESS);
		if (sm_is_err(r))
			break;

		fprintf(stdout, "%4u: rt=%08X, l=%4u: ", u, rt, l);
		u += 8;
		while (l > 0)
		{
			r = sm_rcb_getuint32(rcb, &v);
			SM_TEST(r == SM_SUCCESS);
			if (sm_is_err(r))
				goto error;
			fprintf(stdout, "0x%08X ", v);
			src = (uchar *) &v;
			fprintf(stdout, "%c%c%c%c "
				, PRINTIT(src[0])
				, PRINTIT(src[1])
				, PRINTIT(src[2])
				, PRINTIT(src[3]));
			u += 4;
			SM_TEST(l >= 4);
			if (l >= 4)
				l -= 4;
			else
			{
				/* COMPLAIN? */
				break;
				fprintf(stdout, "\n");
				goto error;
			}
			SM_TEST(u <= tl);
			if (u > tl)
			{
				/* COMPLAIN? */
				fprintf(stdout, "\nERROR: TL exceeded\n");
				goto error;
			}
		}
		fprintf(stdout, "\n");
	}
	SM_TEST(u == tl && SM_RCB_ISEOB(rcb));
	if (u >= tl && !SM_RCB_ISEOB(rcb))
	{
		fprintf(stdout, "ERROR: u=%u, tl=%u, eob=%d\n", u, tl,
			SM_RCB_ISEOB(rcb));
	}

  error:
	return r;
}

int
read_rcb(FILE *fp, sm_rcb_P rcb)
{
	int r, i;
	uint32_t u;

	i = 0;
	while (fscanf(fp, "%x", &u) == 1)
	{
		r = sm_rcb_putuint32(rcb, u);
		SM_TEST(r == SM_SUCCESS);
		if (SmTestVerbose)
			fprintf(stdout, "%4d: %08x  ", i, u);
		++i;
		if (SmTestVerbose && i % 4 == 0)
			fprintf(stdout, "\n");
	}
	if (SmTestVerbose)
		fprintf(stdout, "\ngot %d\n", i);
	r = sm_rcb_close_enc(rcb);
	SM_TEST(r == SM_SUCCESS);
	return 0;
}

int
open_rcb(sm_rcb_P *prcb)
{
	int r;
	sm_rcb_P rcb;

	rcb = sm_rcb_new(NULL, SMAXLEN, SMAXLEN);
	SM_TEST(rcb != NULL);
	if (rcb == NULL)
		return -1;
	r = sm_rcb_open_enc(rcb, SMAXLEN);
	SM_TEST(r == SM_SUCCESS);
	*prcb = rcb;
	return r;
}

int
main(int argc, char *argv[])
{
	int r;
	sm_rcb_P rcb;

	sm_test_begin(argc, argv, "test rcb decode");

	rcb = NULL;
	r = open_rcb(&rcb);
	if (r != SM_SUCCESS)
		return r;
	r = read_rcb(stdin, rcb);
	if (r != SM_SUCCESS)
		return r;
	dec_rcb(rcb);
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1