xref: /freebsd/crypto/krb5/src/util/support/printf.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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