summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bio/b_print.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bio/b_print.c')
-rw-r--r--src/lib/libcrypto/bio/b_print.c631
1 files changed, 627 insertions, 4 deletions
diff --git a/src/lib/libcrypto/bio/b_print.c b/src/lib/libcrypto/bio/b_print.c
index f448004298..2a5e8b58c9 100644
--- a/src/lib/libcrypto/bio/b_print.c
+++ b/src/lib/libcrypto/bio/b_print.c
@@ -62,26 +62,649 @@
62 62
63#include <stdio.h> 63#include <stdio.h>
64#include <stdarg.h> 64#include <stdarg.h>
65#include <string.h>
66#include <ctype.h>
65#include "cryptlib.h" 67#include "cryptlib.h"
68#ifndef NO_SYS_TYPES_H
69#include <sys/types.h>
70#endif
66#include <openssl/bio.h> 71#include <openssl/bio.h>
67 72
73#ifdef BN_LLONG
74# ifndef HAVE_LONG_LONG
75# define HAVE_LONG_LONG
76# endif
77#endif
78
79static void dopr (char *buffer, size_t maxlen, size_t *retlen,
80 const char *format, va_list args);
81
68int BIO_printf (BIO *bio, ...) 82int BIO_printf (BIO *bio, ...)
69 { 83 {
70 va_list args; 84 va_list args;
71 char *format; 85 char *format;
72 int ret; 86 int ret;
87 size_t retlen;
73 MS_STATIC char hugebuf[1024*2]; /* 10k in one chunk is the limit */ 88 MS_STATIC char hugebuf[1024*2]; /* 10k in one chunk is the limit */
74 89
75 va_start(args, bio); 90 va_start(args, bio);
76 format=va_arg(args, char *); 91 format=va_arg(args, char *);
77 92
78 hugebuf[0]='\0'; 93 hugebuf[0]='\0';
79 94 dopr(hugebuf, sizeof(hugebuf), &retlen, format, args);
80 vsprintf(hugebuf,format,args); 95 ret=BIO_write(bio, hugebuf, (int)retlen);
81
82 ret=BIO_write(bio,hugebuf,strlen(hugebuf));
83 96
84 va_end(args); 97 va_end(args);
85 return(ret); 98 return(ret);
86 } 99 }
87 100
101/*
102 * Copyright Patrick Powell 1995
103 * This code is based on code written by Patrick Powell <papowell@astart.com>
104 * It may be used for any purpose as long as this notice remains intact
105 * on all source code distributions.
106 */
107
108/*
109 * This code contains numerious changes and enhancements which were
110 * made by lots of contributors over the last years to Patrick Powell's
111 * original code:
112 *
113 * o Patrick Powell <papowell@astart.com> (1995)
114 * o Brandon Long <blong@fiction.net> (1996, for Mutt)
115 * o Thomas Roessler <roessler@guug.de> (1998, for Mutt)
116 * o Michael Elkins <me@cs.hmc.edu> (1998, for Mutt)
117 * o Andrew Tridgell <tridge@samba.org> (1998, for Samba)
118 * o Luke Mewburn <lukem@netbsd.org> (1999, for LukemFTP)
119 * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
120 */
121
122#if HAVE_LONG_DOUBLE
123#define LDOUBLE long double
124#else
125#define LDOUBLE double
126#endif
127
128#if HAVE_LONG_LONG
129#define LLONG long long
130#else
131#define LLONG long
132#endif
133
134static void fmtstr (char *, size_t *, size_t, char *, int, int, int);
135static void fmtint (char *, size_t *, size_t, LLONG, int, int, int, int);
136static void fmtfp (char *, size_t *, size_t, LDOUBLE, int, int, int);
137static void dopr_outch (char *, size_t *, size_t, int);
138
139/* format read states */
140#define DP_S_DEFAULT 0
141#define DP_S_FLAGS 1
142#define DP_S_MIN 2
143#define DP_S_DOT 3
144#define DP_S_MAX 4
145#define DP_S_MOD 5
146#define DP_S_CONV 6
147#define DP_S_DONE 7
148
149/* format flags - Bits */
150#define DP_F_MINUS (1 << 0)
151#define DP_F_PLUS (1 << 1)
152#define DP_F_SPACE (1 << 2)
153#define DP_F_NUM (1 << 3)
154#define DP_F_ZERO (1 << 4)
155#define DP_F_UP (1 << 5)
156#define DP_F_UNSIGNED (1 << 6)
157
158/* conversion flags */
159#define DP_C_SHORT 1
160#define DP_C_LONG 2
161#define DP_C_LDOUBLE 3
162#define DP_C_LLONG 4
163
164/* some handy macros */
165#define char_to_int(p) (p - '0')
166#define MAX(p,q) ((p >= q) ? p : q)
167
168static void
169dopr(
170 char *buffer,
171 size_t maxlen,
172 size_t *retlen,
173 const char *format,
174 va_list args)
175{
176 char ch;
177 LLONG value;
178 LDOUBLE fvalue;
179 char *strvalue;
180 int min;
181 int max;
182 int state;
183 int flags;
184 int cflags;
185 size_t currlen;
186
187 state = DP_S_DEFAULT;
188 flags = currlen = cflags = min = 0;
189 max = -1;
190 ch = *format++;
191
192 while (state != DP_S_DONE) {
193 if ((ch == '\0') || (currlen >= maxlen))
194 state = DP_S_DONE;
195
196 switch (state) {
197 case DP_S_DEFAULT:
198 if (ch == '%')
199 state = DP_S_FLAGS;
200 else
201 dopr_outch(buffer, &currlen, maxlen, ch);
202 ch = *format++;
203 break;
204 case DP_S_FLAGS:
205 switch (ch) {
206 case '-':
207 flags |= DP_F_MINUS;
208 ch = *format++;
209 break;
210 case '+':
211 flags |= DP_F_PLUS;
212 ch = *format++;
213 break;
214 case ' ':
215 flags |= DP_F_SPACE;
216 ch = *format++;
217 break;
218 case '#':
219 flags |= DP_F_NUM;
220 ch = *format++;
221 break;
222 case '0':
223 flags |= DP_F_ZERO;
224 ch = *format++;
225 break;
226 default:
227 state = DP_S_MIN;
228 break;
229 }
230 break;
231 case DP_S_MIN:
232 if (isdigit((unsigned char)ch)) {
233 min = 10 * min + char_to_int(ch);
234 ch = *format++;
235 } else if (ch == '*') {
236 min = va_arg(args, int);
237 ch = *format++;
238 state = DP_S_DOT;
239 } else
240 state = DP_S_DOT;
241 break;
242 case DP_S_DOT:
243 if (ch == '.') {
244 state = DP_S_MAX;
245 ch = *format++;
246 } else
247 state = DP_S_MOD;
248 break;
249 case DP_S_MAX:
250 if (isdigit((unsigned char)ch)) {
251 if (max < 0)
252 max = 0;
253 max = 10 * max + char_to_int(ch);
254 ch = *format++;
255 } else if (ch == '*') {
256 max = va_arg(args, int);
257 ch = *format++;
258 state = DP_S_MOD;
259 } else
260 state = DP_S_MOD;
261 break;
262 case DP_S_MOD:
263 switch (ch) {
264 case 'h':
265 cflags = DP_C_SHORT;
266 ch = *format++;
267 break;
268 case 'l':
269 if (*format == 'l') {
270 cflags = DP_C_LLONG;
271 format++;
272 } else
273 cflags = DP_C_LONG;
274 ch = *format++;
275 break;
276 case 'q':
277 cflags = DP_C_LLONG;
278 ch = *format++;
279 break;
280 case 'L':
281 cflags = DP_C_LDOUBLE;
282 ch = *format++;
283 break;
284 default:
285 break;
286 }
287 state = DP_S_CONV;
288 break;
289 case DP_S_CONV:
290 switch (ch) {
291 case 'd':
292 case 'i':
293 switch (cflags) {
294 case DP_C_SHORT:
295 value = (short int)va_arg(args, int);
296 break;
297 case DP_C_LONG:
298 value = va_arg(args, long int);
299 break;
300 case DP_C_LLONG:
301 value = va_arg(args, LLONG);
302 break;
303 default:
304 value = va_arg(args, int);
305 break;
306 }
307 fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);
308 break;
309 case 'X':
310 flags |= DP_F_UP;
311 /* FALLTHROUGH */
312 case 'x':
313 case 'o':
314 case 'u':
315 flags |= DP_F_UNSIGNED;
316 switch (cflags) {
317 case DP_C_SHORT:
318 value = (unsigned short int)va_arg(args, unsigned int);
319 break;
320 case DP_C_LONG:
321 value = (LLONG) va_arg(args,
322 unsigned long int);
323 break;
324 case DP_C_LLONG:
325 value = va_arg(args, unsigned LLONG);
326 break;
327 default:
328 value = (LLONG) va_arg(args,
329 unsigned int);
330 break;
331 }
332 fmtint(buffer, &currlen, maxlen, value,
333 ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
334 min, max, flags);
335 break;
336 case 'f':
337 if (cflags == DP_C_LDOUBLE)
338 fvalue = va_arg(args, LDOUBLE);
339 else
340 fvalue = va_arg(args, double);
341 fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);
342 break;
343 case 'E':
344 flags |= DP_F_UP;
345 case 'e':
346 if (cflags == DP_C_LDOUBLE)
347 fvalue = va_arg(args, LDOUBLE);
348 else
349 fvalue = va_arg(args, double);
350 break;
351 case 'G':
352 flags |= DP_F_UP;
353 case 'g':
354 if (cflags == DP_C_LDOUBLE)
355 fvalue = va_arg(args, LDOUBLE);
356 else
357 fvalue = va_arg(args, double);
358 break;
359 case 'c':
360 dopr_outch(buffer, &currlen, maxlen,
361 va_arg(args, int));
362 break;
363 case 's':
364 strvalue = va_arg(args, char *);
365 if (max < 0)
366 max = maxlen;
367 fmtstr(buffer, &currlen, maxlen, strvalue,
368 flags, min, max);
369 break;
370 case 'p':
371 value = (long)va_arg(args, void *);
372 fmtint(buffer, &currlen, maxlen,
373 value, 16, min, max, flags);
374 break;
375 case 'n': /* XXX */
376 if (cflags == DP_C_SHORT) {
377 short int *num;
378 num = va_arg(args, short int *);
379 *num = currlen;
380 } else if (cflags == DP_C_LONG) { /* XXX */
381 long int *num;
382 num = va_arg(args, long int *);
383 *num = (long int) currlen;
384 } else if (cflags == DP_C_LLONG) { /* XXX */
385 LLONG *num;
386 num = va_arg(args, LLONG *);
387 *num = (LLONG) currlen;
388 } else {
389 int *num;
390 num = va_arg(args, int *);
391 *num = currlen;
392 }
393 break;
394 case '%':
395 dopr_outch(buffer, &currlen, maxlen, ch);
396 break;
397 case 'w':
398 /* not supported yet, treat as next char */
399 ch = *format++;
400 break;
401 default:
402 /* unknown, skip */
403 break;
404 }
405 ch = *format++;
406 state = DP_S_DEFAULT;
407 flags = cflags = min = 0;
408 max = -1;
409 break;
410 case DP_S_DONE:
411 break;
412 default:
413 break;
414 }
415 }
416 if (currlen >= maxlen - 1)
417 currlen = maxlen - 1;
418 buffer[currlen] = '\0';
419 *retlen = currlen;
420 return;
421}
422
423static void
424fmtstr(
425 char *buffer,
426 size_t *currlen,
427 size_t maxlen,
428 char *value,
429 int flags,
430 int min,
431 int max)
432{
433 int padlen, strln;
434 int cnt = 0;
435
436 if (value == 0)
437 value = "<NULL>";
438 for (strln = 0; value[strln]; ++strln)
439 ;
440 padlen = min - strln;
441 if (padlen < 0)
442 padlen = 0;
443 if (flags & DP_F_MINUS)
444 padlen = -padlen;
445
446 while ((padlen > 0) && (cnt < max)) {
447 dopr_outch(buffer, currlen, maxlen, ' ');
448 --padlen;
449 ++cnt;
450 }
451 while (*value && (cnt < max)) {
452 dopr_outch(buffer, currlen, maxlen, *value++);
453 ++cnt;
454 }
455 while ((padlen < 0) && (cnt < max)) {
456 dopr_outch(buffer, currlen, maxlen, ' ');
457 ++padlen;
458 ++cnt;
459 }
460}
461
462static void
463fmtint(
464 char *buffer,
465 size_t *currlen,
466 size_t maxlen,
467 LLONG value,
468 int base,
469 int min,
470 int max,
471 int flags)
472{
473 int signvalue = 0;
474 unsigned LLONG uvalue;
475 char convert[20];
476 int place = 0;
477 int spadlen = 0;
478 int zpadlen = 0;
479 int caps = 0;
480
481 if (max < 0)
482 max = 0;
483 uvalue = value;
484 if (!(flags & DP_F_UNSIGNED)) {
485 if (value < 0) {
486 signvalue = '-';
487 uvalue = -value;
488 } else if (flags & DP_F_PLUS)
489 signvalue = '+';
490 else if (flags & DP_F_SPACE)
491 signvalue = ' ';
492 }
493 if (flags & DP_F_UP)
494 caps = 1;
495 do {
496 convert[place++] =
497 (caps ? "0123456789ABCDEF" : "0123456789abcdef")
498 [uvalue % (unsigned) base];
499 uvalue = (uvalue / (unsigned) base);
500 } while (uvalue && (place < 20));
501 if (place == 20)
502 place--;
503 convert[place] = 0;
504
505 zpadlen = max - place;
506 spadlen = min - MAX(max, place) - (signvalue ? 1 : 0);
507 if (zpadlen < 0)
508 zpadlen = 0;
509 if (spadlen < 0)
510 spadlen = 0;
511 if (flags & DP_F_ZERO) {
512 zpadlen = MAX(zpadlen, spadlen);
513 spadlen = 0;
514 }
515 if (flags & DP_F_MINUS)
516 spadlen = -spadlen;
517
518 /* spaces */
519 while (spadlen > 0) {
520 dopr_outch(buffer, currlen, maxlen, ' ');
521 --spadlen;
522 }
523
524 /* sign */
525 if (signvalue)
526 dopr_outch(buffer, currlen, maxlen, signvalue);
527
528 /* zeros */
529 if (zpadlen > 0) {
530 while (zpadlen > 0) {
531 dopr_outch(buffer, currlen, maxlen, '0');
532 --zpadlen;
533 }
534 }
535 /* digits */
536 while (place > 0)
537 dopr_outch(buffer, currlen, maxlen, convert[--place]);
538
539 /* left justified spaces */
540 while (spadlen < 0) {
541 dopr_outch(buffer, currlen, maxlen, ' ');
542 ++spadlen;
543 }
544 return;
545}
546
547static LDOUBLE
548abs_val(LDOUBLE value)
549{
550 LDOUBLE result = value;
551 if (value < 0)
552 result = -value;
553 return result;
554}
555
556static LDOUBLE
557pow10(int exp)
558{
559 LDOUBLE result = 1;
560 while (exp) {
561 result *= 10;
562 exp--;
563 }
564 return result;
565}
566
567static long
568round(LDOUBLE value)
569{
570 long intpart;
571 intpart = (long) value;
572 value = value - intpart;
573 if (value >= 0.5)
574 intpart++;
575 return intpart;
576}
577
578static void
579fmtfp(
580 char *buffer,
581 size_t *currlen,
582 size_t maxlen,
583 LDOUBLE fvalue,
584 int min,
585 int max,
586 int flags)
587{
588 int signvalue = 0;
589 LDOUBLE ufvalue;
590 char iconvert[20];
591 char fconvert[20];
592 int iplace = 0;
593 int fplace = 0;
594 int padlen = 0;
595 int zpadlen = 0;
596 int caps = 0;
597 long intpart;
598 long fracpart;
599
600 if (max < 0)
601 max = 6;
602 ufvalue = abs_val(fvalue);
603 if (fvalue < 0)
604 signvalue = '-';
605 else if (flags & DP_F_PLUS)
606 signvalue = '+';
607 else if (flags & DP_F_SPACE)
608 signvalue = ' ';
609
610 intpart = (long)ufvalue;
611
612 /* sorry, we only support 9 digits past the decimal because of our
613 conversion method */
614 if (max > 9)
615 max = 9;
616
617 /* we "cheat" by converting the fractional part to integer by
618 multiplying by a factor of 10 */
619 fracpart = round((pow10(max)) * (ufvalue - intpart));
620
621 if (fracpart >= pow10(max)) {
622 intpart++;
623 fracpart -= (long)pow10(max);
624 }
625
626 /* convert integer part */
627 do {
628 iconvert[iplace++] =
629 (caps ? "0123456789ABCDEF"
630 : "0123456789abcdef")[intpart % 10];
631 intpart = (intpart / 10);
632 } while (intpart && (iplace < 20));
633 if (iplace == 20)
634 iplace--;
635 iconvert[iplace] = 0;
636
637 /* convert fractional part */
638 do {
639 fconvert[fplace++] =
640 (caps ? "0123456789ABCDEF"
641 : "0123456789abcdef")[fracpart % 10];
642 fracpart = (fracpart / 10);
643 } while (fracpart && (fplace < 20));
644 if (fplace == 20)
645 fplace--;
646 fconvert[fplace] = 0;
647
648 /* -1 for decimal point, another -1 if we are printing a sign */
649 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
650 zpadlen = max - fplace;
651 if (zpadlen < 0)
652 zpadlen = 0;
653 if (padlen < 0)
654 padlen = 0;
655 if (flags & DP_F_MINUS)
656 padlen = -padlen;
657
658 if ((flags & DP_F_ZERO) && (padlen > 0)) {
659 if (signvalue) {
660 dopr_outch(buffer, currlen, maxlen, signvalue);
661 --padlen;
662 signvalue = 0;
663 }
664 while (padlen > 0) {
665 dopr_outch(buffer, currlen, maxlen, '0');
666 --padlen;
667 }
668 }
669 while (padlen > 0) {
670 dopr_outch(buffer, currlen, maxlen, ' ');
671 --padlen;
672 }
673 if (signvalue)
674 dopr_outch(buffer, currlen, maxlen, signvalue);
675
676 while (iplace > 0)
677 dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);
678
679 /*
680 * Decimal point. This should probably use locale to find the correct
681 * char to print out.
682 */
683 if (max > 0) {
684 dopr_outch(buffer, currlen, maxlen, '.');
685
686 while (fplace > 0)
687 dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);
688 }
689 while (zpadlen > 0) {
690 dopr_outch(buffer, currlen, maxlen, '0');
691 --zpadlen;
692 }
693
694 while (padlen < 0) {
695 dopr_outch(buffer, currlen, maxlen, ' ');
696 ++padlen;
697 }
698}
699
700static void
701dopr_outch(
702 char *buffer,
703 size_t *currlen,
704 size_t maxlen,
705 int c)
706{
707 if (*currlen < maxlen)
708 buffer[(*currlen)++] = (char)c;
709 return;
710}