Merge in ast_strftime branch, which changes timestamps to be accurate to the microsec...
[asterisk/asterisk.git] / main / stdtime / localtime.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * Most of this code is in the public domain, so clarified as of
9  * June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
10  *
11  * All modifications to this code to abstract timezones away from
12  * the environment are by Tilghman Lesher, <tlesher@vcch.com>, with
13  * the copyright assigned to Digium.
14  *
15  * See http://www.asterisk.org for more information about
16  * the Asterisk project. Please do not directly contact
17  * any of the maintainers of this project for assistance;
18  * the project provides a web site, mailing lists and IRC
19  * channels for your use.
20  *
21  * This program is free software, distributed under the terms of
22  * the GNU General Public License Version 2. See the LICENSE file
23  * at the top of the source tree.
24  */
25
26 /*! \file
27  *
28  * Multi-timezone Localtime code
29  * 
30  * \author Leap second handling Bradley White (bww@k.gp.cs.cmu.edu).
31  * \author POSIX-style TZ environment variable handling from Guy Harris (guy@auspex.com).
32  *
33  */
34
35 /*
36  * Asterisk defines
37  *
38  * Don't mess with these unless you're really sure you know what you're doing.
39  */
40 #ifndef _THREAD_SAFE
41 #define _THREAD_SAFE
42 #endif
43 #define TZ_STRLEN_MAX   255
44 /* #define DEBUG */
45
46 /*LINTLIBRARY*/
47
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <fcntl.h>
51 #ifdef DEBUG
52 #include <stdio.h>
53 #endif
54
55 #include "private.h"
56 #include "tzfile.h"
57
58 #include "asterisk.h"
59
60 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
61
62 #include "asterisk/lock.h"
63 #include "asterisk/localtime.h"
64 #include "asterisk/strings.h"
65
66 #ifndef lint
67 #ifndef NOID
68 static const char elsieid[] = "@(#)localtime.c  7.57";
69 #endif /* !defined NOID */
70 #endif /* !defined lint */
71
72
73
74 /*
75 ** SunOS 4.1.1 headers lack O_BINARY.
76 */
77
78 #ifdef O_BINARY
79 #define OPEN_MODE       (O_RDONLY | O_BINARY)
80 #endif /* defined O_BINARY */
81 #ifndef O_BINARY
82 #define OPEN_MODE       O_RDONLY
83 #endif /* !defined O_BINARY */
84
85 #ifdef SOLARIS
86 #undef TM_ZONE
87 #undef TM_GMTOFF 
88 #endif
89
90 #ifdef TM_ZONE
91 #ifndef WILDABBR
92 /*! \note
93  * Someone might make incorrect use of a time zone abbreviation:
94  *      1.      They might reference tzname[0] before calling ast_tzset (explicitly
95  *              or implicitly).
96  *      2.      They might reference tzname[1] before calling ast_tzset (explicitly
97  *              or implicitly).
98  *      3.      They might reference tzname[1] after setting to a time zone
99  *              in which Daylight Saving Time is never observed.
100  *      4.      They might reference tzname[0] after setting to a time zone
101  *              in which Standard Time is never observed.
102  *      5.      They might reference tm.TM_ZONE after calling offtime.
103  * What's best to do in the above cases is open to debate;
104  * for now, we just set things up so that in any of the five cases
105  * WILDABBR is used.  Another possibility:  initialize tzname[0] to the
106  * string "tzname[0] used before set", and similarly for the other cases.
107  * And another:  initialize tzname[0] to "ERA", with an explanation in the
108  * manual page of what this "time zone abbreviation" means (doing this so
109  * that tzname[0] has the "normal" length of three characters).
110  */
111 #define WILDABBR        "   "
112 #endif /* !defined WILDABBR */
113
114 static char             wildabbr[] = "WILDABBR";
115 #endif /* TM_ZONE */
116
117 /*! \brief FreeBSD defines 'zone' in 'struct tm' as non-const, so don't declare this
118    string as const. */
119 static char             gmt[] = "GMT";
120
121 /*!< \brief time type information */
122 struct ttinfo {
123         long            tt_gmtoff;      /*!< GMT offset in seconds */
124         int             tt_isdst;       /*!< used to set tm_isdst */
125         int             tt_abbrind;     /*!< abbreviation list index */
126         int             tt_ttisstd;     /*!< TRUE if transition is std time */
127         int             tt_ttisgmt;     /*!< TRUE if transition is GMT */
128 };
129
130 /*! \brief leap second information */
131 struct lsinfo {
132         time_t          ls_trans;       /*!< transition time */
133         long            ls_corr;        /*!< correction to apply */
134 };
135
136 #define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
137
138 #ifdef TZNAME_MAX
139 #define MY_TZNAME_MAX   TZNAME_MAX
140 #endif /* defined TZNAME_MAX */
141 #ifndef TZNAME_MAX
142 #define MY_TZNAME_MAX   255
143 #endif /* !defined TZNAME_MAX */
144
145 struct state {
146         char    name[TZ_STRLEN_MAX + 1];
147         int             leapcnt;
148         int             timecnt;
149         int             typecnt;
150         int             charcnt;
151         time_t          ats[TZ_MAX_TIMES];
152         unsigned char   types[TZ_MAX_TIMES];
153         struct ttinfo   ttis[TZ_MAX_TYPES];
154         char            chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
155                                 (2 * (MY_TZNAME_MAX + 1)))];
156         struct lsinfo   lsis[TZ_MAX_LEAPS];
157         struct state    *next;
158 };
159
160 struct rule {
161         int             r_type;         /*!< type of rule--see below */
162         int             r_day;          /*!< day number of rule */
163         int             r_week;         /*!< week number of rule */
164         int             r_mon;          /*!< month number of rule */
165         long            r_time;         /*!< transition time of rule */
166 };
167
168 #define JULIAN_DAY              0       /*!< Jn - Julian day */
169 #define DAY_OF_YEAR             1       /*!< n - day of year */
170 #define MONTH_NTH_DAY_OF_WEEK   2       /*!< Mm.n.d - month, week, day of week */
171
172 /*
173 ** Prototypes for static functions.
174 */
175
176 static long             detzcode P((const char * codep));
177 static const char *     getnum P((const char * strp, int * nump, int min,
178                                 int max));
179 static const char *     getsecs P((const char * strp, long * secsp));
180 static const char *     getoffset P((const char * strp, long * offsetp));
181 static const char *     getrule P((const char * strp, struct rule * rulep));
182 static void             gmtload P((struct state * sp));
183 static void             gmtsub P((const struct timeval * timep, long offset,
184                                 struct ast_tm * tmp, const char * zone));
185 static void             localsub P((const struct timeval * timep, long offset,
186                                 struct ast_tm * tmp, const char * zone));
187 static int              increment_overflow P((int * number, int delta));
188 static int              normalize_overflow P((int * tensptr, int * unitsptr,
189                                 int base));
190 static time_t           time1 P((struct ast_tm * tmp,
191                                 void(*funcp) P((const struct timeval *,
192                                 long, struct ast_tm *, const char *)),
193                                 long offset, const char * zone));
194 static time_t           time2 P((struct ast_tm *tmp,
195                                 void(*funcp) P((const struct timeval *,
196                                 long, struct ast_tm *, const char *)),
197                                 long offset, int * okayp, const char * zone));
198 static void             timesub P((const struct timeval * timep, long offset,
199                                 const struct state * sp, struct ast_tm *tmp));
200 static int              tmcomp P((const struct ast_tm *atmp,
201                                 const struct ast_tm * btmp));
202 static time_t           transtime P((time_t janfirst, int year,
203                                 const struct rule * rulep, long offset));
204 static int              tzload P((const char * name, struct state * sp));
205 static int              tzparse P((const char * name, struct state * sp,
206                                 int lastditch));
207
208 static struct state *   lclptr      = NULL;
209 static struct state *   last_lclptr = NULL;
210 static struct state *   gmtptr      = NULL;
211
212 #ifndef TZ_STRLEN_MAX
213 #define TZ_STRLEN_MAX 255
214 #endif /* !defined TZ_STRLEN_MAX */
215
216 static int              gmt_is_set;
217 #ifdef  _THREAD_SAFE
218 AST_MUTEX_DEFINE_STATIC(lcl_mutex);
219 AST_MUTEX_DEFINE_STATIC(tzset_mutex);
220 AST_MUTEX_DEFINE_STATIC(tzsetwall_mutex);
221 AST_MUTEX_DEFINE_STATIC(gmt_mutex);
222 #endif
223
224 /*
225 ** Section 4.12.3 of X3.159-1989 requires that
226 **      Except for the strftime function, these functions [asctime,
227 **      ctime, gmtime, localtime] return values in one of two static
228 **      objects: a broken-down time structure and an array of char.
229 ** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
230 */
231
232 static long detzcode(const char * const codep)
233 {
234         register long   result;
235         register int    i;
236
237         result = (codep[0] & 0x80) ? ~0L : 0L;
238         for (i = 0; i < 4; ++i)
239                 result = (result << 8) | (codep[i] & 0xff);
240         return result;
241 }
242
243 static int tzload(register const char *name, register struct state *const       sp)
244 {
245         register const char *   p;
246         register int            i;
247         register int            fid;
248
249 #ifdef DEBUG
250         fprintf(stderr,"tzload called with name=%s, sp=%d\n", name, sp);
251 #endif
252         if (name == NULL && (name = TZDEFAULT) == NULL)
253                 return -1;
254         {
255                 register int    doaccess;
256                 struct stat     stab;
257                 /*
258                 ** Section 4.9.1 of the C standard says that
259                 ** "FILENAME_MAX expands to an integral constant expression
260                 ** that is the size needed for an array of char large enough
261                 ** to hold the longest file name string that the implementation
262                 ** guarantees can be opened."
263                 */
264                 char            fullname[FILENAME_MAX + 1] = "";
265
266                 if (name[0] == ':')
267                         ++name;
268                 doaccess = name[0] == '/';
269                 if (!doaccess) {
270                         if ((p = TZDIR) == NULL)
271                                 return -1;
272                         if ((strlen(p) + 1 + strlen(name) + 1) >= sizeof fullname)
273                                 return -1;
274                         (void) strncpy(fullname, p, sizeof(fullname) - 1);
275                         (void) strncat(fullname, "/", sizeof(fullname) - strlen(fullname) - 1);
276                         (void) strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
277                         /*
278                         ** Set doaccess if '.' (as in "../") shows up in name.
279                         */
280                         if (strchr(name, '.') != NULL)
281                                 doaccess = TRUE;
282                         name = fullname;
283                 }
284                 if (doaccess && access(name, R_OK) != 0)
285                         return -1;
286                 if ((fid = open(name, OPEN_MODE)) == -1)
287                         return -1;
288                 if ((fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) {
289                         close(fid);
290                         return -1;
291                 }
292         }
293         {
294                 struct tzhead * tzhp;
295                 char            buf[sizeof *sp + sizeof *tzhp];
296                 int             ttisstdcnt;
297                 int             ttisgmtcnt;
298
299                 i = read(fid, buf, sizeof buf);
300                 if (close(fid) != 0)
301                         return -1;
302                 p = buf;
303                 p += (sizeof tzhp->tzh_magic) + (sizeof tzhp->tzh_reserved);
304                 ttisstdcnt = (int) detzcode(p);
305                 p += 4;
306                 ttisgmtcnt = (int) detzcode(p);
307                 p += 4;
308                 sp->leapcnt = (int) detzcode(p);
309                 p += 4;
310                 sp->timecnt = (int) detzcode(p);
311                 p += 4;
312                 sp->typecnt = (int) detzcode(p);
313                 p += 4;
314                 sp->charcnt = (int) detzcode(p);
315                 p += 4;
316                 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
317                         sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
318                         sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
319                         sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
320                         (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
321                         (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
322                                 return -1;
323                 if (i - (p - buf) < sp->timecnt * 4 +   /* ats */
324                         sp->timecnt +                   /* types */
325                         sp->typecnt * (4 + 2) +         /* ttinfos */
326                         sp->charcnt +                   /* chars */
327                         sp->leapcnt * (4 + 4) +         /* lsinfos */
328                         ttisstdcnt +                    /* ttisstds */
329                         ttisgmtcnt)                     /* ttisgmts */
330                                 return -1;
331                 for (i = 0; i < sp->timecnt; ++i) {
332                         sp->ats[i] = detzcode(p);
333                         p += 4;
334                 }
335                 for (i = 0; i < sp->timecnt; ++i) {
336                         sp->types[i] = (unsigned char) *p++;
337                         if (sp->types[i] >= sp->typecnt)
338                                 return -1;
339                 }
340                 for (i = 0; i < sp->typecnt; ++i) {
341                         register struct ttinfo *        ttisp;
342
343                         ttisp = &sp->ttis[i];
344                         ttisp->tt_gmtoff = detzcode(p);
345                         p += 4;
346                         ttisp->tt_isdst = (unsigned char) *p++;
347                         if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
348                                 return -1;
349                         ttisp->tt_abbrind = (unsigned char) *p++;
350                         if (ttisp->tt_abbrind < 0 ||
351                                 ttisp->tt_abbrind > sp->charcnt)
352                                         return -1;
353                 }
354                 for (i = 0; i < sp->charcnt; ++i)
355                         sp->chars[i] = *p++;
356                 sp->chars[i] = '\0';    /* ensure '\0' at end */
357                 for (i = 0; i < sp->leapcnt; ++i) {
358                         register struct lsinfo *        lsisp;
359
360                         lsisp = &sp->lsis[i];
361                         lsisp->ls_trans = detzcode(p);
362                         p += 4;
363                         lsisp->ls_corr = detzcode(p);
364                         p += 4;
365                 }
366                 for (i = 0; i < sp->typecnt; ++i) {
367                         register struct ttinfo *        ttisp;
368
369                         ttisp = &sp->ttis[i];
370                         if (ttisstdcnt == 0)
371                                 ttisp->tt_ttisstd = FALSE;
372                         else {
373                                 ttisp->tt_ttisstd = *p++;
374                                 if (ttisp->tt_ttisstd != TRUE &&
375                                         ttisp->tt_ttisstd != FALSE)
376                                                 return -1;
377                         }
378                 }
379                 for (i = 0; i < sp->typecnt; ++i) {
380                         register struct ttinfo *        ttisp;
381
382                         ttisp = &sp->ttis[i];
383                         if (ttisgmtcnt == 0)
384                                 ttisp->tt_ttisgmt = FALSE;
385                         else {
386                                 ttisp->tt_ttisgmt = *p++;
387                                 if (ttisp->tt_ttisgmt != TRUE &&
388                                         ttisp->tt_ttisgmt != FALSE)
389                                                 return -1;
390                         }
391                 }
392         }
393         return 0;
394 }
395
396 static const int        mon_lengths[2][MONSPERYEAR] = {
397         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
398         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
399 };
400
401 static const int        year_lengths[2] = {
402         DAYSPERNYEAR, DAYSPERLYEAR
403 };
404
405 /*! \brief
406  * Given a pointer into a time zone string, extract a number from that string.
407  * \return Check that the number is within a specified range; if it is not, return
408  * NULL.
409  * Otherwise, return a pointer to the first character not part of the number.
410 */
411
412 static const char *getnum(register const char *strp, int * const nump, const int min, const int max)
413 {
414         register char   c;
415         register int    num;
416
417         if (strp == NULL || !is_digit(c = *strp))
418                 return NULL;
419         num = 0;
420         do {
421                 num = num * 10 + (c - '0');
422                 if (num > max)
423                         return NULL;    /* illegal value */
424                 c = *++strp;
425         } while (is_digit(c));
426         if (num < min)
427                 return NULL;            /* illegal value */
428         *nump = num;
429         return strp;
430 }
431
432 /*! \brief
433  * Given a pointer into a time zone string, extract a number of seconds,
434  * in hh[:mm[:ss]] form, from the string.
435  * \return If any error occurs, return NULL.
436  * Otherwise, return a pointer to the first character not part of the number
437  * of seconds.
438 */
439
440 static const char *getsecs(register const char *strp, long * const secsp)
441 {
442         int     num;
443
444         /*
445         ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
446         ** "M10.4.6/26", which does not conform to Posix,
447         ** but which specifies the equivalent of
448         ** ``02:00 on the first Sunday on or after 23 Oct''.
449         */
450         strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
451         if (strp == NULL)
452                 return NULL;
453         *secsp = num * (long) SECSPERHOUR;
454         if (*strp == ':') {
455                 ++strp;
456                 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
457                 if (strp == NULL)
458                         return NULL;
459                 *secsp += num * SECSPERMIN;
460                 if (*strp == ':') {
461                         ++strp;
462                         /* `SECSPERMIN' allows for leap seconds.  */
463                         strp = getnum(strp, &num, 0, SECSPERMIN);
464                         if (strp == NULL)
465                                 return NULL;
466                         *secsp += num;
467                 }
468         }
469         return strp;
470 }
471
472 /*! \brief
473  * Given a pointer into a time zone string, extract an offset, in
474  * [+-]hh[:mm[:ss]] form, from the string.
475  * \return If any error occurs, return NULL.
476  * Otherwise, return a pointer to the first character not part of the time.
477 */
478
479 static const char * getoffset(register const char *strp, long * const offsetp)
480 {
481         register int    neg = 0;
482
483         if (*strp == '-') {
484                 neg = 1;
485                 ++strp;
486         } else if (*strp == '+')
487                 ++strp;
488         strp = getsecs(strp, offsetp);
489         if (strp == NULL)
490                 return NULL;            /* illegal time */
491         if (neg)
492                 *offsetp = -*offsetp;
493         return strp;
494 }
495
496 /*! \brief
497  * Given a pointer into a time zone string, extract a rule in the form
498  * date[/time].  See POSIX section 8 for the format of "date" and "time".
499  * \return If a valid rule is not found, return NULL.
500  * Otherwise, return a pointer to the first character not part of the rule.
501 */
502
503 static const char *getrule(const char *strp, register struct rule * const rulep)
504 {
505         if (*strp == 'J') {
506                 /*
507                 ** Julian day.
508                 */
509                 rulep->r_type = JULIAN_DAY;
510                 ++strp;
511                 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
512         } else if (*strp == 'M') {
513                 /*
514                 ** Month, week, day.
515                 */
516                 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
517                 ++strp;
518                 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
519                 if (strp == NULL)
520                         return NULL;
521                 if (*strp++ != '.')
522                         return NULL;
523                 strp = getnum(strp, &rulep->r_week, 1, 5);
524                 if (strp == NULL)
525                         return NULL;
526                 if (*strp++ != '.')
527                         return NULL;
528                 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
529         } else if (is_digit(*strp)) {
530                 /*
531                 ** Day of year.
532                 */
533                 rulep->r_type = DAY_OF_YEAR;
534                 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
535         } else  return NULL;            /* invalid format */
536         if (strp == NULL)
537                 return NULL;
538         if (*strp == '/') {
539                 /*
540                 ** Time specified.
541                 */
542                 ++strp;
543                 strp = getsecs(strp, &rulep->r_time);
544         } else  rulep->r_time = 2 * SECSPERHOUR;        /* default = 2:00:00 */
545         return strp;
546 }
547
548 /*! \brief
549  * Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the
550  * year, a rule, and the offset from GMT at the time that rule takes effect,
551  * calculate the Epoch-relative time that rule takes effect.
552 */
553
554 static time_t transtime(janfirst, year, rulep, offset)
555 const time_t                            janfirst;
556 const int                               year;
557 register const struct rule * const      rulep;
558 const long                              offset;
559 {
560         register int    leapyear;
561         register time_t value = 0;
562         register int    i;
563         int             d, m1, yy0, yy1, yy2, dow;
564
565         leapyear = isleap(year);
566         switch (rulep->r_type) {
567
568         case JULIAN_DAY:
569                 /*
570                 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
571                 ** years.
572                 ** In non-leap years, or if the day number is 59 or less, just
573                 ** add SECSPERDAY times the day number-1 to the time of
574                 ** January 1, midnight, to get the day.
575                 */
576                 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
577                 if (leapyear && rulep->r_day >= 60)
578                         value += SECSPERDAY;
579                 break;
580
581         case DAY_OF_YEAR:
582                 /*
583                 ** n - day of year.
584                 ** Just add SECSPERDAY times the day number to the time of
585                 ** January 1, midnight, to get the day.
586                 */
587                 value = janfirst + rulep->r_day * SECSPERDAY;
588                 break;
589
590         case MONTH_NTH_DAY_OF_WEEK:
591                 /*
592                 ** Mm.n.d - nth "dth day" of month m.
593                 */
594                 value = janfirst;
595                 for (i = 0; i < rulep->r_mon - 1; ++i)
596                         value += mon_lengths[leapyear][i] * SECSPERDAY;
597
598                 /*
599                 ** Use Zeller's Congruence to get day-of-week of first day of
600                 ** month.
601                 */
602                 m1 = (rulep->r_mon + 9) % 12 + 1;
603                 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
604                 yy1 = yy0 / 100;
605                 yy2 = yy0 % 100;
606                 dow = ((26 * m1 - 2) / 10 +
607                         1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
608                 if (dow < 0)
609                         dow += DAYSPERWEEK;
610
611                 /*
612                 ** "dow" is the day-of-week of the first day of the month.  Get
613                 ** the day-of-month (zero-origin) of the first "dow" day of the
614                 ** month.
615                 */
616                 d = rulep->r_day - dow;
617                 if (d < 0)
618                         d += DAYSPERWEEK;
619                 for (i = 1; i < rulep->r_week; ++i) {
620                         if (d + DAYSPERWEEK >=
621                                 mon_lengths[leapyear][rulep->r_mon - 1])
622                                         break;
623                         d += DAYSPERWEEK;
624                 }
625
626                 /*
627                 ** "d" is the day-of-month (zero-origin) of the day we want.
628                 */
629                 value += d * SECSPERDAY;
630                 break;
631         }
632
633         /*
634         ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
635         ** question.  To get the Epoch-relative time of the specified local
636         ** time on that day, add the transition time and the current offset
637         ** from GMT.
638         */
639         return value + rulep->r_time + offset;
640 }
641
642 /*
643 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
644 ** appropriate.
645 */
646
647 static int
648 tzparse(name, sp, lastditch)
649 const char *                    name;
650 register struct state * const   sp;
651 const int                       lastditch;
652 {
653         const char *                    stdname;
654         const char *                    dstname = NULL;
655         size_t                          stdlen = 0;
656         size_t                          dstlen = 0;
657         long                            stdoffset = 0L;
658         long                            dstoffset = 0L;
659         register time_t *               atp;
660         register unsigned char *        typep;
661         register char *                 cp;
662         register int                    load_result;
663
664         stdname = name;
665 #ifdef DEBUG
666         fprintf(stderr, "tzparse(): loading default rules\n");
667 #endif
668         load_result = tzload(TZDEFRULES, sp);
669         if (load_result != 0)
670                 sp->leapcnt = 0;                /* so, we're off a little */
671         if (*name != '\0') {
672                 if (*name != '\0' && *name != ',' && *name != ';') {
673                         name = getoffset(name, &dstoffset);
674                         if (name == NULL)
675                                 return -1;
676                 } else  dstoffset = stdoffset - SECSPERHOUR;
677                 if (*name == ',' || *name == ';') {
678                         struct rule     start;
679                         struct rule     end;
680                         register int    year;
681                         register time_t janfirst;
682                         time_t          starttime;
683                         time_t          endtime;
684
685                         ++name;
686                         if ((name = getrule(name, &start)) == NULL)
687                                 return -1;
688                         if (*name++ != ',')
689                                 return -1;
690                         if ((name = getrule(name, &end)) == NULL)
691                                 return -1;
692                         if (*name != '\0')
693                                 return -1;
694                         sp->typecnt = 2;        /* standard time and DST */
695                         /*
696                         ** Two transitions per year, from EPOCH_YEAR to 2037.
697                         */
698                         sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
699                         if (sp->timecnt > TZ_MAX_TIMES)
700                                 return -1;
701                         sp->ttis[0].tt_gmtoff = -dstoffset;
702                         sp->ttis[0].tt_isdst = 1;
703                         sp->ttis[0].tt_abbrind = stdlen + 1;
704                         sp->ttis[1].tt_gmtoff = -stdoffset;
705                         sp->ttis[1].tt_isdst = 0;
706                         sp->ttis[1].tt_abbrind = 0;
707                         atp = sp->ats;
708                         typep = sp->types;
709                         janfirst = 0;
710                         for (year = EPOCH_YEAR; year <= 2037; ++year) {
711                                 starttime = transtime(janfirst, year, &start,
712                                         stdoffset);
713                                 endtime = transtime(janfirst, year, &end,
714                                         dstoffset);
715                                 if (starttime > endtime) {
716                                         *atp++ = endtime;
717                                         *typep++ = 1;   /* DST ends */
718                                         *atp++ = starttime;
719                                         *typep++ = 0;   /* DST begins */
720                                 } else {
721                                         *atp++ = starttime;
722                                         *typep++ = 0;   /* DST begins */
723                                         *atp++ = endtime;
724                                         *typep++ = 1;   /* DST ends */
725                                 }
726                                 janfirst += year_lengths[isleap(year)] *
727                                         SECSPERDAY;
728                         }
729                 } else {
730                         register long   theirstdoffset;
731                         register long   theirdstoffset;
732                         register long   theiroffset;
733                         register int    isdst;
734                         register int    i;
735                         register int    j;
736
737                         if (*name != '\0')
738                                 return -1;
739                         if (load_result != 0)
740                                 return -1;
741                         /*
742                         ** Initial values of theirstdoffset and theirdstoffset.
743                         */
744                         theirstdoffset = 0;
745                         for (i = 0; i < sp->timecnt; ++i) {
746                                 j = sp->types[i];
747                                 if (!sp->ttis[j].tt_isdst) {
748                                         theirstdoffset =
749                                                 -sp->ttis[j].tt_gmtoff;
750                                         break;
751                                 }
752                         }
753                         theirdstoffset = 0;
754                         for (i = 0; i < sp->timecnt; ++i) {
755                                 j = sp->types[i];
756                                 if (sp->ttis[j].tt_isdst) {
757                                         theirdstoffset =
758                                                 -sp->ttis[j].tt_gmtoff;
759                                         break;
760                                 }
761                         }
762                         /*
763                         ** Initially we're assumed to be in standard time.
764                         */
765                         isdst = FALSE;
766                         theiroffset = theirstdoffset;
767                         /*
768                         ** Now juggle transition times and types
769                         ** tracking offsets as you do.
770                         */
771                         for (i = 0; i < sp->timecnt; ++i) {
772                                 j = sp->types[i];
773                                 sp->types[i] = sp->ttis[j].tt_isdst;
774                                 if (sp->ttis[j].tt_ttisgmt) {
775                                         /* No adjustment to transition time */
776                                 } else {
777                                         /*
778                                         ** If summer time is in effect, and the
779                                         ** transition time was not specified as
780                                         ** standard time, add the summer time
781                                         ** offset to the transition time;
782                                         ** otherwise, add the standard time
783                                         ** offset to the transition time.
784                                         */
785                                         /*
786                                         ** Transitions from DST to DDST
787                                         ** will effectively disappear since
788                                         ** POSIX provides for only one DST
789                                         ** offset.
790                                         */
791                                         if (isdst && !sp->ttis[j].tt_ttisstd) {
792                                                 sp->ats[i] += dstoffset -
793                                                         theirdstoffset;
794                                         } else {
795                                                 sp->ats[i] += stdoffset -
796                                                         theirstdoffset;
797                                         }
798                                 }
799                                 theiroffset = -sp->ttis[j].tt_gmtoff;
800                                 if (sp->ttis[j].tt_isdst)
801                                         theirdstoffset = theiroffset;
802                                 else    theirstdoffset = theiroffset;
803                         }
804                         /*
805                         ** Finally, fill in ttis.
806                         ** ttisstd and ttisgmt need not be handled.
807                         */
808                         sp->ttis[0].tt_gmtoff = -stdoffset;
809                         sp->ttis[0].tt_isdst = FALSE;
810                         sp->ttis[0].tt_abbrind = 0;
811                         sp->ttis[1].tt_gmtoff = -dstoffset;
812                         sp->ttis[1].tt_isdst = TRUE;
813                         sp->ttis[1].tt_abbrind = stdlen + 1;
814                 }
815         } else {
816                 dstlen = 0;
817                 sp->typecnt = 1;                /* only standard time */
818                 sp->timecnt = 0;
819                 sp->ttis[0].tt_gmtoff = -stdoffset;
820                 sp->ttis[0].tt_isdst = 0;
821                 sp->ttis[0].tt_abbrind = 0;
822         }
823         sp->charcnt = stdlen + 1;
824         if (dstlen != 0)
825                 sp->charcnt += dstlen + 1;
826         if (sp->charcnt > sizeof sp->chars)
827                 return -1;
828         cp = sp->chars;
829         (void) strncpy(cp, stdname, stdlen);
830         cp += stdlen;
831         *cp++ = '\0';
832         if (dstlen != 0) {
833                 (void) strncpy(cp, dstname, dstlen);
834                 *(cp + dstlen) = '\0';
835         }
836         return 0;
837 }
838
839 static void
840 gmtload(sp)
841 struct state * const    sp;
842 {
843         if (tzload(gmt, sp) != 0)
844                 (void) tzparse(gmt, sp, TRUE);
845 }
846
847 /*
848 ** A non-static declaration of ast_tzsetwall in a system header file
849 ** may cause a warning about this upcoming static declaration...
850 */
851 static
852 #ifdef  _THREAD_SAFE
853 int
854 ast_tzsetwall_basic P((void))
855 #else
856 int
857 ast_tzsetwall P((void))
858 #endif
859 {
860         struct state *cur_state = lclptr;
861
862         /* Find the appropriate structure, if already parsed */
863         while (cur_state != NULL) {
864                 if (cur_state->name[0] == '\0')
865                         break;
866                 cur_state = cur_state->next;
867         }
868         if (cur_state != NULL)
869                 return 0;
870         cur_state = malloc(sizeof(struct state));
871         if (cur_state == NULL) {
872                 return -1;
873         }
874         memset(cur_state,0,sizeof(struct state));
875         if (tzload((char *) NULL, cur_state) != 0)
876 #ifdef DEBUG
877         {
878                 fprintf(stderr, "ast_tzsetwall: calling gmtload()\n");
879 #endif
880                 gmtload(cur_state);
881 #ifdef DEBUG
882         }
883 #endif
884
885         if (last_lclptr)
886                 last_lclptr->next = cur_state;
887         else
888                 lclptr = cur_state;
889         last_lclptr = cur_state;
890         return 0;
891 }
892
893 #ifdef  _THREAD_SAFE
894 int
895 ast_tzsetwall P((void))
896 {
897         ast_mutex_lock(&tzsetwall_mutex);
898         ast_tzsetwall_basic();
899         ast_mutex_unlock(&tzsetwall_mutex);
900         return 0;
901 }
902 #endif
903
904 #ifdef  _THREAD_SAFE
905 static int
906 ast_tzset_basic P((const char *name))
907 #else
908 int
909 ast_tzset P((const char *name))
910 #endif
911 {
912         struct state *cur_state = lclptr;
913
914         /* Not set at all */
915         if (name == NULL) {
916                 return ast_tzsetwall();
917         }
918
919         /* Find the appropriate structure, if already parsed */
920         while (cur_state != NULL) {
921                 if (!strcmp(cur_state->name,name))
922                         break;
923                 cur_state = cur_state->next;
924         }
925         if (cur_state != NULL)
926                 return 0;
927
928         cur_state = malloc(sizeof(struct state));
929         if (cur_state == NULL) {
930                 return -1;
931         }
932         memset(cur_state,0,sizeof(*cur_state));
933
934         /* Name is set, but set to the empty string == no adjustments */
935         if (name[0] == '\0') {
936                 /*
937                 ** User wants it fast rather than right.
938                 */
939                 cur_state->leapcnt = 0;         /* so, we're off a little */
940                 cur_state->timecnt = 0;
941                 cur_state->ttis[0].tt_gmtoff = 0;
942                 cur_state->ttis[0].tt_abbrind = 0;
943                 (void) strncpy(cur_state->chars, gmt, sizeof(cur_state->chars) - 1);
944         } else if (tzload(name, cur_state) != 0) {
945                 if (name[0] == ':') {
946                         (void) gmtload(cur_state);
947                 } else if (tzparse(name, cur_state, FALSE) != 0) {
948                         /* If not found, load localtime */
949                         if (tzload("/etc/localtime", cur_state) != 0)
950                                 /* Last ditch, get GMT */
951                                 (void) gmtload(cur_state);
952                 }
953         }
954         strncpy(cur_state->name, name, sizeof(cur_state->name) - 1);
955         if (last_lclptr)
956                 last_lclptr->next = cur_state;
957         else
958                 lclptr = cur_state;
959         last_lclptr = cur_state;
960         return 0;
961 }
962
963 #ifdef  _THREAD_SAFE
964 void
965 ast_tzset P((const char *name))
966 {
967         ast_mutex_lock(&tzset_mutex);
968         ast_tzset_basic(name);
969         ast_mutex_unlock(&tzset_mutex);
970 }
971 #endif
972
973 /*
974 ** The easy way to behave "as if no library function calls" localtime
975 ** is to not call it--so we drop its guts into "localsub", which can be
976 ** freely called.  (And no, the PANS doesn't require the above behavior--
977 ** but it *is* desirable.)
978 **
979 ** The unused offset argument is for the benefit of mktime variants.
980 */
981
982 /*ARGSUSED*/
983 static void
984 localsub(timep, offset, tmp, zone)
985 const struct timeval * const    timep;
986 const long              offset;
987 struct ast_tm * const   tmp;
988 const char * const      zone;
989 {
990         register struct state *         sp;
991         register const struct ttinfo *  ttisp;
992         register int                    i;
993         struct timeval  t;
994         memcpy(&t, timep, sizeof(t));
995
996         sp = lclptr;
997         /* Find the right zone record */
998         if (zone == NULL)
999                 sp = NULL;
1000         else
1001                 while (sp != NULL) {
1002                         if (!strcmp(sp->name,zone))
1003                                 break;
1004                         sp = sp->next;
1005                 }
1006
1007         if (sp == NULL) {
1008                 ast_tzsetwall();
1009                 sp = lclptr;
1010                 /* Find the default zone record */
1011                 while (sp != NULL) {
1012                         if (sp->name[0] == '\0')
1013                                 break;
1014                         sp = sp->next;
1015                 }
1016         }
1017
1018         /* Last ditch effort, use GMT */
1019         if (sp == NULL) {
1020                 gmtsub(timep, offset, tmp, zone);
1021                 return;
1022         }
1023         if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) {
1024                 i = 0;
1025                 while (sp->ttis[i].tt_isdst)
1026                         if (++i >= sp->typecnt) {
1027                                 i = 0;
1028                                 break;
1029                         }
1030         } else {
1031                 for (i = 1; i < sp->timecnt; ++i)
1032                         if (t.tv_sec < sp->ats[i])
1033                                 break;
1034                 i = sp->types[i - 1];
1035         }
1036         ttisp = &sp->ttis[i];
1037         /*
1038         ** To get (wrong) behavior that's compatible with System V Release 2.0
1039         ** you'd replace the statement below with
1040         **      t += ttisp->tt_gmtoff;
1041         **      timesub(&t, 0L, sp, tmp);
1042         */
1043         timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1044         tmp->tm_isdst = ttisp->tt_isdst;
1045         tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
1046 #ifdef TM_ZONE
1047         tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1048 #endif /* defined TM_ZONE */
1049         tmp->tm_usec = timep->tv_usec;
1050 }
1051
1052 struct ast_tm *
1053 ast_localtime(timep, p_tm, zone)
1054 const struct timeval * const    timep;
1055 struct ast_tm *p_tm;
1056 const char * const      zone;
1057 {
1058 #ifdef _THREAD_SAFE
1059         ast_mutex_lock(&lcl_mutex);
1060 #endif
1061         ast_tzset(ast_strlen_zero(zone) ? "/etc/localtime" : zone);
1062         localsub(timep, 0L, p_tm, zone);
1063 #ifdef _THREAD_SAFE
1064         ast_mutex_unlock(&lcl_mutex);
1065 #endif
1066         return(p_tm);
1067 }
1068
1069 /*
1070 ** gmtsub is to gmtime as localsub is to localtime.
1071 */
1072
1073 static void
1074 gmtsub(timep, offset, tmp, zone)
1075 const struct timeval * const    timep;
1076 const long              offset;
1077 struct ast_tm * const   tmp;
1078 const char * const      zone;
1079 {
1080 #ifdef  _THREAD_SAFE
1081         ast_mutex_lock(&gmt_mutex);
1082 #endif
1083         if (!gmt_is_set) {
1084                 gmt_is_set = TRUE;
1085                 gmtptr = (struct state *) malloc(sizeof *gmtptr);
1086                 if (gmtptr != NULL)
1087                         gmtload(gmtptr);
1088         }
1089         ast_mutex_unlock(&gmt_mutex);
1090         timesub(timep, offset, gmtptr, tmp);
1091 #ifdef TM_ZONE
1092         /*
1093         ** Could get fancy here and deliver something such as
1094         ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero,
1095         ** but this is no time for a treasure hunt.
1096         */
1097         if (offset != 0)
1098                 tmp->TM_ZONE = wildabbr;
1099         else {
1100                 if (gmtptr == NULL)
1101                         tmp->TM_ZONE = gmt;
1102                 else    tmp->TM_ZONE = gmtptr->chars;
1103         }
1104 #endif /* defined TM_ZONE */
1105 }
1106
1107 static void
1108 timesub(timep, offset, sp, tmp)
1109 const struct timeval * const    timep;
1110 const long                              offset;
1111 register const struct state * const     sp;
1112 register struct ast_tm * const          tmp;
1113 {
1114         register const struct lsinfo *  lp;
1115         register long                   days;
1116         register long                   rem;
1117         register int                    y;
1118         register int                    yleap;
1119         register const int *            ip;
1120         register long                   corr;
1121         register int                    hit;
1122         register int                    i;
1123
1124         corr = 0;
1125         hit = 0;
1126         i = (sp == NULL) ? 0 : sp->leapcnt;
1127         while (--i >= 0) {
1128                 lp = &sp->lsis[i];
1129                 if (timep->tv_sec >= lp->ls_trans) {
1130                         if (timep->tv_sec == lp->ls_trans) {
1131                                 hit = ((i == 0 && lp->ls_corr > 0) ||
1132                                         lp->ls_corr > sp->lsis[i - 1].ls_corr);
1133                                 if (hit)
1134                                         while (i > 0 &&
1135                                                 sp->lsis[i].ls_trans ==
1136                                                 sp->lsis[i - 1].ls_trans + 1 &&
1137                                                 sp->lsis[i].ls_corr ==
1138                                                 sp->lsis[i - 1].ls_corr + 1) {
1139                                                         ++hit;
1140                                                         --i;
1141                                         }
1142                         }
1143                         corr = lp->ls_corr;
1144                         break;
1145                 }
1146         }
1147         days = timep->tv_sec / SECSPERDAY;
1148         rem = timep->tv_sec % SECSPERDAY;
1149 #ifdef mc68k
1150         if (timep->tv_sec == 0x80000000) {
1151                 /*
1152                 ** A 3B1 muffs the division on the most negative number.
1153                 */
1154                 days = -24855;
1155                 rem = -11648;
1156         }
1157 #endif /* defined mc68k */
1158         rem += (offset - corr);
1159         while (rem < 0) {
1160                 rem += SECSPERDAY;
1161                 --days;
1162         }
1163         while (rem >= SECSPERDAY) {
1164                 rem -= SECSPERDAY;
1165                 ++days;
1166         }
1167         tmp->tm_hour = (int) (rem / SECSPERHOUR);
1168         rem = rem % SECSPERHOUR;
1169         tmp->tm_min = (int) (rem / SECSPERMIN);
1170         /*
1171         ** A positive leap second requires a special
1172         ** representation.  This uses "... ??:59:60" et seq.
1173         */
1174         tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1175         tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
1176         if (tmp->tm_wday < 0)
1177                 tmp->tm_wday += DAYSPERWEEK;
1178         y = EPOCH_YEAR;
1179 #define LEAPS_THRU_END_OF(y)    ((y) / 4 - (y) / 100 + (y) / 400)
1180         while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
1181                 register int    newy;
1182
1183                 newy = y + days / DAYSPERNYEAR;
1184                 if (days < 0)
1185                         --newy;
1186                 days -= (newy - y) * DAYSPERNYEAR +
1187                         LEAPS_THRU_END_OF(newy - 1) -
1188                         LEAPS_THRU_END_OF(y - 1);
1189                 y = newy;
1190         }
1191         tmp->tm_year = y - TM_YEAR_BASE;
1192         tmp->tm_yday = (int) days;
1193         ip = mon_lengths[yleap];
1194         for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
1195                 days = days - (long) ip[tmp->tm_mon];
1196         tmp->tm_mday = (int) (days + 1);
1197         tmp->tm_isdst = 0;
1198 #ifdef TM_GMTOFF
1199         tmp->TM_GMTOFF = offset;
1200 #endif /* defined TM_GMTOFF */
1201         tmp->tm_usec = timep->tv_usec;
1202 }
1203
1204 char *
1205 ast_ctime(timep, buf)
1206 const struct timeval * const    timep;
1207 char *buf;
1208 {
1209         struct ast_tm tm;
1210         return asctime_r((struct tm *)ast_localtime(timep, &tm, NULL), buf);
1211 }
1212
1213 /*
1214 ** Adapted from code provided by Robert Elz, who writes:
1215 **      The "best" way to do mktime I think is based on an idea of Bob
1216 **      Kridle's (so its said...) from a long time ago.
1217 **      [kridle@xinet.com as of 1996-01-16.]
1218 **      It does a binary search of the time_t space.  Since time_t's are
1219 **      just 32 bits, its a max of 32 iterations (even at 64 bits it
1220 **      would still be very reasonable).
1221 */
1222
1223 #ifndef WRONG
1224 #define WRONG   (-1)
1225 #endif /* !defined WRONG */
1226
1227 /*
1228 ** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
1229 */
1230
1231 static int
1232 increment_overflow(number, delta)
1233 int *   number;
1234 int     delta;
1235 {
1236         int     number0;
1237
1238         number0 = *number;
1239         *number += delta;
1240         return (*number < number0) != (delta < 0);
1241 }
1242
1243 static int
1244 normalize_overflow(tensptr, unitsptr, base)
1245 int * const     tensptr;
1246 int * const     unitsptr;
1247 const int       base;
1248 {
1249         register int    tensdelta;
1250
1251         tensdelta = (*unitsptr >= 0) ?
1252                 (*unitsptr / base) :
1253                 (-1 - (-1 - *unitsptr) / base);
1254         *unitsptr -= tensdelta * base;
1255         return increment_overflow(tensptr, tensdelta);
1256 }
1257
1258 static int
1259 tmcomp(atmp, btmp)
1260 register const struct ast_tm * const atmp;
1261 register const struct ast_tm * const btmp;
1262 {
1263         register int    result;
1264
1265         if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1266                 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1267                 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1268                 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1269                 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1270                         result = atmp->tm_sec - btmp->tm_sec;
1271         return result;
1272 }
1273
1274 static time_t
1275 time2(tmp, funcp, offset, okayp, zone)
1276 struct ast_tm * const   tmp;
1277 void (* const           funcp) P((const struct timeval *, long, struct ast_tm*, const char*));
1278 const long              offset;
1279 int * const             okayp;
1280 const char * const      zone;
1281 {
1282         register const struct state *   sp;
1283         register int                    dir;
1284         register int                    bits;
1285         register int                    i, j ;
1286         register int                    saved_seconds;
1287         struct timeval                  newt = { 0, 0 };
1288         struct timeval                  t = { 0, 0 };
1289         struct ast_tm                   yourtm, mytm;
1290
1291         *okayp = FALSE;
1292         yourtm = *tmp;
1293         if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1294                 return WRONG;
1295         if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1296                 return WRONG;
1297         if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
1298                 return WRONG;
1299         /*
1300         ** Turn yourtm.tm_year into an actual year number for now.
1301         ** It is converted back to an offset from TM_YEAR_BASE later.
1302         */
1303         if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
1304                 return WRONG;
1305         while (yourtm.tm_mday <= 0) {
1306                 if (increment_overflow(&yourtm.tm_year, -1))
1307                         return WRONG;
1308                 i = yourtm.tm_year + (1 < yourtm.tm_mon);
1309                 yourtm.tm_mday += year_lengths[isleap(i)];
1310         }
1311         while (yourtm.tm_mday > DAYSPERLYEAR) {
1312                 i = yourtm.tm_year + (1 < yourtm.tm_mon);
1313                 yourtm.tm_mday -= year_lengths[isleap(i)];
1314                 if (increment_overflow(&yourtm.tm_year, 1))
1315                         return WRONG;
1316         }
1317         for ( ; ; ) {
1318                 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
1319                 if (yourtm.tm_mday <= i)
1320                         break;
1321                 yourtm.tm_mday -= i;
1322                 if (++yourtm.tm_mon >= MONSPERYEAR) {
1323                         yourtm.tm_mon = 0;
1324                         if (increment_overflow(&yourtm.tm_year, 1))
1325                                 return WRONG;
1326                 }
1327         }
1328         if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
1329                 return WRONG;
1330         if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
1331                 /*
1332                 ** We can't set tm_sec to 0, because that might push the
1333                 ** time below the minimum representable time.
1334                 ** Set tm_sec to 59 instead.
1335                 ** This assumes that the minimum representable time is
1336                 ** not in the same minute that a leap second was deleted from,
1337                 ** which is a safer assumption than using 58 would be.
1338                 */
1339                 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1340                         return WRONG;
1341                 saved_seconds = yourtm.tm_sec;
1342                 yourtm.tm_sec = SECSPERMIN - 1;
1343         } else {
1344                 saved_seconds = yourtm.tm_sec;
1345                 yourtm.tm_sec = 0;
1346         }
1347         /*
1348         ** Divide the search space in half
1349         ** (this works whether time_t is signed or unsigned).
1350         */
1351         bits = TYPE_BIT(time_t) - 1;
1352         /*
1353         ** If time_t is signed, then 0 is just above the median,
1354         ** assuming two's complement arithmetic.
1355         ** If time_t is unsigned, then (1 << bits) is just above the median.
1356         */
1357         t.tv_sec = 0;
1358         for ( ; ; ) {
1359                 (*funcp)(&t, offset, &mytm, zone);
1360                 dir = tmcomp(&mytm, &yourtm);
1361                 if (dir != 0) {
1362                         if (bits-- < 0)
1363                                 return WRONG;
1364                         if (bits < 0)
1365                                 --t.tv_sec; /* may be needed if new t is minimal */
1366                         else if (dir > 0)
1367                                 t.tv_sec -= ((time_t) 1) << bits;
1368                         else    t.tv_sec += ((time_t) 1) << bits;
1369                         continue;
1370                 }
1371                 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1372                         break;
1373                 /*
1374                 ** Right time, wrong type.
1375                 ** Hunt for right time, right type.
1376                 ** It's okay to guess wrong since the guess
1377                 ** gets checked.
1378                 */
1379                 /*
1380                 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1381                 */
1382                 sp = (const struct state *)
1383                         (((void *) funcp == (void *) localsub) ?
1384                         lclptr : gmtptr);
1385                 if (sp == NULL)
1386                         return WRONG;
1387                 for (i = sp->typecnt - 1; i >= 0; --i) {
1388                         if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1389                                 continue;
1390                         for (j = sp->typecnt - 1; j >= 0; --j) {
1391                                 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1392                                         continue;
1393                                 newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -
1394                                         sp->ttis[i].tt_gmtoff;
1395                                 (*funcp)(&newt, offset, &mytm, zone);
1396                                 if (tmcomp(&mytm, &yourtm) != 0)
1397                                         continue;
1398                                 if (mytm.tm_isdst != yourtm.tm_isdst)
1399                                         continue;
1400                                 /*
1401                                 ** We have a match.
1402                                 */
1403                                 t = newt;
1404                                 goto label;
1405                         }
1406                 }
1407                 return WRONG;
1408         }
1409 label:
1410         newt.tv_sec = t.tv_sec + saved_seconds;
1411         if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
1412                 return WRONG;
1413         t.tv_sec = newt.tv_sec;
1414         (*funcp)(&t, offset, tmp, zone);
1415         *okayp = TRUE;
1416         return t.tv_sec;
1417 }
1418
1419 static time_t
1420 time1(tmp, funcp, offset, zone)
1421 struct ast_tm * const   tmp;
1422 void (* const           funcp) P((const struct timeval *, long, struct ast_tm *, const char*));
1423 const long              offset;
1424 const char * const      zone;
1425 {
1426         register time_t                 t;
1427         register const struct state *   sp;
1428         register int                    samei, otheri;
1429         int                             okay;
1430
1431         if (tmp->tm_isdst > 1)
1432                 tmp->tm_isdst = 1;
1433         t = time2(tmp, funcp, offset, &okay, zone);
1434 #ifdef PCTS
1435         /*
1436         ** PCTS code courtesy Grant Sullivan (grant@osf.org).
1437         */
1438         if (okay)
1439                 return t;
1440         if (tmp->tm_isdst < 0)
1441                 tmp->tm_isdst = 0;      /* reset to std and try again */
1442 #endif /* defined PCTS */
1443 #ifndef PCTS
1444         if (okay || tmp->tm_isdst < 0)
1445                 return t;
1446 #endif /* !defined PCTS */
1447         /*
1448         ** We're supposed to assume that somebody took a time of one type
1449         ** and did some math on it that yielded a "struct tm" that's bad.
1450         ** We try to divine the type they started from and adjust to the
1451         ** type they need.
1452         */
1453         /*
1454         ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1455         */
1456         sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
1457                 lclptr : gmtptr);
1458         if (sp == NULL)
1459                 return WRONG;
1460         for (samei = sp->typecnt - 1; samei >= 0; --samei) {
1461                 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
1462                         continue;
1463                 for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) {
1464                         if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
1465                                 continue;
1466                         tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
1467                                         sp->ttis[samei].tt_gmtoff;
1468                         tmp->tm_isdst = !tmp->tm_isdst;
1469                         t = time2(tmp, funcp, offset, &okay, zone);
1470                         if (okay)
1471                                 return t;
1472                         tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
1473                                         sp->ttis[samei].tt_gmtoff;
1474                         tmp->tm_isdst = !tmp->tm_isdst;
1475                 }
1476         }
1477         return WRONG;
1478 }
1479
1480 time_t
1481 ast_mktime(tmp,zone)
1482 struct ast_tm * const   tmp;
1483 const char * const      zone;
1484 {
1485         time_t mktime_return_value;
1486 #ifdef  _THREAD_SAFE
1487         ast_mutex_lock(&lcl_mutex);
1488 #endif
1489         ast_tzset(!ast_strlen_zero(zone) ? zone : "/etc/localtime");
1490         mktime_return_value = time1(tmp, localsub, 0L, !ast_strlen_zero(zone) ? zone : "/etc/localtime");
1491 #ifdef  _THREAD_SAFE
1492         ast_mutex_unlock(&lcl_mutex);
1493 #endif
1494         return(mktime_return_value);
1495 }
1496
1497 int ast_strftime(char *buf, size_t len, const char *tmp, const struct ast_tm *tm)
1498 {
1499         size_t fmtlen = strlen(tmp) + 1;
1500         char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
1501         int decimals = -1, i, res;
1502         long fraction;
1503
1504         if (!format)
1505                 return -1;
1506         for (; *tmp; tmp++) {
1507                 if (*tmp == '%') {
1508                         switch (tmp[1]) {
1509                         case '1':
1510                         case '2':
1511                         case '3':
1512                         case '4':
1513                         case '5':
1514                         case '6':
1515                                 if (tmp[2] != 'q')
1516                                         goto defcase;
1517                                 decimals = tmp[1] - '0';
1518                                 tmp++;
1519                                 /* Fall through */
1520                         case 'q': /* Milliseconds */
1521                                 if (decimals == -1)
1522                                         decimals = 3;
1523
1524                                 /* Juggle some memory to fit the item */
1525                                 newfmt = ast_realloc(format, fmtlen + decimals);
1526                                 if (!newfmt) {
1527                                         ast_free(format);
1528                                         return -1;
1529                                 }
1530                                 fptr = fptr - format + newfmt;
1531                                 format = newfmt;
1532                                 fmtlen += decimals;
1533
1534                                 /* Reduce the fraction of time to the accuracy needed */
1535                                 for (i = 6, fraction = tm->tm_usec; i > decimals; i--)
1536                                         fraction /= 10;
1537                                 fptr += sprintf(fptr, "%0*ld", decimals, fraction);
1538
1539                                 /* Reset, in case more than one 'q' specifier exists */
1540                                 decimals = -1;
1541                                 tmp++;
1542                                 break;
1543                         default:
1544                                 goto defcase;
1545                         }
1546                 } else
1547 defcase:        *fptr++ = *tmp;
1548         }
1549         *fptr = '\0';
1550 #undef strftime
1551         res = (int)strftime(buf, len, format, (struct tm *)tm);
1552         ast_free(format);
1553         return res;
1554 }
1555