1157016Sdes/* 2157016Sdes * Copyright (c) 2004 Darren Tucker. 3157016Sdes * 4157016Sdes * Based originally on asprintf.c from OpenBSD: 5157016Sdes * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> 6157016Sdes * 7157016Sdes * Permission to use, copy, modify, and distribute this software for any 8157016Sdes * purpose with or without fee is hereby granted, provided that the above 9157016Sdes * copyright notice and this permission notice appear in all copies. 10157016Sdes * 11157016Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12157016Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13157016Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14157016Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15157016Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16157016Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17157016Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18157016Sdes */ 19157016Sdes 20157016Sdes#include "includes.h" 21157016Sdes 22157016Sdes#ifndef HAVE_VASPRINTF 23157016Sdes 24162852Sdes#include <errno.h> 25162852Sdes#include <stdarg.h> 26162852Sdes#include <stdlib.h> 27162852Sdes 28157016Sdes#ifndef VA_COPY 29157016Sdes# ifdef HAVE_VA_COPY 30157016Sdes# define VA_COPY(dest, src) va_copy(dest, src) 31157016Sdes# else 32157016Sdes# ifdef HAVE___VA_COPY 33157016Sdes# define VA_COPY(dest, src) __va_copy(dest, src) 34157016Sdes# else 35157016Sdes# define VA_COPY(dest, src) (dest) = (src) 36157016Sdes# endif 37157016Sdes# endif 38157016Sdes#endif 39157016Sdes 40157016Sdes#define INIT_SZ 128 41157016Sdes 42181111Sdesint 43181111Sdesvasprintf(char **str, const char *fmt, va_list ap) 44157016Sdes{ 45157016Sdes int ret = -1; 46157016Sdes va_list ap2; 47157016Sdes char *string, *newstr; 48157016Sdes size_t len; 49157016Sdes 50157016Sdes VA_COPY(ap2, ap); 51157016Sdes if ((string = malloc(INIT_SZ)) == NULL) 52157016Sdes goto fail; 53157016Sdes 54157016Sdes ret = vsnprintf(string, INIT_SZ, fmt, ap2); 55157016Sdes if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ 56157016Sdes *str = string; 57181111Sdes } else if (ret == INT_MAX || ret < 0) { /* Bad length */ 58181111Sdes free(string); 59157016Sdes goto fail; 60157016Sdes } else { /* bigger than initial, realloc allowing for nul */ 61157016Sdes len = (size_t)ret + 1; 62157016Sdes if ((newstr = realloc(string, len)) == NULL) { 63157016Sdes free(string); 64157016Sdes goto fail; 65157016Sdes } else { 66157016Sdes va_end(ap2); 67157016Sdes VA_COPY(ap2, ap); 68157016Sdes ret = vsnprintf(newstr, len, fmt, ap2); 69157016Sdes if (ret >= 0 && (size_t)ret < len) { 70157016Sdes *str = newstr; 71157016Sdes } else { /* failed with realloc'ed string, give up */ 72157016Sdes free(newstr); 73157016Sdes goto fail; 74157016Sdes } 75157016Sdes } 76157016Sdes } 77157016Sdes va_end(ap2); 78157016Sdes return (ret); 79157016Sdes 80157016Sdesfail: 81157016Sdes *str = NULL; 82157016Sdes errno = ENOMEM; 83157016Sdes va_end(ap2); 84157016Sdes return (-1); 85157016Sdes} 86157016Sdes#endif 87157016Sdes 88157016Sdes#ifndef HAVE_ASPRINTF 89157016Sdesint asprintf(char **str, const char *fmt, ...) 90157016Sdes{ 91157016Sdes va_list ap; 92157016Sdes int ret; 93157016Sdes 94157016Sdes *str = NULL; 95157016Sdes va_start(ap, fmt); 96157016Sdes ret = vasprintf(str, fmt, ap); 97157016Sdes va_end(ap); 98157016Sdes 99157016Sdes return ret; 100157016Sdes} 101157016Sdes#endif 102