1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr.h" 18#include "apr_private.h" 19 20#include "apr_lib.h" 21#include "apr_strings.h" 22#include "apr_network_io.h" 23#include "apr_portable.h" 24#include "apr_errno.h" 25#include <math.h> 26#if APR_HAVE_CTYPE_H 27#include <ctype.h> 28#endif 29#if APR_HAVE_NETINET_IN_H 30#include <netinet/in.h> 31#endif 32#if APR_HAVE_SYS_SOCKET_H 33#include <sys/socket.h> 34#endif 35#if APR_HAVE_ARPA_INET_H 36#include <arpa/inet.h> 37#endif 38#if APR_HAVE_LIMITS_H 39#include <limits.h> 40#endif 41#if APR_HAVE_STRING_H 42#include <string.h> 43#endif 44 45typedef enum { 46 NO = 0, YES = 1 47} boolean_e; 48 49#ifndef FALSE 50#define FALSE 0 51#endif 52#ifndef TRUE 53#define TRUE 1 54#endif 55#define NUL '\0' 56 57static const char null_string[] = "(null)"; 58#define S_NULL ((char *)null_string) 59#define S_NULL_LEN 6 60 61#define FLOAT_DIGITS 6 62#define EXPONENT_LENGTH 10 63 64/* 65 * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions 66 * 67 * NOTICE: this is a magic number; do not decrease it 68 */ 69#define NUM_BUF_SIZE 512 70 71/* 72 * cvt - IEEE floating point formatting routines. 73 * Derived from UNIX V7, Copyright(C) Caldera International Inc. 74 */ 75 76/* 77 * apr_ecvt converts to decimal 78 * the number of digits is specified by ndigit 79 * decpt is set to the position of the decimal point 80 * sign is set to 0 for positive, 1 for negative 81 */ 82 83#define NDIG 80 84 85/* buf must have at least NDIG bytes */ 86static char *apr_cvt(double arg, int ndigits, int *decpt, int *sign, 87 int eflag, char *buf) 88{ 89 register int r2; 90 double fi, fj; 91 register char *p, *p1; 92 93 if (ndigits >= NDIG - 1) 94 ndigits = NDIG - 2; 95 r2 = 0; 96 *sign = 0; 97 p = &buf[0]; 98 if (arg < 0) { 99 *sign = 1; 100 arg = -arg; 101 } 102 arg = modf(arg, &fi); 103 /* 104 * Do integer part 105 */ 106 if (fi != 0) { 107 p1 = &buf[NDIG]; 108 while (p1 > &buf[0] && fi != 0) { 109 fj = modf(fi / 10, &fi); 110 *--p1 = (int) ((fj + .03) * 10) + '0'; 111 r2++; 112 } 113 while (p1 < &buf[NDIG]) 114 *p++ = *p1++; 115 } 116 else if (arg > 0) { 117 while ((fj = arg * 10) < 1) { 118 arg = fj; 119 r2--; 120 } 121 } 122 p1 = &buf[ndigits]; 123 if (eflag == 0) 124 p1 += r2; 125 if (p1 < &buf[0]) { 126 *decpt = -ndigits; 127 buf[0] = '\0'; 128 return (buf); 129 } 130 *decpt = r2; 131 while (p <= p1 && p < &buf[NDIG]) { 132 arg *= 10; 133 arg = modf(arg, &fj); 134 *p++ = (int) fj + '0'; 135 } 136 if (p1 >= &buf[NDIG]) { 137 buf[NDIG - 1] = '\0'; 138 return (buf); 139 } 140 p = p1; 141 *p1 += 5; 142 while (*p1 > '9') { 143 *p1 = '0'; 144 if (p1 > buf) 145 ++ * --p1; 146 else { 147 *p1 = '1'; 148 (*decpt)++; 149 if (eflag == 0) { 150 if (p > buf) 151 *p = '0'; 152 p++; 153 } 154 } 155 } 156 *p = '\0'; 157 return (buf); 158} 159 160static char *apr_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf) 161{ 162 return (apr_cvt(arg, ndigits, decpt, sign, 1, buf)); 163} 164 165static char *apr_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf) 166{ 167 return (apr_cvt(arg, ndigits, decpt, sign, 0, buf)); 168} 169 170/* 171 * apr_gcvt - Floating output conversion to 172 * minimal length string 173 */ 174 175static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform) 176{ 177 int sign, decpt; 178 register char *p1, *p2; 179 register int i; 180 char buf1[NDIG]; 181 182 p1 = apr_ecvt(number, ndigit, &decpt, &sign, buf1); 183 p2 = buf; 184 if (sign) 185 *p2++ = '-'; 186 for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--) 187 ndigit--; 188 if ((decpt >= 0 && decpt - ndigit > 4) 189 || (decpt < 0 && decpt < -3)) { /* use E-style */ 190 decpt--; 191 *p2++ = *p1++; 192 *p2++ = '.'; 193 for (i = 1; i < ndigit; i++) 194 *p2++ = *p1++; 195 *p2++ = 'e'; 196 if (decpt < 0) { 197 decpt = -decpt; 198 *p2++ = '-'; 199 } 200 else 201 *p2++ = '+'; 202 if (decpt / 100 > 0) 203 *p2++ = decpt / 100 + '0'; 204 if (decpt / 10 > 0) 205 *p2++ = (decpt % 100) / 10 + '0'; 206 *p2++ = decpt % 10 + '0'; 207 } 208 else { 209 if (decpt <= 0) { 210 if (*p1 != '0') 211 *p2++ = '.'; 212 while (decpt < 0) { 213 decpt++; 214 *p2++ = '0'; 215 } 216 } 217 for (i = 1; i <= ndigit; i++) { 218 *p2++ = *p1++; 219 if (i == decpt) 220 *p2++ = '.'; 221 } 222 if (ndigit < decpt) { 223 while (ndigit++ < decpt) 224 *p2++ = '0'; 225 *p2++ = '.'; 226 } 227 } 228 if (p2[-1] == '.' && !altform) 229 p2--; 230 *p2 = '\0'; 231 return (buf); 232} 233 234/* 235 * The INS_CHAR macro inserts a character in the buffer and writes 236 * the buffer back to disk if necessary 237 * It uses the char pointers sp and bep: 238 * sp points to the next available character in the buffer 239 * bep points to the end-of-buffer+1 240 * While using this macro, note that the nextb pointer is NOT updated. 241 * 242 * NOTE: Evaluation of the c argument should not have any side-effects 243 */ 244#define INS_CHAR(c, sp, bep, cc) \ 245{ \ 246 if (sp) { \ 247 if (sp >= bep) { \ 248 vbuff->curpos = sp; \ 249 if (flush_func(vbuff)) \ 250 return -1; \ 251 sp = vbuff->curpos; \ 252 bep = vbuff->endpos; \ 253 } \ 254 *sp++ = (c); \ 255 } \ 256 cc++; \ 257} 258 259#define NUM(c) (c - '0') 260 261#define STR_TO_DEC(str, num) \ 262 num = NUM(*str++); \ 263 while (apr_isdigit(*str)) \ 264 { \ 265 num *= 10 ; \ 266 num += NUM(*str++); \ 267 } 268 269/* 270 * This macro does zero padding so that the precision 271 * requirement is satisfied. The padding is done by 272 * adding '0's to the left of the string that is going 273 * to be printed. We don't allow precision to be large 274 * enough that we continue past the start of s. 275 * 276 * NOTE: this makes use of the magic info that s is 277 * always based on num_buf with a size of NUM_BUF_SIZE. 278 */ 279#define FIX_PRECISION(adjust, precision, s, s_len) \ 280 if (adjust) { \ 281 apr_size_t p = (precision + 1 < NUM_BUF_SIZE) \ 282 ? precision : NUM_BUF_SIZE - 1; \ 283 while (s_len < p) \ 284 { \ 285 *--s = '0'; \ 286 s_len++; \ 287 } \ 288 } 289 290/* 291 * Macro that does padding. The padding is done by printing 292 * the character ch. 293 */ 294#define PAD(width, len, ch) \ 295do \ 296{ \ 297 INS_CHAR(ch, sp, bep, cc); \ 298 width--; \ 299} \ 300while (width > len) 301 302/* 303 * Prefix the character ch to the string str 304 * Increase length 305 * Set the has_prefix flag 306 */ 307#define PREFIX(str, length, ch) \ 308 *--str = ch; \ 309 length++; \ 310 has_prefix=YES; 311 312 313/* 314 * Convert num to its decimal format. 315 * Return value: 316 * - a pointer to a string containing the number (no sign) 317 * - len contains the length of the string 318 * - is_negative is set to TRUE or FALSE depending on the sign 319 * of the number (always set to FALSE if is_unsigned is TRUE) 320 * 321 * The caller provides a buffer for the string: that is the buf_end argument 322 * which is a pointer to the END of the buffer + 1 (i.e. if the buffer 323 * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) 324 * 325 * Note: we have 2 versions. One is used when we need to use quads 326 * (conv_10_quad), the other when we don't (conv_10). We're assuming the 327 * latter is faster. 328 */ 329static char *conv_10(register apr_int32_t num, register int is_unsigned, 330 register int *is_negative, char *buf_end, 331 register apr_size_t *len) 332{ 333 register char *p = buf_end; 334 register apr_uint32_t magnitude = num; 335 336 if (is_unsigned) { 337 *is_negative = FALSE; 338 } 339 else { 340 *is_negative = (num < 0); 341 342 /* 343 * On a 2's complement machine, negating the most negative integer 344 * results in a number that cannot be represented as a signed integer. 345 * Here is what we do to obtain the number's magnitude: 346 * a. add 1 to the number 347 * b. negate it (becomes positive) 348 * c. convert it to unsigned 349 * d. add 1 350 */ 351 if (*is_negative) { 352 apr_int32_t t = num + 1; 353 magnitude = ((apr_uint32_t) -t) + 1; 354 } 355 } 356 357 /* 358 * We use a do-while loop so that we write at least 1 digit 359 */ 360 do { 361 register apr_uint32_t new_magnitude = magnitude / 10; 362 363 *--p = (char) (magnitude - new_magnitude * 10 + '0'); 364 magnitude = new_magnitude; 365 } 366 while (magnitude); 367 368 *len = buf_end - p; 369 return (p); 370} 371 372static char *conv_10_quad(apr_int64_t num, register int is_unsigned, 373 register int *is_negative, char *buf_end, 374 register apr_size_t *len) 375{ 376 register char *p = buf_end; 377 apr_uint64_t magnitude = num; 378 379 /* 380 * We see if we can use the faster non-quad version by checking the 381 * number against the largest long value it can be. If <=, we 382 * punt to the quicker version. 383 */ 384 if ((magnitude <= APR_UINT32_MAX && is_unsigned) 385 || (num <= APR_INT32_MAX && num >= APR_INT32_MIN && !is_unsigned)) 386 return(conv_10((apr_int32_t)num, is_unsigned, is_negative, buf_end, len)); 387 388 if (is_unsigned) { 389 *is_negative = FALSE; 390 } 391 else { 392 *is_negative = (num < 0); 393 394 /* 395 * On a 2's complement machine, negating the most negative integer 396 * results in a number that cannot be represented as a signed integer. 397 * Here is what we do to obtain the number's magnitude: 398 * a. add 1 to the number 399 * b. negate it (becomes positive) 400 * c. convert it to unsigned 401 * d. add 1 402 */ 403 if (*is_negative) { 404 apr_int64_t t = num + 1; 405 magnitude = ((apr_uint64_t) -t) + 1; 406 } 407 } 408 409 /* 410 * We use a do-while loop so that we write at least 1 digit 411 */ 412 do { 413 apr_uint64_t new_magnitude = magnitude / 10; 414 415 *--p = (char) (magnitude - new_magnitude * 10 + '0'); 416 magnitude = new_magnitude; 417 } 418 while (magnitude); 419 420 *len = buf_end - p; 421 return (p); 422} 423 424static char *conv_in_addr(struct in_addr *ia, char *buf_end, apr_size_t *len) 425{ 426 unsigned addr = ntohl(ia->s_addr); 427 char *p = buf_end; 428 int is_negative; 429 apr_size_t sub_len; 430 431 p = conv_10((addr & 0x000000FF) , TRUE, &is_negative, p, &sub_len); 432 *--p = '.'; 433 p = conv_10((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p, &sub_len); 434 *--p = '.'; 435 p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len); 436 *--p = '.'; 437 p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len); 438 439 *len = buf_end - p; 440 return (p); 441} 442 443 444/* Must be passed a buffer of size NUM_BUF_SIZE where buf_end points 445 * to 1 byte past the end of the buffer. */ 446static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, apr_size_t *len) 447{ 448 char *p = buf_end; 449 int is_negative; 450 apr_size_t sub_len; 451 char *ipaddr_str; 452 453 p = conv_10(sa->port, TRUE, &is_negative, p, &sub_len); 454 *--p = ':'; 455 ipaddr_str = buf_end - NUM_BUF_SIZE; 456 if (apr_sockaddr_ip_getbuf(ipaddr_str, sa->addr_str_len, sa)) { 457 /* Should only fail if the buffer is too small, which it 458 * should not be; but fail safe anyway: */ 459 *--p = '?'; 460 *len = buf_end - p; 461 return p; 462 } 463 sub_len = strlen(ipaddr_str); 464#if APR_HAVE_IPV6 465 if (sa->family == APR_INET6 && 466 !IN6_IS_ADDR_V4MAPPED(&sa->sa.sin6.sin6_addr)) { 467 *(p - 1) = ']'; 468 p -= sub_len + 2; 469 *p = '['; 470 memcpy(p + 1, ipaddr_str, sub_len); 471 } 472 else 473#endif 474 { 475 p -= sub_len; 476 memcpy(p, ipaddr_str, sub_len); 477 } 478 479 *len = buf_end - p; 480 return (p); 481} 482 483 484 485#if APR_HAS_THREADS 486static char *conv_os_thread_t(apr_os_thread_t *tid, char *buf_end, apr_size_t *len) 487{ 488 union { 489 apr_os_thread_t tid; 490 apr_uint64_t u64; 491 apr_uint32_t u32; 492 } u; 493 int is_negative; 494 495 u.tid = *tid; 496 switch(sizeof(u.tid)) { 497 case sizeof(apr_int32_t): 498 return conv_10(u.u32, TRUE, &is_negative, buf_end, len); 499 case sizeof(apr_int64_t): 500 return conv_10_quad(u.u64, TRUE, &is_negative, buf_end, len); 501 default: 502 /* not implemented; stick 0 in the buffer */ 503 return conv_10(0, TRUE, &is_negative, buf_end, len); 504 } 505} 506#endif 507 508 509 510/* 511 * Convert a floating point number to a string formats 'f', 'e' or 'E'. 512 * The result is placed in buf, and len denotes the length of the string 513 * The sign is returned in the is_negative argument (and is not placed 514 * in buf). 515 */ 516static char *conv_fp(register char format, register double num, 517 boolean_e add_dp, int precision, int *is_negative, 518 char *buf, apr_size_t *len) 519{ 520 register char *s = buf; 521 register char *p; 522 int decimal_point; 523 char buf1[NDIG]; 524 525 if (format == 'f') 526 p = apr_fcvt(num, precision, &decimal_point, is_negative, buf1); 527 else /* either e or E format */ 528 p = apr_ecvt(num, precision + 1, &decimal_point, is_negative, buf1); 529 530 /* 531 * Check for Infinity and NaN 532 */ 533 if (apr_isalpha(*p)) { 534 *len = strlen(p); 535 memcpy(buf, p, *len + 1); 536 *is_negative = FALSE; 537 return (buf); 538 } 539 540 if (format == 'f') { 541 if (decimal_point <= 0) { 542 *s++ = '0'; 543 if (precision > 0) { 544 *s++ = '.'; 545 while (decimal_point++ < 0) 546 *s++ = '0'; 547 } 548 else if (add_dp) 549 *s++ = '.'; 550 } 551 else { 552 while (decimal_point-- > 0) 553 *s++ = *p++; 554 if (precision > 0 || add_dp) 555 *s++ = '.'; 556 } 557 } 558 else { 559 *s++ = *p++; 560 if (precision > 0 || add_dp) 561 *s++ = '.'; 562 } 563 564 /* 565 * copy the rest of p, the NUL is NOT copied 566 */ 567 while (*p) 568 *s++ = *p++; 569 570 if (format != 'f') { 571 char temp[EXPONENT_LENGTH]; /* for exponent conversion */ 572 apr_size_t t_len; 573 int exponent_is_negative; 574 575 *s++ = format; /* either e or E */ 576 decimal_point--; 577 if (decimal_point != 0) { 578 p = conv_10((apr_int32_t) decimal_point, FALSE, &exponent_is_negative, 579 &temp[EXPONENT_LENGTH], &t_len); 580 *s++ = exponent_is_negative ? '-' : '+'; 581 582 /* 583 * Make sure the exponent has at least 2 digits 584 */ 585 if (t_len == 1) 586 *s++ = '0'; 587 while (t_len--) 588 *s++ = *p++; 589 } 590 else { 591 *s++ = '+'; 592 *s++ = '0'; 593 *s++ = '0'; 594 } 595 } 596 597 *len = s - buf; 598 return (buf); 599} 600 601 602/* 603 * Convert num to a base X number where X is a power of 2. nbits determines X. 604 * For example, if nbits is 3, we do base 8 conversion 605 * Return value: 606 * a pointer to a string containing the number 607 * 608 * The caller provides a buffer for the string: that is the buf_end argument 609 * which is a pointer to the END of the buffer + 1 (i.e. if the buffer 610 * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) 611 * 612 * As with conv_10, we have a faster version which is used when 613 * the number isn't quad size. 614 */ 615static char *conv_p2(register apr_uint32_t num, register int nbits, 616 char format, char *buf_end, register apr_size_t *len) 617{ 618 register int mask = (1 << nbits) - 1; 619 register char *p = buf_end; 620 static const char low_digits[] = "0123456789abcdef"; 621 static const char upper_digits[] = "0123456789ABCDEF"; 622 register const char *digits = (format == 'X') ? upper_digits : low_digits; 623 624 do { 625 *--p = digits[num & mask]; 626 num >>= nbits; 627 } 628 while (num); 629 630 *len = buf_end - p; 631 return (p); 632} 633 634static char *conv_p2_quad(apr_uint64_t num, register int nbits, 635 char format, char *buf_end, register apr_size_t *len) 636{ 637 register int mask = (1 << nbits) - 1; 638 register char *p = buf_end; 639 static const char low_digits[] = "0123456789abcdef"; 640 static const char upper_digits[] = "0123456789ABCDEF"; 641 register const char *digits = (format == 'X') ? upper_digits : low_digits; 642 643 if (num <= APR_UINT32_MAX) 644 return(conv_p2((apr_uint32_t)num, nbits, format, buf_end, len)); 645 646 do { 647 *--p = digits[num & mask]; 648 num >>= nbits; 649 } 650 while (num); 651 652 *len = buf_end - p; 653 return (p); 654} 655 656#if APR_HAS_THREADS 657static char *conv_os_thread_t_hex(apr_os_thread_t *tid, char *buf_end, apr_size_t *len) 658{ 659 union { 660 apr_os_thread_t tid; 661 apr_uint64_t u64; 662 apr_uint32_t u32; 663 } u; 664 int is_negative; 665 666 u.tid = *tid; 667 switch(sizeof(u.tid)) { 668 case sizeof(apr_int32_t): 669 return conv_p2(u.u32, 4, 'x', buf_end, len); 670 case sizeof(apr_int64_t): 671 return conv_p2_quad(u.u64, 4, 'x', buf_end, len); 672 default: 673 /* not implemented; stick 0 in the buffer */ 674 return conv_10(0, TRUE, &is_negative, buf_end, len); 675 } 676} 677#endif 678 679/* 680 * Do format conversion placing the output in buffer 681 */ 682APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), 683 apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap) 684{ 685 register char *sp; 686 register char *bep; 687 register int cc = 0; 688 register apr_size_t i; 689 690 register char *s = NULL; 691 char *q; 692 apr_size_t s_len = 0; 693 694 register apr_size_t min_width = 0; 695 apr_size_t precision = 0; 696 enum { 697 LEFT, RIGHT 698 } adjust; 699 char pad_char; 700 char prefix_char; 701 702 double fp_num; 703 apr_int64_t i_quad = 0; 704 apr_uint64_t ui_quad; 705 apr_int32_t i_num = 0; 706 apr_uint32_t ui_num = 0; 707 708 char num_buf[NUM_BUF_SIZE]; 709 char char_buf[2]; /* for printing %% and %<unknown> */ 710 char buf[5]; /* for printing %B, %F, and %S */ 711 712 enum var_type_enum { 713 IS_QUAD, IS_LONG, IS_SHORT, IS_INT 714 }; 715 enum var_type_enum var_type = IS_INT; 716 717 /* 718 * Flag variables 719 */ 720 boolean_e alternate_form; 721 boolean_e print_sign; 722 boolean_e print_blank; 723 boolean_e adjust_precision; 724 boolean_e adjust_width; 725 int is_negative; 726 727 sp = vbuff->curpos; 728 bep = vbuff->endpos; 729 730 while (*fmt) { 731 if (*fmt != '%') { 732 INS_CHAR(*fmt, sp, bep, cc); 733 } 734 else { 735 /* 736 * Default variable settings 737 */ 738 boolean_e print_something = YES; 739 adjust = RIGHT; 740 alternate_form = print_sign = print_blank = NO; 741 pad_char = ' '; 742 prefix_char = NUL; 743 744 fmt++; 745 746 /* 747 * Try to avoid checking for flags, width or precision 748 */ 749 if (!apr_islower(*fmt)) { 750 /* 751 * Recognize flags: -, #, BLANK, + 752 */ 753 for (;; fmt++) { 754 if (*fmt == '-') 755 adjust = LEFT; 756 else if (*fmt == '+') 757 print_sign = YES; 758 else if (*fmt == '#') 759 alternate_form = YES; 760 else if (*fmt == ' ') 761 print_blank = YES; 762 else if (*fmt == '0') 763 pad_char = '0'; 764 else 765 break; 766 } 767 768 /* 769 * Check if a width was specified 770 */ 771 if (apr_isdigit(*fmt)) { 772 STR_TO_DEC(fmt, min_width); 773 adjust_width = YES; 774 } 775 else if (*fmt == '*') { 776 int v = va_arg(ap, int); 777 fmt++; 778 adjust_width = YES; 779 if (v < 0) { 780 adjust = LEFT; 781 min_width = (apr_size_t)(-v); 782 } 783 else 784 min_width = (apr_size_t)v; 785 } 786 else 787 adjust_width = NO; 788 789 /* 790 * Check if a precision was specified 791 */ 792 if (*fmt == '.') { 793 adjust_precision = YES; 794 fmt++; 795 if (apr_isdigit(*fmt)) { 796 STR_TO_DEC(fmt, precision); 797 } 798 else if (*fmt == '*') { 799 int v = va_arg(ap, int); 800 fmt++; 801 precision = (v < 0) ? 0 : (apr_size_t)v; 802 } 803 else 804 precision = 0; 805 } 806 else 807 adjust_precision = NO; 808 } 809 else 810 adjust_precision = adjust_width = NO; 811 812 /* 813 * Modifier check. In same cases, APR_OFF_T_FMT can be 814 * "lld" and APR_INT64_T_FMT can be "ld" (that is, off_t is 815 * "larger" than int64). Check that case 1st. 816 * Note that if APR_OFF_T_FMT is "d", 817 * the first if condition is never true. If APR_INT64_T_FMT 818 * is "d' then the second if condition is never true. 819 */ 820 if ((sizeof(APR_OFF_T_FMT) > sizeof(APR_INT64_T_FMT)) && 821 ((sizeof(APR_OFF_T_FMT) == 4 && 822 fmt[0] == APR_OFF_T_FMT[0] && 823 fmt[1] == APR_OFF_T_FMT[1]) || 824 (sizeof(APR_OFF_T_FMT) == 3 && 825 fmt[0] == APR_OFF_T_FMT[0]) || 826 (sizeof(APR_OFF_T_FMT) > 4 && 827 strncmp(fmt, APR_OFF_T_FMT, 828 sizeof(APR_OFF_T_FMT) - 2) == 0))) { 829 /* Need to account for trailing 'd' and null in sizeof() */ 830 var_type = IS_QUAD; 831 fmt += (sizeof(APR_OFF_T_FMT) - 2); 832 } 833 else if ((sizeof(APR_INT64_T_FMT) == 4 && 834 fmt[0] == APR_INT64_T_FMT[0] && 835 fmt[1] == APR_INT64_T_FMT[1]) || 836 (sizeof(APR_INT64_T_FMT) == 3 && 837 fmt[0] == APR_INT64_T_FMT[0]) || 838 (sizeof(APR_INT64_T_FMT) > 4 && 839 strncmp(fmt, APR_INT64_T_FMT, 840 sizeof(APR_INT64_T_FMT) - 2) == 0)) { 841 /* Need to account for trailing 'd' and null in sizeof() */ 842 var_type = IS_QUAD; 843 fmt += (sizeof(APR_INT64_T_FMT) - 2); 844 } 845 else if (*fmt == 'q') { 846 var_type = IS_QUAD; 847 fmt++; 848 } 849 else if (*fmt == 'l') { 850 var_type = IS_LONG; 851 fmt++; 852 } 853 else if (*fmt == 'h') { 854 var_type = IS_SHORT; 855 fmt++; 856 } 857 else { 858 var_type = IS_INT; 859 } 860 861 /* 862 * Argument extraction and printing. 863 * First we determine the argument type. 864 * Then, we convert the argument to a string. 865 * On exit from the switch, s points to the string that 866 * must be printed, s_len has the length of the string 867 * The precision requirements, if any, are reflected in s_len. 868 * 869 * NOTE: pad_char may be set to '0' because of the 0 flag. 870 * It is reset to ' ' by non-numeric formats 871 */ 872 switch (*fmt) { 873 case 'u': 874 if (var_type == IS_QUAD) { 875 i_quad = va_arg(ap, apr_uint64_t); 876 s = conv_10_quad(i_quad, 1, &is_negative, 877 &num_buf[NUM_BUF_SIZE], &s_len); 878 } 879 else { 880 if (var_type == IS_LONG) 881 i_num = (apr_int32_t) va_arg(ap, apr_uint32_t); 882 else if (var_type == IS_SHORT) 883 i_num = (apr_int32_t) (unsigned short) va_arg(ap, unsigned int); 884 else 885 i_num = (apr_int32_t) va_arg(ap, unsigned int); 886 s = conv_10(i_num, 1, &is_negative, 887 &num_buf[NUM_BUF_SIZE], &s_len); 888 } 889 FIX_PRECISION(adjust_precision, precision, s, s_len); 890 break; 891 892 case 'd': 893 case 'i': 894 if (var_type == IS_QUAD) { 895 i_quad = va_arg(ap, apr_int64_t); 896 s = conv_10_quad(i_quad, 0, &is_negative, 897 &num_buf[NUM_BUF_SIZE], &s_len); 898 } 899 else { 900 if (var_type == IS_LONG) 901 i_num = va_arg(ap, apr_int32_t); 902 else if (var_type == IS_SHORT) 903 i_num = (short) va_arg(ap, int); 904 else 905 i_num = va_arg(ap, int); 906 s = conv_10(i_num, 0, &is_negative, 907 &num_buf[NUM_BUF_SIZE], &s_len); 908 } 909 FIX_PRECISION(adjust_precision, precision, s, s_len); 910 911 if (is_negative) 912 prefix_char = '-'; 913 else if (print_sign) 914 prefix_char = '+'; 915 else if (print_blank) 916 prefix_char = ' '; 917 break; 918 919 920 case 'o': 921 if (var_type == IS_QUAD) { 922 ui_quad = va_arg(ap, apr_uint64_t); 923 s = conv_p2_quad(ui_quad, 3, *fmt, 924 &num_buf[NUM_BUF_SIZE], &s_len); 925 } 926 else { 927 if (var_type == IS_LONG) 928 ui_num = va_arg(ap, apr_uint32_t); 929 else if (var_type == IS_SHORT) 930 ui_num = (unsigned short) va_arg(ap, unsigned int); 931 else 932 ui_num = va_arg(ap, unsigned int); 933 s = conv_p2(ui_num, 3, *fmt, 934 &num_buf[NUM_BUF_SIZE], &s_len); 935 } 936 FIX_PRECISION(adjust_precision, precision, s, s_len); 937 if (alternate_form && *s != '0') { 938 *--s = '0'; 939 s_len++; 940 } 941 break; 942 943 944 case 'x': 945 case 'X': 946 if (var_type == IS_QUAD) { 947 ui_quad = va_arg(ap, apr_uint64_t); 948 s = conv_p2_quad(ui_quad, 4, *fmt, 949 &num_buf[NUM_BUF_SIZE], &s_len); 950 } 951 else { 952 if (var_type == IS_LONG) 953 ui_num = va_arg(ap, apr_uint32_t); 954 else if (var_type == IS_SHORT) 955 ui_num = (unsigned short) va_arg(ap, unsigned int); 956 else 957 ui_num = va_arg(ap, unsigned int); 958 s = conv_p2(ui_num, 4, *fmt, 959 &num_buf[NUM_BUF_SIZE], &s_len); 960 } 961 FIX_PRECISION(adjust_precision, precision, s, s_len); 962 if (alternate_form && ui_num != 0) { 963 *--s = *fmt; /* 'x' or 'X' */ 964 *--s = '0'; 965 s_len += 2; 966 } 967 break; 968 969 970 case 's': 971 s = va_arg(ap, char *); 972 if (s != NULL) { 973 if (!adjust_precision) { 974 s_len = strlen(s); 975 } 976 else { 977 /* From the C library standard in section 7.9.6.1: 978 * ...if the precision is specified, no more then 979 * that many characters are written. If the 980 * precision is not specified or is greater 981 * than the size of the array, the array shall 982 * contain a null character. 983 * 984 * My reading is is precision is specified and 985 * is less then or equal to the size of the 986 * array, no null character is required. So 987 * we can't do a strlen. 988 * 989 * This figures out the length of the string 990 * up to the precision. Once it's long enough 991 * for the specified precision, we don't care 992 * anymore. 993 * 994 * NOTE: you must do the length comparison 995 * before the check for the null character. 996 * Otherwise, you'll check one beyond the 997 * last valid character. 998 */ 999 const char *walk; 1000 1001 for (walk = s, s_len = 0; 1002 (s_len < precision) && (*walk != '\0'); 1003 ++walk, ++s_len); 1004 } 1005 } 1006 else { 1007 s = S_NULL; 1008 s_len = S_NULL_LEN; 1009 } 1010 pad_char = ' '; 1011 break; 1012 1013 1014 case 'f': 1015 case 'e': 1016 case 'E': 1017 fp_num = va_arg(ap, double); 1018 /* 1019 * We use &num_buf[ 1 ], so that we have room for the sign 1020 */ 1021 s = NULL; 1022#ifdef HAVE_ISNAN 1023 if (isnan(fp_num)) { 1024 s = "nan"; 1025 s_len = 3; 1026 } 1027#endif 1028#ifdef HAVE_ISINF 1029 if (!s && isinf(fp_num)) { 1030 s = "inf"; 1031 s_len = 3; 1032 } 1033#endif 1034 if (!s) { 1035 s = conv_fp(*fmt, fp_num, alternate_form, 1036 (int)((adjust_precision == NO) ? FLOAT_DIGITS : precision), 1037 &is_negative, &num_buf[1], &s_len); 1038 if (is_negative) 1039 prefix_char = '-'; 1040 else if (print_sign) 1041 prefix_char = '+'; 1042 else if (print_blank) 1043 prefix_char = ' '; 1044 } 1045 break; 1046 1047 1048 case 'g': 1049 case 'G': 1050 if (adjust_precision == NO) 1051 precision = FLOAT_DIGITS; 1052 else if (precision == 0) 1053 precision = 1; 1054 /* 1055 * * We use &num_buf[ 1 ], so that we have room for the sign 1056 */ 1057 s = apr_gcvt(va_arg(ap, double), (int) precision, &num_buf[1], 1058 alternate_form); 1059 if (*s == '-') 1060 prefix_char = *s++; 1061 else if (print_sign) 1062 prefix_char = '+'; 1063 else if (print_blank) 1064 prefix_char = ' '; 1065 1066 s_len = strlen(s); 1067 1068 if (alternate_form && (q = strchr(s, '.')) == NULL) { 1069 s[s_len++] = '.'; 1070 s[s_len] = '\0'; /* delimit for following strchr() */ 1071 } 1072 if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL) 1073 *q = 'E'; 1074 break; 1075 1076 1077 case 'c': 1078 char_buf[0] = (char) (va_arg(ap, int)); 1079 s = &char_buf[0]; 1080 s_len = 1; 1081 pad_char = ' '; 1082 break; 1083 1084 1085 case '%': 1086 char_buf[0] = '%'; 1087 s = &char_buf[0]; 1088 s_len = 1; 1089 pad_char = ' '; 1090 break; 1091 1092 1093 case 'n': 1094 if (var_type == IS_QUAD) 1095 *(va_arg(ap, apr_int64_t *)) = cc; 1096 else if (var_type == IS_LONG) 1097 *(va_arg(ap, long *)) = cc; 1098 else if (var_type == IS_SHORT) 1099 *(va_arg(ap, short *)) = cc; 1100 else 1101 *(va_arg(ap, int *)) = cc; 1102 print_something = NO; 1103 break; 1104 1105 /* 1106 * This is where we extend the printf format, with a second 1107 * type specifier 1108 */ 1109 case 'p': 1110 switch(*++fmt) { 1111 /* 1112 * If the pointer size is equal to or smaller than the size 1113 * of the largest unsigned int, we convert the pointer to a 1114 * hex number, otherwise we print "%p" to indicate that we 1115 * don't handle "%p". 1116 */ 1117 case 'p': 1118#if APR_SIZEOF_VOIDP == 8 1119 if (sizeof(void *) <= sizeof(apr_uint64_t)) { 1120 ui_quad = (apr_uint64_t) va_arg(ap, void *); 1121 s = conv_p2_quad(ui_quad, 4, 'x', 1122 &num_buf[NUM_BUF_SIZE], &s_len); 1123 } 1124#else 1125 if (sizeof(void *) <= sizeof(apr_uint32_t)) { 1126 ui_num = (apr_uint32_t) va_arg(ap, void *); 1127 s = conv_p2(ui_num, 4, 'x', 1128 &num_buf[NUM_BUF_SIZE], &s_len); 1129 } 1130#endif 1131 else { 1132 s = "%p"; 1133 s_len = 2; 1134 prefix_char = NUL; 1135 } 1136 pad_char = ' '; 1137 break; 1138 1139 /* print an apr_sockaddr_t as a.b.c.d:port */ 1140 case 'I': 1141 { 1142 apr_sockaddr_t *sa; 1143 1144 sa = va_arg(ap, apr_sockaddr_t *); 1145 if (sa != NULL) { 1146 s = conv_apr_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len); 1147 if (adjust_precision && precision < s_len) 1148 s_len = precision; 1149 } 1150 else { 1151 s = S_NULL; 1152 s_len = S_NULL_LEN; 1153 } 1154 pad_char = ' '; 1155 } 1156 break; 1157 1158 /* print a struct in_addr as a.b.c.d */ 1159 case 'A': 1160 { 1161 struct in_addr *ia; 1162 1163 ia = va_arg(ap, struct in_addr *); 1164 if (ia != NULL) { 1165 s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len); 1166 if (adjust_precision && precision < s_len) 1167 s_len = precision; 1168 } 1169 else { 1170 s = S_NULL; 1171 s_len = S_NULL_LEN; 1172 } 1173 pad_char = ' '; 1174 } 1175 break; 1176 1177 /* print the error for an apr_status_t */ 1178 case 'm': 1179 { 1180 apr_status_t *mrv; 1181 1182 mrv = va_arg(ap, apr_status_t *); 1183 if (mrv != NULL) { 1184 s = apr_strerror(*mrv, num_buf, NUM_BUF_SIZE-1); 1185 s_len = strlen(s); 1186 } 1187 else { 1188 s = S_NULL; 1189 s_len = S_NULL_LEN; 1190 } 1191 pad_char = ' '; 1192 } 1193 break; 1194 1195 case 'T': 1196#if APR_HAS_THREADS 1197 { 1198 apr_os_thread_t *tid; 1199 1200 tid = va_arg(ap, apr_os_thread_t *); 1201 if (tid != NULL) { 1202 s = conv_os_thread_t(tid, &num_buf[NUM_BUF_SIZE], &s_len); 1203 if (adjust_precision && precision < s_len) 1204 s_len = precision; 1205 } 1206 else { 1207 s = S_NULL; 1208 s_len = S_NULL_LEN; 1209 } 1210 pad_char = ' '; 1211 } 1212#else 1213 char_buf[0] = '0'; 1214 s = &char_buf[0]; 1215 s_len = 1; 1216 pad_char = ' '; 1217#endif 1218 break; 1219 1220 case 't': 1221#if APR_HAS_THREADS 1222 { 1223 apr_os_thread_t *tid; 1224 1225 tid = va_arg(ap, apr_os_thread_t *); 1226 if (tid != NULL) { 1227 s = conv_os_thread_t_hex(tid, &num_buf[NUM_BUF_SIZE], &s_len); 1228 if (adjust_precision && precision < s_len) 1229 s_len = precision; 1230 } 1231 else { 1232 s = S_NULL; 1233 s_len = S_NULL_LEN; 1234 } 1235 pad_char = ' '; 1236 } 1237#else 1238 char_buf[0] = '0'; 1239 s = &char_buf[0]; 1240 s_len = 1; 1241 pad_char = ' '; 1242#endif 1243 break; 1244 1245 case 'B': 1246 case 'F': 1247 case 'S': 1248 { 1249 apr_off_t size = 0; 1250 1251 if (*fmt == 'B') { 1252 apr_uint32_t *arg = va_arg(ap, apr_uint32_t *); 1253 size = (arg) ? *arg : 0; 1254 } 1255 else if (*fmt == 'F') { 1256 apr_off_t *arg = va_arg(ap, apr_off_t *); 1257 size = (arg) ? *arg : 0; 1258 } 1259 else { 1260 apr_size_t *arg = va_arg(ap, apr_size_t *); 1261 size = (arg) ? *arg : 0; 1262 } 1263 1264 s = apr_strfsize(size, buf); 1265 s_len = strlen(s); 1266 pad_char = ' '; 1267 } 1268 break; 1269 1270 case NUL: 1271 /* if %p ends the string, oh well ignore it */ 1272 continue; 1273 1274 default: 1275 s = "bogus %p"; 1276 s_len = 8; 1277 prefix_char = NUL; 1278 (void)va_arg(ap, void *); /* skip the bogus argument on the stack */ 1279 break; 1280 } 1281 break; 1282 1283 case NUL: 1284 /* 1285 * The last character of the format string was %. 1286 * We ignore it. 1287 */ 1288 continue; 1289 1290 1291 /* 1292 * The default case is for unrecognized %'s. 1293 * We print %<char> to help the user identify what 1294 * option is not understood. 1295 * This is also useful in case the user wants to pass 1296 * the output of format_converter to another function 1297 * that understands some other %<char> (like syslog). 1298 * Note that we can't point s inside fmt because the 1299 * unknown <char> could be preceded by width etc. 1300 */ 1301 default: 1302 char_buf[0] = '%'; 1303 char_buf[1] = *fmt; 1304 s = char_buf; 1305 s_len = 2; 1306 pad_char = ' '; 1307 break; 1308 } 1309 1310 if (prefix_char != NUL && s != S_NULL && s != char_buf) { 1311 *--s = prefix_char; 1312 s_len++; 1313 } 1314 1315 if (adjust_width && adjust == RIGHT && min_width > s_len) { 1316 if (pad_char == '0' && prefix_char != NUL) { 1317 INS_CHAR(*s, sp, bep, cc); 1318 s++; 1319 s_len--; 1320 min_width--; 1321 } 1322 PAD(min_width, s_len, pad_char); 1323 } 1324 1325 /* 1326 * Print the string s. 1327 */ 1328 if (print_something == YES) { 1329 for (i = s_len; i != 0; i--) { 1330 INS_CHAR(*s, sp, bep, cc); 1331 s++; 1332 } 1333 } 1334 1335 if (adjust_width && adjust == LEFT && min_width > s_len) 1336 PAD(min_width, s_len, pad_char); 1337 } 1338 fmt++; 1339 } 1340 vbuff->curpos = sp; 1341 1342 return cc; 1343} 1344 1345 1346static int snprintf_flush(apr_vformatter_buff_t *vbuff) 1347{ 1348 /* if the buffer fills we have to abort immediately, there is no way 1349 * to "flush" an apr_snprintf... there's nowhere to flush it to. 1350 */ 1351 return -1; 1352} 1353 1354 1355APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, 1356 const char *format, ...) 1357{ 1358 int cc; 1359 va_list ap; 1360 apr_vformatter_buff_t vbuff; 1361 1362 if (len == 0) { 1363 /* NOTE: This is a special case; we just want to return the number 1364 * of chars that would be written (minus \0) if the buffer 1365 * size was infinite. We leverage the fact that INS_CHAR 1366 * just does actual inserts iff the buffer pointer is non-NULL. 1367 * In this case, we don't care what buf is; it can be NULL, since 1368 * we don't touch it at all. 1369 */ 1370 vbuff.curpos = NULL; 1371 vbuff.endpos = NULL; 1372 } else { 1373 /* save one byte for nul terminator */ 1374 vbuff.curpos = buf; 1375 vbuff.endpos = buf + len - 1; 1376 } 1377 va_start(ap, format); 1378 cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); 1379 va_end(ap); 1380 if (len != 0) { 1381 *vbuff.curpos = '\0'; 1382 } 1383 return (cc == -1) ? (int)len - 1 : cc; 1384} 1385 1386 1387APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, 1388 va_list ap) 1389{ 1390 int cc; 1391 apr_vformatter_buff_t vbuff; 1392 1393 if (len == 0) { 1394 /* See above note */ 1395 vbuff.curpos = NULL; 1396 vbuff.endpos = NULL; 1397 } else { 1398 /* save one byte for nul terminator */ 1399 vbuff.curpos = buf; 1400 vbuff.endpos = buf + len - 1; 1401 } 1402 cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); 1403 if (len != 0) { 1404 *vbuff.curpos = '\0'; 1405 } 1406 return (cc == -1) ? (int)len - 1 : cc; 1407} 1408