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