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