/* * Copyright (c) 2005, 2006 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: cstrscpyv0.c,v 1.6 2006/10/05 04:27:37 ca Exp $") #include "sm/assert.h" #include "sm/magic.h" #include "sm/memops.h" #include "sm/varargs.h" #include "sm/limits.h" #include "sm/cstr.h" /* ** SM_CSTR_SCPYVN0 -- Create a cstring and copy n bytes from src into it; ** repeat that process until a NULL is encountered. ** This is used to create a '\0' terminated string without counting ** the trailing '\0'. ** ** Parameters: ** src -- Byte array to copy from ** n -- Number of bytes to copy from src ** ... repeated until src == NULL ** ** Returns: ** New cstr object ** NULL on error (ENOMEM) */ sm_cstr_P sm_cstr_scpyvn0(const uchar *src, uint n, ...) { sm_cstr_P cstr; const uchar *s0; uint total_len, n0, offset; va_list ap; #if MTA_USE_PTHREADS int r; #endif SM_REQUIRE(src != NULL); if (n >= CSTR_MAX_SIZE) return NULL; total_len = 0; va_start(ap, n); s0 = src; n0 = n; while (s0 != NULL) { total_len += n0; if (n0 >= CSTR_MAX_SIZE) return NULL; if (total_len >= CSTR_MAX_SIZE) return NULL; s0 = va_arg(ap, uchar *); if (s0 != NULL) n0 = va_arg(ap, uint); } va_end(ap); cstr = sm_malloc(sizeof(*cstr)); if (cstr == NULL) return NULL; cstr->sm_cstr_base = sm_malloc(total_len + 1); if (cstr->sm_cstr_base == NULL) { sm_free_size(cstr, sizeof(*cstr)); return NULL; } #if MTA_USE_PTHREADS r = pthread_mutex_init(&cstr->sm_cstr_mutex, SM_PTHREAD_MUTEXATTR); if (r != 0) { sm_free_size(cstr->sm_cstr_base, n + 1); sm_free_size(cstr, sizeof(*cstr)); return NULL; } #endif /* MTA_USE_PTHREADS */ cstr->sm_cstr_len = total_len; cstr->sm_cstr_refcnt = 1; va_start(ap, n); s0 = src; n0 = n; offset = 0; while (s0 != NULL) { SM_ASSERT(offset < total_len); SM_ASSERT(offset + n0 <= total_len); if (n0 > 0) { sm_memcpy(cstr->sm_cstr_base + offset, s0, n0); offset += n0; } s0 = va_arg(ap, uchar *); if (s0 != NULL) n0 = va_arg(ap, uint); } va_end(ap); cstr->sm_cstr_base[total_len] = '\0'; cstr->sm_magic = SM_CSTR_MAGIC; return cstr; }