/* * Copyright (c) 2000-2002, 2004 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. */ /* * Copyright (c) 1997 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: vasprintf.c,v 1.10 2004/12/29 23:47:35 ca Exp $") #include "sm/varargs.h" #include "sm/io.h" #include "sm/assert.h" #include "sm/heap.h" #include "io-int.h" /* ** SM_VASPRINTF -- printf to a dynamically allocated string ** ** Write 'printf' output to a dynamically allocated string ** buffer which is returned to the caller. ** ** Parameters: ** str -- *str receives a pointer to the allocated string ** fmt -- format directives for printing ** ap -- variable argument list ** ** Results: ** On failure, set *str to NULL, set errno, and return -1. ** ** On success, set *str to a pointer to a nul-terminated ** string buffer containing printf output, and return the ** length of the string (not counting the nul). */ #define SM_VA_BUFSIZE 128 int sm_vasprintf(char **str, const char *fmt, va_list ap) { int ret; sm_file_T fake; uchar *base; fake.sm_magic = SM_FILE_MAGIC; f_fd(fake) = -1; f_flags(fake) = SMWR | SMSTR | SMALC; f_bfbase(fake) = f_p(fake) = (uchar *)sm_malloc(SM_VA_BUFSIZE); if (f_bfbase(fake) == NULL) goto err2; 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; f_bfsize(fake) = f_w(fake) = SM_VA_BUFSIZE - 1; fake.f_timeout = SM_TIME_FOREVER; ret = sm_io_vfprintf(&fake, fmt, ap); if (ret == -1) goto err; *f_p(fake) = '\0'; /* use no more space than necessary */ base = (uchar *) sm_realloc(f_bfbase(fake), ret + 1); if (base == NULL) goto err; *str = (char *)base; return ret; err: if (f_bfbase(fake) != NULL) { sm_free(f_bfbase(fake)); f_bfbase(fake) = NULL; } err2: *str = NULL; errno = ENOMEM; return -1; }