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. 8280297Sjkim * 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). 15280297Sjkim * 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. 22280297Sjkim * 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 :-). 37280297Sjkim * 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)" 40280297Sjkim * 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. 52280297Sjkim * 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 66280297Sjkim/* 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 77280297Sjkim# 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 97280297Sjkim/*- 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 113280297Sjkim# define LDOUBLE long double 11459191Skris#else 115280297Sjkim# define LDOUBLE double 11659191Skris#endif 11759191Skris 118238405Sjkim#ifdef HAVE_LONG_LONG 119238405Sjkim# if defined(_WIN32) && !defined(__GNUC__) 120280297Sjkim# define LLONG __int64 12179998Skris# else 122280297Sjkim# define LLONG long long 12379998Skris# endif 12459191Skris#else 125280297Sjkim# define LLONG long 12659191Skris#endif 12759191Skris 128296279Sjkimstatic int fmtstr(char **, char **, size_t *, size_t *, 129296279Sjkim const char *, int, int, int); 130296279Sjkimstatic int fmtint(char **, char **, size_t *, size_t *, 131296279Sjkim LLONG, int, int, int, int); 132296279Sjkimstatic int fmtfp(char **, char **, size_t *, size_t *, 133296279Sjkim LDOUBLE, int, int, int); 134296279Sjkimstatic int doapr_outch(char **, char **, size_t *, size_t *, int); 135296279Sjkimstatic int _dopr(char **sbuffer, char **buffer, 136296279Sjkim size_t *maxlen, size_t *retlen, int *truncated, 137296279Sjkim 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 168296279Sjkimstatic int 169280297Sjkim_dopr(char **sbuffer, 170280297Sjkim char **buffer, 171280297Sjkim size_t *maxlen, 172280297Sjkim 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 199296279Sjkim if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 200296279Sjkim 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 } 306296279Sjkim if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, 307296279Sjkim max, flags)) 308296279Sjkim 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: 322280297Sjkim 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: 328280297Sjkim value = (LLONG) va_arg(args, unsigned int); 32959191Skris break; 33059191Skris } 331296279Sjkim if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 332296279Sjkim ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), 333296279Sjkim min, max, flags)) 334296279Sjkim 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); 341296279Sjkim if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, 342296279Sjkim flags)) 343296279Sjkim 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': 362296279Sjkim if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, 363296279Sjkim va_arg(args, int))) 364296279Sjkim return 0; 36559191Skris break; 36659191Skris case 's': 36759191Skris strvalue = va_arg(args, char *); 36868651Skris if (max < 0) { 369280297Sjkim if (buffer) 370280297Sjkim max = INT_MAX; 371280297Sjkim else 372280297Sjkim max = *maxlen; 373280297Sjkim } 374296279Sjkim if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, 375296279Sjkim flags, min, max)) 376296279Sjkim return 0; 37759191Skris break; 37859191Skris case 'p': 37959191Skris value = (long)va_arg(args, void *); 380296279Sjkim if (!fmtint(sbuffer, buffer, &currlen, maxlen, 381296279Sjkim value, 16, min, max, flags | DP_F_NUM)) 382296279Sjkim return 0; 38359191Skris break; 384280297Sjkim case 'n': /* XXX */ 38559191Skris if (cflags == DP_C_SHORT) { 38659191Skris short int *num; 38759191Skris num = va_arg(args, short int *); 388326663Sjkim *num = (short int)currlen; 38959191Skris } else if (cflags == DP_C_LONG) { /* XXX */ 39059191Skris long int *num; 39159191Skris num = va_arg(args, long int *); 392280297Sjkim *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 { 398280297Sjkim int *num; 39959191Skris num = va_arg(args, int *); 40059191Skris *num = currlen; 40159191Skris } 40259191Skris break; 40359191Skris case '%': 404296279Sjkim if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) 405296279Sjkim 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 } 426306195Sjkim /* 427306195Sjkim * We have to truncate if there is no dynamic buffer and we have filled the 428306195Sjkim * static buffer. 429306195Sjkim */ 430306195Sjkim if (buffer == NULL) { 431306195Sjkim *truncated = (currlen > *maxlen - 1); 432306195Sjkim if (*truncated) 433306195Sjkim currlen = *maxlen - 1; 434306195Sjkim } 435296279Sjkim if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) 436296279Sjkim return 0; 43768651Skris *retlen = currlen - 1; 438296279Sjkim return 1; 43959191Skris} 44059191Skris 441296279Sjkimstatic int 442280297Sjkimfmtstr(char **sbuffer, 443280297Sjkim char **buffer, 444280297Sjkim size_t *currlen, 445280297Sjkim size_t *maxlen, const char *value, int flags, int min, int max) 44659191Skris{ 447296279Sjkim int padlen; 448296279Sjkim size_t strln; 44959191Skris int cnt = 0; 45059191Skris 45159191Skris if (value == 0) 45259191Skris value = "<NULL>"; 453296279Sjkim 454296279Sjkim strln = strlen(value); 455296279Sjkim if (strln > INT_MAX) 456296279Sjkim strln = INT_MAX; 457296279Sjkim 45859191Skris padlen = min - strln; 459296279Sjkim if (min < 0 || padlen < 0) 46059191Skris padlen = 0; 46159191Skris if (flags & DP_F_MINUS) 46259191Skris padlen = -padlen; 46359191Skris 46459191Skris while ((padlen > 0) && (cnt < max)) { 465296279Sjkim if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 466296279Sjkim return 0; 46759191Skris --padlen; 46859191Skris ++cnt; 46959191Skris } 47059191Skris while (*value && (cnt < max)) { 471296279Sjkim if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) 472296279Sjkim return 0; 47359191Skris ++cnt; 47459191Skris } 47559191Skris while ((padlen < 0) && (cnt < max)) { 476296279Sjkim if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 477296279Sjkim return 0; 47859191Skris ++padlen; 47959191Skris ++cnt; 48059191Skris } 481296279Sjkim return 1; 48259191Skris} 48359191Skris 484296279Sjkimstatic int 485280297Sjkimfmtint(char **sbuffer, 486280297Sjkim char **buffer, 487280297Sjkim size_t *currlen, 488280297Sjkim size_t *maxlen, LLONG value, int base, int min, int max, int flags) 48959191Skris{ 49059191Skris int signvalue = 0; 491160814Ssimon const char *prefix = ""; 49259191Skris unsigned LLONG uvalue; 493280297Sjkim char convert[DECIMAL_SIZE(value) + 3]; 49459191Skris int place = 0; 49559191Skris int spadlen = 0; 49659191Skris int zpadlen = 0; 49759191Skris int caps = 0; 49859191Skris 49959191Skris if (max < 0) 50059191Skris max = 0; 50159191Skris uvalue = value; 50259191Skris if (!(flags & DP_F_UNSIGNED)) { 50359191Skris if (value < 0) { 50459191Skris signvalue = '-'; 505326663Sjkim uvalue = 0 - (unsigned LLONG)value; 50659191Skris } else if (flags & DP_F_PLUS) 50759191Skris signvalue = '+'; 50859191Skris else if (flags & DP_F_SPACE) 50959191Skris signvalue = ' '; 51059191Skris } 511120631Snectar if (flags & DP_F_NUM) { 512280297Sjkim if (base == 8) 513280297Sjkim prefix = "0"; 514280297Sjkim if (base == 16) 515280297Sjkim prefix = "0x"; 516120631Snectar } 51759191Skris if (flags & DP_F_UP) 51859191Skris caps = 1; 51959191Skris do { 520280297Sjkim convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef") 521280297Sjkim [uvalue % (unsigned)base]; 522280297Sjkim uvalue = (uvalue / (unsigned)base); 523160814Ssimon } while (uvalue && (place < (int)sizeof(convert))); 524160814Ssimon if (place == sizeof(convert)) 52559191Skris place--; 52659191Skris convert[place] = 0; 52759191Skris 52859191Skris zpadlen = max - place; 529280297Sjkim spadlen = 530280297Sjkim min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); 53159191Skris if (zpadlen < 0) 53259191Skris zpadlen = 0; 53359191Skris if (spadlen < 0) 53459191Skris spadlen = 0; 53559191Skris if (flags & DP_F_ZERO) { 53679998Skris zpadlen = OSSL_MAX(zpadlen, spadlen); 53759191Skris spadlen = 0; 53859191Skris } 53959191Skris if (flags & DP_F_MINUS) 54059191Skris spadlen = -spadlen; 54159191Skris 54259191Skris /* spaces */ 54359191Skris while (spadlen > 0) { 544296279Sjkim if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 545296279Sjkim return 0; 54659191Skris --spadlen; 54759191Skris } 54859191Skris 54959191Skris /* sign */ 55059191Skris if (signvalue) 551296279Sjkim if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 552296279Sjkim return 0; 55359191Skris 554120631Snectar /* prefix */ 555120631Snectar while (*prefix) { 556296279Sjkim if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) 557296279Sjkim return 0; 558280297Sjkim prefix++; 559120631Snectar } 560120631Snectar 56159191Skris /* zeros */ 56259191Skris if (zpadlen > 0) { 56359191Skris while (zpadlen > 0) { 564296279Sjkim if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 565296279Sjkim return 0; 56659191Skris --zpadlen; 56759191Skris } 56859191Skris } 56959191Skris /* digits */ 570296279Sjkim while (place > 0) { 571296279Sjkim if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) 572296279Sjkim return 0; 573296279Sjkim } 57459191Skris 57559191Skris /* left justified spaces */ 57659191Skris while (spadlen < 0) { 577296279Sjkim if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 578296279Sjkim return 0; 57959191Skris ++spadlen; 58059191Skris } 581296279Sjkim return 1; 58259191Skris} 58359191Skris 584280297Sjkimstatic LDOUBLE abs_val(LDOUBLE value) 58559191Skris{ 58659191Skris LDOUBLE result = value; 58759191Skris if (value < 0) 58859191Skris result = -value; 58959191Skris return result; 59059191Skris} 59159191Skris 592280297Sjkimstatic LDOUBLE pow_10(int in_exp) 59359191Skris{ 59459191Skris LDOUBLE result = 1; 595127128Snectar while (in_exp) { 59659191Skris result *= 10; 597127128Snectar in_exp--; 59859191Skris } 59959191Skris return result; 60059191Skris} 60159191Skris 602280297Sjkimstatic long roundv(LDOUBLE value) 60359191Skris{ 60459191Skris long intpart; 605280297Sjkim intpart = (long)value; 60659191Skris value = value - intpart; 60759191Skris if (value >= 0.5) 60859191Skris intpart++; 60959191Skris return intpart; 61059191Skris} 61159191Skris 612296279Sjkimstatic int 613280297Sjkimfmtfp(char **sbuffer, 614280297Sjkim char **buffer, 615280297Sjkim size_t *currlen, 616280297Sjkim size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags) 61759191Skris{ 61859191Skris int signvalue = 0; 61959191Skris LDOUBLE ufvalue; 62059191Skris char iconvert[20]; 62159191Skris char fconvert[20]; 62259191Skris int iplace = 0; 62359191Skris int fplace = 0; 62459191Skris int padlen = 0; 62559191Skris int zpadlen = 0; 62659191Skris long intpart; 62759191Skris long fracpart; 628160814Ssimon long max10; 62959191Skris 63059191Skris if (max < 0) 63159191Skris max = 6; 63259191Skris ufvalue = abs_val(fvalue); 63359191Skris if (fvalue < 0) 63459191Skris signvalue = '-'; 63559191Skris else if (flags & DP_F_PLUS) 63659191Skris signvalue = '+'; 63759191Skris else if (flags & DP_F_SPACE) 63859191Skris signvalue = ' '; 63959191Skris 64059191Skris intpart = (long)ufvalue; 64159191Skris 642280297Sjkim /* 643280297Sjkim * sorry, we only support 9 digits past the decimal because of our 644280297Sjkim * conversion method 645280297Sjkim */ 64659191Skris if (max > 9) 64759191Skris max = 9; 64859191Skris 649280297Sjkim /* 650280297Sjkim * we "cheat" by converting the fractional part to integer by multiplying 651280297Sjkim * by a factor of 10 652280297Sjkim */ 653160814Ssimon max10 = roundv(pow_10(max)); 654160814Ssimon fracpart = roundv(pow_10(max) * (ufvalue - intpart)); 65559191Skris 656160814Ssimon if (fracpart >= max10) { 65759191Skris intpart++; 658160814Ssimon fracpart -= max10; 65959191Skris } 66059191Skris 66159191Skris /* convert integer part */ 66259191Skris do { 663280297Sjkim iconvert[iplace++] = "0123456789"[intpart % 10]; 66459191Skris intpart = (intpart / 10); 665160814Ssimon } while (intpart && (iplace < (int)sizeof(iconvert))); 666331638Sjkim if (iplace == sizeof(iconvert)) 66759191Skris iplace--; 66859191Skris iconvert[iplace] = 0; 66959191Skris 67059191Skris /* convert fractional part */ 67159191Skris do { 672280297Sjkim fconvert[fplace++] = "0123456789"[fracpart % 10]; 67359191Skris fracpart = (fracpart / 10); 67479998Skris } while (fplace < max); 675331638Sjkim if (fplace == sizeof(fconvert)) 67659191Skris fplace--; 67759191Skris fconvert[fplace] = 0; 67859191Skris 67959191Skris /* -1 for decimal point, another -1 if we are printing a sign */ 68059191Skris padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 68159191Skris zpadlen = max - fplace; 68259191Skris if (zpadlen < 0) 68359191Skris zpadlen = 0; 68459191Skris if (padlen < 0) 68559191Skris padlen = 0; 68659191Skris if (flags & DP_F_MINUS) 68759191Skris padlen = -padlen; 68859191Skris 68959191Skris if ((flags & DP_F_ZERO) && (padlen > 0)) { 69059191Skris if (signvalue) { 691296279Sjkim if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 692296279Sjkim return 0; 69359191Skris --padlen; 69459191Skris signvalue = 0; 69559191Skris } 69659191Skris while (padlen > 0) { 697296279Sjkim if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 698296279Sjkim return 0; 69959191Skris --padlen; 70059191Skris } 70159191Skris } 70259191Skris while (padlen > 0) { 703296279Sjkim if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 704296279Sjkim return 0; 70559191Skris --padlen; 70659191Skris } 707296279Sjkim if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) 708296279Sjkim return 0; 70959191Skris 710296279Sjkim while (iplace > 0) { 711296279Sjkim if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) 712296279Sjkim return 0; 713296279Sjkim } 71459191Skris 71559191Skris /* 71659191Skris * Decimal point. This should probably use locale to find the correct 71759191Skris * char to print out. 71859191Skris */ 719120631Snectar if (max > 0 || (flags & DP_F_NUM)) { 720296279Sjkim if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) 721296279Sjkim return 0; 72259191Skris 723296279Sjkim while (fplace > 0) { 724296279Sjkim if(!doapr_outch(sbuffer, buffer, currlen, maxlen, 725296279Sjkim fconvert[--fplace])) 726296279Sjkim return 0; 727296279Sjkim } 72859191Skris } 72959191Skris while (zpadlen > 0) { 730296279Sjkim if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) 731296279Sjkim return 0; 73259191Skris --zpadlen; 73359191Skris } 73459191Skris 73559191Skris while (padlen < 0) { 736296279Sjkim if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) 737296279Sjkim return 0; 73859191Skris ++padlen; 73959191Skris } 740296279Sjkim return 1; 74159191Skris} 74259191Skris 743296279Sjkim#define BUFFER_INC 1024 744296279Sjkim 745296279Sjkimstatic int 746280297Sjkimdoapr_outch(char **sbuffer, 747280297Sjkim char **buffer, size_t *currlen, size_t *maxlen, int c) 74859191Skris{ 74968651Skris /* If we haven't at least one buffer, someone has doe a big booboo */ 75068651Skris assert(*sbuffer != NULL || buffer != NULL); 75159191Skris 752284283Sjkim /* |currlen| must always be <= |*maxlen| */ 753284283Sjkim assert(*currlen <= *maxlen); 754284283Sjkim 755284283Sjkim if (buffer && *currlen == *maxlen) { 756296279Sjkim if (*maxlen > INT_MAX - BUFFER_INC) 757296279Sjkim return 0; 758296279Sjkim 759296279Sjkim *maxlen += BUFFER_INC; 760284283Sjkim if (*buffer == NULL) { 761284283Sjkim *buffer = OPENSSL_malloc(*maxlen); 762296279Sjkim if (*buffer == NULL) 763296279Sjkim return 0; 764284283Sjkim if (*currlen > 0) { 765284283Sjkim assert(*sbuffer != NULL); 766284283Sjkim memcpy(*buffer, *sbuffer, *currlen); 767284283Sjkim } 768284283Sjkim *sbuffer = NULL; 769284283Sjkim } else { 770296279Sjkim char *tmpbuf; 771296279Sjkim tmpbuf = OPENSSL_realloc(*buffer, *maxlen); 772296279Sjkim if (tmpbuf == NULL) 773296279Sjkim return 0; 774296279Sjkim *buffer = tmpbuf; 775280297Sjkim } 77659191Skris } 77768651Skris 77868651Skris if (*currlen < *maxlen) { 779280297Sjkim if (*sbuffer) 780280297Sjkim (*sbuffer)[(*currlen)++] = (char)c; 781280297Sjkim else 782280297Sjkim (*buffer)[(*currlen)++] = (char)c; 78359191Skris } 78459191Skris 785296279Sjkim return 1; 78659191Skris} 78768651Skris 78868651Skris/***************************************************************************/ 78968651Skris 790280297Sjkimint BIO_printf(BIO *bio, const char *format, ...) 791280297Sjkim{ 792280297Sjkim va_list args; 793280297Sjkim int ret; 79468651Skris 795280297Sjkim va_start(args, format); 79668651Skris 797280297Sjkim ret = BIO_vprintf(bio, format, args); 79868651Skris 799280297Sjkim va_end(args); 800280297Sjkim return (ret); 801280297Sjkim} 80268651Skris 803280297Sjkimint BIO_vprintf(BIO *bio, const char *format, va_list args) 804280297Sjkim{ 805280297Sjkim int ret; 806280297Sjkim size_t retlen; 807280297Sjkim char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable 808280297Sjkim * in small-stack environments, like threads 809280297Sjkim * or DOS programs. */ 810280297Sjkim char *hugebufp = hugebuf; 811280297Sjkim size_t hugebufsize = sizeof(hugebuf); 812280297Sjkim char *dynbuf = NULL; 813280297Sjkim int ignored; 81468651Skris 815280297Sjkim dynbuf = NULL; 816280297Sjkim CRYPTO_push_info("doapr()"); 817296279Sjkim if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, 818296279Sjkim args)) { 819296279Sjkim OPENSSL_free(dynbuf); 820296279Sjkim return -1; 821296279Sjkim } 822280297Sjkim if (dynbuf) { 823280297Sjkim ret = BIO_write(bio, dynbuf, (int)retlen); 824280297Sjkim OPENSSL_free(dynbuf); 825280297Sjkim } else { 826280297Sjkim ret = BIO_write(bio, hugebuf, (int)retlen); 827280297Sjkim } 828280297Sjkim CRYPTO_pop_info(); 829280297Sjkim return (ret); 830280297Sjkim} 83168651Skris 832280297Sjkim/* 833280297Sjkim * As snprintf is not available everywhere, we provide our own 834280297Sjkim * implementation. This function has nothing to do with BIOs, but it's 835280297Sjkim * closely related to BIO_printf, and we need *some* name prefix ... (XXX the 836280297Sjkim * function should be renamed, but to what?) 837280297Sjkim */ 83868651Skrisint BIO_snprintf(char *buf, size_t n, const char *format, ...) 839280297Sjkim{ 840280297Sjkim va_list args; 841280297Sjkim int ret; 84268651Skris 843280297Sjkim va_start(args, format); 84468651Skris 845280297Sjkim ret = BIO_vsnprintf(buf, n, format, args); 84668651Skris 847280297Sjkim va_end(args); 848280297Sjkim return (ret); 849280297Sjkim} 85068651Skris 85168651Skrisint BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) 852280297Sjkim{ 853280297Sjkim size_t retlen; 854280297Sjkim int truncated; 85568651Skris 856296279Sjkim if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) 857296279Sjkim return -1; 85868651Skris 859280297Sjkim if (truncated) 860280297Sjkim /* 861280297Sjkim * In case of truncation, return -1 like traditional snprintf. 862280297Sjkim * (Current drafts for ISO/IEC 9899 say snprintf should return the 863280297Sjkim * number of characters that would have been written, had the buffer 864280297Sjkim * been large enough.) 865280297Sjkim */ 866280297Sjkim return -1; 867280297Sjkim else 868280297Sjkim return (retlen <= INT_MAX) ? (int)retlen : -1; 869280297Sjkim} 870