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. 8296341Sdelphij * 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). 15296341Sdelphij * 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. 22296341Sdelphij * 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 :-). 37296341Sdelphij * 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)" 40296341Sdelphij * 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. 52296341Sdelphij * 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 66296341Sdelphij/* 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 77296341Sdelphij# 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 97296341Sdelphij/*- 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 113296341Sdelphij# define LDOUBLE long double 11459191Skris#else 115296341Sdelphij# define LDOUBLE double 11659191Skris#endif 11759191Skris 118238405Sjkim#ifdef HAVE_LONG_LONG 119238405Sjkim# if defined(_WIN32) && !defined(__GNUC__) 120296341Sdelphij# define LLONG __int64 12179998Skris# else 122296341Sdelphij# define LLONG long long 12379998Skris# endif 12459191Skris#else 125296341Sdelphij# define LLONG long 12659191Skris#endif 12759191Skris 128296341Sdelphijstatic int fmtstr(char **, char **, size_t *, size_t *, 129296341Sdelphij const char *, int, int, int); 130296341Sdelphijstatic int fmtint(char **, char **, size_t *, size_t *, 131296341Sdelphij LLONG, int, int, int, int); 132296341Sdelphijstatic int fmtfp(char **, char **, size_t *, size_t *, 133296341Sdelphij LDOUBLE, int, int, int); 134296341Sdelphijstatic int doapr_outch(char **, char **, size_t *, size_t *, int); 135296341Sdelphijstatic int _dopr(char **sbuffer, char **buffer, 136296341Sdelphij size_t *maxlen, size_t *retlen, int *truncated, 137296341Sdelphij const char *format, va_list args); 13859191Skris 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 */ 16559191Skris#define char_to_int(p) (p - '0') 16679998Skris#define OSSL_MAX(p,q) ((p >= q) ? p : q) 16759191Skris 168296341Sdelphijstatic int 169296341Sdelphij_dopr(char **sbuffer, 170296341Sdelphij char **buffer, 171296341Sdelphij size_t *maxlen, 172296341Sdelphij 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: 19659191Skris if (ch == '%') 19759191Skris state = DP_S_FLAGS; 19859191Skris else 199296341Sdelphij if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 200296341Sdelphij return 0; 20159191Skris ch = *format++; 20259191Skris break; 20359191Skris 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: 30359191Skris value = va_arg(args, int); 30459191Skris break; 30559191Skris } 306296341Sdelphij if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, 307296341Sdelphij max, flags)) 308296341Sdelphij return 0; 30959191Skris break; 31059191Skris case 'X': 31159191Skris 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: 322296341Sdelphij 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: 328296341Sdelphij value = (LLONG) va_arg(args, unsigned int); 32959191Skris break; 33059191Skris } 331296341Sdelphij if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 332296341Sdelphij ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), 333296341Sdelphij min, max, flags)) 334296341Sdelphij return 0; 33559191Skris break; 33659191Skris case 'f': 33759191Skris if (cflags == DP_C_LDOUBLE) 33859191Skris fvalue = va_arg(args, LDOUBLE); 33959191Skris else 34059191Skris fvalue = va_arg(args, double); 341296341Sdelphij if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 342296341Sdelphij flags)) 343296341Sdelphij return 0; 34459191Skris break; 34559191Skris case 'E': 34659191Skris 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 35959191Skris fvalue = va_arg(args, double); 36059191Skris break; 36159191Skris case 'c': 362296341Sdelphij if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, 363296341Sdelphij va_arg(args, int))) 364296341Sdelphij return 0; 36559191Skris break; 36659191Skris case 's': 36759191Skris strvalue = va_arg(args, char *); 36868651Skris if (max < 0) { 369296341Sdelphij if (buffer) 370296341Sdelphij max = INT_MAX; 371296341Sdelphij else 372296341Sdelphij max = *maxlen; 373296341Sdelphij } 374296341Sdelphij if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, 375296341Sdelphij flags, min, max)) 376296341Sdelphij return 0; 37759191Skris break; 37859191Skris case 'p': 37959191Skris value = (long)va_arg(args, void *); 380296341Sdelphij if (!fmtint(sbuffer, buffer, &currlen, maxlen, 381296341Sdelphij value, 16, min, max, flags | DP_F_NUM)) 382296341Sdelphij return 0; 38359191Skris break; 384296341Sdelphij case 'n': /* XXX */ 38559191Skris 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 *); 392296341Sdelphij *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 { 398296341Sdelphij int *num; 39959191Skris num = va_arg(args, int *); 40059191Skris *num = currlen; 40159191Skris } 40259191Skris break; 40359191Skris case '%': 404296341Sdelphij if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 405296341Sdelphij return 0; 40659191Skris break; 40759191Skris case 'w': 40859191Skris /* 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 } 42668651Skris *truncated = (currlen > *maxlen - 1); 42768651Skris if (*truncated) 42859191Skris currlen = *maxlen - 1; 429296341Sdelphij if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) 430296341Sdelphij return 0; 43168651Skris *retlen = currlen - 1; 432296341Sdelphij return 1; 43359191Skris} 43459191Skris 435296341Sdelphijstatic int 436296341Sdelphijfmtstr(char **sbuffer, 437296341Sdelphij char **buffer, 438296341Sdelphij size_t *currlen, 439296341Sdelphij size_t *maxlen, const char *value, int flags, int min, int max) 44059191Skris{ 441296341Sdelphij int padlen; 442296341Sdelphij size_t strln; 44359191Skris int cnt = 0; 44459191Skris 44559191Skris if (value == 0) 44659191Skris value = "<NULL>"; 447296341Sdelphij 448296341Sdelphij strln = strlen(value); 449296341Sdelphij if (strln > INT_MAX) 450296341Sdelphij strln = INT_MAX; 451296341Sdelphij 45259191Skris padlen = min - strln; 453296341Sdelphij if (min < 0 || padlen < 0) 45459191Skris padlen = 0; 45559191Skris if (flags & DP_F_MINUS) 45659191Skris padlen = -padlen; 45759191Skris 45859191Skris while ((padlen > 0) && (cnt < max)) { 459296341Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 460296341Sdelphij return 0; 46159191Skris --padlen; 46259191Skris ++cnt; 46359191Skris } 46459191Skris while (*value && (cnt < max)) { 465296341Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) 466296341Sdelphij return 0; 46759191Skris ++cnt; 46859191Skris } 46959191Skris while ((padlen < 0) && (cnt < max)) { 470296341Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 471296341Sdelphij return 0; 47259191Skris ++padlen; 47359191Skris ++cnt; 47459191Skris } 475296341Sdelphij return 1; 47659191Skris} 47759191Skris 478296341Sdelphijstatic int 479296341Sdelphijfmtint(char **sbuffer, 480296341Sdelphij char **buffer, 481296341Sdelphij size_t *currlen, 482296341Sdelphij 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; 487296341Sdelphij 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) { 506296341Sdelphij if (base == 8) 507296341Sdelphij prefix = "0"; 508296341Sdelphij if (base == 16) 509296341Sdelphij prefix = "0x"; 510120631Snectar } 51159191Skris if (flags & DP_F_UP) 51259191Skris caps = 1; 51359191Skris do { 514296341Sdelphij convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") 515296341Sdelphij [uvalue % (unsigned)base]; 516296341Sdelphij 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; 523296341Sdelphij spadlen = 524296341Sdelphij 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; 53559191Skris 53659191Skris /* spaces */ 53759191Skris while (spadlen > 0) { 538296341Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 539296341Sdelphij return 0; 54059191Skris --spadlen; 54159191Skris } 54259191Skris 54359191Skris /* sign */ 54459191Skris if (signvalue) 545296341Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 546296341Sdelphij return 0; 54759191Skris 548120631Snectar /* prefix */ 549120631Snectar while (*prefix) { 550296341Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) 551296341Sdelphij return 0; 552296341Sdelphij prefix++; 553120631Snectar } 554120631Snectar 55559191Skris /* zeros */ 55659191Skris if (zpadlen > 0) { 55759191Skris while (zpadlen > 0) { 558296341Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 559296341Sdelphij return 0; 56059191Skris --zpadlen; 56159191Skris } 56259191Skris } 56359191Skris /* digits */ 564296341Sdelphij while (place > 0) { 565296341Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) 566296341Sdelphij return 0; 567296341Sdelphij } 56859191Skris 56959191Skris /* left justified spaces */ 57059191Skris while (spadlen < 0) { 571296341Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 572296341Sdelphij return 0; 57359191Skris ++spadlen; 57459191Skris } 575296341Sdelphij return 1; 57659191Skris} 57759191Skris 578296341Sdelphijstatic LDOUBLE abs_val(LDOUBLE value) 57959191Skris{ 58059191Skris LDOUBLE result = value; 58159191Skris if (value < 0) 58259191Skris result = -value; 58359191Skris return result; 58459191Skris} 58559191Skris 586296341Sdelphijstatic 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 596296341Sdelphijstatic long roundv(LDOUBLE value) 59759191Skris{ 59859191Skris long intpart; 599296341Sdelphij intpart = (long)value; 60059191Skris value = value - intpart; 60159191Skris if (value >= 0.5) 60259191Skris intpart++; 60359191Skris return intpart; 60459191Skris} 60559191Skris 606296341Sdelphijstatic int 607296341Sdelphijfmtfp(char **sbuffer, 608296341Sdelphij char **buffer, 609296341Sdelphij size_t *currlen, 610296341Sdelphij 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 long intpart; 62159191Skris long fracpart; 622160814Ssimon long max10; 62359191Skris 62459191Skris if (max < 0) 62559191Skris max = 6; 62659191Skris ufvalue = abs_val(fvalue); 62759191Skris if (fvalue < 0) 62859191Skris signvalue = '-'; 62959191Skris else if (flags & DP_F_PLUS) 63059191Skris signvalue = '+'; 63159191Skris else if (flags & DP_F_SPACE) 63259191Skris signvalue = ' '; 63359191Skris 63459191Skris intpart = (long)ufvalue; 63559191Skris 636296341Sdelphij /* 637296341Sdelphij * sorry, we only support 9 digits past the decimal because of our 638296341Sdelphij * conversion method 639296341Sdelphij */ 64059191Skris if (max > 9) 64159191Skris max = 9; 64259191Skris 643296341Sdelphij /* 644296341Sdelphij * we "cheat" by converting the fractional part to integer by multiplying 645296341Sdelphij * by a factor of 10 646296341Sdelphij */ 647160814Ssimon max10 = roundv(pow_10(max)); 648160814Ssimon fracpart = roundv(pow_10(max) * (ufvalue - intpart)); 64959191Skris 650160814Ssimon if (fracpart >= max10) { 65159191Skris intpart++; 652160814Ssimon fracpart -= max10; 65359191Skris } 65459191Skris 65559191Skris /* convert integer part */ 65659191Skris do { 657296341Sdelphij iconvert[iplace++] = "0123456789"[intpart % 10]; 65859191Skris intpart = (intpart / 10); 659160814Ssimon } while (intpart && (iplace < (int)sizeof(iconvert))); 660127128Snectar if (iplace == sizeof iconvert) 66159191Skris iplace--; 66259191Skris iconvert[iplace] = 0; 66359191Skris 66459191Skris /* convert fractional part */ 66559191Skris do { 666296341Sdelphij fconvert[fplace++] = "0123456789"[fracpart % 10]; 66759191Skris fracpart = (fracpart / 10); 66879998Skris } while (fplace < max); 669127128Snectar if (fplace == sizeof fconvert) 67059191Skris fplace--; 67159191Skris fconvert[fplace] = 0; 67259191Skris 67359191Skris /* -1 for decimal point, another -1 if we are printing a sign */ 67459191Skris padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 67559191Skris zpadlen = max - fplace; 67659191Skris if (zpadlen < 0) 67759191Skris zpadlen = 0; 67859191Skris if (padlen < 0) 67959191Skris padlen = 0; 68059191Skris if (flags & DP_F_MINUS) 68159191Skris padlen = -padlen; 68259191Skris 68359191Skris if ((flags & DP_F_ZERO) && (padlen > 0)) { 68459191Skris if (signvalue) { 685296341Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 686296341Sdelphij return 0; 68759191Skris --padlen; 68859191Skris signvalue = 0; 68959191Skris } 69059191Skris while (padlen > 0) { 691296341Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 692296341Sdelphij return 0; 69359191Skris --padlen; 69459191Skris } 69559191Skris } 69659191Skris while (padlen > 0) { 697296341Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 698296341Sdelphij return 0; 69959191Skris --padlen; 70059191Skris } 701296341Sdelphij if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 702296341Sdelphij return 0; 70359191Skris 704296341Sdelphij while (iplace > 0) { 705296341Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) 706296341Sdelphij return 0; 707296341Sdelphij } 70859191Skris 70959191Skris /* 71059191Skris * Decimal point. This should probably use locale to find the correct 71159191Skris * char to print out. 71259191Skris */ 713120631Snectar if (max > 0 || (flags & DP_F_NUM)) { 714296341Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) 715296341Sdelphij return 0; 71659191Skris 717296341Sdelphij while (fplace > 0) { 718296341Sdelphij if(!doapr_outch(sbuffer, buffer, currlen, maxlen, 719296341Sdelphij fconvert[--fplace])) 720296341Sdelphij return 0; 721296341Sdelphij } 72259191Skris } 72359191Skris while (zpadlen > 0) { 724296341Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 725296341Sdelphij return 0; 72659191Skris --zpadlen; 72759191Skris } 72859191Skris 72959191Skris while (padlen < 0) { 730296341Sdelphij if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 731296341Sdelphij return 0; 73259191Skris ++padlen; 73359191Skris } 734296341Sdelphij return 1; 73559191Skris} 73659191Skris 737296341Sdelphij#define BUFFER_INC 1024 738296341Sdelphij 739296341Sdelphijstatic int 740296341Sdelphijdoapr_outch(char **sbuffer, 741296341Sdelphij char **buffer, size_t *currlen, size_t *maxlen, int c) 74259191Skris{ 74368651Skris /* If we haven't at least one buffer, someone has doe a big booboo */ 74468651Skris assert(*sbuffer != NULL || buffer != NULL); 74559191Skris 746296341Sdelphij /* |currlen| must always be <= |*maxlen| */ 747296341Sdelphij assert(*currlen <= *maxlen); 748296341Sdelphij 749296341Sdelphij if (buffer && *currlen == *maxlen) { 750296341Sdelphij if (*maxlen > INT_MAX - BUFFER_INC) 751296341Sdelphij return 0; 752296341Sdelphij 753296341Sdelphij *maxlen += BUFFER_INC; 754296341Sdelphij if (*buffer == NULL) { 755296341Sdelphij *buffer = OPENSSL_malloc(*maxlen); 756296341Sdelphij if (*buffer == NULL) 757296341Sdelphij return 0; 758296341Sdelphij if (*currlen > 0) { 759296341Sdelphij assert(*sbuffer != NULL); 760296341Sdelphij memcpy(*buffer, *sbuffer, *currlen); 761296341Sdelphij } 762296341Sdelphij *sbuffer = NULL; 763296341Sdelphij } else { 764296341Sdelphij char *tmpbuf; 765296341Sdelphij tmpbuf = OPENSSL_realloc(*buffer, *maxlen); 766296341Sdelphij if (tmpbuf == NULL) 767296341Sdelphij return 0; 768296341Sdelphij *buffer = tmpbuf; 769296341Sdelphij } 77059191Skris } 77168651Skris 77268651Skris if (*currlen < *maxlen) { 773296341Sdelphij if (*sbuffer) 774296341Sdelphij (*sbuffer)[(*currlen)++] = (char)c; 775296341Sdelphij else 776296341Sdelphij (*buffer)[(*currlen)++] = (char)c; 77759191Skris } 77859191Skris 779296341Sdelphij return 1; 78059191Skris} 78168651Skris 78268651Skris/***************************************************************************/ 78368651Skris 784296341Sdelphijint BIO_printf(BIO *bio, const char *format, ...) 785296341Sdelphij{ 786296341Sdelphij va_list args; 787296341Sdelphij int ret; 78868651Skris 789296341Sdelphij va_start(args, format); 79068651Skris 791296341Sdelphij ret = BIO_vprintf(bio, format, args); 79268651Skris 793296341Sdelphij va_end(args); 794296341Sdelphij return (ret); 795296341Sdelphij} 79668651Skris 797296341Sdelphijint BIO_vprintf(BIO *bio, const char *format, va_list args) 798296341Sdelphij{ 799296341Sdelphij int ret; 800296341Sdelphij size_t retlen; 801296341Sdelphij char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable 802296341Sdelphij * in small-stack environments, like threads 803296341Sdelphij * or DOS programs. */ 804296341Sdelphij char *hugebufp = hugebuf; 805296341Sdelphij size_t hugebufsize = sizeof(hugebuf); 806296341Sdelphij char *dynbuf = NULL; 807296341Sdelphij int ignored; 80868651Skris 809296341Sdelphij dynbuf = NULL; 810296341Sdelphij CRYPTO_push_info("doapr()"); 811296341Sdelphij if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, 812296341Sdelphij args)) { 813296341Sdelphij OPENSSL_free(dynbuf); 814296341Sdelphij return -1; 815296341Sdelphij } 816296341Sdelphij if (dynbuf) { 817296341Sdelphij ret = BIO_write(bio, dynbuf, (int)retlen); 818296341Sdelphij OPENSSL_free(dynbuf); 819296341Sdelphij } else { 820296341Sdelphij ret = BIO_write(bio, hugebuf, (int)retlen); 821296341Sdelphij } 822296341Sdelphij CRYPTO_pop_info(); 823296341Sdelphij return (ret); 824296341Sdelphij} 82568651Skris 826296341Sdelphij/* 827296341Sdelphij * As snprintf is not available everywhere, we provide our own 828296341Sdelphij * implementation. This function has nothing to do with BIOs, but it's 829296341Sdelphij * closely related to BIO_printf, and we need *some* name prefix ... (XXX the 830296341Sdelphij * function should be renamed, but to what?) 831296341Sdelphij */ 83268651Skrisint BIO_snprintf(char *buf, size_t n, const char *format, ...) 833296341Sdelphij{ 834296341Sdelphij va_list args; 835296341Sdelphij int ret; 83668651Skris 837296341Sdelphij va_start(args, format); 83868651Skris 839296341Sdelphij ret = BIO_vsnprintf(buf, n, format, args); 84068651Skris 841296341Sdelphij va_end(args); 842296341Sdelphij return (ret); 843296341Sdelphij} 84468651Skris 84568651Skrisint BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 846296341Sdelphij{ 847296341Sdelphij size_t retlen; 848296341Sdelphij int truncated; 84968651Skris 850296341Sdelphij if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) 851296341Sdelphij return -1; 85268651Skris 853296341Sdelphij if (truncated) 854296341Sdelphij /* 855296341Sdelphij * In case of truncation, return -1 like traditional snprintf. 856296341Sdelphij * (Current drafts for ISO/IEC 9899 say snprintf should return the 857296341Sdelphij * number of characters that would have been written, had the buffer 858296341Sdelphij * been large enough.) 859296341Sdelphij */ 860296341Sdelphij return -1; 861296341Sdelphij else 862296341Sdelphij return (retlen <= INT_MAX) ? (int)retlen : -1; 863296341Sdelphij} 864