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