bsd-asprintf.c revision 323124
1218792Snp/* 2319270Snp * Copyright (c) 2004 Darren Tucker. 3218792Snp * 4218792Snp * Based originally on asprintf.c from OpenBSD: 5218792Snp * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> 6218792Snp * 7218792Snp * Permission to use, copy, modify, and distribute this software for any 8218792Snp * purpose with or without fee is hereby granted, provided that the above 9218792Snp * copyright notice and this permission notice appear in all copies. 10218792Snp * 11218792Snp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12218792Snp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13218792Snp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14218792Snp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15218792Snp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16218792Snp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17218792Snp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18218792Snp */ 19218792Snp 20218792Snp#include "includes.h" 21218792Snp 22218792Snp#ifndef HAVE_VASPRINTF 23218792Snp 24218792Snp#include <errno.h> 25218792Snp#include <stdarg.h> 26218792Snp#include <stdlib.h> 27218792Snp 28218792Snp#define INIT_SZ 128 29218792Snp 30218792Snpint 31218792Snpvasprintf(char **str, const char *fmt, va_list ap) 32218792Snp{ 33218792Snp int ret = -1; 34218792Snp va_list ap2; 35218792Snp char *string, *newstr; 36218792Snp size_t len; 37218792Snp 38218792Snp VA_COPY(ap2, ap); 39218792Snp if ((string = malloc(INIT_SZ)) == NULL) 40228561Snp goto fail; 41218792Snp 42228561Snp ret = vsnprintf(string, INIT_SZ, fmt, ap2); 43218792Snp if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ 44218792Snp *str = string; 45218792Snp } else if (ret == INT_MAX || ret < 0) { /* Bad length */ 46218792Snp free(string); 47228561Snp goto fail; 48247289Snp } else { /* bigger than initial, realloc allowing for nul */ 49218792Snp len = (size_t)ret + 1; 50228561Snp if ((newstr = realloc(string, len)) == NULL) { 51218792Snp free(string); 52247289Snp goto fail; 53218792Snp } else { 54228561Snp va_end(ap2); 55228561Snp VA_COPY(ap2, ap); 56228561Snp ret = vsnprintf(newstr, len, fmt, ap2); 57228561Snp if (ret >= 0 && (size_t)ret < len) { 58228561Snp *str = newstr; 59218792Snp } else { /* failed with realloc'ed string, give up */ 60220232Snp free(newstr); 61218792Snp goto fail; 62218792Snp } 63218792Snp } 64218792Snp } 65218792Snp va_end(ap2); 66218792Snp return (ret); 67218792Snp 68218792Snpfail: 69218792Snp *str = NULL; 70218792Snp errno = ENOMEM; 71218792Snp va_end(ap2); 72222513Snp return (-1); 73222513Snp} 74228561Snp#endif 75228561Snp 76331719Snp#ifndef HAVE_ASPRINTF 77218792Snpint asprintf(char **str, const char *fmt, ...) 78218792Snp{ 79218792Snp va_list ap; 80256791Snp int ret; 81256791Snp 82256791Snp *str = NULL; 83256791Snp va_start(ap, fmt); 84256791Snp ret = vasprintf(str, fmt, ap); 85256791Snp va_end(ap); 86256791Snp 87256791Snp return ret; 88256791Snp} 89256791Snp#endif 90331719Snp