/*
 * Copyright (c) 2002, 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: fputv.c,v 1.11 2006/07/14 14:42:25 ca Exp $")
#include "sm/error.h"
#include "sm/io.h"
#include "sm/assert.h"
#include "sm/varargs.h"
#include "sm/limits.h"
#include "sm/strrcb.h"
#include "sm/rcb.h"
#include "sm/str-int.h"
#if !SM_NO_CSTR
# include "sm/cstr.h"
#endif

/*
**  SM_IO_FPUTV -- put several values into fp buffer
**
**	Parameters:
**		fp -- the file pointer for the buffer to be written to
**		... -- arguments
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
sm_io_fputv(sm_file_T *fp, ...)
{
	int k;
	uint32_t rt, v;
	sm_str_P str;
#if !SM_NO_CSTR
	sm_cstr_P cstr;
#endif
	uchar *buf;
	size_t len;
	sm_ret_T ret;
	va_list ap;

	SM_IS_FP(fp);
	va_start(ap, fp);
	for (;;)
	{
		k = va_arg(ap, int);
		if (k == SM_RCBV_END)
			break;
		rt = va_arg(ap, uint32_t);
		switch (k)
		{
		  case SM_RCBV_INT:
			v = va_arg(ap, uint32_t);
			ret = sm_io_fput3uint32(fp, rt, 4, v);
			if (sm_is_err(ret))
				goto err1;
			break;
		  case SM_RCBV_STR:
			str = va_arg(ap, sm_str_P);
			SM_IS_BUF(str);
			ret = sm_io_fput2uint32(fp, rt, sm_str_getlen(str));
			if (sm_is_err(ret))
				goto err1;
			ret = sm_io_fputn(fp, sm_str_data(str),
				sm_str_getlen(str));
			if (sm_is_err(ret))
				goto err1;
			break;
#if !SM_NO_CSTR
		  case SM_RCBV_CSTR:
			cstr = va_arg(ap, sm_cstr_P);
			if (cstr == NULL)
			{
				ret = sm_io_fput2uint32(fp, rt, 0);
				if (sm_is_err(ret))
					goto err1;
				break;
			}

			SM_IS_CSTR(cstr);
			ret = sm_io_fput2uint32(fp, rt, sm_cstr_getlen(cstr));
			if (sm_is_err(ret))
				goto err1;
			ret = sm_io_fputn(fp, sm_cstr_data(cstr),
				sm_cstr_getlen(cstr));
			if (sm_is_err(ret))
				goto err1;
			break;
#endif /* !SM_NO_CSTR */
		  case SM_RCBV_BUF:
			buf = va_arg(ap, uchar *);
			len = va_arg(ap, size_t);
			ret = sm_io_fput2uint32(fp, rt, len);
			if (sm_is_err(ret))
				goto err1;
			ret = sm_io_fputn(fp, buf, len);
			if (sm_is_err(ret))
				goto err1;
			break;
		  default:
			ret = sm_error_perm(SM_EM_RCB, EINVAL);
			goto err1;
		}
	}
	va_end(ap);
	return SM_SUCCESS;

  err1:
	va_end(ap);
	return ret;
}


syntax highlighted by Code2HTML, v. 0.9.1