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 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( 170 char **sbuffer, 171 char **buffer, 172 size_t *maxlen, 173 size_t *retlen, 174 int *truncated, 175 const char *format, 176 va_list args) 177 { 178 char ch; 179 LLONG value; 180 LDOUBLE fvalue; 181 char *strvalue; 182 int min; 183 int max; 184 int state; 185 int flags; 186 int cflags; 187 size_t currlen; 188 189 state = DP_S_DEFAULT; 190 flags = currlen = cflags = min = 0; 191 max = -1; 192 ch = *format++; 193 194 while (state != DP_S_DONE) { 195 if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) 196 state = DP_S_DONE; 197 198 switch (state) { 199 case DP_S_DEFAULT: 200 if (ch == '%') 201 state = DP_S_FLAGS; 202 else 203 doapr_outch(sbuffer,buffer, &currlen, maxlen, ch); 204 ch = *format++; 205 break; 206 case DP_S_FLAGS: 207 switch (ch) { 208 case '-': 209 flags |= DP_F_MINUS; 210 ch = *format++; 211 break; 212 case '+': 213 flags |= DP_F_PLUS; 214 ch = *format++; 215 break; 216 case ' ': 217 flags |= DP_F_SPACE; 218 ch = *format++; 219 break; 220 case '#': 221 flags |= DP_F_NUM; 222 ch = *format++; 223 break; 224 case '0': 225 flags |= DP_F_ZERO; 226 ch = *format++; 227 break; 228 default: 229 state = DP_S_MIN; 230 break; 231 } 232 break; 233 case DP_S_MIN: 234 if (isdigit((unsigned char)ch)) { 235 min = 10 * min + char_to_int(ch); 236 ch = *format++; 237 } else if (ch == '*') { 238 min = va_arg(args, int); 239 ch = *format++; 240 state = DP_S_DOT; 241 } else 242 state = DP_S_DOT; 243 break; 244 case DP_S_DOT: 245 if (ch == '.') { 246 state = DP_S_MAX; 247 ch = *format++; 248 } else 249 state = DP_S_MOD; 250 break; 251 case DP_S_MAX: 252 if (isdigit((unsigned char)ch)) { 253 if (max < 0) 254 max = 0; 255 max = 10 * max + char_to_int(ch); 256 ch = *format++; 257 } else if (ch == '*') { 258 max = va_arg(args, int); 259 ch = *format++; 260 state = DP_S_MOD; 261 } else 262 state = DP_S_MOD; 263 break; 264 case DP_S_MOD: 265 switch (ch) { 266 case 'h': 267 cflags = DP_C_SHORT; 268 ch = *format++; 269 break; 270 case 'l': 271 if (*format == 'l') { 272 cflags = DP_C_LLONG; 273 format++; 274 } else 275 cflags = DP_C_LONG; 276 ch = *format++; 277 break; 278 case 'q': 279 cflags = DP_C_LLONG; 280 ch = *format++; 281 break; 282 case 'L': 283 cflags = DP_C_LDOUBLE; 284 ch = *format++; 285 break; 286 default: 287 break; 288 } 289 state = DP_S_CONV; 290 break; 291 case DP_S_CONV: 292 switch (ch) { 293 case 'd': 294 case 'i': 295 switch (cflags) { 296 case DP_C_SHORT: 297 value = (short int)va_arg(args, int); 298 break; 299 case DP_C_LONG: 300 value = va_arg(args, long int); 301 break; 302 case DP_C_LLONG: 303 value = va_arg(args, LLONG); 304 break; 305 default: 306 value = va_arg(args, int); 307 break; 308 } 309 fmtint(sbuffer, buffer, &currlen, maxlen, 310 value, 10, min, max, flags); 311 break; 312 case 'X': 313 flags |= DP_F_UP; 314 /* FALLTHROUGH */ 315 case 'x': 316 case 'o': 317 case 'u': 318 flags |= DP_F_UNSIGNED; 319 switch (cflags) { 320 case DP_C_SHORT: 321 value = (unsigned short int)va_arg(args, unsigned int); 322 break; 323 case DP_C_LONG: 324 value = (LLONG) va_arg(args, 325 unsigned long int); 326 break; 327 case DP_C_LLONG: 328 value = va_arg(args, unsigned LLONG); 329 break; 330 default: 331 value = (LLONG) va_arg(args, 332 unsigned int); 333 break; 334 } 335 fmtint(sbuffer, buffer, &currlen, maxlen, value, 336 ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), 337 min, max, flags); 338 break; 339 case 'f': 340 if (cflags == DP_C_LDOUBLE) 341 fvalue = va_arg(args, LDOUBLE); 342 else 343 fvalue = va_arg(args, double); 344 fmtfp(sbuffer, buffer, &currlen, maxlen, 345 fvalue, min, max, flags); 346 break; 347 case 'E': 348 flags |= DP_F_UP; 349 case 'e': 350 if (cflags == DP_C_LDOUBLE) 351 fvalue = va_arg(args, LDOUBLE); 352 else 353 fvalue = va_arg(args, double); 354 break; 355 case 'G': 356 flags |= DP_F_UP; 357 case 'g': 358 if (cflags == DP_C_LDOUBLE) 359 fvalue = va_arg(args, LDOUBLE); 360 else 361 fvalue = va_arg(args, double); 362 break; 363 case 'c': 364 doapr_outch(sbuffer, buffer, &currlen, maxlen, 365 va_arg(args, int)); 366 break; 367 case 's': 368 strvalue = va_arg(args, char *); 369 if (max < 0) { 370 if (buffer) 371 max = INT_MAX; 372 else 373 max = *maxlen; 374 } 375 fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, 376 flags, min, max); 377 break; 378 case 'p': 379 value = (long)va_arg(args, void *); 380 fmtint(sbuffer, buffer, &currlen, maxlen, 381 value, 16, min, max, flags|DP_F_NUM); 382 break; 383 case 'n': /* XXX */ 384 if (cflags == DP_C_SHORT) { 385 short int *num; 386 num = va_arg(args, short int *); 387 *num = currlen; 388 } else if (cflags == DP_C_LONG) { /* XXX */ 389 long int *num; 390 num = va_arg(args, long int *); 391 *num = (long int) currlen; 392 } else if (cflags == DP_C_LLONG) { /* XXX */ 393 LLONG *num; 394 num = va_arg(args, LLONG *); 395 *num = (LLONG) currlen; 396 } else { 397 int *num; 398 num = va_arg(args, int *); 399 *num = currlen; 400 } 401 break; 402 case '%': 403 doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); 404 break; 405 case 'w': 406 /* not supported yet, treat as next char */ 407 ch = *format++; 408 break; 409 default: 410 /* unknown, skip */ 411 break; 412 } 413 ch = *format++; 414 state = DP_S_DEFAULT; 415 flags = cflags = min = 0; 416 max = -1; 417 break; 418 case DP_S_DONE: 419 break; 420 default: 421 break; 422 } 423 } 424 *truncated = (currlen > *maxlen - 1); 425 if (*truncated) 426 currlen = *maxlen - 1; 427 doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'); 428 *retlen = currlen - 1; 429 return; 430 } 431 432 static void 433 fmtstr( 434 char **sbuffer, 435 char **buffer, 436 size_t *currlen, 437 size_t *maxlen, 438 const char *value, 439 int flags, 440 int min, 441 int max) 442 { 443 int padlen, strln; 444 int cnt = 0; 445 446 if (value == 0) 447 value = "<NULL>"; 448 for (strln = 0; value[strln]; ++strln) 449 ; 450 padlen = min - strln; 451 if (padlen < 0) 452 padlen = 0; 453 if (flags & DP_F_MINUS) 454 padlen = -padlen; 455 456 while ((padlen > 0) && (cnt < max)) { 457 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 458 --padlen; 459 ++cnt; 460 } 461 while (*value && (cnt < max)) { 462 doapr_outch(sbuffer, buffer, currlen, maxlen, *value++); 463 ++cnt; 464 } 465 while ((padlen < 0) && (cnt < max)) { 466 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 467 ++padlen; 468 ++cnt; 469 } 470 } 471 472 static void 473 fmtint( 474 char **sbuffer, 475 char **buffer, 476 size_t *currlen, 477 size_t *maxlen, 478 LLONG value, 479 int base, 480 int min, 481 int max, 482 int flags) 483 { 484 int signvalue = 0; 485 const char *prefix = ""; 486 unsigned LLONG uvalue; 487 char convert[DECIMAL_SIZE(value)+3]; 488 int place = 0; 489 int spadlen = 0; 490 int zpadlen = 0; 491 int caps = 0; 492 493 if (max < 0) 494 max = 0; 495 uvalue = value; 496 if (!(flags & DP_F_UNSIGNED)) { 497 if (value < 0) { 498 signvalue = '-'; 499 uvalue = -value; 500 } else if (flags & DP_F_PLUS) 501 signvalue = '+'; 502 else if (flags & DP_F_SPACE) 503 signvalue = ' '; 504 } 505 if (flags & DP_F_NUM) { 506 if (base == 8) prefix = "0"; 507 if (base == 16) prefix = "0x"; 508 } 509 if (flags & DP_F_UP) 510 caps = 1; 511 do { 512 convert[place++] = 513 (caps ? "0123456789ABCDEF" : "0123456789abcdef") 514 [uvalue % (unsigned) base]; 515 uvalue = (uvalue / (unsigned) base); 516 } while (uvalue && (place < (int)sizeof(convert))); 517 if (place == sizeof(convert)) 518 place--; 519 convert[place] = 0; 520 521 zpadlen = max - place; 522 spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); 523 if (zpadlen < 0) 524 zpadlen = 0; 525 if (spadlen < 0) 526 spadlen = 0; 527 if (flags & DP_F_ZERO) { 528 zpadlen = OSSL_MAX(zpadlen, spadlen); 529 spadlen = 0; 530 } 531 if (flags & DP_F_MINUS) 532 spadlen = -spadlen; 533 534 /* spaces */ 535 while (spadlen > 0) { 536 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 537 --spadlen; 538 } 539 540 /* sign */ 541 if (signvalue) 542 doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); 543 544 /* prefix */ 545 while (*prefix) { 546 doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix); 547 prefix++; 548 } 549 550 /* zeros */ 551 if (zpadlen > 0) { 552 while (zpadlen > 0) { 553 doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); 554 --zpadlen; 555 } 556 } 557 /* digits */ 558 while (place > 0) 559 doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]); 560 561 /* left justified spaces */ 562 while (spadlen < 0) { 563 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 564 ++spadlen; 565 } 566 return; 567 } 568 569 static LDOUBLE 570 abs_val(LDOUBLE value) 571 { 572 LDOUBLE result = value; 573 if (value < 0) 574 result = -value; 575 return result; 576 } 577 578 static LDOUBLE 579 pow_10(int in_exp) 580 { 581 LDOUBLE result = 1; 582 while (in_exp) { 583 result *= 10; 584 in_exp--; 585 } 586 return result; 587 } 588 589 static long 590 roundv(LDOUBLE value) 591 { 592 long intpart; 593 intpart = (long) value; 594 value = value - intpart; 595 if (value >= 0.5) 596 intpart++; 597 return intpart; 598 } 599 600 static void 601 fmtfp( 602 char **sbuffer, 603 char **buffer, 604 size_t *currlen, 605 size_t *maxlen, 606 LDOUBLE fvalue, 607 int min, 608 int max, 609 int flags) 610 { 611 int signvalue = 0; 612 LDOUBLE ufvalue; 613 char iconvert[20]; 614 char fconvert[20]; 615 int iplace = 0; 616 int fplace = 0; 617 int padlen = 0; 618 int zpadlen = 0; 619 int caps = 0; 620 long intpart; 621 long fracpart; 622 long max10; 623 624 if (max < 0) 625 max = 6; 626 ufvalue = abs_val(fvalue); 627 if (fvalue < 0) 628 signvalue = '-'; 629 else if (flags & DP_F_PLUS) 630 signvalue = '+'; 631 else if (flags & DP_F_SPACE) 632 signvalue = ' '; 633 634 intpart = (long)ufvalue; 635 636 /* sorry, we only support 9 digits past the decimal because of our 637 conversion method */ 638 if (max > 9) 639 max = 9; 640 641 /* we "cheat" by converting the fractional part to integer by 642 multiplying by a factor of 10 */ 643 max10 = roundv(pow_10(max)); 644 fracpart = roundv(pow_10(max) * (ufvalue - intpart)); 645 646 if (fracpart >= max10) { 647 intpart++; 648 fracpart -= max10; 649 } 650 651 /* convert integer part */ 652 do { 653 iconvert[iplace++] = 654 (caps ? "0123456789ABCDEF" 655 : "0123456789abcdef")[intpart % 10]; 656 intpart = (intpart / 10); 657 } while (intpart && (iplace < (int)sizeof(iconvert))); 658 if (iplace == sizeof iconvert) 659 iplace--; 660 iconvert[iplace] = 0; 661 662 /* convert fractional part */ 663 do { 664 fconvert[fplace++] = 665 (caps ? "0123456789ABCDEF" 666 : "0123456789abcdef")[fracpart % 10]; 667 fracpart = (fracpart / 10); 668 } while (fplace < max); 669 if (fplace == sizeof fconvert) 670 fplace--; 671 fconvert[fplace] = 0; 672 673 /* -1 for decimal point, another -1 if we are printing a sign */ 674 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 675 zpadlen = max - fplace; 676 if (zpadlen < 0) 677 zpadlen = 0; 678 if (padlen < 0) 679 padlen = 0; 680 if (flags & DP_F_MINUS) 681 padlen = -padlen; 682 683 if ((flags & DP_F_ZERO) && (padlen > 0)) { 684 if (signvalue) { 685 doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); 686 --padlen; 687 signvalue = 0; 688 } 689 while (padlen > 0) { 690 doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); 691 --padlen; 692 } 693 } 694 while (padlen > 0) { 695 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 696 --padlen; 697 } 698 if (signvalue) 699 doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); 700 701 while (iplace > 0) 702 doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]); 703 704 /* 705 * Decimal point. This should probably use locale to find the correct 706 * char to print out. 707 */ 708 if (max > 0 || (flags & DP_F_NUM)) { 709 doapr_outch(sbuffer, buffer, currlen, maxlen, '.'); 710 711 while (fplace > 0) 712 doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]); 713 } 714 while (zpadlen > 0) { 715 doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); 716 --zpadlen; 717 } 718 719 while (padlen < 0) { 720 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 721 ++padlen; 722 } 723 } 724 725 static void 726 doapr_outch( 727 char **sbuffer, 728 char **buffer, 729 size_t *currlen, 730 size_t *maxlen, 731 int c) 732 { 733 /* If we haven't at least one buffer, someone has doe a big booboo */ 734 assert(*sbuffer != NULL || buffer != NULL); 735 736 if (buffer) { 737 while (*currlen >= *maxlen) { 738 if (*buffer == NULL) { 739 if (*maxlen == 0) 740 *maxlen = 1024; 741 *buffer = OPENSSL_malloc(*maxlen); 742 if (*currlen > 0) { 743 assert(*sbuffer != NULL); 744 memcpy(*buffer, *sbuffer, *currlen); 745 } 746 *sbuffer = NULL; 747 } else { 748 *maxlen += 1024; 749 *buffer = OPENSSL_realloc(*buffer, *maxlen); 750 } 751 } 752 /* What to do if *buffer is NULL? */ 753 assert(*sbuffer != NULL || *buffer != NULL); 754 } 755 756 if (*currlen < *maxlen) { 757 if (*sbuffer) 758 (*sbuffer)[(*currlen)++] = (char)c; 759 else 760 (*buffer)[(*currlen)++] = (char)c; 761 } 762 763 return; 764 } 765 766 /***************************************************************************/ 767 768 int BIO_printf (BIO *bio, const char *format, ...) 769 { 770 va_list args; 771 int ret; 772 773 va_start(args, format); 774 775 ret = BIO_vprintf(bio, format, args); 776 777 va_end(args); 778 return(ret); 779 } 780 781 int BIO_vprintf (BIO *bio, const char *format, va_list args) 782 { 783 int ret; 784 size_t retlen; 785 char hugebuf[1024*2]; /* Was previously 10k, which is unreasonable 786 in small-stack environments, like threads 787 or DOS programs. */ 788 char *hugebufp = hugebuf; 789 size_t hugebufsize = sizeof(hugebuf); 790 char *dynbuf = NULL; 791 int ignored; 792 793 dynbuf = NULL; 794 CRYPTO_push_info("doapr()"); 795 _dopr(&hugebufp, &dynbuf, &hugebufsize, 796 &retlen, &ignored, format, args); 797 if (dynbuf) 798 { 799 ret=BIO_write(bio, dynbuf, (int)retlen); 800 OPENSSL_free(dynbuf); 801 } 802 else 803 { 804 ret=BIO_write(bio, hugebuf, (int)retlen); 805 } 806 CRYPTO_pop_info(); 807 return(ret); 808 } 809 810 /* As snprintf is not available everywhere, we provide our own implementation. 811 * This function has nothing to do with BIOs, but it's closely related 812 * to BIO_printf, and we need *some* name prefix ... 813 * (XXX the function should be renamed, but to what?) */ 814 int BIO_snprintf(char *buf, size_t n, const char *format, ...) 815 { 816 va_list args; 817 int ret; 818 819 va_start(args, format); 820 821 ret = BIO_vsnprintf(buf, n, format, args); 822 823 va_end(args); 824 return(ret); 825 } 826 827 int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 828 { 829 size_t retlen; 830 int truncated; 831 832 _dopr(&buf, NULL, &n, &retlen, &truncated, format, args); 833 834 if (truncated) 835 /* In case of truncation, return -1 like traditional snprintf. 836 * (Current drafts for ISO/IEC 9899 say snprintf should return 837 * the number of characters that would have been written, 838 * had the buffer been large enough.) */ 839 return -1; 840 else 841 return (retlen <= INT_MAX) ? (int)retlen : -1; 842 }