]>
Commit | Line | Data |
---|---|---|
7ebf4412 | 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 | ||
2e437378 | 24 | #include <errno.h> |
25 | #include <stdarg.h> | |
26 | #include <stdlib.h> | |
27 | ||
7ebf4412 | 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 | ||
42 | int vasprintf(char **str, const char *fmt, va_list ap) | |
43 | { | |
44 | int ret = -1; | |
45 | va_list ap2; | |
46 | char *string, *newstr; | |
47 | size_t len; | |
48 | ||
49 | VA_COPY(ap2, ap); | |
50 | if ((string = malloc(INIT_SZ)) == NULL) | |
51 | goto fail; | |
52 | ||
53 | ret = vsnprintf(string, INIT_SZ, fmt, ap2); | |
54 | if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ | |
55 | *str = string; | |
56 | } else if (ret == INT_MAX) { /* shouldn't happen */ | |
57 | goto fail; | |
58 | } else { /* bigger than initial, realloc allowing for nul */ | |
59 | len = (size_t)ret + 1; | |
60 | if ((newstr = realloc(string, len)) == NULL) { | |
61 | free(string); | |
62 | goto fail; | |
63 | } else { | |
64 | va_end(ap2); | |
65 | VA_COPY(ap2, ap); | |
66 | ret = vsnprintf(newstr, len, fmt, ap2); | |
67 | if (ret >= 0 && (size_t)ret < len) { | |
68 | *str = newstr; | |
69 | } else { /* failed with realloc'ed string, give up */ | |
70 | free(newstr); | |
71 | goto fail; | |
72 | } | |
73 | } | |
74 | } | |
75 | va_end(ap2); | |
76 | return (ret); | |
77 | ||
78 | fail: | |
79 | *str = NULL; | |
80 | errno = ENOMEM; | |
81 | va_end(ap2); | |
82 | return (-1); | |
83 | } | |
84 | #endif | |
85 | ||
86 | #ifndef HAVE_ASPRINTF | |
87 | int asprintf(char **str, const char *fmt, ...) | |
88 | { | |
89 | va_list ap; | |
90 | int ret; | |
91 | ||
92 | *str = NULL; | |
93 | va_start(ap, fmt); | |
94 | ret = vasprintf(str, fmt, ap); | |
95 | va_end(ap); | |
96 | ||
97 | return ret; | |
98 | } | |
99 | #endif |