155714Skris/* crypto/bio/b_print.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8296465Sdelphij * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15296465Sdelphij * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22296465Sdelphij * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40296465Sdelphij * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52296465Sdelphij * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 59100936Snectar/* disable assert() unless BIO_DEBUG has been defined */ 60100936Snectar#ifndef BIO_DEBUG 61100936Snectar# ifndef NDEBUG 62100936Snectar# define NDEBUG 63100936Snectar# endif 64100936Snectar#endif 65100936Snectar 66296465Sdelphij/* 6755714Skris * Stolen from tjh's ssl/ssl_trc.c stuff. 6855714Skris */ 6955714Skris 7055714Skris#include <stdio.h> 7159191Skris#include <string.h> 7259191Skris#include <ctype.h> 7359191Skris#include <assert.h> 7459191Skris#include <limits.h> 7555714Skris#include "cryptlib.h" 7659191Skris#ifndef NO_SYS_TYPES_H 77296465Sdelphij# include <sys/types.h> 7859191Skris#endif 7979998Skris#include <openssl/bn.h> /* To get BN_LLONG properly defined */ 8055714Skris#include <openssl/bio.h> 8155714Skris 82194206Ssimon#if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT) 8359191Skris# ifndef HAVE_LONG_LONG 8459191Skris# define HAVE_LONG_LONG 1 8559191Skris# endif 8659191Skris#endif 8759191Skris 8868651Skris/***************************************************************************/ 8959191Skris 9059191Skris/* 9159191Skris * Copyright Patrick Powell 1995 9259191Skris * This code is based on code written by Patrick Powell <papowell@astart.com> 9359191Skris * It may be used for any purpose as long as this notice remains intact 9459191Skris * on all source code distributions. 9559191Skris */ 9659191Skris 97296465Sdelphij/*- 9859191Skris * This code contains numerious changes and enhancements which were 9959191Skris * made by lots of contributors over the last years to Patrick Powell's 10059191Skris * original code: 10159191Skris * 10259191Skris * o Patrick Powell <papowell@astart.com> (1995) 10359191Skris * o Brandon Long <blong@fiction.net> (1996, for Mutt) 10459191Skris * o Thomas Roessler <roessler@guug.de> (1998, for Mutt) 10559191Skris * o Michael Elkins <me@cs.hmc.edu> (1998, for Mutt) 10659191Skris * o Andrew Tridgell <tridge@samba.org> (1998, for Samba) 10759191Skris * o Luke Mewburn <lukem@netbsd.org> (1999, for LukemFTP) 10859191Skris * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth) 10968651Skris * o ... (for OpenSSL) 11059191Skris */ 11159191Skris 112101613Snectar#ifdef HAVE_LONG_DOUBLE 113296465Sdelphij# define LDOUBLE long double 11459191Skris#else 115296465Sdelphij# define LDOUBLE double 11659191Skris#endif 11759191Skris 11859191Skris#if HAVE_LONG_LONG 119109998Smarkm# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__) 120296465Sdelphij# define LLONG __int64 12179998Skris# else 122296465Sdelphij# define LLONG long long 12379998Skris# endif 12459191Skris#else 125296465Sdelphij# define LLONG long 126296465Sdelphij#endif 127296465Sdelphij 128296465Sdelphijstatic int fmtstr(char **, char **, size_t *, size_t *, 129296465Sdelphij const char *, int, int, int); 130296465Sdelphijstatic int fmtint(char **, char **, size_t *, size_t *, 131296465Sdelphij LLONG, int, int, int, int); 132296465Sdelphijstatic int fmtfp(char **, char **, size_t *, size_t *, 133296465Sdelphij LDOUBLE, int, int, int); 134296465Sdelphijstatic int doapr_outch(char **, char **, size_t *, size_t *, int); 135296465Sdelphijstatic int _dopr(char **sbuffer, char **buffer, 136296465Sdelphij size_t *maxlen, size_t *retlen, int *truncated, 137296465Sdelphij const char *format, va_list args); 138296465Sdelphij 13959191Skris/* format read states */ 14059191Skris#define DP_S_DEFAULT 0 14159191Skris#define DP_S_FLAGS 1 14259191Skris#define DP_S_MIN 2 14359191Skris#define DP_S_DOT 3 14459191Skris#define DP_S_MAX 4 14559191Skris#define DP_S_MOD 5 14659191Skris#define DP_S_CONV 6 14759191Skris#define DP_S_DONE 7 14859191Skris 14959191Skris/* format flags - Bits */ 15059191Skris#define DP_F_MINUS (1 << 0) 15159191Skris#define DP_F_PLUS (1 << 1) 15259191Skris#define DP_F_SPACE (1 << 2) 15359191Skris#define DP_F_NUM (1 << 3) 15459191Skris#define DP_F_ZERO (1 << 4) 15559191Skris#define DP_F_UP (1 << 5) 15659191Skris#define DP_F_UNSIGNED (1 << 6) 15759191Skris 15859191Skris/* conversion flags */ 15959191Skris#define DP_C_SHORT 1 16059191Skris#define DP_C_LONG 2 16159191Skris#define DP_C_LDOUBLE 3 16259191Skris#define DP_C_LLONG 4 16359191Skris 16459191Skris/* some handy macros */ 165296465Sdelphij#define char_to_int(p) (p - '0') 166296465Sdelphij#define OSSL_MAX(p,q) ((p >= q) ? p : q) 167296465Sdelphij 168296465Sdelphijstatic int 169296465Sdelphij_dopr(char **sbuffer, 170296465Sdelphij char **buffer, 171296465Sdelphij size_t *maxlen, 172296465Sdelphij size_t *retlen, int *truncated, const char *format, va_list args) 17359191Skris{ 17459191Skris char ch; 17559191Skris LLONG value; 17659191Skris LDOUBLE fvalue; 17759191Skris char *strvalue; 17859191Skris int min; 17959191Skris int max; 18059191Skris int state; 18159191Skris int flags; 18259191Skris int cflags; 18359191Skris size_t currlen; 18459191Skris 18559191Skris state = DP_S_DEFAULT; 18659191Skris flags = currlen = cflags = min = 0; 18759191Skris max = -1; 18859191Skris ch = *format++; 18959191Skris 19059191Skris while (state != DP_S_DONE) { 19168651Skris if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) 19259191Skris state = DP_S_DONE; 19359191Skris 19459191Skris switch (state) { 19559191Skris case DP_S_DEFAULT: 196296465Sdelphij if (ch == '%') 197296465Sdelphij state = DP_S_FLAGS; 198296465Sdelphij else 199296465Sdelphij if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 200296465Sdelphij return 0; 201296465Sdelphij ch = *format++; 202296465Sdelphij break; 203296465Sdelphij case DP_S_FLAGS: 20459191Skris switch (ch) { 20559191Skris case '-': 20659191Skris flags |= DP_F_MINUS; 20759191Skris ch = *format++; 20859191Skris break; 20959191Skris case '+': 21059191Skris flags |= DP_F_PLUS; 21159191Skris ch = *format++; 21259191Skris break; 21359191Skris case ' ': 21459191Skris flags |= DP_F_SPACE; 21559191Skris ch = *format++; 21659191Skris break; 21759191Skris case '#': 21859191Skris flags |= DP_F_NUM; 21959191Skris ch = *format++; 22059191Skris break; 22159191Skris case '0': 22259191Skris flags |= DP_F_ZERO; 22359191Skris ch = *format++; 22459191Skris break; 22559191Skris default: 22659191Skris state = DP_S_MIN; 22759191Skris break; 22859191Skris } 22959191Skris break; 23059191Skris case DP_S_MIN: 23159191Skris if (isdigit((unsigned char)ch)) { 23259191Skris min = 10 * min + char_to_int(ch); 23359191Skris ch = *format++; 23459191Skris } else if (ch == '*') { 23559191Skris min = va_arg(args, int); 23659191Skris ch = *format++; 23759191Skris state = DP_S_DOT; 23859191Skris } else 23959191Skris state = DP_S_DOT; 24059191Skris break; 24159191Skris case DP_S_DOT: 24259191Skris if (ch == '.') { 24359191Skris state = DP_S_MAX; 24459191Skris ch = *format++; 24559191Skris } else 24659191Skris state = DP_S_MOD; 24759191Skris break; 24859191Skris case DP_S_MAX: 24959191Skris if (isdigit((unsigned char)ch)) { 25059191Skris if (max < 0) 25159191Skris max = 0; 25259191Skris max = 10 * max + char_to_int(ch); 25359191Skris ch = *format++; 25459191Skris } else if (ch == '*') { 25559191Skris max = va_arg(args, int); 25659191Skris ch = *format++; 25759191Skris state = DP_S_MOD; 25859191Skris } else 25959191Skris state = DP_S_MOD; 26059191Skris break; 26159191Skris case DP_S_MOD: 26259191Skris switch (ch) { 26359191Skris case 'h': 26459191Skris cflags = DP_C_SHORT; 26559191Skris ch = *format++; 26659191Skris break; 26759191Skris case 'l': 26859191Skris if (*format == 'l') { 26959191Skris cflags = DP_C_LLONG; 27059191Skris format++; 27159191Skris } else 27259191Skris cflags = DP_C_LONG; 27359191Skris ch = *format++; 27459191Skris break; 27559191Skris case 'q': 27659191Skris cflags = DP_C_LLONG; 27759191Skris ch = *format++; 27859191Skris break; 27959191Skris case 'L': 28059191Skris cflags = DP_C_LDOUBLE; 28159191Skris ch = *format++; 28259191Skris break; 28359191Skris default: 28459191Skris break; 28559191Skris } 28659191Skris state = DP_S_CONV; 28759191Skris break; 28859191Skris case DP_S_CONV: 28959191Skris switch (ch) { 29059191Skris case 'd': 29159191Skris case 'i': 29259191Skris switch (cflags) { 29359191Skris case DP_C_SHORT: 29459191Skris value = (short int)va_arg(args, int); 29559191Skris break; 29659191Skris case DP_C_LONG: 29759191Skris value = va_arg(args, long int); 29859191Skris break; 29959191Skris case DP_C_LLONG: 30059191Skris value = va_arg(args, LLONG); 30159191Skris break; 30259191Skris default: 303296465Sdelphij value = va_arg(args, int); 304296465Sdelphij break; 305296465Sdelphij } 306296465Sdelphij if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, 307296465Sdelphij max, flags)) 308296465Sdelphij return 0; 309296465Sdelphij break; 310296465Sdelphij case 'X': 311296465Sdelphij flags |= DP_F_UP; 31259191Skris /* FALLTHROUGH */ 31359191Skris case 'x': 31459191Skris case 'o': 31559191Skris case 'u': 31659191Skris flags |= DP_F_UNSIGNED; 31759191Skris switch (cflags) { 31859191Skris case DP_C_SHORT: 31959191Skris value = (unsigned short int)va_arg(args, unsigned int); 32059191Skris break; 32159191Skris case DP_C_LONG: 322296465Sdelphij value = (LLONG) va_arg(args, unsigned long int); 32359191Skris break; 32459191Skris case DP_C_LLONG: 32559191Skris value = va_arg(args, unsigned LLONG); 32659191Skris break; 32759191Skris default: 328296465Sdelphij value = (LLONG) va_arg(args, unsigned int); 329296465Sdelphij break; 330296465Sdelphij } 331296465Sdelphij if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 332296465Sdelphij ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), 333296465Sdelphij min, max, flags)) 334296465Sdelphij return 0; 335296465Sdelphij break; 336296465Sdelphij case 'f': 337296465Sdelphij if (cflags == DP_C_LDOUBLE) 338296465Sdelphij fvalue = va_arg(args, LDOUBLE); 339296465Sdelphij else 340296465Sdelphij fvalue = va_arg(args, double); 341296465Sdelphij if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 342296465Sdelphij flags)) 343296465Sdelphij return 0; 344296465Sdelphij break; 345296465Sdelphij case 'E': 346296465Sdelphij flags |= DP_F_UP; 34759191Skris case 'e': 34859191Skris if (cflags == DP_C_LDOUBLE) 34959191Skris fvalue = va_arg(args, LDOUBLE); 35059191Skris else 35159191Skris fvalue = va_arg(args, double); 35259191Skris break; 35359191Skris case 'G': 35459191Skris flags |= DP_F_UP; 35559191Skris case 'g': 35659191Skris if (cflags == DP_C_LDOUBLE) 35759191Skris fvalue = va_arg(args, LDOUBLE); 35859191Skris else 359296465Sdelphij fvalue = va_arg(args, double); 360296465Sdelphij break; 361296465Sdelphij case 'c': 362296465Sdelphij if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, 363296465Sdelphij va_arg(args, int))) 364296465Sdelphij return 0; 365296465Sdelphij break; 366296465Sdelphij case 's': 367296465Sdelphij strvalue = va_arg(args, char *); 36868651Skris if (max < 0) { 369296465Sdelphij if (buffer) 370296465Sdelphij max = INT_MAX; 371296465Sdelphij else 372296465Sdelphij max = *maxlen; 373296465Sdelphij } 374296465Sdelphij if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, 375296465Sdelphij flags, min, max)) 376296465Sdelphij return 0; 377296465Sdelphij break; 378296465Sdelphij case 'p': 379296465Sdelphij value = (long)va_arg(args, void *); 380296465Sdelphij if (!fmtint(sbuffer, buffer, &currlen, maxlen, 381296465Sdelphij value, 16, min, max, flags | DP_F_NUM)) 382296465Sdelphij return 0; 383296465Sdelphij break; 384296465Sdelphij case 'n': /* XXX */ 385296465Sdelphij if (cflags == DP_C_SHORT) { 38659191Skris short int *num; 38759191Skris num = va_arg(args, short int *); 38859191Skris *num = currlen; 38959191Skris } else if (cflags == DP_C_LONG) { /* XXX */ 39059191Skris long int *num; 39159191Skris num = va_arg(args, long int *); 392296465Sdelphij *num = (long int)currlen; 39359191Skris } else if (cflags == DP_C_LLONG) { /* XXX */ 39459191Skris LLONG *num; 39559191Skris num = va_arg(args, LLONG *); 39659191Skris *num = (LLONG) currlen; 39759191Skris } else { 398296465Sdelphij int *num; 39959191Skris num = va_arg(args, int *); 40059191Skris *num = currlen; 401296465Sdelphij } 402296465Sdelphij break; 403296465Sdelphij case '%': 404296465Sdelphij if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 405296465Sdelphij return 0; 406296465Sdelphij break; 407296465Sdelphij case 'w': 408296465Sdelphij /* not supported yet, treat as next char */ 40959191Skris ch = *format++; 41059191Skris break; 41159191Skris default: 41259191Skris /* unknown, skip */ 41359191Skris break; 41459191Skris } 41559191Skris ch = *format++; 41659191Skris state = DP_S_DEFAULT; 41759191Skris flags = cflags = min = 0; 41859191Skris max = -1; 41959191Skris break; 42059191Skris case DP_S_DONE: 42159191Skris break; 42259191Skris default: 42359191Skris break; 42459191Skris } 42559191Skris } 426296465Sdelphij *truncated = (currlen > *maxlen - 1); 427296465Sdelphij if (*truncated) 428296465Sdelphij currlen = *maxlen - 1; 429296465Sdelphij if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) 430296465Sdelphij return 0; 431296465Sdelphij *retlen = currlen - 1; 432296465Sdelphij return 1; 433296465Sdelphij} 434296465Sdelphij 435296465Sdelphijstatic int 436296465Sdelphijfmtstr(char **sbuffer, 437296465Sdelphij char **buffer, 438296465Sdelphij size_t *currlen, 439296465Sdelphij size_t *maxlen, const char *value, int flags, int min, int max) 440296465Sdelphij{ 441296465Sdelphij int padlen; 442296465Sdelphij size_t strln; 443296465Sdelphij int cnt = 0; 444296465Sdelphij 445296465Sdelphij if (value == 0) 446296465Sdelphij value = "<NULL>"; 447296465Sdelphij 448296465Sdelphij strln = strlen(value); 449296465Sdelphij if (strln > INT_MAX) 450296465Sdelphij strln = INT_MAX; 451296465Sdelphij 452296465Sdelphij padlen = min - strln; 453296465Sdelphij if (min < 0 || padlen < 0) 454296465Sdelphij padlen = 0; 455296465Sdelphij if (flags & DP_F_MINUS) 456296465Sdelphij padlen = -padlen; 457296465Sdelphij 458296465Sdelphij while ((padlen > 0) && (cnt < max)) { 459296465Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 460296465Sdelphij return 0; 461296465Sdelphij --padlen; 462296465Sdelphij ++cnt; 463296465Sdelphij } 464296465Sdelphij while (*value && (cnt < max)) { 465296465Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) 466296465Sdelphij return 0; 467296465Sdelphij ++cnt; 468296465Sdelphij } 469296465Sdelphij while ((padlen < 0) && (cnt < max)) { 470296465Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 471296465Sdelphij return 0; 472296465Sdelphij ++padlen; 473296465Sdelphij ++cnt; 474296465Sdelphij } 475296465Sdelphij return 1; 476296465Sdelphij} 477296465Sdelphij 478296465Sdelphijstatic int 479296465Sdelphijfmtint(char **sbuffer, 480296465Sdelphij char **buffer, 481296465Sdelphij size_t *currlen, 482296465Sdelphij size_t *maxlen, LLONG value, int base, int min, int max, int flags) 48359191Skris{ 48459191Skris int signvalue = 0; 485160814Ssimon const char *prefix = ""; 48659191Skris unsigned LLONG uvalue; 487296465Sdelphij char convert[DECIMAL_SIZE(value) + 3]; 48859191Skris int place = 0; 48959191Skris int spadlen = 0; 49059191Skris int zpadlen = 0; 49159191Skris int caps = 0; 49259191Skris 49359191Skris if (max < 0) 49459191Skris max = 0; 49559191Skris uvalue = value; 49659191Skris if (!(flags & DP_F_UNSIGNED)) { 49759191Skris if (value < 0) { 49859191Skris signvalue = '-'; 49959191Skris uvalue = -value; 50059191Skris } else if (flags & DP_F_PLUS) 50159191Skris signvalue = '+'; 50259191Skris else if (flags & DP_F_SPACE) 50359191Skris signvalue = ' '; 50459191Skris } 505120631Snectar if (flags & DP_F_NUM) { 506296465Sdelphij if (base == 8) 507296465Sdelphij prefix = "0"; 508296465Sdelphij if (base == 16) 509296465Sdelphij prefix = "0x"; 510120631Snectar } 51159191Skris if (flags & DP_F_UP) 51259191Skris caps = 1; 51359191Skris do { 514296465Sdelphij convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") 515296465Sdelphij [uvalue % (unsigned)base]; 516296465Sdelphij uvalue = (uvalue / (unsigned)base); 517160814Ssimon } while (uvalue && (place < (int)sizeof(convert))); 518160814Ssimon if (place == sizeof(convert)) 51959191Skris place--; 52059191Skris convert[place] = 0; 52159191Skris 52259191Skris zpadlen = max - place; 523296465Sdelphij spadlen = 524296465Sdelphij min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); 52559191Skris if (zpadlen < 0) 52659191Skris zpadlen = 0; 52759191Skris if (spadlen < 0) 52859191Skris spadlen = 0; 52959191Skris if (flags & DP_F_ZERO) { 53079998Skris zpadlen = OSSL_MAX(zpadlen, spadlen); 53159191Skris spadlen = 0; 53259191Skris } 53359191Skris if (flags & DP_F_MINUS) 53459191Skris spadlen = -spadlen; 535296465Sdelphij 536296465Sdelphij /* spaces */ 537296465Sdelphij while (spadlen > 0) { 538296465Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 539296465Sdelphij return 0; 540296465Sdelphij --spadlen; 541296465Sdelphij } 542296465Sdelphij 543296465Sdelphij /* sign */ 544296465Sdelphij if (signvalue) 545296465Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 546296465Sdelphij return 0; 547296465Sdelphij 548296465Sdelphij /* prefix */ 549296465Sdelphij while (*prefix) { 550296465Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) 551296465Sdelphij return 0; 552296465Sdelphij prefix++; 553296465Sdelphij } 554296465Sdelphij 555296465Sdelphij /* zeros */ 556296465Sdelphij if (zpadlen > 0) { 557296465Sdelphij while (zpadlen > 0) { 558296465Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 559296465Sdelphij return 0; 560296465Sdelphij --zpadlen; 561296465Sdelphij } 562296465Sdelphij } 563296465Sdelphij /* digits */ 564296465Sdelphij while (place > 0) { 565296465Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) 566296465Sdelphij return 0; 567296465Sdelphij } 568296465Sdelphij 569296465Sdelphij /* left justified spaces */ 570296465Sdelphij while (spadlen < 0) { 571296465Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 572296465Sdelphij return 0; 573296465Sdelphij ++spadlen; 574296465Sdelphij } 575296465Sdelphij return 1; 576296465Sdelphij} 577296465Sdelphij 578296465Sdelphijstatic LDOUBLE abs_val(LDOUBLE value) 57959191Skris{ 58059191Skris LDOUBLE result = value; 58159191Skris if (value < 0) 58259191Skris result = -value; 58359191Skris return result; 58459191Skris} 58559191Skris 586296465Sdelphijstatic LDOUBLE pow_10(int in_exp) 58759191Skris{ 58859191Skris LDOUBLE result = 1; 589127128Snectar while (in_exp) { 59059191Skris result *= 10; 591127128Snectar in_exp--; 59259191Skris } 59359191Skris return result; 59459191Skris} 59559191Skris 596296465Sdelphijstatic long roundv(LDOUBLE value) 59759191Skris{ 59859191Skris long intpart; 599296465Sdelphij intpart = (long)value; 60059191Skris value = value - intpart; 60159191Skris if (value >= 0.5) 60259191Skris intpart++; 603296465Sdelphij return intpart; 604296465Sdelphij} 605296465Sdelphij 606296465Sdelphijstatic int 607296465Sdelphijfmtfp(char **sbuffer, 608296465Sdelphij char **buffer, 609296465Sdelphij size_t *currlen, 610296465Sdelphij size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags) 61159191Skris{ 61259191Skris int signvalue = 0; 61359191Skris LDOUBLE ufvalue; 61459191Skris char iconvert[20]; 61559191Skris char fconvert[20]; 61659191Skris int iplace = 0; 61759191Skris int fplace = 0; 61859191Skris int padlen = 0; 61959191Skris int zpadlen = 0; 62059191Skris int caps = 0; 62159191Skris long intpart; 62259191Skris long fracpart; 623160814Ssimon long max10; 62459191Skris 62559191Skris if (max < 0) 62659191Skris max = 6; 62759191Skris ufvalue = abs_val(fvalue); 62859191Skris if (fvalue < 0) 62959191Skris signvalue = '-'; 63059191Skris else if (flags & DP_F_PLUS) 63159191Skris signvalue = '+'; 63259191Skris else if (flags & DP_F_SPACE) 63359191Skris signvalue = ' '; 63459191Skris 63559191Skris intpart = (long)ufvalue; 63659191Skris 637296465Sdelphij /* 638296465Sdelphij * sorry, we only support 9 digits past the decimal because of our 639296465Sdelphij * conversion method 640296465Sdelphij */ 64159191Skris if (max > 9) 64259191Skris max = 9; 64359191Skris 644296465Sdelphij /* 645296465Sdelphij * we "cheat" by converting the fractional part to integer by multiplying 646296465Sdelphij * by a factor of 10 647296465Sdelphij */ 648160814Ssimon max10 = roundv(pow_10(max)); 649160814Ssimon fracpart = roundv(pow_10(max) * (ufvalue - intpart)); 65059191Skris 651160814Ssimon if (fracpart >= max10) { 65259191Skris intpart++; 653160814Ssimon fracpart -= max10; 65459191Skris } 65559191Skris 65659191Skris /* convert integer part */ 65759191Skris do { 65859191Skris iconvert[iplace++] = 659296465Sdelphij (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10]; 66059191Skris intpart = (intpart / 10); 661160814Ssimon } while (intpart && (iplace < (int)sizeof(iconvert))); 662127128Snectar if (iplace == sizeof iconvert) 66359191Skris iplace--; 66459191Skris iconvert[iplace] = 0; 66559191Skris 66659191Skris /* convert fractional part */ 66759191Skris do { 66859191Skris fconvert[fplace++] = 669296465Sdelphij (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 10]; 67059191Skris fracpart = (fracpart / 10); 67179998Skris } while (fplace < max); 672127128Snectar if (fplace == sizeof fconvert) 67359191Skris fplace--; 67459191Skris fconvert[fplace] = 0; 67559191Skris 67659191Skris /* -1 for decimal point, another -1 if we are printing a sign */ 67759191Skris padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 67859191Skris zpadlen = max - fplace; 67959191Skris if (zpadlen < 0) 68059191Skris zpadlen = 0; 68159191Skris if (padlen < 0) 68259191Skris padlen = 0; 68359191Skris if (flags & DP_F_MINUS) 68459191Skris padlen = -padlen; 685296465Sdelphij 686296465Sdelphij if ((flags & DP_F_ZERO) && (padlen > 0)) { 687296465Sdelphij if (signvalue) { 688296465Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 689296465Sdelphij return 0; 690296465Sdelphij --padlen; 691296465Sdelphij signvalue = 0; 692296465Sdelphij } 693296465Sdelphij while (padlen > 0) { 694296465Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 695296465Sdelphij return 0; 696296465Sdelphij --padlen; 697296465Sdelphij } 698296465Sdelphij } 699296465Sdelphij while (padlen > 0) { 700296465Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 701296465Sdelphij return 0; 702296465Sdelphij --padlen; 703296465Sdelphij } 704296465Sdelphij if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 705296465Sdelphij return 0; 706296465Sdelphij 707296465Sdelphij while (iplace > 0) { 708296465Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) 709296465Sdelphij return 0; 710296465Sdelphij } 711296465Sdelphij 712296465Sdelphij /* 713296465Sdelphij * Decimal point. This should probably use locale to find the correct 714296465Sdelphij * char to print out. 715296465Sdelphij */ 716296465Sdelphij if (max > 0 || (flags & DP_F_NUM)) { 717296465Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) 718296465Sdelphij return 0; 719296465Sdelphij 720296465Sdelphij while (fplace > 0) { 721296465Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, 722296465Sdelphij fconvert[--fplace])) 723296465Sdelphij return 0; 724296465Sdelphij } 725296465Sdelphij } 726296465Sdelphij while (zpadlen > 0) { 727296465Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 728296465Sdelphij return 0; 729296465Sdelphij --zpadlen; 730296465Sdelphij } 731296465Sdelphij 732296465Sdelphij while (padlen < 0) { 733296465Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 734296465Sdelphij return 0; 735296465Sdelphij ++padlen; 736296465Sdelphij } 737296465Sdelphij return 1; 738296465Sdelphij} 739296465Sdelphij 740296465Sdelphij#define BUFFER_INC 1024 741296465Sdelphij 742296465Sdelphijstatic int 743296465Sdelphijdoapr_outch(char **sbuffer, 744296465Sdelphij char **buffer, size_t *currlen, size_t *maxlen, int c) 745296465Sdelphij{ 746296465Sdelphij /* If we haven't at least one buffer, someone has doe a big booboo */ 747296465Sdelphij assert(*sbuffer != NULL || buffer != NULL); 748296465Sdelphij 749296465Sdelphij /* |currlen| must always be <= |*maxlen| */ 750296465Sdelphij assert(*currlen <= *maxlen); 751296465Sdelphij 752296465Sdelphij if (buffer && *currlen == *maxlen) { 753296465Sdelphij if (*maxlen > INT_MAX - BUFFER_INC) 754296465Sdelphij return 0; 755296465Sdelphij 756296465Sdelphij *maxlen += BUFFER_INC; 757296465Sdelphij if (*buffer == NULL) { 758296465Sdelphij *buffer = OPENSSL_malloc(*maxlen); 759296465Sdelphij if (*buffer == NULL) 760296465Sdelphij return 0; 761296465Sdelphij if (*currlen > 0) { 762296465Sdelphij assert(*sbuffer != NULL); 763296465Sdelphij memcpy(*buffer, *sbuffer, *currlen); 764296465Sdelphij } 765296465Sdelphij *sbuffer = NULL; 766296465Sdelphij } else { 767296465Sdelphij char *tmpbuf; 768296465Sdelphij tmpbuf = OPENSSL_realloc(*buffer, *maxlen); 769296465Sdelphij if (tmpbuf == NULL) 770296465Sdelphij return 0; 771296465Sdelphij *buffer = tmpbuf; 772296465Sdelphij } 773296465Sdelphij } 774296465Sdelphij 775296465Sdelphij if (*currlen < *maxlen) { 776296465Sdelphij if (*sbuffer) 777296465Sdelphij (*sbuffer)[(*currlen)++] = (char)c; 778296465Sdelphij else 779296465Sdelphij (*buffer)[(*currlen)++] = (char)c; 780296465Sdelphij } 781296465Sdelphij 782296465Sdelphij return 1; 783296465Sdelphij} 784296465Sdelphij 785296465Sdelphij/***************************************************************************/ 78659191Skris 787296465Sdelphijint BIO_printf(BIO *bio, const char *format, ...) 788296465Sdelphij{ 789296465Sdelphij va_list args; 790296465Sdelphij int ret; 79159191Skris 792296465Sdelphij va_start(args, format); 79359191Skris 794296465Sdelphij ret = BIO_vprintf(bio, format, args); 79559191Skris 796296465Sdelphij va_end(args); 797296465Sdelphij return (ret); 79859191Skris} 79959191Skris 800296465Sdelphijint BIO_vprintf(BIO *bio, const char *format, va_list args) 80159191Skris{ 802296465Sdelphij int ret; 803296465Sdelphij size_t retlen; 804296465Sdelphij char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable 805296465Sdelphij * in small-stack environments, like threads 806296465Sdelphij * or DOS programs. */ 807296465Sdelphij char *hugebufp = hugebuf; 808296465Sdelphij size_t hugebufsize = sizeof(hugebuf); 809296465Sdelphij char *dynbuf = NULL; 810296465Sdelphij int ignored; 811296465Sdelphij 812296465Sdelphij dynbuf = NULL; 813296465Sdelphij CRYPTO_push_info("doapr()"); 814296465Sdelphij if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, 815296465Sdelphij args)) { 816296465Sdelphij OPENSSL_free(dynbuf); 817296465Sdelphij return -1; 818296465Sdelphij } 819296465Sdelphij if (dynbuf) { 820296465Sdelphij ret = BIO_write(bio, dynbuf, (int)retlen); 821296465Sdelphij OPENSSL_free(dynbuf); 822296465Sdelphij } else { 823296465Sdelphij ret = BIO_write(bio, hugebuf, (int)retlen); 82459191Skris } 825296465Sdelphij CRYPTO_pop_info(); 826296465Sdelphij return (ret); 82759191Skris} 82868651Skris 829296465Sdelphij/* 830296465Sdelphij * As snprintf is not available everywhere, we provide our own 831296465Sdelphij * implementation. This function has nothing to do with BIOs, but it's 832296465Sdelphij * closely related to BIO_printf, and we need *some* name prefix ... (XXX the 833296465Sdelphij * function should be renamed, but to what?) 834296465Sdelphij */ 83568651Skrisint BIO_snprintf(char *buf, size_t n, const char *format, ...) 836296465Sdelphij{ 837296465Sdelphij va_list args; 838296465Sdelphij int ret; 83968651Skris 840296465Sdelphij va_start(args, format); 84168651Skris 842296465Sdelphij ret = BIO_vsnprintf(buf, n, format, args); 84368651Skris 844296465Sdelphij va_end(args); 845296465Sdelphij return (ret); 846296465Sdelphij} 84768651Skris 84868651Skrisint BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 849296465Sdelphij{ 850296465Sdelphij size_t retlen; 851296465Sdelphij int truncated; 852296465Sdelphij 853296465Sdelphij if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) 854296465Sdelphij return -1; 855296465Sdelphij 856296465Sdelphij if (truncated) 857296465Sdelphij /* 858296465Sdelphij * In case of truncation, return -1 like traditional snprintf. 859296465Sdelphij * (Current drafts for ISO/IEC 9899 say snprintf should return the 860296465Sdelphij * number of characters that would have been written, had the buffer 861296465Sdelphij * been large enough.) 862296465Sdelphij */ 863296465Sdelphij return -1; 864296465Sdelphij else 865296465Sdelphij return (retlen <= INT_MAX) ? (int)retlen : -1; 866296465Sdelphij} 867