1*d0983205SRoger A. Faulkner /* 2*d0983205SRoger A. Faulkner * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3*d0983205SRoger A. Faulkner * Use is subject to license terms. 4*d0983205SRoger A. Faulkner */ 5*d0983205SRoger A. Faulkner 6*d0983205SRoger A. Faulkner /* 7*d0983205SRoger A. Faulkner * Copyright (c) 2004 Darren Tucker. 8*d0983205SRoger A. Faulkner * 9*d0983205SRoger A. Faulkner * Based originally on asprintf.c from OpenBSD: 10*d0983205SRoger A. Faulkner * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> 11*d0983205SRoger A. Faulkner * 12*d0983205SRoger A. Faulkner * Permission to use, copy, modify, and distribute this software for any 13*d0983205SRoger A. Faulkner * purpose with or without fee is hereby granted, provided that the above 14*d0983205SRoger A. Faulkner * copyright notice and this permission notice appear in all copies. 15*d0983205SRoger A. Faulkner * 16*d0983205SRoger A. Faulkner * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 17*d0983205SRoger A. Faulkner * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 18*d0983205SRoger A. Faulkner * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 19*d0983205SRoger A. Faulkner * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 20*d0983205SRoger A. Faulkner * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 21*d0983205SRoger A. Faulkner * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 22*d0983205SRoger A. Faulkner * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 23*d0983205SRoger A. Faulkner */ 24*d0983205SRoger A. Faulkner 25*d0983205SRoger A. Faulkner #include <lint.h> 26*d0983205SRoger A. Faulkner #include <stdio.h> 27*d0983205SRoger A. Faulkner #include <stdarg.h> 28*d0983205SRoger A. Faulkner #include <stdlib.h> 29*d0983205SRoger A. Faulkner #include <string.h> 30*d0983205SRoger A. Faulkner #include <limits.h> 31*d0983205SRoger A. Faulkner #include <errno.h> 32*d0983205SRoger A. Faulkner 33*d0983205SRoger A. Faulkner #define INIT_SZ 128 34*d0983205SRoger A. Faulkner 35*d0983205SRoger A. Faulkner /* VARARGS2 */ 36*d0983205SRoger A. Faulkner int 37*d0983205SRoger A. Faulkner vasprintf(char **str, const char *format, va_list ap) 38*d0983205SRoger A. Faulkner { 39*d0983205SRoger A. Faulkner char string[INIT_SZ]; 40*d0983205SRoger A. Faulkner char *newstr; 41*d0983205SRoger A. Faulkner int ret; 42*d0983205SRoger A. Faulkner size_t len; 43*d0983205SRoger A. Faulkner 44*d0983205SRoger A. Faulkner *str = NULL; 45*d0983205SRoger A. Faulkner ret = vsnprintf(string, INIT_SZ, format, ap); 46*d0983205SRoger A. Faulkner if (ret < 0) /* retain the value of errno from vsnprintf() */ 47*d0983205SRoger A. Faulkner return (-1); 48*d0983205SRoger A. Faulkner if (ret < INIT_SZ) { 49*d0983205SRoger A. Faulkner len = ret + 1; 50*d0983205SRoger A. Faulkner if ((newstr = malloc(len)) == NULL) 51*d0983205SRoger A. Faulkner return (-1); /* retain errno from malloc() */ 52*d0983205SRoger A. Faulkner (void) strlcpy(newstr, string, len); 53*d0983205SRoger A. Faulkner *str = newstr; 54*d0983205SRoger A. Faulkner return (ret); 55*d0983205SRoger A. Faulkner } 56*d0983205SRoger A. Faulkner /* 57*d0983205SRoger A. Faulkner * We will perform this loop more than once only if some other 58*d0983205SRoger A. Faulkner * thread modifies one of the vasprintf() arguments after our 59*d0983205SRoger A. Faulkner * previous call to vsnprintf(). 60*d0983205SRoger A. Faulkner */ 61*d0983205SRoger A. Faulkner for (;;) { 62*d0983205SRoger A. Faulkner if (ret == INT_MAX) { /* Bad length */ 63*d0983205SRoger A. Faulkner errno = ENOMEM; 64*d0983205SRoger A. Faulkner return (-1); 65*d0983205SRoger A. Faulkner } 66*d0983205SRoger A. Faulkner len = ret + 1; 67*d0983205SRoger A. Faulkner if ((newstr = malloc(len)) == NULL) 68*d0983205SRoger A. Faulkner return (-1); /* retain errno from malloc() */ 69*d0983205SRoger A. Faulkner ret = vsnprintf(newstr, len, format, ap); 70*d0983205SRoger A. Faulkner if (ret < 0) { /* retain errno from vsnprintf() */ 71*d0983205SRoger A. Faulkner free(newstr); 72*d0983205SRoger A. Faulkner return (-1); 73*d0983205SRoger A. Faulkner } 74*d0983205SRoger A. Faulkner if (ret < len) { 75*d0983205SRoger A. Faulkner *str = newstr; 76*d0983205SRoger A. Faulkner return (ret); 77*d0983205SRoger A. Faulkner } 78*d0983205SRoger A. Faulkner free(newstr); 79*d0983205SRoger A. Faulkner } 80*d0983205SRoger A. Faulkner } 81*d0983205SRoger A. Faulkner 82*d0983205SRoger A. Faulkner int 83*d0983205SRoger A. Faulkner asprintf(char **str, const char *format, ...) 84*d0983205SRoger A. Faulkner { 85*d0983205SRoger A. Faulkner va_list ap; 86*d0983205SRoger A. Faulkner int ret; 87*d0983205SRoger A. Faulkner 88*d0983205SRoger A. Faulkner *str = NULL; 89*d0983205SRoger A. Faulkner va_start(ap, format); 90*d0983205SRoger A. Faulkner ret = vasprintf(str, format, ap); 91*d0983205SRoger A. Faulkner va_end(ap); 92*d0983205SRoger A. Faulkner 93*d0983205SRoger A. Faulkner return (ret); 94*d0983205SRoger A. Faulkner } 95