Check dgram_sctp_write() return value.
[openssl.git] / crypto / bio / b_print.c
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 "internal/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
128 static void fmtstr(char **, char **, size_t *, size_t *,
129                    const char *, int, int, int);
130 static void fmtint(char **, char **, size_t *, size_t *,
131                    LLONG, int, int, int, int);
132 static void fmtfp(char **, char **, size_t *, size_t *,
133                   LDOUBLE, int, int, int);
134 static void doapr_outch(char **, char **, size_t *, size_t *, int);
135 static 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
168 static 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
426 static void
427 fmtstr(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
460 static void
461 fmtint(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
553 static LDOUBLE abs_val(LDOUBLE value)
554 {
555     LDOUBLE result = value;
556     if (value < 0)
557         result = -value;
558     return result;
559 }
560
561 static 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
571 static 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
581 static void
582 fmtfp(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
700 static void
701 doapr_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
744 int 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
757 int 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  */
788 int 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
801 int 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 }