b_print.c revision 100936
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#ifdef BN_LLONG 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#if HAVE_LONG_DOUBLE 113#define LDOUBLE long double 114#else 115#define LDOUBLE double 116#endif 117 118#if 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( 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); 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 432static void 433fmtstr( 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 472static void 473fmtint( 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 unsigned LLONG uvalue; 486 char convert[20]; 487 int place = 0; 488 int spadlen = 0; 489 int zpadlen = 0; 490 int caps = 0; 491 492 if (max < 0) 493 max = 0; 494 uvalue = value; 495 if (!(flags & DP_F_UNSIGNED)) { 496 if (value < 0) { 497 signvalue = '-'; 498 uvalue = -value; 499 } else if (flags & DP_F_PLUS) 500 signvalue = '+'; 501 else if (flags & DP_F_SPACE) 502 signvalue = ' '; 503 } 504 if (flags & DP_F_UP) 505 caps = 1; 506 do { 507 convert[place++] = 508 (caps ? "0123456789ABCDEF" : "0123456789abcdef") 509 [uvalue % (unsigned) base]; 510 uvalue = (uvalue / (unsigned) base); 511 } while (uvalue && (place < 20)); 512 if (place == 20) 513 place--; 514 convert[place] = 0; 515 516 zpadlen = max - place; 517 spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0); 518 if (zpadlen < 0) 519 zpadlen = 0; 520 if (spadlen < 0) 521 spadlen = 0; 522 if (flags & DP_F_ZERO) { 523 zpadlen = OSSL_MAX(zpadlen, spadlen); 524 spadlen = 0; 525 } 526 if (flags & DP_F_MINUS) 527 spadlen = -spadlen; 528 529 /* spaces */ 530 while (spadlen > 0) { 531 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 532 --spadlen; 533 } 534 535 /* sign */ 536 if (signvalue) 537 doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); 538 539 /* zeros */ 540 if (zpadlen > 0) { 541 while (zpadlen > 0) { 542 doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); 543 --zpadlen; 544 } 545 } 546 /* digits */ 547 while (place > 0) 548 doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]); 549 550 /* left justified spaces */ 551 while (spadlen < 0) { 552 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 553 ++spadlen; 554 } 555 return; 556} 557 558static LDOUBLE 559abs_val(LDOUBLE value) 560{ 561 LDOUBLE result = value; 562 if (value < 0) 563 result = -value; 564 return result; 565} 566 567static LDOUBLE 568pow10(int exp) 569{ 570 LDOUBLE result = 1; 571 while (exp) { 572 result *= 10; 573 exp--; 574 } 575 return result; 576} 577 578static long 579roundv(LDOUBLE value) 580{ 581 long intpart; 582 intpart = (long) value; 583 value = value - intpart; 584 if (value >= 0.5) 585 intpart++; 586 return intpart; 587} 588 589static void 590fmtfp( 591 char **sbuffer, 592 char **buffer, 593 size_t *currlen, 594 size_t *maxlen, 595 LDOUBLE fvalue, 596 int min, 597 int max, 598 int flags) 599{ 600 int signvalue = 0; 601 LDOUBLE ufvalue; 602 char iconvert[20]; 603 char fconvert[20]; 604 int iplace = 0; 605 int fplace = 0; 606 int padlen = 0; 607 int zpadlen = 0; 608 int caps = 0; 609 long intpart; 610 long fracpart; 611 612 if (max < 0) 613 max = 6; 614 ufvalue = abs_val(fvalue); 615 if (fvalue < 0) 616 signvalue = '-'; 617 else if (flags & DP_F_PLUS) 618 signvalue = '+'; 619 else if (flags & DP_F_SPACE) 620 signvalue = ' '; 621 622 intpart = (long)ufvalue; 623 624 /* sorry, we only support 9 digits past the decimal because of our 625 conversion method */ 626 if (max > 9) 627 max = 9; 628 629 /* we "cheat" by converting the fractional part to integer by 630 multiplying by a factor of 10 */ 631 fracpart = roundv((pow10(max)) * (ufvalue - intpart)); 632 633 if (fracpart >= pow10(max)) { 634 intpart++; 635 fracpart -= (long)pow10(max); 636 } 637 638 /* convert integer part */ 639 do { 640 iconvert[iplace++] = 641 (caps ? "0123456789ABCDEF" 642 : "0123456789abcdef")[intpart % 10]; 643 intpart = (intpart / 10); 644 } while (intpart && (iplace < 20)); 645 if (iplace == 20) 646 iplace--; 647 iconvert[iplace] = 0; 648 649 /* convert fractional part */ 650 do { 651 fconvert[fplace++] = 652 (caps ? "0123456789ABCDEF" 653 : "0123456789abcdef")[fracpart % 10]; 654 fracpart = (fracpart / 10); 655 } while (fplace < max); 656 if (fplace == 20) 657 fplace--; 658 fconvert[fplace] = 0; 659 660 /* -1 for decimal point, another -1 if we are printing a sign */ 661 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 662 zpadlen = max - fplace; 663 if (zpadlen < 0) 664 zpadlen = 0; 665 if (padlen < 0) 666 padlen = 0; 667 if (flags & DP_F_MINUS) 668 padlen = -padlen; 669 670 if ((flags & DP_F_ZERO) && (padlen > 0)) { 671 if (signvalue) { 672 doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); 673 --padlen; 674 signvalue = 0; 675 } 676 while (padlen > 0) { 677 doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); 678 --padlen; 679 } 680 } 681 while (padlen > 0) { 682 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 683 --padlen; 684 } 685 if (signvalue) 686 doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); 687 688 while (iplace > 0) 689 doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]); 690 691 /* 692 * Decimal point. This should probably use locale to find the correct 693 * char to print out. 694 */ 695 if (max > 0) { 696 doapr_outch(sbuffer, buffer, currlen, maxlen, '.'); 697 698 while (fplace > 0) 699 doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]); 700 } 701 while (zpadlen > 0) { 702 doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); 703 --zpadlen; 704 } 705 706 while (padlen < 0) { 707 doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); 708 ++padlen; 709 } 710} 711 712static void 713doapr_outch( 714 char **sbuffer, 715 char **buffer, 716 size_t *currlen, 717 size_t *maxlen, 718 int c) 719{ 720 /* If we haven't at least one buffer, someone has doe a big booboo */ 721 assert(*sbuffer != NULL || buffer != NULL); 722 723 if (buffer) { 724 while (*currlen >= *maxlen) { 725 if (*buffer == NULL) { 726 if (*maxlen == 0) 727 *maxlen = 1024; 728 *buffer = OPENSSL_malloc(*maxlen); 729 if (*currlen > 0) { 730 assert(*sbuffer != NULL); 731 memcpy(*buffer, *sbuffer, *currlen); 732 } 733 *sbuffer = NULL; 734 } else { 735 *maxlen += 1024; 736 *buffer = OPENSSL_realloc(*buffer, *maxlen); 737 } 738 } 739 /* What to do if *buffer is NULL? */ 740 assert(*sbuffer != NULL || *buffer != NULL); 741 } 742 743 if (*currlen < *maxlen) { 744 if (*sbuffer) 745 (*sbuffer)[(*currlen)++] = (char)c; 746 else 747 (*buffer)[(*currlen)++] = (char)c; 748 } 749 750 return; 751} 752 753/***************************************************************************/ 754 755int BIO_printf (BIO *bio, const char *format, ...) 756 { 757 va_list args; 758 int ret; 759 760 va_start(args, format); 761 762 ret = BIO_vprintf(bio, format, args); 763 764 va_end(args); 765 return(ret); 766 } 767 768int BIO_vprintf (BIO *bio, const char *format, va_list args) 769 { 770 int ret; 771 size_t retlen; 772 char hugebuf[1024*2]; /* Was previously 10k, which is unreasonable 773 in small-stack environments, like threads 774 or DOS programs. */ 775 char *hugebufp = hugebuf; 776 size_t hugebufsize = sizeof(hugebuf); 777 char *dynbuf = NULL; 778 int ignored; 779 780 dynbuf = NULL; 781 CRYPTO_push_info("doapr()"); 782 _dopr(&hugebufp, &dynbuf, &hugebufsize, 783 &retlen, &ignored, format, args); 784 if (dynbuf) 785 { 786 ret=BIO_write(bio, dynbuf, (int)retlen); 787 OPENSSL_free(dynbuf); 788 } 789 else 790 { 791 ret=BIO_write(bio, hugebuf, (int)retlen); 792 } 793 CRYPTO_pop_info(); 794 return(ret); 795 } 796 797/* As snprintf is not available everywhere, we provide our own implementation. 798 * This function has nothing to do with BIOs, but it's closely related 799 * to BIO_printf, and we need *some* name prefix ... 800 * (XXX the function should be renamed, but to what?) */ 801int BIO_snprintf(char *buf, size_t n, const char *format, ...) 802 { 803 va_list args; 804 int ret; 805 806 va_start(args, format); 807 808 ret = BIO_vsnprintf(buf, n, format, args); 809 810 va_end(args); 811 return(ret); 812 } 813 814int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 815 { 816 size_t retlen; 817 int truncated; 818 819 _dopr(&buf, NULL, &n, &retlen, &truncated, format, args); 820 821 if (truncated) 822 /* In case of truncation, return -1 like traditional snprintf. 823 * (Current drafts for ISO/IEC 9899 say snprintf should return 824 * the number of characters that would have been written, 825 * had the buffer been large enough.) */ 826 return -1; 827 else 828 return (retlen <= INT_MAX) ? retlen : -1; 829 } 830