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