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#define INIT_SZ 128 29157016Sdes 30181111Sdesint 31181111Sdesvasprintf(char **str, const char *fmt, va_list ap) 32157016Sdes{ 33157016Sdes int ret = -1; 34157016Sdes va_list ap2; 35157016Sdes char *string, *newstr; 36157016Sdes size_t len; 37157016Sdes 38157016Sdes VA_COPY(ap2, ap); 39157016Sdes if ((string = malloc(INIT_SZ)) == NULL) 40157016Sdes goto fail; 41157016Sdes 42157016Sdes ret = vsnprintf(string, INIT_SZ, fmt, ap2); 43157016Sdes if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ 44157016Sdes *str = string; 45181111Sdes } else if (ret == INT_MAX || ret < 0) { /* Bad length */ 46181111Sdes free(string); 47157016Sdes goto fail; 48157016Sdes } else { /* bigger than initial, realloc allowing for nul */ 49157016Sdes len = (size_t)ret + 1; 50157016Sdes if ((newstr = realloc(string, len)) == NULL) { 51157016Sdes free(string); 52157016Sdes goto fail; 53157016Sdes } else { 54157016Sdes va_end(ap2); 55157016Sdes VA_COPY(ap2, ap); 56157016Sdes ret = vsnprintf(newstr, len, fmt, ap2); 57157016Sdes if (ret >= 0 && (size_t)ret < len) { 58157016Sdes *str = newstr; 59157016Sdes } else { /* failed with realloc'ed string, give up */ 60157016Sdes free(newstr); 61157016Sdes goto fail; 62157016Sdes } 63157016Sdes } 64157016Sdes } 65157016Sdes va_end(ap2); 66157016Sdes return (ret); 67157016Sdes 68157016Sdesfail: 69157016Sdes *str = NULL; 70157016Sdes errno = ENOMEM; 71157016Sdes va_end(ap2); 72157016Sdes return (-1); 73157016Sdes} 74157016Sdes#endif 75157016Sdes 76157016Sdes#ifndef HAVE_ASPRINTF 77157016Sdesint asprintf(char **str, const char *fmt, ...) 78157016Sdes{ 79157016Sdes va_list ap; 80157016Sdes int ret; 81157016Sdes 82157016Sdes *str = NULL; 83157016Sdes va_start(ap, fmt); 84157016Sdes ret = vasprintf(str, fmt, ap); 85157016Sdes va_end(ap); 86157016Sdes 87157016Sdes return ret; 88157016Sdes} 89157016Sdes#endif 90