1/* Replacements for routines missing on some systems. 2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 3 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software 4 Foundation, Inc. 5 6This file is part of GNU Wget. 7 8GNU Wget is free software; you can redistribute it and/or modify 9it under the terms of the GNU General Public License as published by 10the Free Software Foundation; either version 3 of the License, or 11(at your option) any later version. 12 13GNU Wget is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along with Wget. If not, see <http://www.gnu.org/licenses/>. 20 21Additional permission under GNU GPL version 3 section 7 22 23If you modify this program, or any covered work, by linking or 24combining it with the OpenSSL project's OpenSSL library (or a 25modified version of that library), containing parts covered by the 26terms of the OpenSSL or SSLeay licenses, the Free Software Foundation 27grants you additional permission to convey the resulting work. 28Corresponding Source for a non-source form of such a combination 29shall include the source code for the parts of OpenSSL used as well 30as that of the covered work. */ 31 32#include "wget.h" 33 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37#include <time.h> 38 39#include <unistd.h> 40 41#include <errno.h> 42 43/* Some systems lack certain functions normally taken for granted. 44 For example, Windows doesn't have strptime, and some systems don't 45 have a usable fnmatch. This file should contain fallback 46 implementations of such missing functions. It should *not* define 47 new Wget-specific interfaces -- those should be placed in utils.c 48 or elsewhere. */ 49 50/* strcasecmp and strncasecmp apparently originated with BSD 4.4. 51 SUSv3 seems to be the only standard out there (that I can find) 52 that requires their existence, so in theory there might be systems 53 still in use that lack them. Note that these don't get defined 54 under Windows because mswindows.h defines them to the equivalent 55 Windows functions stricmp and strnicmp. */ 56 57#ifndef HAVE_STRCASECMP 58/* From GNU libc. */ 59/* Compare S1 and S2, ignoring case, returning less than, equal to or 60 greater than zero if S1 is lexiographically less than, 61 equal to or greater than S2. */ 62int 63strcasecmp (const char *s1, const char *s2) 64{ 65 register const unsigned char *p1 = (const unsigned char *) s1; 66 register const unsigned char *p2 = (const unsigned char *) s2; 67 unsigned char c1, c2; 68 69 if (p1 == p2) 70 return 0; 71 72 do 73 { 74 c1 = c_tolower (*p1++); 75 c2 = c_tolower (*p2++); 76 if (c1 == '\0') 77 break; 78 } 79 while (c1 == c2); 80 81 return c1 - c2; 82} 83#endif /* not HAVE_STRCASECMP */ 84 85#ifndef HAVE_STRNCASECMP 86/* From GNU libc. */ 87/* Compare no more than N characters of S1 and S2, 88 ignoring case, returning less than, equal to or 89 greater than zero if S1 is lexicographically less 90 than, equal to or greater than S2. */ 91int 92strncasecmp (const char *s1, const char *s2, size_t n) 93{ 94 register const unsigned char *p1 = (const unsigned char *) s1; 95 register const unsigned char *p2 = (const unsigned char *) s2; 96 unsigned char c1, c2; 97 98 if (p1 == p2 || n == 0) 99 return 0; 100 101 do 102 { 103 c1 = c_tolower (*p1++); 104 c2 = c_tolower (*p2++); 105 if (c1 == '\0' || c1 != c2) 106 return c1 - c2; 107 } while (--n > 0); 108 109 return c1 - c2; 110} 111#endif /* not HAVE_STRNCASECMP */ 112 113#ifndef HAVE_MEMRCHR 114/* memrchr is a GNU extension. It is like the memchr function, except 115 that it searches backwards from the end of the n bytes pointed to 116 by s instead of forwards from the front. */ 117 118void * 119memrchr (const void *s, int c, size_t n) 120{ 121 const char *b = s; 122 const char *e = b + n; 123 while (e > b) 124 if (*--e == c) 125 return (void *) e; 126 return NULL; 127} 128#endif 129 130/* strptime is required by POSIX, but it is missing from Windows, 131 which means we must keep a fallback implementation. It is 132 reportedly missing or broken on many older Unix systems as well, so 133 it's good to have around. */ 134 135#ifndef HAVE_STRPTIME 136/* From GNU libc 2.1.3. */ 137/* Ulrich, thanks for helping me out with this! --hniksic */ 138 139/* strptime - Convert a string representation of time to a time value. 140 Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. 141 This file is part of the GNU C Library. 142 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. */ 143 144/* XXX This version of the implementation is not really complete. 145 Some of the fields cannot add information alone. But if seeing 146 some of them in the same format (such as year, week and weekday) 147 this is enough information for determining the date. */ 148 149#ifndef __P 150# define __P(args) args 151#endif /* not __P */ 152 153#if ! HAVE_LOCALTIME_R && ! defined localtime_r 154# ifdef _LIBC 155# define localtime_r __localtime_r 156# else 157/* Approximate localtime_r as best we can in its absence. */ 158# define localtime_r my_localtime_r 159static struct tm *localtime_r __P ((const time_t *, struct tm *)); 160static struct tm * 161localtime_r (t, tp) 162 const time_t *t; 163 struct tm *tp; 164{ 165 struct tm *l = localtime (t); 166 if (! l) 167 return 0; 168 *tp = *l; 169 return tp; 170} 171# endif /* ! _LIBC */ 172#endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */ 173 174 175#define match_char(ch1, ch2) if (ch1 != ch2) return NULL 176#if defined __GNUC__ && __GNUC__ >= 2 177# define match_string(cs1, s2) \ 178 ({ size_t len = strlen (cs1); \ 179 int result = strncasecmp ((cs1), (s2), len) == 0; \ 180 if (result) (s2) += len; \ 181 result; }) 182#else 183/* Oh come on. Get a reasonable compiler. */ 184# define match_string(cs1, s2) \ 185 (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1)) 186#endif 187/* We intentionally do not use isdigit() for testing because this will 188 lead to problems with the wide character version. */ 189#define get_number(from, to, n) \ 190 do { \ 191 int __n = n; \ 192 val = 0; \ 193 while (*rp == ' ') \ 194 ++rp; \ 195 if (*rp < '0' || *rp > '9') \ 196 return NULL; \ 197 do { \ 198 val *= 10; \ 199 val += *rp++ - '0'; \ 200 } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \ 201 if (val < from || val > to) \ 202 return NULL; \ 203 } while (0) 204#ifdef _NL_CURRENT 205/* Added check for __GNUC__ extensions here for Wget. --abbotti */ 206# if defined __GNUC__ && __GNUC__ >= 2 207# define get_alt_number(from, to, n) \ 208 ({ \ 209 __label__ do_normal; \ 210 if (*decided != raw) \ 211 { \ 212 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \ 213 int __n = n; \ 214 int any = 0; \ 215 while (*rp == ' ') \ 216 ++rp; \ 217 val = 0; \ 218 do { \ 219 val *= 10; \ 220 while (*alts != '\0') \ 221 { \ 222 size_t len = strlen (alts); \ 223 if (strncasecmp (alts, rp, len) == 0) \ 224 break; \ 225 alts += len + 1; \ 226 ++val; \ 227 } \ 228 if (*alts == '\0') \ 229 { \ 230 if (*decided == not && ! any) \ 231 goto do_normal; \ 232 /* If we haven't read anything it's an error. */ \ 233 if (! any) \ 234 return NULL; \ 235 /* Correct the premature multiplication. */ \ 236 val /= 10; \ 237 break; \ 238 } \ 239 else \ 240 *decided = loc; \ 241 } while (--__n > 0 && val * 10 <= to); \ 242 if (val < from || val > to) \ 243 return NULL; \ 244 } \ 245 else \ 246 { \ 247 do_normal: \ 248 get_number (from, to, n); \ 249 } \ 250 0; \ 251 }) 252# else 253# define get_alt_number(from, to, n) \ 254 do { 255 if (*decided != raw) \ 256 { \ 257 const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \ 258 int __n = n; \ 259 int any = 0; \ 260 while (*rp == ' ') \ 261 ++rp; \ 262 val = 0; \ 263 do { \ 264 val *= 10; \ 265 while (*alts != '\0') \ 266 { \ 267 size_t len = strlen (alts); \ 268 if (strncasecmp (alts, rp, len) == 0) \ 269 break; \ 270 alts += len + 1; \ 271 ++val; \ 272 } \ 273 if (*alts == '\0') \ 274 { \ 275 if (*decided == not && ! any) \ 276 goto do_normal; \ 277 /* If we haven't read anything it's an error. */ \ 278 if (! any) \ 279 return NULL; \ 280 /* Correct the premature multiplication. */ \ 281 val /= 10; \ 282 break; \ 283 } \ 284 else \ 285 *decided = loc; \ 286 } while (--__n > 0 && val * 10 <= to); \ 287 if (val < from || val > to) \ 288 return NULL; \ 289 } \ 290 else \ 291 { \ 292 do_normal: \ 293 get_number (from, to, n); \ 294 } \ 295 } while (0) 296# endif /* defined __GNUC__ && __GNUC__ >= 2 */ 297#else 298# define get_alt_number(from, to, n) \ 299 /* We don't have the alternate representation. */ \ 300 get_number(from, to, n) 301#endif 302#define recursive(new_fmt) \ 303 (*(new_fmt) != '\0' \ 304 && (rp = strptime_internal (rp, (new_fmt), tm, decided)) != NULL) 305 306 307#ifdef _LIBC 308/* This is defined in locale/C-time.c in the GNU libc. */ 309extern const struct locale_data _nl_C_LC_TIME; 310extern const unsigned short int __mon_yday[2][13]; 311 312# define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string) 313# define ab_weekday_name \ 314 (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string) 315# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string) 316# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string) 317# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string) 318# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string) 319# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string) 320# define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string) 321# define HERE_T_FMT_AMPM \ 322 (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string) 323# define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string) 324 325# define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n) 326#else 327static char const weekday_name[][10] = 328 { 329 "Sunday", "Monday", "Tuesday", "Wednesday", 330 "Thursday", "Friday", "Saturday" 331 }; 332static char const ab_weekday_name[][4] = 333 { 334 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 335 }; 336static char const month_name[][10] = 337 { 338 "January", "February", "March", "April", "May", "June", 339 "July", "August", "September", "October", "November", "December" 340 }; 341static char const ab_month_name[][4] = 342 { 343 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 344 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 345 }; 346# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y" 347# define HERE_D_FMT "%m/%d/%y" 348# define HERE_AM_STR "AM" 349# define HERE_PM_STR "PM" 350# define HERE_T_FMT_AMPM "%I:%M:%S %p" 351# define HERE_T_FMT "%H:%M:%S" 352 353const unsigned short int __mon_yday[2][13]; 354# ifndef NEED_MON_YDAY 355# define NEED_MON_YDAY 356# endif 357#endif 358 359/* Status of lookup: do we use the locale data or the raw data? */ 360enum locale_status { not, loc, raw }; 361 362 363#ifndef __isleap 364/* Nonzero if YEAR is a leap year (every 4 years, 365 except every 100th isn't, and every 400th is). */ 366# define __isleap(year) \ 367 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) 368#endif 369 370/* Compute the day of the week. */ 371static void 372day_of_the_week (struct tm *tm) 373{ 374 /* We know that January 1st 1970 was a Thursday (= 4). Compute the 375 difference between this data in the one on TM and so determine 376 the weekday. */ 377 int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2); 378 int wday = (-473 379 + (365 * (tm->tm_year - 70)) 380 + (corr_year / 4) 381 - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0) 382 + (((corr_year / 4) / 25) / 4) 383 + __mon_yday[0][tm->tm_mon] 384 + tm->tm_mday - 1); 385 tm->tm_wday = ((wday % 7) + 7) % 7; 386} 387 388/* Compute the day of the year. */ 389static void 390day_of_the_year (struct tm *tm) 391{ 392 tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon] 393 + (tm->tm_mday - 1)); 394} 395 396static char * 397#ifdef _LIBC 398internal_function 399#endif 400strptime_internal __P ((const char *buf, const char *format, struct tm *tm, 401 enum locale_status *decided)); 402 403static char * 404#ifdef _LIBC 405internal_function 406#endif 407strptime_internal (rp, fmt, tm, decided) 408 const char *rp; 409 const char *fmt; 410 struct tm *tm; 411 enum locale_status *decided; 412{ 413#ifdef _NL_CURRENT 414 const char *rp_backup; 415#endif 416 int cnt; 417 size_t val; 418 int have_I, is_pm; 419 int century, want_century; 420 int have_wday, want_xday; 421 int have_yday; 422 int have_mon, have_mday; 423 424 have_I = is_pm = 0; 425 century = -1; 426 want_century = 0; 427 have_wday = want_xday = have_yday = have_mon = have_mday = 0; 428 429 while (*fmt != '\0') 430 { 431 /* A white space in the format string matches 0 more or white 432 space in the input string. */ 433 if (c_isspace (*fmt)) 434 { 435 while (c_isspace (*rp)) 436 ++rp; 437 ++fmt; 438 continue; 439 } 440 441 /* Any character but `%' must be matched by the same character 442 in the iput string. */ 443 if (*fmt != '%') 444 { 445 match_char (*fmt++, *rp++); 446 continue; 447 } 448 449 ++fmt; 450#ifndef _NL_CURRENT 451 /* We need this for handling the `E' modifier. */ 452 start_over: 453#endif 454 455#ifdef _NL_CURRENT 456 /* Make back up of current processing pointer. */ 457 rp_backup = rp; 458#endif 459 460 switch (*fmt++) 461 { 462 case '%': 463 /* Match the `%' character itself. */ 464 match_char ('%', *rp++); 465 break; 466 case 'a': 467 case 'A': 468 /* Match day of week. */ 469 for (cnt = 0; cnt < 7; ++cnt) 470 { 471#ifdef _NL_CURRENT 472 if (*decided !=raw) 473 { 474 if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp)) 475 { 476 if (*decided == not 477 && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt), 478 weekday_name[cnt])) 479 *decided = loc; 480 break; 481 } 482 if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp)) 483 { 484 if (*decided == not 485 && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), 486 ab_weekday_name[cnt])) 487 *decided = loc; 488 break; 489 } 490 } 491#endif 492 if (*decided != loc 493 && (match_string (weekday_name[cnt], rp) 494 || match_string (ab_weekday_name[cnt], rp))) 495 { 496 *decided = raw; 497 break; 498 } 499 } 500 if (cnt == 7) 501 /* Does not match a weekday name. */ 502 return NULL; 503 tm->tm_wday = cnt; 504 have_wday = 1; 505 break; 506 case 'b': 507 case 'B': 508 case 'h': 509 /* Match month name. */ 510 for (cnt = 0; cnt < 12; ++cnt) 511 { 512#ifdef _NL_CURRENT 513 if (*decided !=raw) 514 { 515 if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp)) 516 { 517 if (*decided == not 518 && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt), 519 month_name[cnt])) 520 *decided = loc; 521 break; 522 } 523 if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp)) 524 { 525 if (*decided == not 526 && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), 527 ab_month_name[cnt])) 528 *decided = loc; 529 break; 530 } 531 } 532#endif 533 if (match_string (month_name[cnt], rp) 534 || match_string (ab_month_name[cnt], rp)) 535 { 536 *decided = raw; 537 break; 538 } 539 } 540 if (cnt == 12) 541 /* Does not match a month name. */ 542 return NULL; 543 tm->tm_mon = cnt; 544 want_xday = 1; 545 break; 546 case 'c': 547 /* Match locale's date and time format. */ 548#ifdef _NL_CURRENT 549 if (*decided != raw) 550 { 551 if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT))) 552 { 553 if (*decided == loc) 554 return NULL; 555 else 556 rp = rp_backup; 557 } 558 else 559 { 560 if (*decided == not && 561 strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT)) 562 *decided = loc; 563 want_xday = 1; 564 break; 565 } 566 *decided = raw; 567 } 568#endif 569 if (!recursive (HERE_D_T_FMT)) 570 return NULL; 571 want_xday = 1; 572 break; 573 case 'C': 574 /* Match century number. */ 575 get_number (0, 99, 2); 576 century = val; 577 want_xday = 1; 578 break; 579 case 'd': 580 case 'e': 581 /* Match day of month. */ 582 get_number (1, 31, 2); 583 tm->tm_mday = val; 584 have_mday = 1; 585 want_xday = 1; 586 break; 587 case 'F': 588 if (!recursive ("%Y-%m-%d")) 589 return NULL; 590 want_xday = 1; 591 break; 592 case 'x': 593#ifdef _NL_CURRENT 594 if (*decided != raw) 595 { 596 if (!recursive (_NL_CURRENT (LC_TIME, D_FMT))) 597 { 598 if (*decided == loc) 599 return NULL; 600 else 601 rp = rp_backup; 602 } 603 else 604 { 605 if (*decided == not 606 && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT)) 607 *decided = loc; 608 want_xday = 1; 609 break; 610 } 611 *decided = raw; 612 } 613#endif 614 /* Fall through. */ 615 case 'D': 616 /* Match standard day format. */ 617 if (!recursive (HERE_D_FMT)) 618 return NULL; 619 want_xday = 1; 620 break; 621 case 'k': 622 case 'H': 623 /* Match hour in 24-hour clock. */ 624 get_number (0, 23, 2); 625 tm->tm_hour = val; 626 have_I = 0; 627 break; 628 case 'I': 629 /* Match hour in 12-hour clock. */ 630 get_number (1, 12, 2); 631 tm->tm_hour = val % 12; 632 have_I = 1; 633 break; 634 case 'j': 635 /* Match day number of year. */ 636 get_number (1, 366, 3); 637 tm->tm_yday = val - 1; 638 have_yday = 1; 639 break; 640 case 'm': 641 /* Match number of month. */ 642 get_number (1, 12, 2); 643 tm->tm_mon = val - 1; 644 have_mon = 1; 645 want_xday = 1; 646 break; 647 case 'M': 648 /* Match minute. */ 649 get_number (0, 59, 2); 650 tm->tm_min = val; 651 break; 652 case 'n': 653 case 't': 654 /* Match any white space. */ 655 while (c_isspace (*rp)) 656 ++rp; 657 break; 658 case 'p': 659 /* Match locale's equivalent of AM/PM. */ 660#ifdef _NL_CURRENT 661 if (*decided != raw) 662 { 663 if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp)) 664 { 665 if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR)) 666 *decided = loc; 667 break; 668 } 669 if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp)) 670 { 671 if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR)) 672 *decided = loc; 673 is_pm = 1; 674 break; 675 } 676 *decided = raw; 677 } 678#endif 679 if (!match_string (HERE_AM_STR, rp)) 680 { 681 if (match_string (HERE_PM_STR, rp)) 682 is_pm = 1; 683 else 684 return NULL; 685 } 686 break; 687 case 'r': 688#ifdef _NL_CURRENT 689 if (*decided != raw) 690 { 691 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM))) 692 { 693 if (*decided == loc) 694 return NULL; 695 else 696 rp = rp_backup; 697 } 698 else 699 { 700 if (*decided == not && 701 strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM), 702 HERE_T_FMT_AMPM)) 703 *decided = loc; 704 break; 705 } 706 *decided = raw; 707 } 708#endif 709 if (!recursive (HERE_T_FMT_AMPM)) 710 return NULL; 711 break; 712 case 'R': 713 if (!recursive ("%H:%M")) 714 return NULL; 715 break; 716 case 's': 717 { 718 /* The number of seconds may be very high so we cannot use 719 the `get_number' macro. Instead read the number 720 character for character and construct the result while 721 doing this. */ 722 time_t secs = 0; 723 if (*rp < '0' || *rp > '9') 724 /* We need at least one digit. */ 725 return NULL; 726 727 do 728 { 729 secs *= 10; 730 secs += *rp++ - '0'; 731 } 732 while (*rp >= '0' && *rp <= '9'); 733 734 if (localtime_r (&secs, tm) == NULL) 735 /* Error in function. */ 736 return NULL; 737 } 738 break; 739 case 'S': 740 get_number (0, 61, 2); 741 tm->tm_sec = val; 742 break; 743 case 'X': 744#ifdef _NL_CURRENT 745 if (*decided != raw) 746 { 747 if (!recursive (_NL_CURRENT (LC_TIME, T_FMT))) 748 { 749 if (*decided == loc) 750 return NULL; 751 else 752 rp = rp_backup; 753 } 754 else 755 { 756 if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT)) 757 *decided = loc; 758 break; 759 } 760 *decided = raw; 761 } 762#endif 763 /* Fall through. */ 764 case 'T': 765 if (!recursive (HERE_T_FMT)) 766 return NULL; 767 break; 768 case 'u': 769 get_number (1, 7, 1); 770 tm->tm_wday = val % 7; 771 have_wday = 1; 772 break; 773 case 'g': 774 get_number (0, 99, 2); 775 /* XXX This cannot determine any field in TM. */ 776 break; 777 case 'G': 778 if (*rp < '0' || *rp > '9') 779 return NULL; 780 /* XXX Ignore the number since we would need some more 781 information to compute a real date. */ 782 do 783 ++rp; 784 while (*rp >= '0' && *rp <= '9'); 785 break; 786 case 'U': 787 case 'V': 788 case 'W': 789 get_number (0, 53, 2); 790 /* XXX This cannot determine any field in TM without some 791 information. */ 792 break; 793 case 'w': 794 /* Match number of weekday. */ 795 get_number (0, 6, 1); 796 tm->tm_wday = val; 797 have_wday = 1; 798 break; 799 case 'y': 800 /* Match year within century. */ 801 get_number (0, 99, 2); 802 /* The "Year 2000: The Millennium Rollover" paper suggests that 803 values in the range 69-99 refer to the twentieth century. */ 804 tm->tm_year = val >= 69 ? val : val + 100; 805 /* Indicate that we want to use the century, if specified. */ 806 want_century = 1; 807 want_xday = 1; 808 break; 809 case 'Y': 810 /* Match year including century number. */ 811 get_number (0, 9999, 4); 812 tm->tm_year = val - 1900; 813 want_century = 0; 814 want_xday = 1; 815 break; 816 case 'Z': 817 /* XXX How to handle this? */ 818 break; 819 case 'E': 820#ifdef _NL_CURRENT 821 switch (*fmt++) 822 { 823 case 'c': 824 /* Match locale's alternate date and time format. */ 825 if (*decided != raw) 826 { 827 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT); 828 829 if (*fmt == '\0') 830 fmt = _NL_CURRENT (LC_TIME, D_T_FMT); 831 832 if (!recursive (fmt)) 833 { 834 if (*decided == loc) 835 return NULL; 836 else 837 rp = rp_backup; 838 } 839 else 840 { 841 if (strcmp (fmt, HERE_D_T_FMT)) 842 *decided = loc; 843 want_xday = 1; 844 break; 845 } 846 *decided = raw; 847 } 848 /* The C locale has no era information, so use the 849 normal representation. */ 850 if (!recursive (HERE_D_T_FMT)) 851 return NULL; 852 want_xday = 1; 853 break; 854 case 'C': 855 case 'y': 856 case 'Y': 857 /* Match name of base year in locale's alternate 858 representation. */ 859 /* XXX This is currently not implemented. It should 860 use the value _NL_CURRENT (LC_TIME, ERA). */ 861 break; 862 case 'x': 863 if (*decided != raw) 864 { 865 const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT); 866 867 if (*fmt == '\0') 868 fmt = _NL_CURRENT (LC_TIME, D_FMT); 869 870 if (!recursive (fmt)) 871 { 872 if (*decided == loc) 873 return NULL; 874 else 875 rp = rp_backup; 876 } 877 else 878 { 879 if (strcmp (fmt, HERE_D_FMT)) 880 *decided = loc; 881 break; 882 } 883 *decided = raw; 884 } 885 if (!recursive (HERE_D_FMT)) 886 return NULL; 887 break; 888 case 'X': 889 if (*decided != raw) 890 { 891 const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT); 892 893 if (*fmt == '\0') 894 fmt = _NL_CURRENT (LC_TIME, T_FMT); 895 896 if (!recursive (fmt)) 897 { 898 if (*decided == loc) 899 return NULL; 900 else 901 rp = rp_backup; 902 } 903 else 904 { 905 if (strcmp (fmt, HERE_T_FMT)) 906 *decided = loc; 907 break; 908 } 909 *decided = raw; 910 } 911 if (!recursive (HERE_T_FMT)) 912 return NULL; 913 break; 914 default: 915 return NULL; 916 } 917 break; 918#else 919 /* We have no information about the era format. Just use 920 the normal format. */ 921 if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y' 922 && *fmt != 'x' && *fmt != 'X') 923 /* This is an illegal format. */ 924 return NULL; 925 926 goto start_over; 927#endif 928 case 'O': 929 switch (*fmt++) 930 { 931 case 'd': 932 case 'e': 933 /* Match day of month using alternate numeric symbols. */ 934 get_alt_number (1, 31, 2); 935 tm->tm_mday = val; 936 have_mday = 1; 937 want_xday = 1; 938 break; 939 case 'H': 940 /* Match hour in 24-hour clock using alternate numeric 941 symbols. */ 942 get_alt_number (0, 23, 2); 943 tm->tm_hour = val; 944 have_I = 0; 945 break; 946 case 'I': 947 /* Match hour in 12-hour clock using alternate numeric 948 symbols. */ 949 get_alt_number (1, 12, 2); 950 tm->tm_hour = val - 1; 951 have_I = 1; 952 break; 953 case 'm': 954 /* Match month using alternate numeric symbols. */ 955 get_alt_number (1, 12, 2); 956 tm->tm_mon = val - 1; 957 have_mon = 1; 958 want_xday = 1; 959 break; 960 case 'M': 961 /* Match minutes using alternate numeric symbols. */ 962 get_alt_number (0, 59, 2); 963 tm->tm_min = val; 964 break; 965 case 'S': 966 /* Match seconds using alternate numeric symbols. */ 967 get_alt_number (0, 61, 2); 968 tm->tm_sec = val; 969 break; 970 case 'U': 971 case 'V': 972 case 'W': 973 get_alt_number (0, 53, 2); 974 /* XXX This cannot determine any field in TM without 975 further information. */ 976 break; 977 case 'w': 978 /* Match number of weekday using alternate numeric symbols. */ 979 get_alt_number (0, 6, 1); 980 tm->tm_wday = val; 981 have_wday = 1; 982 break; 983 case 'y': 984 /* Match year within century using alternate numeric symbols. */ 985 get_alt_number (0, 99, 2); 986 tm->tm_year = val >= 69 ? val : val + 100; 987 want_xday = 1; 988 break; 989 default: 990 return NULL; 991 } 992 break; 993 default: 994 return NULL; 995 } 996 } 997 998 if (have_I && is_pm) 999 tm->tm_hour += 12; 1000 1001 if (century != -1) 1002 { 1003 if (want_century) 1004 tm->tm_year = tm->tm_year % 100 + (century - 19) * 100; 1005 else 1006 /* Only the century, but not the year. Strange, but so be it. */ 1007 tm->tm_year = (century - 19) * 100; 1008 } 1009 1010 if (want_xday && !have_wday) { 1011 if ( !(have_mon && have_mday) && have_yday) { 1012 /* we don't have tm_mon and/or tm_mday, compute them */ 1013 int t_mon = 0; 1014 while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday) 1015 t_mon++; 1016 if (!have_mon) 1017 tm->tm_mon = t_mon - 1; 1018 if (!have_mday) 1019 tm->tm_mday = tm->tm_yday - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1; 1020 } 1021 day_of_the_week (tm); 1022 } 1023 if (want_xday && !have_yday) 1024 day_of_the_year (tm); 1025 1026 return (char *) rp; 1027} 1028 1029 1030char * 1031strptime (buf, format, tm) 1032 const char *buf; 1033 const char *format; 1034 struct tm *tm; 1035{ 1036 enum locale_status decided; 1037#ifdef _NL_CURRENT 1038 decided = not; 1039#else 1040 decided = raw; 1041#endif 1042 return strptime_internal (buf, format, tm, &decided); 1043} 1044#endif /* not HAVE_STRPTIME */ 1045 1046#ifdef NEED_MON_YDAY 1047const unsigned short int __mon_yday[2][13] = 1048 { 1049 /* Normal years. */ 1050 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 1051 /* Leap years. */ 1052 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } 1053 }; 1054#endif 1055 1056/* fnmatch is required by POSIX, but we include an implementation for 1057 the sake of systems that don't have it, most notably Windows. Some 1058 systems do have fnmatch, but Apache's installation process installs 1059 its own fnmatch.h (incompatible with the system one!) in a system 1060 include directory, effectively rendering fnmatch unusable. This 1061 has been fixed with Apache 2, where fnmatch has been moved to apr 1062 and given a prefix, but many systems out there are still (as of 1063 this writing in 2005) broken and we must cater to them. 1064 1065 Additionally, according to some conventional wisdom, many 1066 historical implementations of fnmatch are buggy and unreliable. If 1067 yours is such, undefine SYSTEM_FNMATCH in sysdep.h and tell us 1068 about it. */ 1069 1070#ifndef SYSTEM_FNMATCH 1071 1072#define __FNM_FLAGS (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD) 1073 1074/* Match STRING against the filename pattern PATTERN, returning zero 1075 if it matches, FNM_NOMATCH if not. This implementation comes from 1076 an earlier version of GNU Bash. (It doesn't make sense to update 1077 it with a newer version because those versions add a lot of 1078 features Wget doesn't use or care about.) */ 1079 1080int 1081fnmatch (const char *pattern, const char *string, int flags) 1082{ 1083 register const char *p = pattern, *n = string; 1084 register char c; 1085 1086 if ((flags & ~__FNM_FLAGS) != 0) 1087 { 1088 errno = EINVAL; 1089 return (-1); 1090 } 1091 1092 while ((c = *p++) != '\0') 1093 { 1094 switch (c) 1095 { 1096 case '?': 1097 if (*n == '\0') 1098 return (FNM_NOMATCH); 1099 else if ((flags & FNM_PATHNAME) && *n == '/') 1100 return (FNM_NOMATCH); 1101 else if ((flags & FNM_PERIOD) && *n == '.' && 1102 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) 1103 return (FNM_NOMATCH); 1104 break; 1105 1106 case '\\': 1107 if (!(flags & FNM_NOESCAPE)) 1108 c = *p++; 1109 if (*n != c) 1110 return (FNM_NOMATCH); 1111 break; 1112 1113 case '*': 1114 if ((flags & FNM_PERIOD) && *n == '.' && 1115 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) 1116 return (FNM_NOMATCH); 1117 1118 for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) 1119 if (((flags & FNM_PATHNAME) && *n == '/') || 1120 (c == '?' && *n == '\0')) 1121 return (FNM_NOMATCH); 1122 1123 if (c == '\0') 1124 return (0); 1125 1126 { 1127 char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; 1128 for (--p; *n != '\0'; ++n) 1129 if ((c == '[' || *n == c1) && 1130 fnmatch (p, n, flags & ~FNM_PERIOD) == 0) 1131 return (0); 1132 return (FNM_NOMATCH); 1133 } 1134 1135 case '[': 1136 { 1137 /* Nonzero if the sense of the character class is 1138 inverted. */ 1139 register int not; 1140 1141 if (*n == '\0') 1142 return (FNM_NOMATCH); 1143 1144 if ((flags & FNM_PERIOD) && *n == '.' && 1145 (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) 1146 return (FNM_NOMATCH); 1147 1148 /* Make sure there is a closing `]'. If there isn't, 1149 the `[' is just a character to be matched. */ 1150 { 1151 register const char *np; 1152 1153 for (np = p; np && *np && *np != ']'; np++) 1154 ; 1155 1156 if (np && !*np) 1157 { 1158 if (*n != '[') 1159 return (FNM_NOMATCH); 1160 goto next_char; 1161 } 1162 } 1163 1164 not = (*p == '!' || *p == '^'); 1165 if (not) 1166 ++p; 1167 1168 c = *p++; 1169 while (1) 1170 { 1171 register char cstart = c, cend = c; 1172 1173 if (!(flags & FNM_NOESCAPE) && c == '\\') 1174 cstart = cend = *p++; 1175 1176 if (c == '\0') 1177 /* [ (unterminated) loses. */ 1178 return (FNM_NOMATCH); 1179 1180 c = *p++; 1181 1182 if ((flags & FNM_PATHNAME) && c == '/') 1183 /* [/] can never match. */ 1184 return (FNM_NOMATCH); 1185 1186 if (c == '-' && *p != ']') 1187 { 1188 cend = *p++; 1189 if (!(flags & FNM_NOESCAPE) && cend == '\\') 1190 cend = *p++; 1191 if (cend == '\0') 1192 return (FNM_NOMATCH); 1193 c = *p++; 1194 } 1195 1196 if (*n >= cstart && *n <= cend) 1197 goto matched; 1198 1199 if (c == ']') 1200 break; 1201 } 1202 if (!not) 1203 return (FNM_NOMATCH); 1204 1205 next_char: 1206 break; 1207 1208 matched: 1209 /* Skip the rest of the [...] that already matched. */ 1210 while (c != ']') 1211 { 1212 if (c == '\0') 1213 /* [... (unterminated) loses. */ 1214 return (FNM_NOMATCH); 1215 1216 c = *p++; 1217 if (!(flags & FNM_NOESCAPE) && c == '\\') 1218 /* 1003.2d11 is unclear if this is right. %%% */ 1219 ++p; 1220 } 1221 if (not) 1222 return (FNM_NOMATCH); 1223 } 1224 break; 1225 1226 default: 1227 if (c != *n) 1228 return (FNM_NOMATCH); 1229 } 1230 1231 ++n; 1232 } 1233 1234 if (*n == '\0') 1235 return (0); 1236 1237 return (FNM_NOMATCH); 1238} 1239 1240#endif /* not SYSTEM_FNMATCH */ 1241 1242#ifndef HAVE_TIMEGM 1243/* timegm is a GNU extension, but lately also available on *BSD 1244 systems and possibly elsewhere. */ 1245 1246/* True if YEAR is a leap year. */ 1247#define ISLEAP(year) \ 1248 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) 1249 1250/* Number of leap years in the range [y1, y2). */ 1251#define LEAPYEARS(y1, y2) \ 1252 ((y2-1)/4 - (y1-1)/4) - ((y2-1)/100 - (y1-1)/100) + ((y2-1)/400 - (y1-1)/400) 1253 1254/* Inverse of gmtime: converts struct tm to time_t, assuming the data 1255 in tm is UTC rather than local timezone. This implementation 1256 returns the number of seconds elapsed since midnight 1970-01-01, 1257 converted to time_t. */ 1258 1259time_t 1260timegm (struct tm *t) 1261{ 1262 static const unsigned short int month_to_days[][13] = { 1263 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, /* normal */ 1264 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } /* leap */ 1265 }; 1266 const int year = 1900 + t->tm_year; 1267 unsigned long secs; /* until 2106-02-07 for 32-bit unsigned long */ 1268 int days; 1269 1270 if (year < 1970) 1271 return (time_t) -1; 1272 1273 days = 365 * (year - 1970); 1274 /* Take into account leap years between 1970 and YEAR, not counting 1275 YEAR itself. */ 1276 days += LEAPYEARS (1970, year); 1277 if (t->tm_mon < 0 || t->tm_mon >= 12) 1278 return (time_t) -1; 1279 days += month_to_days[ISLEAP (year)][t->tm_mon]; 1280 days += t->tm_mday - 1; 1281 1282 secs = days * 86400 + t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec; 1283 return (time_t) secs; 1284} 1285#endif /* HAVE_TIMEGM */ 1286 1287#ifdef NEED_STRTOLL 1288/* strtoll is required by C99 and used by Wget only on systems with 1289 LFS. Unfortunately, some systems have LFS, but no strtoll or 1290 equivalent. These include HPUX 11.0 and Windows. 1291 1292 We use #ifdef NEED_STRTOLL instead of #ifndef HAVE_STRTOLL because 1293 of the systems which have a suitable replacement (e.g. _strtoi64 on 1294 Windows), on which Wget's str_to_wgint is instructed to use that 1295 instead. */ 1296 1297static inline int 1298char_value (char c, int base) 1299{ 1300 int value; 1301 if (c < '0') 1302 return -1; 1303 if ('0' <= c && c <= '9') 1304 value = c - '0'; 1305 else if ('a' <= c && c <= 'z') 1306 value = c - 'a' + 10; 1307 else if ('A' <= c && c <= 'Z') 1308 value = c - 'A' + 10; 1309 else 1310 return -1; 1311 if (value >= base) 1312 return -1; 1313 return value; 1314} 1315 1316#define STRTOLL_MAX TYPE_MAXIMUM (strtoll_type) 1317/* This definition assumes two's complement arithmetic */ 1318#define STRTOLL_MIN (-STRTOLL_MAX - 1) 1319 1320/* Like a%b, but always returns a positive number when A is negative. 1321 (C doesn't guarantee the sign of the result.) */ 1322#define MOD(a, b) ((strtoll_type) -1 % 2 == 1 ? (a) % (b) : - ((a) % (b))) 1323 1324/* A strtoll-like replacement for systems that have an integral type 1325 larger than long but don't supply strtoll. This implementation 1326 makes no assumptions about the size of strtoll_type. */ 1327 1328strtoll_type 1329strtoll (const char *nptr, char **endptr, int base) 1330{ 1331 strtoll_type result = 0; 1332 bool negative; 1333 1334 if (base != 0 && (base < 2 || base > 36)) 1335 { 1336 errno = EINVAL; 1337 return 0; 1338 } 1339 1340 while (*nptr == ' ' || *nptr == '\t') 1341 ++nptr; 1342 if (*nptr == '-') 1343 { 1344 negative = true; 1345 ++nptr; 1346 } 1347 else if (*nptr == '+') 1348 { 1349 negative = false; 1350 ++nptr; 1351 } 1352 else 1353 negative = false; 1354 1355 /* If BASE is 0, determine the real base based on the beginning on 1356 the number; octal numbers begin with "0", hexadecimal with "0x", 1357 and the others are considered octal. */ 1358 if (*nptr == '0') 1359 { 1360 if ((base == 0 || base == 16) 1361 && 1362 (*(nptr + 1) == 'x' || *(nptr + 1) == 'X')) 1363 { 1364 base = 16; 1365 nptr += 2; 1366 /* "0x" must be followed by at least one hex char. If not, 1367 return 0 and place ENDPTR on 'x'. */ 1368 if (!c_isxdigit (*nptr)) 1369 { 1370 --nptr; 1371 goto out; 1372 } 1373 } 1374 else if (base == 0) 1375 base = 8; 1376 } 1377 else if (base == 0) 1378 base = 10; 1379 1380 if (!negative) 1381 { 1382 /* Parse positive number, checking for overflow. */ 1383 int digit; 1384 /* Overflow watermark. If RESULT exceeds it, overflow occurs on 1385 this digit. If result==WATERMARK, current digit may not 1386 exceed the last digit of maximum value. */ 1387 const strtoll_type WATERMARK = STRTOLL_MAX / base; 1388 for (; (digit = char_value (*nptr, base)) != -1; ++nptr) 1389 { 1390 if (result > WATERMARK 1391 || (result == WATERMARK && digit > STRTOLL_MAX % base)) 1392 { 1393 result = STRTOLL_MAX; 1394 errno = ERANGE; 1395 break; 1396 } 1397 result = base * result + digit; 1398 } 1399 } 1400 else 1401 { 1402 /* Parse negative number, checking for underflow. */ 1403 int digit; 1404 const strtoll_type WATERMARK = STRTOLL_MIN / base; 1405 for (; (digit = char_value (*nptr, base)) != -1; ++nptr) 1406 { 1407 if (result < WATERMARK 1408 || (result == WATERMARK && digit > MOD (STRTOLL_MIN, base))) 1409 { 1410 result = STRTOLL_MIN; 1411 errno = ERANGE; 1412 break; 1413 } 1414 result = base * result - digit; 1415 } 1416 } 1417 out: 1418 if (endptr) 1419 *endptr = (char *) nptr; 1420 return result; 1421} 1422 1423#undef STRTOLL_MAX 1424#undef STRTOLL_MIN 1425#undef ABS 1426 1427#endif /* NEED_STRTOLL */ 1428