/* * 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: strcatmv.c,v 1.13 2005/06/02 19:00:37 ca Exp $") #include "sm/assert.h" #include "sm/magic.h" #include "sm/rpool.h" #include "sm/varargs.h" #include "sm/limits.h" #include "sm/str.h" #include "sm/str-int.h" /* ** SM_STR_CATMV -- Append multiple strings to dst (only if it fits) ** This version creates a full copy or none. ** ** Parameters: ** dst -- str destination ** n -- number of source strings ** ... -- str to append ** (should we use NULL as end marker instead?) ** ** Returns: ** usual sm_error code; ENOMEM, SM_E_OVFLW_SC, SM_E_OVFLW_NS */ sm_ret_T sm_str_catmv(sm_str_P dst, int n, ...) { int h; uint total, prev; sm_ret_T res; sm_str_P str; va_list ap; SM_IS_BUF(dst); va_start(ap, n); /* ** Compute length first and see whether it exceeds max. ** That would also allow to resize the destination string ** only once. ** Disadvantage: walks twice through the args. */ h = n; total = 0; prev = 0; /* loop through all source strings */ while (h-- > 0) { str = va_arg(ap, sm_str_P); SM_IS_BUF(str); total += sm_str_getlen(str); if (sm_str_getlen(str) != 0 && (total > sm_str_getmax(dst) || total < prev)) { va_end(ap); return sm_error_perm(SM_EM_STR, SM_E_OVFLW_NS); } prev = total; } va_end(ap); va_start(ap, n); if (total > dst->sm_str_size) SM_STR_INCREASE_R(dst, total); /* loop through all source strings */ while (n-- > 0) { str = va_arg(ap, sm_str_P); res = sm_str_cat(dst, str); if (sm_is_err(res)) { va_end(ap); return res; } } va_end(ap); return SM_SUCCESS; }