1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /* util/support/printf.c */
3*7f2fe78bSCy Schubert /*
4*7f2fe78bSCy Schubert * Copyright 2003, 2004, 2005, 2007, 2008 Massachusetts Institute of
5*7f2fe78bSCy Schubert * Technology. All Rights Reserved.
6*7f2fe78bSCy Schubert *
7*7f2fe78bSCy Schubert * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert * permission. Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert * this software for any purpose. It is provided "as is" without express
24*7f2fe78bSCy Schubert * or implied warranty.
25*7f2fe78bSCy Schubert */
26*7f2fe78bSCy Schubert
27*7f2fe78bSCy Schubert /* Provide {,v}asprintf for platforms that don't have them. */
28*7f2fe78bSCy Schubert
29*7f2fe78bSCy Schubert #include "k5-platform.h"
30*7f2fe78bSCy Schubert
31*7f2fe78bSCy Schubert /* On error: BSD: Set *ret to NULL. GNU: *ret is undefined.
32*7f2fe78bSCy Schubert
33*7f2fe78bSCy Schubert Since we want to be able to use the GNU version directly, we need
34*7f2fe78bSCy Schubert provide only the weaker guarantee in this version. */
35*7f2fe78bSCy Schubert int
krb5int_vasprintf(char ** ret,const char * format,va_list ap)36*7f2fe78bSCy Schubert krb5int_vasprintf(char **ret, const char *format, va_list ap)
37*7f2fe78bSCy Schubert {
38*7f2fe78bSCy Schubert va_list ap2;
39*7f2fe78bSCy Schubert char *str = NULL, *nstr;
40*7f2fe78bSCy Schubert size_t len = 80;
41*7f2fe78bSCy Schubert int len2;
42*7f2fe78bSCy Schubert
43*7f2fe78bSCy Schubert while (1) {
44*7f2fe78bSCy Schubert if (len >= INT_MAX || len == 0)
45*7f2fe78bSCy Schubert goto fail;
46*7f2fe78bSCy Schubert nstr = realloc(str, len);
47*7f2fe78bSCy Schubert if (nstr == NULL)
48*7f2fe78bSCy Schubert goto fail;
49*7f2fe78bSCy Schubert str = nstr;
50*7f2fe78bSCy Schubert va_copy(ap2, ap);
51*7f2fe78bSCy Schubert len2 = vsnprintf(str, len, format, ap2);
52*7f2fe78bSCy Schubert va_end(ap2);
53*7f2fe78bSCy Schubert /* ISO C vsnprintf returns the needed length. Some old
54*7f2fe78bSCy Schubert vsnprintf implementations return -1 on truncation. */
55*7f2fe78bSCy Schubert if (len2 < 0) {
56*7f2fe78bSCy Schubert /* Don't know how much space we need, just that we didn't
57*7f2fe78bSCy Schubert supply enough; get a bigger buffer and try again. */
58*7f2fe78bSCy Schubert if (len <= SIZE_MAX/2)
59*7f2fe78bSCy Schubert len *= 2;
60*7f2fe78bSCy Schubert else if (len < SIZE_MAX)
61*7f2fe78bSCy Schubert len = SIZE_MAX;
62*7f2fe78bSCy Schubert else
63*7f2fe78bSCy Schubert goto fail;
64*7f2fe78bSCy Schubert } else if ((unsigned int) len2 >= SIZE_MAX) {
65*7f2fe78bSCy Schubert /* Need more space than we can request. */
66*7f2fe78bSCy Schubert goto fail;
67*7f2fe78bSCy Schubert } else if ((size_t) len2 >= len) {
68*7f2fe78bSCy Schubert /* Need more space, but we know how much. */
69*7f2fe78bSCy Schubert len = (size_t) len2 + 1;
70*7f2fe78bSCy Schubert } else {
71*7f2fe78bSCy Schubert /* Success! */
72*7f2fe78bSCy Schubert break;
73*7f2fe78bSCy Schubert }
74*7f2fe78bSCy Schubert }
75*7f2fe78bSCy Schubert /* We might've allocated more than we need, if we're still using
76*7f2fe78bSCy Schubert the initial guess, or we got here by doubling. */
77*7f2fe78bSCy Schubert if ((size_t) len2 < len - 1) {
78*7f2fe78bSCy Schubert nstr = realloc(str, (size_t) len2 + 1);
79*7f2fe78bSCy Schubert if (nstr)
80*7f2fe78bSCy Schubert str = nstr;
81*7f2fe78bSCy Schubert }
82*7f2fe78bSCy Schubert *ret = str;
83*7f2fe78bSCy Schubert return len2;
84*7f2fe78bSCy Schubert
85*7f2fe78bSCy Schubert fail:
86*7f2fe78bSCy Schubert free(str);
87*7f2fe78bSCy Schubert return -1;
88*7f2fe78bSCy Schubert }
89*7f2fe78bSCy Schubert
90*7f2fe78bSCy Schubert int
krb5int_asprintf(char ** ret,const char * format,...)91*7f2fe78bSCy Schubert krb5int_asprintf(char **ret, const char *format, ...)
92*7f2fe78bSCy Schubert {
93*7f2fe78bSCy Schubert va_list ap;
94*7f2fe78bSCy Schubert int n;
95*7f2fe78bSCy Schubert
96*7f2fe78bSCy Schubert va_start(ap, format);
97*7f2fe78bSCy Schubert n = krb5int_vasprintf(ret, format, ap);
98*7f2fe78bSCy Schubert va_end(ap);
99*7f2fe78bSCy Schubert return n;
100*7f2fe78bSCy Schubert }
101