/* * 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: strprintf.c,v 1.11 2005/12/07 00:49:46 ca Exp $") #include "sm/varargs.h" #include "sm/io.h" #include "sm/assert.h" #include "sm/limits.h" #include "sm/str.h" #include "io-int.h" /* ** SM_STRPRINTF -- format data for "output" into a str (append!) ** ** Parameters: ** str -- str ** fmt -- the formatting directives ** ... -- the data to satisfy the formatting ** ** Returns: ** Failure: error code from sm_io_vfprintf() ** Success: length of str if all characters would have been ** written, not including the trailing '\0', ** up to a maximum of INT_MAX, as if there was ** no buffer size limitation. ** If the result >= sm_str_getmax(str) ** then the output was truncated. ** ** Side Effects: ** If n > 0, then between 0 and n-len(str) bytes of formatted ** output are written into 'str', followed by a '\0'. ** str may be "resized" if necessary. */ int sm_strprintf(sm_str_P str, char const *fmt, ...) { uint n, l; int ret; va_list ap; sm_file_T fake; SM_REQUIRE(str != NULL); SM_REQUIRE(fmt != NULL); /* While snprintf(3) specifies size_t stdio uses an int internally */ l = sm_str_getlen(str); n = sm_str_getmax(str) - l; if (n > INT_MAX) n = INT_MAX; va_start(ap, fmt); /* question: put this into a static?? */ fake.sm_magic = SM_FILE_MAGIC; f_fd(fake) = -1; f_flags(fake) = SMWR|SMSTRSTR; fake.f_cookie = (void *)str; f_bfbase(fake) = f_p(fake) = str->sm_str_base + l; f_bfsize(fake) = f_w(fake) = n ? n - 1 : 0; fake.f_timeout = SM_TIME_FOREVER; f_read(fake) = NULL; f_write(fake) = NULL; f_close(fake) = NULL; f_open(fake) = NULL; f_seek(fake) = NULL; f_setinfo(fake) = f_getinfo(fake) = NULL; ret = sm_io_vfprintf(&fake, fmt, ap); sm_str_term(str); va_end(ap); return ret + l; }