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