1*2d40c451Schristos /*
2*2d40c451Schristos * Copyright (c) 2004 Darren Tucker.
3*2d40c451Schristos *
4*2d40c451Schristos * Based originally on asprintf.c from OpenBSD:
5*2d40c451Schristos * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
6*2d40c451Schristos *
7*2d40c451Schristos * Permission to use, copy, modify, and distribute this software for any
8*2d40c451Schristos * purpose with or without fee is hereby granted, provided that the above
9*2d40c451Schristos * copyright notice and this permission notice appear in all copies.
10*2d40c451Schristos *
11*2d40c451Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12*2d40c451Schristos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13*2d40c451Schristos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14*2d40c451Schristos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15*2d40c451Schristos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*2d40c451Schristos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17*2d40c451Schristos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*2d40c451Schristos */
19*2d40c451Schristos
20*2d40c451Schristos #include "openbsd-compat.h"
21*2d40c451Schristos
22*2d40c451Schristos #ifndef HAVE_ASPRINTF
23*2d40c451Schristos
24*2d40c451Schristos #include <errno.h>
25*2d40c451Schristos #include <limits.h> /* for INT_MAX */
26*2d40c451Schristos #include <stdarg.h>
27*2d40c451Schristos #include <stdio.h> /* for vsnprintf */
28*2d40c451Schristos #include <stdlib.h>
29*2d40c451Schristos
30*2d40c451Schristos #define VA_COPY(dest, src) va_copy(dest, src)
31*2d40c451Schristos
32*2d40c451Schristos #define INIT_SZ 128
33*2d40c451Schristos
34*2d40c451Schristos int
vasprintf(char ** str,const char * fmt,va_list ap)35*2d40c451Schristos vasprintf(char **str, const char *fmt, va_list ap)
36*2d40c451Schristos {
37*2d40c451Schristos int ret;
38*2d40c451Schristos va_list ap2;
39*2d40c451Schristos char *string, *newstr;
40*2d40c451Schristos size_t len;
41*2d40c451Schristos
42*2d40c451Schristos if ((string = malloc(INIT_SZ)) == NULL)
43*2d40c451Schristos goto fail;
44*2d40c451Schristos
45*2d40c451Schristos VA_COPY(ap2, ap);
46*2d40c451Schristos ret = vsnprintf(string, INIT_SZ, fmt, ap2);
47*2d40c451Schristos va_end(ap2);
48*2d40c451Schristos if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */
49*2d40c451Schristos *str = string;
50*2d40c451Schristos } else if (ret == INT_MAX || ret < 0) { /* Bad length */
51*2d40c451Schristos free(string);
52*2d40c451Schristos goto fail;
53*2d40c451Schristos } else { /* bigger than initial, realloc allowing for nul */
54*2d40c451Schristos len = (size_t)ret + 1;
55*2d40c451Schristos if ((newstr = realloc(string, len)) == NULL) {
56*2d40c451Schristos free(string);
57*2d40c451Schristos goto fail;
58*2d40c451Schristos }
59*2d40c451Schristos VA_COPY(ap2, ap);
60*2d40c451Schristos ret = vsnprintf(newstr, len, fmt, ap2);
61*2d40c451Schristos va_end(ap2);
62*2d40c451Schristos if (ret < 0 || (size_t)ret >= len) { /* failed with realloc'ed string */
63*2d40c451Schristos free(newstr);
64*2d40c451Schristos goto fail;
65*2d40c451Schristos }
66*2d40c451Schristos *str = newstr;
67*2d40c451Schristos }
68*2d40c451Schristos return (ret);
69*2d40c451Schristos
70*2d40c451Schristos fail:
71*2d40c451Schristos *str = NULL;
72*2d40c451Schristos errno = ENOMEM;
73*2d40c451Schristos return (-1);
74*2d40c451Schristos }
75*2d40c451Schristos
asprintf(char ** str,const char * fmt,...)76*2d40c451Schristos int asprintf(char **str, const char *fmt, ...)
77*2d40c451Schristos {
78*2d40c451Schristos va_list ap;
79*2d40c451Schristos int ret;
80*2d40c451Schristos
81*2d40c451Schristos *str = NULL;
82*2d40c451Schristos va_start(ap, fmt);
83*2d40c451Schristos ret = vasprintf(str, fmt, ap);
84*2d40c451Schristos va_end(ap);
85*2d40c451Schristos
86*2d40c451Schristos return ret;
87*2d40c451Schristos }
88*2d40c451Schristos #endif
89