/*
 * 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.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: strscatn.c,v 1.19 2007/01/30 04:59:05 ca Exp $")

#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/rpool.h"
#include "sm/varargs.h"
#include "sm/limits.h"
#include "sm/strrcb.h"
#include "sm/str-int.h"
#include "sm/str2rcb.h"

/*
**  SM_STR_SCATN -- Append a copy of a sized char * to the end of a
**			sm_str_P.
**
**	The bytes you are appending do not have to be '\0' terminated.
**	In fact, this will gladly copy '\0' characters if they are
**	included in the range of len.
**
**	Parameters:
**		str -- sm_str_P object to append onto.
**		append -- Array of bytes to append.
**		len -- Number of bytes to append.
**
**	Returns:
**		usual sm_error code; ENOMEM, SM_E_FULL, SM_E_OVFLW_SC
*/

sm_ret_T
#if SM_STR_READ
sm_rcb_putn(sm_str_P str, const uchar *append, uint len)
#else
sm_str_scatn(sm_str_P str, const char *append, uint len)
#endif
{
	uint new_alloc;
#if SM_STR_CHECK && SM_STR_READ
	uint olen;
#endif

	SM_IS_BUF(str);
	SM_REQUIRE(append != NULL);
	SM_REQUIRE(len < INT_MAX - 4);

#if SM_STR_READ
# if SM_RCB_CHECK
	SM_REQUIRE(str->sm_rcb_state == SM_RCB_ENC);
# endif
# if SM_STR_CHECK
	olen = len;
# endif
	len = SM_ALIGN4(len);

	/* do we really want to do this? */
	if (str->sm_rcb_rw >= 0 && (int)len > str->sm_rcb_rw)
		return sm_error_perm(SM_EM_STR_RCB, SM_E_FULL);
#endif /* SM_STR_READ */
	new_alloc = str->sm_str_len + len;

	/* overflow? */
	if (len > 0 && new_alloc <= str->sm_str_len)
		return sm_error_perm(SM_EM_STR_RCB, SM_E_OVFLW_SC);
	if (new_alloc > str->sm_str_size)
		SM_STR_INCREASE_R(str, new_alloc);
#if SM_STR_CHECK && SM_STR_READ
	sm_memcpy(str->sm_str_base + str->sm_str_len, append, olen);

	/* clear the "aligned" bytes to avoid complaints from purify */
	if (len > olen)
		sm_memzero(str->sm_str_base + str->sm_str_len + olen, len - olen);
#else /* SM_STR_CHECK && SM_STR_READ */
	sm_memcpy(str->sm_str_base + str->sm_str_len, append, len);
#endif /* SM_STR_CHECK && SM_STR_READ */
	str->sm_str_len += len;
#if SM_STR_READ
	if (str->sm_rcb_rw >= 0)
		str->sm_rcb_rw -= len;
#endif /* SM_STR_READ */
	return SM_SUCCESS;
}


syntax highlighted by Code2HTML, v. 0.9.1