b_print.c revision 284283
1/* crypto/bio/b_print.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59/* disable assert() unless BIO_DEBUG has been defined */
60#ifndef BIO_DEBUG
61# ifndef NDEBUG
62#  define NDEBUG
63# endif
64#endif
65
66/*
67 * Stolen from tjh's ssl/ssl_trc.c stuff.
68 */
69
70#include <stdio.h>
71#include <string.h>
72#include <ctype.h>
73#include <assert.h>
74#include <limits.h>
75#include "cryptlib.h"
76#ifndef NO_SYS_TYPES_H
77# include <sys/types.h>
78#endif
79#include <openssl/bn.h>         /* To get BN_LLONG properly defined */
80#include <openssl/bio.h>
81
82#if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT)
83# ifndef HAVE_LONG_LONG
84#  define HAVE_LONG_LONG 1
85# endif
86#endif
87
88/***************************************************************************/
89
90/*
91 * Copyright Patrick Powell 1995
92 * This code is based on code written by Patrick Powell <papowell@astart.com>
93 * It may be used for any purpose as long as this notice remains intact
94 * on all source code distributions.
95 */
96
97/*-
98 * This code contains numerious changes and enhancements which were
99 * made by lots of contributors over the last years to Patrick Powell's
100 * original code:
101 *
102 * o Patrick Powell <papowell@astart.com>      (1995)
103 * o Brandon Long <blong@fiction.net>          (1996, for Mutt)
104 * o Thomas Roessler <roessler@guug.de>        (1998, for Mutt)
105 * o Michael Elkins <me@cs.hmc.edu>            (1998, for Mutt)
106 * o Andrew Tridgell <tridge@samba.org>        (1998, for Samba)
107 * o Luke Mewburn <lukem@netbsd.org>           (1999, for LukemFTP)
108 * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
109 * o ...                                       (for OpenSSL)
110 */
111
112#ifdef HAVE_LONG_DOUBLE
113# define LDOUBLE long double
114#else
115# define LDOUBLE double
116#endif
117
118#ifdef HAVE_LONG_LONG
119# if defined(_WIN32) && !defined(__GNUC__)
120#  define LLONG __int64
121# else
122#  define LLONG long long
123# endif
124#else
125# define LLONG long
126#endif
127
128static void fmtstr(char **, char **, size_t *, size_t *,
129                   const char *, int, int, int);
130static void fmtint(char **, char **, size_t *, size_t *,
131                   LLONG, int, int, int, int);
132static void fmtfp(char **, char **, size_t *, size_t *,
133                  LDOUBLE, int, int, int);
134static void doapr_outch(char **, char **, size_t *, size_t *, int);
135static void _dopr(char **sbuffer, char **buffer,
136                  size_t *maxlen, size_t *retlen, int *truncated,
137                  const char *format, va_list args);
138
139/* format read states */
140#define DP_S_DEFAULT    0
141#define DP_S_FLAGS      1
142#define DP_S_MIN        2
143#define DP_S_DOT        3
144#define DP_S_MAX        4
145#define DP_S_MOD        5
146#define DP_S_CONV       6
147#define DP_S_DONE       7
148
149/* format flags - Bits */
150#define DP_F_MINUS      (1 << 0)
151#define DP_F_PLUS       (1 << 1)
152#define DP_F_SPACE      (1 << 2)
153#define DP_F_NUM        (1 << 3)
154#define DP_F_ZERO       (1 << 4)
155#define DP_F_UP         (1 << 5)
156#define DP_F_UNSIGNED   (1 << 6)
157
158/* conversion flags */
159#define DP_C_SHORT      1
160#define DP_C_LONG       2
161#define DP_C_LDOUBLE    3
162#define DP_C_LLONG      4
163
164/* some handy macros */
165#define char_to_int(p) (p - '0')
166#define OSSL_MAX(p,q) ((p >= q) ? p : q)
167
168static void
169_dopr(char **sbuffer,
170      char **buffer,
171      size_t *maxlen,
172      size_t *retlen, int *truncated, const char *format, va_list args)
173{
174    char ch;
175    LLONG value;
176    LDOUBLE fvalue;
177    char *strvalue;
178    int min;
179    int max;
180    int state;
181    int flags;
182    int cflags;
183    size_t currlen;
184
185    state = DP_S_DEFAULT;
186    flags = currlen = cflags = min = 0;
187    max = -1;
188    ch = *format++;
189
190    while (state != DP_S_DONE) {
191        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
192            state = DP_S_DONE;
193
194        switch (state) {
195        case DP_S_DEFAULT:
196            if (ch == '%')
197                state = DP_S_FLAGS;
198            else
199                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
200            ch = *format++;
201            break;
202        case DP_S_FLAGS:
203            switch (ch) {
204            case '-':
205                flags |= DP_F_MINUS;
206                ch = *format++;
207                break;
208            case '+':
209                flags |= DP_F_PLUS;
210                ch = *format++;
211                break;
212            case ' ':
213                flags |= DP_F_SPACE;
214                ch = *format++;
215                break;
216            case '#':
217                flags |= DP_F_NUM;
218                ch = *format++;
219                break;
220            case '0':
221                flags |= DP_F_ZERO;
222                ch = *format++;
223                break;
224            default:
225                state = DP_S_MIN;
226                break;
227            }
228            break;
229        case DP_S_MIN:
230            if (isdigit((unsigned char)ch)) {
231                min = 10 * min + char_to_int(ch);
232                ch = *format++;
233            } else if (ch == '*') {
234                min = va_arg(args, int);
235                ch = *format++;
236                state = DP_S_DOT;
237            } else
238                state = DP_S_DOT;
239            break;
240        case DP_S_DOT:
241            if (ch == '.') {
242                state = DP_S_MAX;
243                ch = *format++;
244            } else
245                state = DP_S_MOD;
246            break;
247        case DP_S_MAX:
248            if (isdigit((unsigned char)ch)) {
249                if (max < 0)
250                    max = 0;
251                max = 10 * max + char_to_int(ch);
252                ch = *format++;
253            } else if (ch == '*') {
254                max = va_arg(args, int);
255                ch = *format++;
256                state = DP_S_MOD;
257            } else
258                state = DP_S_MOD;
259            break;
260        case DP_S_MOD:
261            switch (ch) {
262            case 'h':
263                cflags = DP_C_SHORT;
264                ch = *format++;
265                break;
266            case 'l':
267                if (*format == 'l') {
268                    cflags = DP_C_LLONG;
269                    format++;
270                } else
271                    cflags = DP_C_LONG;
272                ch = *format++;
273                break;
274            case 'q':
275                cflags = DP_C_LLONG;
276                ch = *format++;
277                break;
278            case 'L':
279                cflags = DP_C_LDOUBLE;
280                ch = *format++;
281                break;
282            default:
283                break;
284            }
285            state = DP_S_CONV;
286            break;
287        case DP_S_CONV:
288            switch (ch) {
289            case 'd':
290            case 'i':
291                switch (cflags) {
292                case DP_C_SHORT:
293                    value = (short int)va_arg(args, int);
294                    break;
295                case DP_C_LONG:
296                    value = va_arg(args, long int);
297                    break;
298                case DP_C_LLONG:
299                    value = va_arg(args, LLONG);
300                    break;
301                default:
302                    value = va_arg(args, int);
303                    break;
304                }
305                fmtint(sbuffer, buffer, &currlen, maxlen,
306                       value, 10, min, max, flags);
307                break;
308            case 'X':
309                flags |= DP_F_UP;
310                /* FALLTHROUGH */
311            case 'x':
312            case 'o':
313            case 'u':
314                flags |= DP_F_UNSIGNED;
315                switch (cflags) {
316                case DP_C_SHORT:
317                    value = (unsigned short int)va_arg(args, unsigned int);
318                    break;
319                case DP_C_LONG:
320                    value = (LLONG) va_arg(args, unsigned long int);
321                    break;
322                case DP_C_LLONG:
323                    value = va_arg(args, unsigned LLONG);
324                    break;
325                default:
326                    value = (LLONG) va_arg(args, unsigned int);
327                    break;
328                }
329                fmtint(sbuffer, buffer, &currlen, maxlen, value,
330                       ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
331                       min, max, flags);
332                break;
333            case 'f':
334                if (cflags == DP_C_LDOUBLE)
335                    fvalue = va_arg(args, LDOUBLE);
336                else
337                    fvalue = va_arg(args, double);
338                fmtfp(sbuffer, buffer, &currlen, maxlen,
339                      fvalue, min, max, flags);
340                break;
341            case 'E':
342                flags |= DP_F_UP;
343            case 'e':
344                if (cflags == DP_C_LDOUBLE)
345                    fvalue = va_arg(args, LDOUBLE);
346                else
347                    fvalue = va_arg(args, double);
348                break;
349            case 'G':
350                flags |= DP_F_UP;
351            case 'g':
352                if (cflags == DP_C_LDOUBLE)
353                    fvalue = va_arg(args, LDOUBLE);
354                else
355                    fvalue = va_arg(args, double);
356                break;
357            case 'c':
358                doapr_outch(sbuffer, buffer, &currlen, maxlen,
359                            va_arg(args, int));
360                break;
361            case 's':
362                strvalue = va_arg(args, char *);
363                if (max < 0) {
364                    if (buffer)
365                        max = INT_MAX;
366                    else
367                        max = *maxlen;
368                }
369                fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
370                       flags, min, max);
371                break;
372            case 'p':
373                value = (long)va_arg(args, void *);
374                fmtint(sbuffer, buffer, &currlen, maxlen,
375                       value, 16, min, max, flags | DP_F_NUM);
376                break;
377            case 'n':          /* XXX */
378                if (cflags == DP_C_SHORT) {
379                    short int *num;
380                    num = va_arg(args, short int *);
381                    *num = currlen;
382                } else if (cflags == DP_C_LONG) { /* XXX */
383                    long int *num;
384                    num = va_arg(args, long int *);
385                    *num = (long int)currlen;
386                } else if (cflags == DP_C_LLONG) { /* XXX */
387                    LLONG *num;
388                    num = va_arg(args, LLONG *);
389                    *num = (LLONG) currlen;
390                } else {
391                    int *num;
392                    num = va_arg(args, int *);
393                    *num = currlen;
394                }
395                break;
396            case '%':
397                doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
398                break;
399            case 'w':
400                /* not supported yet, treat as next char */
401                ch = *format++;
402                break;
403            default:
404                /* unknown, skip */
405                break;
406            }
407            ch = *format++;
408            state = DP_S_DEFAULT;
409            flags = cflags = min = 0;
410            max = -1;
411            break;
412        case DP_S_DONE:
413            break;
414        default:
415            break;
416        }
417    }
418    *truncated = (currlen > *maxlen - 1);
419    if (*truncated)
420        currlen = *maxlen - 1;
421    doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
422    *retlen = currlen - 1;
423    return;
424}
425
426static void
427fmtstr(char **sbuffer,
428       char **buffer,
429       size_t *currlen,
430       size_t *maxlen, const char *value, int flags, int min, int max)
431{
432    int padlen, strln;
433    int cnt = 0;
434
435    if (value == 0)
436        value = "<NULL>";
437    for (strln = 0; value[strln]; ++strln) ;
438    padlen = min - strln;
439    if (padlen < 0)
440        padlen = 0;
441    if (flags & DP_F_MINUS)
442        padlen = -padlen;
443
444    while ((padlen > 0) && (cnt < max)) {
445        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
446        --padlen;
447        ++cnt;
448    }
449    while (*value && (cnt < max)) {
450        doapr_outch(sbuffer, buffer, currlen, maxlen, *value++);
451        ++cnt;
452    }
453    while ((padlen < 0) && (cnt < max)) {
454        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
455        ++padlen;
456        ++cnt;
457    }
458}
459
460static void
461fmtint(char **sbuffer,
462       char **buffer,
463       size_t *currlen,
464       size_t *maxlen, LLONG value, int base, int min, int max, int flags)
465{
466    int signvalue = 0;
467    const char *prefix = "";
468    unsigned LLONG uvalue;
469    char convert[DECIMAL_SIZE(value) + 3];
470    int place = 0;
471    int spadlen = 0;
472    int zpadlen = 0;
473    int caps = 0;
474
475    if (max < 0)
476        max = 0;
477    uvalue = value;
478    if (!(flags & DP_F_UNSIGNED)) {
479        if (value < 0) {
480            signvalue = '-';
481            uvalue = -value;
482        } else if (flags & DP_F_PLUS)
483            signvalue = '+';
484        else if (flags & DP_F_SPACE)
485            signvalue = ' ';
486    }
487    if (flags & DP_F_NUM) {
488        if (base == 8)
489            prefix = "0";
490        if (base == 16)
491            prefix = "0x";
492    }
493    if (flags & DP_F_UP)
494        caps = 1;
495    do {
496        convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
497            [uvalue % (unsigned)base];
498        uvalue = (uvalue / (unsigned)base);
499    } while (uvalue && (place < (int)sizeof(convert)));
500    if (place == sizeof(convert))
501        place--;
502    convert[place] = 0;
503
504    zpadlen = max - place;
505    spadlen =
506        min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
507    if (zpadlen < 0)
508        zpadlen = 0;
509    if (spadlen < 0)
510        spadlen = 0;
511    if (flags & DP_F_ZERO) {
512        zpadlen = OSSL_MAX(zpadlen, spadlen);
513        spadlen = 0;
514    }
515    if (flags & DP_F_MINUS)
516        spadlen = -spadlen;
517
518    /* spaces */
519    while (spadlen > 0) {
520        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
521        --spadlen;
522    }
523
524    /* sign */
525    if (signvalue)
526        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
527
528    /* prefix */
529    while (*prefix) {
530        doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix);
531        prefix++;
532    }
533
534    /* zeros */
535    if (zpadlen > 0) {
536        while (zpadlen > 0) {
537            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
538            --zpadlen;
539        }
540    }
541    /* digits */
542    while (place > 0)
543        doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
544
545    /* left justified spaces */
546    while (spadlen < 0) {
547        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
548        ++spadlen;
549    }
550    return;
551}
552
553static LDOUBLE abs_val(LDOUBLE value)
554{
555    LDOUBLE result = value;
556    if (value < 0)
557        result = -value;
558    return result;
559}
560
561static LDOUBLE pow_10(int in_exp)
562{
563    LDOUBLE result = 1;
564    while (in_exp) {
565        result *= 10;
566        in_exp--;
567    }
568    return result;
569}
570
571static long roundv(LDOUBLE value)
572{
573    long intpart;
574    intpart = (long)value;
575    value = value - intpart;
576    if (value >= 0.5)
577        intpart++;
578    return intpart;
579}
580
581static void
582fmtfp(char **sbuffer,
583      char **buffer,
584      size_t *currlen,
585      size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags)
586{
587    int signvalue = 0;
588    LDOUBLE ufvalue;
589    char iconvert[20];
590    char fconvert[20];
591    int iplace = 0;
592    int fplace = 0;
593    int padlen = 0;
594    int zpadlen = 0;
595    long intpart;
596    long fracpart;
597    long max10;
598
599    if (max < 0)
600        max = 6;
601    ufvalue = abs_val(fvalue);
602    if (fvalue < 0)
603        signvalue = '-';
604    else if (flags & DP_F_PLUS)
605        signvalue = '+';
606    else if (flags & DP_F_SPACE)
607        signvalue = ' ';
608
609    intpart = (long)ufvalue;
610
611    /*
612     * sorry, we only support 9 digits past the decimal because of our
613     * conversion method
614     */
615    if (max > 9)
616        max = 9;
617
618    /*
619     * we "cheat" by converting the fractional part to integer by multiplying
620     * by a factor of 10
621     */
622    max10 = roundv(pow_10(max));
623    fracpart = roundv(pow_10(max) * (ufvalue - intpart));
624
625    if (fracpart >= max10) {
626        intpart++;
627        fracpart -= max10;
628    }
629
630    /* convert integer part */
631    do {
632        iconvert[iplace++] = "0123456789"[intpart % 10];
633        intpart = (intpart / 10);
634    } while (intpart && (iplace < (int)sizeof(iconvert)));
635    if (iplace == sizeof iconvert)
636        iplace--;
637    iconvert[iplace] = 0;
638
639    /* convert fractional part */
640    do {
641        fconvert[fplace++] = "0123456789"[fracpart % 10];
642        fracpart = (fracpart / 10);
643    } while (fplace < max);
644    if (fplace == sizeof fconvert)
645        fplace--;
646    fconvert[fplace] = 0;
647
648    /* -1 for decimal point, another -1 if we are printing a sign */
649    padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
650    zpadlen = max - fplace;
651    if (zpadlen < 0)
652        zpadlen = 0;
653    if (padlen < 0)
654        padlen = 0;
655    if (flags & DP_F_MINUS)
656        padlen = -padlen;
657
658    if ((flags & DP_F_ZERO) && (padlen > 0)) {
659        if (signvalue) {
660            doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
661            --padlen;
662            signvalue = 0;
663        }
664        while (padlen > 0) {
665            doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
666            --padlen;
667        }
668    }
669    while (padlen > 0) {
670        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
671        --padlen;
672    }
673    if (signvalue)
674        doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
675
676    while (iplace > 0)
677        doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
678
679    /*
680     * Decimal point. This should probably use locale to find the correct
681     * char to print out.
682     */
683    if (max > 0 || (flags & DP_F_NUM)) {
684        doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
685
686        while (fplace > 0)
687            doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
688    }
689    while (zpadlen > 0) {
690        doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
691        --zpadlen;
692    }
693
694    while (padlen < 0) {
695        doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
696        ++padlen;
697    }
698}
699
700static void
701doapr_outch(char **sbuffer,
702            char **buffer, size_t *currlen, size_t *maxlen, int c)
703{
704    /* If we haven't at least one buffer, someone has doe a big booboo */
705    assert(*sbuffer != NULL || buffer != NULL);
706
707    /* |currlen| must always be <= |*maxlen| */
708    assert(*currlen <= *maxlen);
709
710    if (buffer && *currlen == *maxlen) {
711        *maxlen += 1024;
712        if (*buffer == NULL) {
713            *buffer = OPENSSL_malloc(*maxlen);
714            if (!*buffer) {
715                /* Panic! Can't really do anything sensible. Just return */
716                return;
717            }
718            if (*currlen > 0) {
719                assert(*sbuffer != NULL);
720                memcpy(*buffer, *sbuffer, *currlen);
721            }
722            *sbuffer = NULL;
723        } else {
724            *buffer = OPENSSL_realloc(*buffer, *maxlen);
725            if (!*buffer) {
726                /* Panic! Can't really do anything sensible. Just return */
727                return;
728            }
729        }
730    }
731
732    if (*currlen < *maxlen) {
733        if (*sbuffer)
734            (*sbuffer)[(*currlen)++] = (char)c;
735        else
736            (*buffer)[(*currlen)++] = (char)c;
737    }
738
739    return;
740}
741
742/***************************************************************************/
743
744int BIO_printf(BIO *bio, const char *format, ...)
745{
746    va_list args;
747    int ret;
748
749    va_start(args, format);
750
751    ret = BIO_vprintf(bio, format, args);
752
753    va_end(args);
754    return (ret);
755}
756
757int BIO_vprintf(BIO *bio, const char *format, va_list args)
758{
759    int ret;
760    size_t retlen;
761    char hugebuf[1024 * 2];     /* Was previously 10k, which is unreasonable
762                                 * in small-stack environments, like threads
763                                 * or DOS programs. */
764    char *hugebufp = hugebuf;
765    size_t hugebufsize = sizeof(hugebuf);
766    char *dynbuf = NULL;
767    int ignored;
768
769    dynbuf = NULL;
770    CRYPTO_push_info("doapr()");
771    _dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, args);
772    if (dynbuf) {
773        ret = BIO_write(bio, dynbuf, (int)retlen);
774        OPENSSL_free(dynbuf);
775    } else {
776        ret = BIO_write(bio, hugebuf, (int)retlen);
777    }
778    CRYPTO_pop_info();
779    return (ret);
780}
781
782/*
783 * As snprintf is not available everywhere, we provide our own
784 * implementation. This function has nothing to do with BIOs, but it's
785 * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
786 * function should be renamed, but to what?)
787 */
788int BIO_snprintf(char *buf, size_t n, const char *format, ...)
789{
790    va_list args;
791    int ret;
792
793    va_start(args, format);
794
795    ret = BIO_vsnprintf(buf, n, format, args);
796
797    va_end(args);
798    return (ret);
799}
800
801int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
802{
803    size_t retlen;
804    int truncated;
805
806    _dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
807
808    if (truncated)
809        /*
810         * In case of truncation, return -1 like traditional snprintf.
811         * (Current drafts for ISO/IEC 9899 say snprintf should return the
812         * number of characters that would have been written, had the buffer
813         * been large enough.)
814         */
815        return -1;
816    else
817        return (retlen <= INT_MAX) ? (int)retlen : -1;
818}
819