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