]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/tzcode/stdtime/localtime.c
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / tzcode / stdtime / localtime.c
1 /*
2 ** This file is in the public domain, so clarified as of
3 ** 1996-06-05 by Arthur David Olson.
4 */
5
6 #include <sys/cdefs.h>
7 #ifndef lint
8 #ifndef NOID
9 static char     elsieid[] __unused = "@(#)localtime.c   8.14";
10 #endif /* !defined NOID */
11 #endif /* !defined lint */
12 __FBSDID("$FreeBSD$");
13
14 /*
15 ** Leap second handling from Bradley White.
16 ** POSIX-style TZ environment variable handling from Guy Harris.
17 */
18
19 /*LINTLIBRARY*/
20
21 #include "namespace.h"
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <pthread.h>
27 #include "private.h"
28 #include "un-namespace.h"
29
30 #include "tzfile.h"
31 #include "float.h"      /* for FLT_MAX and DBL_MAX */
32
33 #ifndef TZ_ABBR_MAX_LEN
34 #define TZ_ABBR_MAX_LEN 16
35 #endif /* !defined TZ_ABBR_MAX_LEN */
36
37 #ifndef TZ_ABBR_CHAR_SET
38 #define TZ_ABBR_CHAR_SET \
39         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
40 #endif /* !defined TZ_ABBR_CHAR_SET */
41
42 #ifndef TZ_ABBR_ERR_CHAR
43 #define TZ_ABBR_ERR_CHAR        '_'
44 #endif /* !defined TZ_ABBR_ERR_CHAR */
45
46 #include "libc_private.h"
47
48 #define _MUTEX_LOCK(x)          if (__isthreaded) _pthread_mutex_lock(x)
49 #define _MUTEX_UNLOCK(x)        if (__isthreaded) _pthread_mutex_unlock(x)
50
51 #define _RWLOCK_RDLOCK(x)                                               \
52                 do {                                                    \
53                         if (__isthreaded) _pthread_rwlock_rdlock(x);    \
54                 } while (0)
55
56 #define _RWLOCK_WRLOCK(x)                                               \
57                 do {                                                    \
58                         if (__isthreaded) _pthread_rwlock_wrlock(x);    \
59                 } while (0)
60
61 #define _RWLOCK_UNLOCK(x)                                               \
62                 do {                                                    \
63                         if (__isthreaded) _pthread_rwlock_unlock(x);    \
64                 } while (0)
65
66 /*
67 ** SunOS 4.1.1 headers lack O_BINARY.
68 */
69
70 #ifdef O_BINARY
71 #define OPEN_MODE       (O_RDONLY | O_BINARY)
72 #endif /* defined O_BINARY */
73 #ifndef O_BINARY
74 #define OPEN_MODE       O_RDONLY
75 #endif /* !defined O_BINARY */
76
77 #ifndef WILDABBR
78 /*
79 ** Someone might make incorrect use of a time zone abbreviation:
80 **      1.      They might reference tzname[0] before calling tzset (explicitly
81 **              or implicitly).
82 **      2.      They might reference tzname[1] before calling tzset (explicitly
83 **              or implicitly).
84 **      3.      They might reference tzname[1] after setting to a time zone
85 **              in which Daylight Saving Time is never observed.
86 **      4.      They might reference tzname[0] after setting to a time zone
87 **              in which Standard Time is never observed.
88 **      5.      They might reference tm.TM_ZONE after calling offtime.
89 ** What's best to do in the above cases is open to debate;
90 ** for now, we just set things up so that in any of the five cases
91 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
92 ** string "tzname[0] used before set", and similarly for the other cases.
93 ** And another: initialize tzname[0] to "ERA", with an explanation in the
94 ** manual page of what this "time zone abbreviation" means (doing this so
95 ** that tzname[0] has the "normal" length of three characters).
96 */
97 #define WILDABBR        "   "
98 #endif /* !defined WILDABBR */
99
100 static char             wildabbr[] = WILDABBR;
101
102 /*
103  * In June 2004 it was decided UTC was a more appropriate default time
104  * zone than GMT.
105  */
106
107 static const char       gmt[] = "UTC";
108
109 /*
110 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
111 ** We default to US rules as of 1999-08-17.
112 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
113 ** implementation dependent; for historical reasons, US rules are a
114 ** common default.
115 */
116 #ifndef TZDEFRULESTRING
117 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
118 #endif /* !defined TZDEFDST */
119
120 struct ttinfo {                         /* time type information */
121         long            tt_gmtoff;      /* UTC offset in seconds */
122         int             tt_isdst;       /* used to set tm_isdst */
123         int             tt_abbrind;     /* abbreviation list index */
124         int             tt_ttisstd;     /* TRUE if transition is std time */
125         int             tt_ttisgmt;     /* TRUE if transition is UTC */
126 };
127
128 struct lsinfo {                         /* leap second information */
129         time_t          ls_trans;       /* transition time */
130         long            ls_corr;        /* correction to apply */
131 };
132
133 #define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
134
135 #ifdef TZNAME_MAX
136 #define MY_TZNAME_MAX   TZNAME_MAX
137 #endif /* defined TZNAME_MAX */
138 #ifndef TZNAME_MAX
139 #define MY_TZNAME_MAX   255
140 #endif /* !defined TZNAME_MAX */
141
142 struct state {
143         int             leapcnt;
144         int             timecnt;
145         int             typecnt;
146         int             charcnt;
147         int             goback;
148         int             goahead;
149         time_t          ats[TZ_MAX_TIMES];
150         unsigned char   types[TZ_MAX_TIMES];
151         struct ttinfo   ttis[TZ_MAX_TYPES];
152         char            chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
153                                 (2 * (MY_TZNAME_MAX + 1)))];
154         struct lsinfo   lsis[TZ_MAX_LEAPS];
155 };
156
157 struct rule {
158         int             r_type;         /* type of rule--see below */
159         int             r_day;          /* day number of rule */
160         int             r_week;         /* week number of rule */
161         int             r_mon;          /* month number of rule */
162         long            r_time;         /* transition time of rule */
163 };
164
165 #define JULIAN_DAY              0       /* Jn - Julian day */
166 #define DAY_OF_YEAR             1       /* n - day of year */
167 #define MONTH_NTH_DAY_OF_WEEK   2       /* Mm.n.d - month, week, day of week */
168
169 /*
170 ** Prototypes for static functions.
171 */
172
173 static long             detzcode(const char * codep);
174 static time_t           detzcode64(const char * codep);
175 static int              differ_by_repeat(time_t t1, time_t t0);
176 static const char *     getzname(const char * strp);
177 static const char *     getqzname(const char * strp, const int delim);
178 static const char *     getnum(const char * strp, int * nump, int min,
179                                 int max);
180 static const char *     getsecs(const char * strp, long * secsp);
181 static const char *     getoffset(const char * strp, long * offsetp);
182 static const char *     getrule(const char * strp, struct rule * rulep);
183 static void             gmtload(struct state * sp);
184 static struct tm *      gmtsub(const time_t * timep, long offset,
185                                 struct tm * tmp);
186 static struct tm *      localsub(const time_t * timep, long offset,
187                                 struct tm * tmp);
188 static int              increment_overflow(int * number, int delta);
189 static int              leaps_thru_end_of(int y);
190 static int              long_increment_overflow(long * number, int delta);
191 static int              long_normalize_overflow(long * tensptr,
192                                 int * unitsptr, int base);
193 static int              normalize_overflow(int * tensptr, int * unitsptr,
194                                 int base);
195 static void             settzname(void);
196 static time_t           time1(struct tm * tmp,
197                                 struct tm * (*funcp)(const time_t *,
198                                 long, struct tm *),
199                                 long offset);
200 static time_t           time2(struct tm *tmp,
201                                 struct tm * (*funcp)(const time_t *,
202                                 long, struct tm*),
203                                 long offset, int * okayp);
204 static time_t           time2sub(struct tm *tmp,
205                                 struct tm * (*funcp)(const time_t *,
206                                 long, struct tm*),
207                                 long offset, int * okayp, int do_norm_secs);
208 static struct tm *      timesub(const time_t * timep, long offset,
209                                 const struct state * sp, struct tm * tmp);
210 static int              tmcomp(const struct tm * atmp,
211                                 const struct tm * btmp);
212 static time_t           transtime(time_t janfirst, int year,
213                                 const struct rule * rulep, long offset);
214 static int              typesequiv(const struct state * sp, int a, int b);
215 static int              tzload(const char * name, struct state * sp,
216                                 int doextend);
217 static int              tzparse(const char * name, struct state * sp,
218                                 int lastditch);
219
220 #ifdef ALL_STATE
221 static struct state *   lclptr;
222 static struct state *   gmtptr;
223 #endif /* defined ALL_STATE */
224
225 #ifndef ALL_STATE
226 static struct state     lclmem;
227 static struct state     gmtmem;
228 #define lclptr          (&lclmem)
229 #define gmtptr          (&gmtmem)
230 #endif /* State Farm */
231
232 #ifndef TZ_STRLEN_MAX
233 #define TZ_STRLEN_MAX 255
234 #endif /* !defined TZ_STRLEN_MAX */
235
236 static char             lcl_TZname[TZ_STRLEN_MAX + 1];
237 static int              lcl_is_set;
238 static pthread_once_t   gmt_once = PTHREAD_ONCE_INIT;
239 static pthread_rwlock_t lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER;
240 static pthread_once_t   gmtime_once = PTHREAD_ONCE_INIT;
241 static pthread_key_t    gmtime_key;
242 static int              gmtime_key_error;
243 static pthread_once_t   localtime_once = PTHREAD_ONCE_INIT;
244 static pthread_key_t    localtime_key;
245 static int              localtime_key_error;
246
247 char *                  tzname[2] = {
248         wildabbr,
249         wildabbr
250 };
251
252 /*
253 ** Section 4.12.3 of X3.159-1989 requires that
254 **      Except for the strftime function, these functions [asctime,
255 **      ctime, gmtime, localtime] return values in one of two static
256 **      objects: a broken-down time structure and an array of char.
257 ** Thanks to Paul Eggert for noting this.
258 */
259
260 static struct tm        tm;
261
262 #ifdef USG_COMPAT
263 time_t                  timezone = 0;
264 int                     daylight = 0;
265 #endif /* defined USG_COMPAT */
266
267 #ifdef ALTZONE
268 time_t                  altzone = 0;
269 #endif /* defined ALTZONE */
270
271 static long
272 detzcode(codep)
273 const char * const      codep;
274 {
275         long    result;
276         int     i;
277
278         result = (codep[0] & 0x80) ? ~0L : 0;
279         for (i = 0; i < 4; ++i)
280                 result = (result << 8) | (codep[i] & 0xff);
281         return result;
282 }
283
284 static time_t
285 detzcode64(codep)
286 const char * const      codep;
287 {
288         register time_t result;
289         register int    i;
290
291         result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
292         for (i = 0; i < 8; ++i)
293                 result = result * 256 + (codep[i] & 0xff);
294         return result;
295 }
296
297 static void
298 settzname(void)
299 {
300         struct state *  sp = lclptr;
301         int                     i;
302
303         tzname[0] = wildabbr;
304         tzname[1] = wildabbr;
305 #ifdef USG_COMPAT
306         daylight = 0;
307         timezone = 0;
308 #endif /* defined USG_COMPAT */
309 #ifdef ALTZONE
310         altzone = 0;
311 #endif /* defined ALTZONE */
312 #ifdef ALL_STATE
313         if (sp == NULL) {
314                 tzname[0] = tzname[1] = gmt;
315                 return;
316         }
317 #endif /* defined ALL_STATE */
318         /*
319         ** And to get the latest zone names into tzname. . .
320         */
321         for (i = 0; i < sp->typecnt; ++i) {
322                 const struct ttinfo * const ttisp = &sp->ttis[sp->types[i]];
323
324                 tzname[ttisp->tt_isdst] =
325                         &sp->chars[ttisp->tt_abbrind];
326 #ifdef USG_COMPAT
327                 if (ttisp->tt_isdst)
328                         daylight = 1;
329                 if (!ttisp->tt_isdst)
330                         timezone = -(ttisp->tt_gmtoff);
331 #endif /* defined USG_COMPAT */
332 #ifdef ALTZONE
333                 if (ttisp->tt_isdst)
334                         altzone = -(ttisp->tt_gmtoff);
335 #endif /* defined ALTZONE */
336         }
337         /*
338         ** Finally, scrub the abbreviations.
339         ** First, replace bogus characters.
340         */
341         for (i = 0; i < sp->charcnt; ++i)
342                 if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
343                         sp->chars[i] = TZ_ABBR_ERR_CHAR;
344         /*
345         ** Second, truncate long abbreviations.
346         */
347         for (i = 0; i < sp->typecnt; ++i) {
348                 register const struct ttinfo * const    ttisp = &sp->ttis[i];
349                 register char *                         cp = &sp->chars[ttisp->tt_abbrind];
350
351                 if (strlen(cp) > TZ_ABBR_MAX_LEN &&
352                         strcmp(cp, GRANDPARENTED) != 0)
353                                 *(cp + TZ_ABBR_MAX_LEN) = '\0';
354         }
355 }
356
357 static int
358 differ_by_repeat(t1, t0)
359 const time_t    t1;
360 const time_t    t0;
361 {
362         int_fast64_t _t0 = t0;
363         int_fast64_t _t1 = t1;
364
365         if (TYPE_INTEGRAL(time_t) &&
366                 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
367                         return 0;
368         //turn ((int_fast64_t)(t1 - t0) == SECSPERREPEAT);
369         return _t1 - _t0 == SECSPERREPEAT;
370 }
371
372 static int
373 tzload(name, sp, doextend)
374 const char *            name;
375 struct state * const    sp;
376 register const int      doextend;
377 {
378         const char *    p;
379         int             i;
380         int             fid;
381         int             stored;
382         int             nread;
383         int             res;
384         union {
385                 struct tzhead   tzhead;
386                 char            buf[2 * sizeof(struct tzhead) +
387                                         2 * sizeof *sp +
388                                         4 * TZ_MAX_TIMES];
389         } *u;
390
391         u = NULL;
392         res = -1;
393         sp->goback = sp->goahead = FALSE;
394
395         /* XXX The following is from OpenBSD, and I'm not sure it is correct */
396         if (name != NULL && issetugid() != 0)
397                 if ((name[0] == ':' && name[1] == '/') || 
398                     name[0] == '/' || strchr(name, '.'))
399                         name = NULL;
400         if (name == NULL && (name = TZDEFAULT) == NULL)
401                 return -1;
402         {
403                 int     doaccess;
404                 struct stat     stab;
405                 /*
406                 ** Section 4.9.1 of the C standard says that
407                 ** "FILENAME_MAX expands to an integral constant expression
408                 ** that is the size needed for an array of char large enough
409                 ** to hold the longest file name string that the implementation
410                 ** guarantees can be opened."
411                 */
412                 char            *fullname;
413
414                 fullname = malloc(FILENAME_MAX + 1);
415                 if (fullname == NULL)
416                         goto out;
417
418                 if (name[0] == ':')
419                         ++name;
420                 doaccess = name[0] == '/';
421                 if (!doaccess) {
422                         if ((p = TZDIR) == NULL) {
423                                 free(fullname);
424                                 return -1;
425                         }
426                         if (strlen(p) + 1 + strlen(name) >= FILENAME_MAX) {
427                                 free(fullname);
428                                 return -1;
429                         }
430                         (void) strcpy(fullname, p);
431                         (void) strcat(fullname, "/");
432                         (void) strcat(fullname, name);
433                         /*
434                         ** Set doaccess if '.' (as in "../") shows up in name.
435                         */
436                         if (strchr(name, '.') != NULL)
437                                 doaccess = TRUE;
438                         name = fullname;
439                 }
440                 if (doaccess && access(name, R_OK) != 0) {
441                         free(fullname);
442                         return -1;
443                 }
444                 if ((fid = _open(name, OPEN_MODE)) == -1) {
445                         free(fullname);
446                         return -1;
447                 }
448                 if ((_fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) {
449                         free(fullname);
450                         _close(fid);
451                         return -1;
452                 }
453         }
454         u = malloc(sizeof(*u));
455         if (u == NULL)
456                 goto out;
457         nread = _read(fid, u->buf, sizeof u->buf);
458         if (_close(fid) < 0 || nread <= 0)
459                 goto out;
460         for (stored = 4; stored <= 8; stored *= 2) {
461                 int             ttisstdcnt;
462                 int             ttisgmtcnt;
463
464                 ttisstdcnt = (int) detzcode(u->tzhead.tzh_ttisstdcnt);
465                 ttisgmtcnt = (int) detzcode(u->tzhead.tzh_ttisgmtcnt);
466                 sp->leapcnt = (int) detzcode(u->tzhead.tzh_leapcnt);
467                 sp->timecnt = (int) detzcode(u->tzhead.tzh_timecnt);
468                 sp->typecnt = (int) detzcode(u->tzhead.tzh_typecnt);
469                 sp->charcnt = (int) detzcode(u->tzhead.tzh_charcnt);
470                 p = u->tzhead.tzh_charcnt + sizeof u->tzhead.tzh_charcnt;
471                 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
472                         sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
473                         sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
474                         sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
475                         (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
476                         (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
477                                 goto out;
478                 if (nread - (p - u->buf) <
479                         sp->timecnt * stored +          /* ats */
480                         sp->timecnt +                   /* types */
481                         sp->typecnt * 6 +               /* ttinfos */
482                         sp->charcnt +                   /* chars */
483                         sp->leapcnt * (stored + 4) +    /* lsinfos */
484                         ttisstdcnt +                    /* ttisstds */
485                         ttisgmtcnt)                     /* ttisgmts */
486                                 goto out;
487                 for (i = 0; i < sp->timecnt; ++i) {
488                         sp->ats[i] = (stored == 4) ?
489                                 detzcode(p) : detzcode64(p);
490                         p += stored;
491                 }
492                 for (i = 0; i < sp->timecnt; ++i) {
493                         sp->types[i] = (unsigned char) *p++;
494                         if (sp->types[i] >= sp->typecnt)
495                                 goto out;
496                 }
497                 for (i = 0; i < sp->typecnt; ++i) {
498                         struct ttinfo * ttisp;
499
500                         ttisp = &sp->ttis[i];
501                         ttisp->tt_gmtoff = detzcode(p);
502                         p += 4;
503                         ttisp->tt_isdst = (unsigned char) *p++;
504                         if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
505                                 goto out;
506                         ttisp->tt_abbrind = (unsigned char) *p++;
507                         if (ttisp->tt_abbrind < 0 ||
508                                 ttisp->tt_abbrind > sp->charcnt)
509                                         goto out;
510                 }
511                 for (i = 0; i < sp->charcnt; ++i)
512                         sp->chars[i] = *p++;
513                 sp->chars[i] = '\0';    /* ensure '\0' at end */
514                 for (i = 0; i < sp->leapcnt; ++i) {
515                         struct lsinfo * lsisp;
516
517                         lsisp = &sp->lsis[i];
518                         lsisp->ls_trans = (stored == 4) ?
519                                 detzcode(p) : detzcode64(p);
520                         p += stored;
521                         lsisp->ls_corr = detzcode(p);
522                         p += 4;
523                 }
524                 for (i = 0; i < sp->typecnt; ++i) {
525                         struct ttinfo * ttisp;
526
527                         ttisp = &sp->ttis[i];
528                         if (ttisstdcnt == 0)
529                                 ttisp->tt_ttisstd = FALSE;
530                         else {
531                                 ttisp->tt_ttisstd = *p++;
532                                 if (ttisp->tt_ttisstd != TRUE &&
533                                         ttisp->tt_ttisstd != FALSE)
534                                                 goto out;
535                         }
536                 }
537                 for (i = 0; i < sp->typecnt; ++i) {
538                         struct ttinfo * ttisp;
539
540                         ttisp = &sp->ttis[i];
541                         if (ttisgmtcnt == 0)
542                                 ttisp->tt_ttisgmt = FALSE;
543                         else {
544                                 ttisp->tt_ttisgmt = *p++;
545                                 if (ttisp->tt_ttisgmt != TRUE &&
546                                         ttisp->tt_ttisgmt != FALSE)
547                                                 goto out;
548                         }
549                 }
550                 /*
551                 ** Out-of-sort ats should mean we're running on a
552                 ** signed time_t system but using a data file with
553                 ** unsigned values (or vice versa).
554                 */
555                 for (i = 0; i < sp->timecnt - 2; ++i)
556                         if (sp->ats[i] > sp->ats[i + 1]) {
557                                 ++i;
558                                 if (TYPE_SIGNED(time_t)) {
559                                         /*
560                                         ** Ignore the end (easy).
561                                         */
562                                         sp->timecnt = i;
563                                 } else {
564                                         /*
565                                         ** Ignore the beginning (harder).
566                                         */
567                                         register int    j;
568
569                                         for (j = 0; j + i < sp->timecnt; ++j) {
570                                                 sp->ats[j] = sp->ats[j + i];
571                                                 sp->types[j] = sp->types[j + i];
572                                         }
573                                         sp->timecnt = j;
574                                 }
575                                 break;
576                         }
577                 /*
578                 ** If this is an old file, we're done.
579                 */
580                 if (u->tzhead.tzh_version[0] == '\0')
581                         break;
582                 nread -= p - u->buf;
583                 for (i = 0; i < nread; ++i)
584                         u->buf[i] = p[i];
585                 /*
586                 ** If this is a narrow integer time_t system, we're done.
587                 */
588                 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
589                         break;
590         }
591         if (doextend && nread > 2 &&
592                 u->buf[0] == '\n' && u->buf[nread - 1] == '\n' &&
593                 sp->typecnt + 2 <= TZ_MAX_TYPES) {
594                         struct state    *ts;
595                         register int    result;
596
597                         ts = malloc(sizeof(*ts));
598                         if (ts == NULL)
599                                 goto out;
600                         u->buf[nread - 1] = '\0';
601                         result = tzparse(&u->buf[1], ts, FALSE);
602                         if (result == 0 && ts->typecnt == 2 &&
603                                 sp->charcnt + ts->charcnt <= TZ_MAX_CHARS) {
604                                         for (i = 0; i < 2; ++i)
605                                                 ts->ttis[i].tt_abbrind +=
606                                                         sp->charcnt;
607                                         for (i = 0; i < ts->charcnt; ++i)
608                                                 sp->chars[sp->charcnt++] =
609                                                         ts->chars[i];
610                                         i = 0;
611                                         while (i < ts->timecnt &&
612                                                 ts->ats[i] <=
613                                                 sp->ats[sp->timecnt - 1])
614                                                         ++i;
615                                         while (i < ts->timecnt &&
616                                             sp->timecnt < TZ_MAX_TIMES) {
617                                                 sp->ats[sp->timecnt] =
618                                                         ts->ats[i];
619                                                 sp->types[sp->timecnt] =
620                                                         sp->typecnt +
621                                                         ts->types[i];
622                                                 ++sp->timecnt;
623                                                 ++i;
624                                         }
625                                         sp->ttis[sp->typecnt++] = ts->ttis[0];
626                                         sp->ttis[sp->typecnt++] = ts->ttis[1];
627                         }
628                         free(ts);
629         }
630         if (sp->timecnt > 1) {
631                 for (i = 1; i < sp->timecnt; ++i)
632                         if (typesequiv(sp, sp->types[i], sp->types[0]) &&
633                                 differ_by_repeat(sp->ats[i], sp->ats[0])) {
634                                         sp->goback = TRUE;
635                                         break;
636                                 }
637                 for (i = sp->timecnt - 2; i >= 0; --i)
638                         if (typesequiv(sp, sp->types[sp->timecnt - 1],
639                                 sp->types[i]) &&
640                                 differ_by_repeat(sp->ats[sp->timecnt - 1],
641                                 sp->ats[i])) {
642                                         sp->goahead = TRUE;
643                                         break;
644                 }
645         }
646         res = 0;
647 out:
648         free(u);
649         return (res);
650 }
651
652 static int
653 typesequiv(sp, a, b)
654 const struct state * const      sp;
655 const int                       a;
656 const int                       b;
657 {
658         register int    result;
659
660         if (sp == NULL ||
661                 a < 0 || a >= sp->typecnt ||
662                 b < 0 || b >= sp->typecnt)
663                         result = FALSE;
664         else {
665                 register const struct ttinfo *  ap = &sp->ttis[a];
666                 register const struct ttinfo *  bp = &sp->ttis[b];
667                 result = ap->tt_gmtoff == bp->tt_gmtoff &&
668                         ap->tt_isdst == bp->tt_isdst &&
669                         ap->tt_ttisstd == bp->tt_ttisstd &&
670                         ap->tt_ttisgmt == bp->tt_ttisgmt &&
671                         strcmp(&sp->chars[ap->tt_abbrind],
672                         &sp->chars[bp->tt_abbrind]) == 0;
673         }
674         return result;
675 }
676
677 static const int        mon_lengths[2][MONSPERYEAR] = {
678         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
679         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
680 };
681
682 static const int        year_lengths[2] = {
683         DAYSPERNYEAR, DAYSPERLYEAR
684 };
685
686 /*
687 ** Given a pointer into a time zone string, scan until a character that is not
688 ** a valid character in a zone name is found. Return a pointer to that
689 ** character.
690 */
691
692 static const char *
693 getzname(strp)
694 const char *    strp;
695 {
696         char    c;
697
698         while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
699                 c != '+')
700                         ++strp;
701         return strp;
702 }
703
704 /*
705 ** Given a pointer into an extended time zone string, scan until the ending
706 ** delimiter of the zone name is located. Return a pointer to the delimiter.
707 **
708 ** As with getzname above, the legal character set is actually quite
709 ** restricted, with other characters producing undefined results.
710 ** We don't do any checking here; checking is done later in common-case code.
711 */
712
713 static const char *
714 getqzname(register const char *strp, const int delim)
715 {
716         register int    c;
717
718         while ((c = *strp) != '\0' && c != delim)
719                 ++strp;
720         return strp;
721 }
722
723 /*
724 ** Given a pointer into a time zone string, extract a number from that string.
725 ** Check that the number is within a specified range; if it is not, return
726 ** NULL.
727 ** Otherwise, return a pointer to the first character not part of the number.
728 */
729
730 static const char *
731 getnum(strp, nump, min, max)
732 const char *    strp;
733 int * const             nump;
734 const int               min;
735 const int               max;
736 {
737         char    c;
738         int     num;
739
740         if (strp == NULL || !is_digit(c = *strp))
741                 return NULL;
742         num = 0;
743         do {
744                 num = num * 10 + (c - '0');
745                 if (num > max)
746                         return NULL;    /* illegal value */
747                 c = *++strp;
748         } while (is_digit(c));
749         if (num < min)
750                 return NULL;            /* illegal value */
751         *nump = num;
752         return strp;
753 }
754
755 /*
756 ** Given a pointer into a time zone string, extract a number of seconds,
757 ** in hh[:mm[:ss]] form, from the string.
758 ** If any error occurs, return NULL.
759 ** Otherwise, return a pointer to the first character not part of the number
760 ** of seconds.
761 */
762
763 static const char *
764 getsecs(strp, secsp)
765 const char *    strp;
766 long * const            secsp;
767 {
768         int     num;
769
770         /*
771         ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
772         ** "M10.4.6/26", which does not conform to Posix,
773         ** but which specifies the equivalent of
774         ** ``02:00 on the first Sunday on or after 23 Oct''.
775         */
776         strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
777         if (strp == NULL)
778                 return NULL;
779         *secsp = num * (long) SECSPERHOUR;
780         if (*strp == ':') {
781                 ++strp;
782                 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
783                 if (strp == NULL)
784                         return NULL;
785                 *secsp += num * SECSPERMIN;
786                 if (*strp == ':') {
787                         ++strp;
788                         /* `SECSPERMIN' allows for leap seconds. */
789                         strp = getnum(strp, &num, 0, SECSPERMIN);
790                         if (strp == NULL)
791                                 return NULL;
792                         *secsp += num;
793                 }
794         }
795         return strp;
796 }
797
798 /*
799 ** Given a pointer into a time zone string, extract an offset, in
800 ** [+-]hh[:mm[:ss]] form, from the string.
801 ** If any error occurs, return NULL.
802 ** Otherwise, return a pointer to the first character not part of the time.
803 */
804
805 static const char *
806 getoffset(strp, offsetp)
807 const char *    strp;
808 long * const            offsetp;
809 {
810         int     neg = 0;
811
812         if (*strp == '-') {
813                 neg = 1;
814                 ++strp;
815         } else if (*strp == '+')
816                 ++strp;
817         strp = getsecs(strp, offsetp);
818         if (strp == NULL)
819                 return NULL;            /* illegal time */
820         if (neg)
821                 *offsetp = -*offsetp;
822         return strp;
823 }
824
825 /*
826 ** Given a pointer into a time zone string, extract a rule in the form
827 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
828 ** If a valid rule is not found, return NULL.
829 ** Otherwise, return a pointer to the first character not part of the rule.
830 */
831
832 static const char *
833 getrule(strp, rulep)
834 const char *                    strp;
835 struct rule * const     rulep;
836 {
837         if (*strp == 'J') {
838                 /*
839                 ** Julian day.
840                 */
841                 rulep->r_type = JULIAN_DAY;
842                 ++strp;
843                 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
844         } else if (*strp == 'M') {
845                 /*
846                 ** Month, week, day.
847                 */
848                 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
849                 ++strp;
850                 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
851                 if (strp == NULL)
852                         return NULL;
853                 if (*strp++ != '.')
854                         return NULL;
855                 strp = getnum(strp, &rulep->r_week, 1, 5);
856                 if (strp == NULL)
857                         return NULL;
858                 if (*strp++ != '.')
859                         return NULL;
860                 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
861         } else if (is_digit(*strp)) {
862                 /*
863                 ** Day of year.
864                 */
865                 rulep->r_type = DAY_OF_YEAR;
866                 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
867         } else  return NULL;            /* invalid format */
868         if (strp == NULL)
869                 return NULL;
870         if (*strp == '/') {
871                 /*
872                 ** Time specified.
873                 */
874                 ++strp;
875                 strp = getsecs(strp, &rulep->r_time);
876         } else  rulep->r_time = 2 * SECSPERHOUR;        /* default = 2:00:00 */
877         return strp;
878 }
879
880 /*
881 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
882 ** year, a rule, and the offset from UTC at the time that rule takes effect,
883 ** calculate the Epoch-relative time that rule takes effect.
884 */
885
886 static time_t
887 transtime(janfirst, year, rulep, offset)
888 const time_t                            janfirst;
889 const int                               year;
890 const struct rule * const       rulep;
891 const long                              offset;
892 {
893         int     leapyear;
894         time_t  value;
895         int     i;
896         int             d, m1, yy0, yy1, yy2, dow;
897
898         INITIALIZE(value);
899         leapyear = isleap(year);
900         switch (rulep->r_type) {
901
902         case JULIAN_DAY:
903                 /*
904                 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
905                 ** years.
906                 ** In non-leap years, or if the day number is 59 or less, just
907                 ** add SECSPERDAY times the day number-1 to the time of
908                 ** January 1, midnight, to get the day.
909                 */
910                 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
911                 if (leapyear && rulep->r_day >= 60)
912                         value += SECSPERDAY;
913                 break;
914
915         case DAY_OF_YEAR:
916                 /*
917                 ** n - day of year.
918                 ** Just add SECSPERDAY times the day number to the time of
919                 ** January 1, midnight, to get the day.
920                 */
921                 value = janfirst + rulep->r_day * SECSPERDAY;
922                 break;
923
924         case MONTH_NTH_DAY_OF_WEEK:
925                 /*
926                 ** Mm.n.d - nth "dth day" of month m.
927                 */
928                 value = janfirst;
929                 for (i = 0; i < rulep->r_mon - 1; ++i)
930                         value += mon_lengths[leapyear][i] * SECSPERDAY;
931
932                 /*
933                 ** Use Zeller's Congruence to get day-of-week of first day of
934                 ** month.
935                 */
936                 m1 = (rulep->r_mon + 9) % 12 + 1;
937                 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
938                 yy1 = yy0 / 100;
939                 yy2 = yy0 % 100;
940                 dow = ((26 * m1 - 2) / 10 +
941                         1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
942                 if (dow < 0)
943                         dow += DAYSPERWEEK;
944
945                 /*
946                 ** "dow" is the day-of-week of the first day of the month. Get
947                 ** the day-of-month (zero-origin) of the first "dow" day of the
948                 ** month.
949                 */
950                 d = rulep->r_day - dow;
951                 if (d < 0)
952                         d += DAYSPERWEEK;
953                 for (i = 1; i < rulep->r_week; ++i) {
954                         if (d + DAYSPERWEEK >=
955                                 mon_lengths[leapyear][rulep->r_mon - 1])
956                                         break;
957                         d += DAYSPERWEEK;
958                 }
959
960                 /*
961                 ** "d" is the day-of-month (zero-origin) of the day we want.
962                 */
963                 value += d * SECSPERDAY;
964                 break;
965         }
966
967         /*
968         ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
969         ** question. To get the Epoch-relative time of the specified local
970         ** time on that day, add the transition time and the current offset
971         ** from UTC.
972         */
973         return value + rulep->r_time + offset;
974 }
975
976 /*
977 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
978 ** appropriate.
979 */
980
981 static int
982 tzparse(name, sp, lastditch)
983 const char *                    name;
984 struct state * const    sp;
985 const int                       lastditch;
986 {
987         const char *                    stdname;
988         const char *                    dstname;
989         size_t                          stdlen;
990         size_t                          dstlen;
991         long                            stdoffset;
992         long                            dstoffset;
993         time_t *                atp;
994         unsigned char * typep;
995         char *                  cp;
996         int                     load_result;
997
998         INITIALIZE(dstname);
999         stdname = name;
1000         if (lastditch) {
1001                 stdlen = strlen(name);  /* length of standard zone name */
1002                 name += stdlen;
1003                 if (stdlen >= sizeof sp->chars)
1004                         stdlen = (sizeof sp->chars) - 1;
1005                 stdoffset = 0;
1006         } else {
1007                 if (*name == '<') {
1008                         name++;
1009                         stdname = name;
1010                         name = getqzname(name, '>');
1011                         if (*name != '>')
1012                                 return (-1);
1013                         stdlen = name - stdname;
1014                         name++;
1015                 } else {
1016                         name = getzname(name);
1017                         stdlen = name - stdname;
1018                 }
1019                 if (*name == '\0')
1020                         return -1;      /* was "stdoffset = 0;" */
1021                 else {
1022                         name = getoffset(name, &stdoffset);
1023                         if (name == NULL)
1024                                 return -1;
1025                 }
1026         }
1027         load_result = tzload(TZDEFRULES, sp, FALSE);
1028         if (load_result != 0)
1029                 sp->leapcnt = 0;                /* so, we're off a little */
1030         if (*name != '\0') {
1031                 if (*name == '<') {
1032                         dstname = ++name;
1033                         name = getqzname(name, '>');
1034                         if (*name != '>')
1035                                 return -1;
1036                         dstlen = name - dstname;
1037                         name++;
1038                 } else {
1039                         dstname = name;
1040                         name = getzname(name);
1041                         dstlen = name - dstname; /* length of DST zone name */
1042                 }
1043                 if (*name != '\0' && *name != ',' && *name != ';') {
1044                         name = getoffset(name, &dstoffset);
1045                         if (name == NULL)
1046                                 return -1;
1047                 } else  dstoffset = stdoffset - SECSPERHOUR;
1048                 if (*name == '\0' && load_result != 0)
1049                         name = TZDEFRULESTRING;
1050                 if (*name == ',' || *name == ';') {
1051                         struct rule     start;
1052                         struct rule     end;
1053                         int     year;
1054                         time_t  janfirst;
1055                         time_t          starttime;
1056                         time_t          endtime;
1057
1058                         ++name;
1059                         if ((name = getrule(name, &start)) == NULL)
1060                                 return -1;
1061                         if (*name++ != ',')
1062                                 return -1;
1063                         if ((name = getrule(name, &end)) == NULL)
1064                                 return -1;
1065                         if (*name != '\0')
1066                                 return -1;
1067                         sp->typecnt = 2;        /* standard time and DST */
1068                         /*
1069                         ** Two transitions per year, from EPOCH_YEAR forward.
1070                         */
1071                         sp->ttis[0].tt_gmtoff = -dstoffset;
1072                         sp->ttis[0].tt_isdst = 1;
1073                         sp->ttis[0].tt_abbrind = stdlen + 1;
1074                         sp->ttis[1].tt_gmtoff = -stdoffset;
1075                         sp->ttis[1].tt_isdst = 0;
1076                         sp->ttis[1].tt_abbrind = 0;
1077                         atp = sp->ats;
1078                         typep = sp->types;
1079                         janfirst = 0;
1080                         sp->timecnt = 0;
1081                         for (year = EPOCH_YEAR;
1082                             sp->timecnt + 2 <= TZ_MAX_TIMES;
1083                             ++year) {
1084                                 time_t  newfirst;
1085
1086                                 starttime = transtime(janfirst, year, &start,
1087                                         stdoffset);
1088                                 endtime = transtime(janfirst, year, &end,
1089                                         dstoffset);
1090                                 if (starttime > endtime) {
1091                                         *atp++ = endtime;
1092                                         *typep++ = 1;   /* DST ends */
1093                                         *atp++ = starttime;
1094                                         *typep++ = 0;   /* DST begins */
1095                                 } else {
1096                                         *atp++ = starttime;
1097                                         *typep++ = 0;   /* DST begins */
1098                                         *atp++ = endtime;
1099                                         *typep++ = 1;   /* DST ends */
1100                                 }
1101                                 sp->timecnt += 2;
1102                                 newfirst = janfirst;
1103                                 newfirst += year_lengths[isleap(year)] *
1104                                         SECSPERDAY;
1105                                 if (newfirst <= janfirst)
1106                                         break;
1107                                 janfirst = newfirst;
1108                         }
1109                 } else {
1110                         long    theirstdoffset;
1111                         long    theirdstoffset;
1112                         long    theiroffset;
1113                         int     isdst;
1114                         int     i;
1115                         int     j;
1116
1117                         if (*name != '\0')
1118                                 return -1;
1119                         /*
1120                         ** Initial values of theirstdoffset and theirdstoffset.
1121                         */
1122                         theirstdoffset = 0;
1123                         for (i = 0; i < sp->timecnt; ++i) {
1124                                 j = sp->types[i];
1125                                 if (!sp->ttis[j].tt_isdst) {
1126                                         theirstdoffset =
1127                                                 -sp->ttis[j].tt_gmtoff;
1128                                         break;
1129                                 }
1130                         }
1131                         theirdstoffset = 0;
1132                         for (i = 0; i < sp->timecnt; ++i) {
1133                                 j = sp->types[i];
1134                                 if (sp->ttis[j].tt_isdst) {
1135                                         theirdstoffset =
1136                                                 -sp->ttis[j].tt_gmtoff;
1137                                         break;
1138                                 }
1139                         }
1140                         /*
1141                         ** Initially we're assumed to be in standard time.
1142                         */
1143                         isdst = FALSE;
1144                         theiroffset = theirstdoffset;
1145                         /*
1146                         ** Now juggle transition times and types
1147                         ** tracking offsets as you do.
1148                         */
1149                         for (i = 0; i < sp->timecnt; ++i) {
1150                                 j = sp->types[i];
1151                                 sp->types[i] = sp->ttis[j].tt_isdst;
1152                                 if (sp->ttis[j].tt_ttisgmt) {
1153                                         /* No adjustment to transition time */
1154                                 } else {
1155                                         /*
1156                                         ** If summer time is in effect, and the
1157                                         ** transition time was not specified as
1158                                         ** standard time, add the summer time
1159                                         ** offset to the transition time;
1160                                         ** otherwise, add the standard time
1161                                         ** offset to the transition time.
1162                                         */
1163                                         /*
1164                                         ** Transitions from DST to DDST
1165                                         ** will effectively disappear since
1166                                         ** POSIX provides for only one DST
1167                                         ** offset.
1168                                         */
1169                                         if (isdst && !sp->ttis[j].tt_ttisstd) {
1170                                                 sp->ats[i] += dstoffset -
1171                                                         theirdstoffset;
1172                                         } else {
1173                                                 sp->ats[i] += stdoffset -
1174                                                         theirstdoffset;
1175                                         }
1176                                 }
1177                                 theiroffset = -sp->ttis[j].tt_gmtoff;
1178                                 if (sp->ttis[j].tt_isdst)
1179                                         theirdstoffset = theiroffset;
1180                                 else    theirstdoffset = theiroffset;
1181                         }
1182                         /*
1183                         ** Finally, fill in ttis.
1184                         ** ttisstd and ttisgmt need not be handled.
1185                         */
1186                         sp->ttis[0].tt_gmtoff = -stdoffset;
1187                         sp->ttis[0].tt_isdst = FALSE;
1188                         sp->ttis[0].tt_abbrind = 0;
1189                         sp->ttis[1].tt_gmtoff = -dstoffset;
1190                         sp->ttis[1].tt_isdst = TRUE;
1191                         sp->ttis[1].tt_abbrind = stdlen + 1;
1192                         sp->typecnt = 2;
1193                 }
1194         } else {
1195                 dstlen = 0;
1196                 sp->typecnt = 1;                /* only standard time */
1197                 sp->timecnt = 0;
1198                 sp->ttis[0].tt_gmtoff = -stdoffset;
1199                 sp->ttis[0].tt_isdst = 0;
1200                 sp->ttis[0].tt_abbrind = 0;
1201         }
1202         sp->charcnt = stdlen + 1;
1203         if (dstlen != 0)
1204                 sp->charcnt += dstlen + 1;
1205         if ((size_t) sp->charcnt > sizeof sp->chars)
1206                 return -1;
1207         cp = sp->chars;
1208         (void) strncpy(cp, stdname, stdlen);
1209         cp += stdlen;
1210         *cp++ = '\0';
1211         if (dstlen != 0) {
1212                 (void) strncpy(cp, dstname, dstlen);
1213                 *(cp + dstlen) = '\0';
1214         }
1215         return 0;
1216 }
1217
1218 static void
1219 gmtload(sp)
1220 struct state * const    sp;
1221 {
1222         if (tzload(gmt, sp, TRUE) != 0)
1223                 (void) tzparse(gmt, sp, TRUE);
1224 }
1225
1226 static void
1227 tzsetwall_basic(int rdlocked)
1228 {
1229         if (!rdlocked)
1230                 _RWLOCK_RDLOCK(&lcl_rwlock);
1231         if (lcl_is_set < 0) {
1232                 if (!rdlocked)
1233                         _RWLOCK_UNLOCK(&lcl_rwlock);
1234                 return;
1235         }
1236         _RWLOCK_UNLOCK(&lcl_rwlock);
1237
1238         _RWLOCK_WRLOCK(&lcl_rwlock);
1239         lcl_is_set = -1;
1240
1241 #ifdef ALL_STATE
1242         if (lclptr == NULL) {
1243                 lclptr = (struct state *) calloc(1, sizeof *lclptr);
1244                 if (lclptr == NULL) {
1245                         settzname();    /* all we can do */
1246                         _RWLOCK_UNLOCK(&lcl_rwlock);
1247                         if (rdlocked)
1248                                 _RWLOCK_RDLOCK(&lcl_rwlock);
1249                         return;
1250                 }
1251         }
1252 #endif /* defined ALL_STATE */
1253         if (tzload((char *) NULL, lclptr, TRUE) != 0)
1254                 gmtload(lclptr);
1255         settzname();
1256         _RWLOCK_UNLOCK(&lcl_rwlock);
1257
1258         if (rdlocked)
1259                 _RWLOCK_RDLOCK(&lcl_rwlock);
1260 }
1261
1262 void
1263 tzsetwall(void)
1264 {
1265         tzsetwall_basic(0);
1266 }
1267
1268 static void
1269 tzset_basic(int rdlocked)
1270 {
1271         const char *    name;
1272
1273         name = getenv("TZ");
1274         if (name == NULL) {
1275                 tzsetwall_basic(rdlocked);
1276                 return;
1277         }
1278
1279         if (!rdlocked)
1280                 _RWLOCK_RDLOCK(&lcl_rwlock);
1281         if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) {
1282                 if (!rdlocked)
1283                         _RWLOCK_UNLOCK(&lcl_rwlock);
1284                 return;
1285         }
1286         _RWLOCK_UNLOCK(&lcl_rwlock);
1287
1288         _RWLOCK_WRLOCK(&lcl_rwlock);
1289         lcl_is_set = strlen(name) < sizeof lcl_TZname;
1290         if (lcl_is_set)
1291                 (void) strcpy(lcl_TZname, name);
1292
1293 #ifdef ALL_STATE
1294         if (lclptr == NULL) {
1295                 lclptr = (struct state *) calloc(1, sizeof *lclptr);
1296                 if (lclptr == NULL) {
1297                         settzname();    /* all we can do */
1298                         _RWLOCK_UNLOCK(&lcl_rwlock);
1299                         if (rdlocked)
1300                                 _RWLOCK_RDLOCK(&lcl_rwlock);
1301                         return;
1302                 }
1303         }
1304 #endif /* defined ALL_STATE */
1305         if (*name == '\0') {
1306                 /*
1307                 ** User wants it fast rather than right.
1308                 */
1309                 lclptr->leapcnt = 0;            /* so, we're off a little */
1310                 lclptr->timecnt = 0;
1311                 lclptr->typecnt = 0;
1312                 lclptr->ttis[0].tt_isdst = 0;
1313                 lclptr->ttis[0].tt_gmtoff = 0;
1314                 lclptr->ttis[0].tt_abbrind = 0;
1315                 (void) strcpy(lclptr->chars, gmt);
1316         } else if (tzload(name, lclptr, TRUE) != 0)
1317                 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
1318                         (void) gmtload(lclptr);
1319         settzname();
1320         _RWLOCK_UNLOCK(&lcl_rwlock);
1321
1322         if (rdlocked)
1323                 _RWLOCK_RDLOCK(&lcl_rwlock);
1324 }
1325
1326 void
1327 tzset(void)
1328 {
1329         tzset_basic(0);
1330 }
1331
1332 /*
1333 ** The easy way to behave "as if no library function calls" localtime
1334 ** is to not call it--so we drop its guts into "localsub", which can be
1335 ** freely called. (And no, the PANS doesn't require the above behavior--
1336 ** but it *is* desirable.)
1337 **
1338 ** The unused offset argument is for the benefit of mktime variants.
1339 */
1340
1341 /*ARGSUSED*/
1342 static struct tm *
1343 localsub(timep, offset, tmp)
1344 const time_t * const    timep;
1345 const long              offset;
1346 struct tm * const       tmp;
1347 {
1348         struct state *          sp;
1349         const struct ttinfo *   ttisp;
1350         int                     i;
1351         struct tm *             result;
1352         const time_t            t = *timep;
1353
1354         sp = lclptr;
1355 #ifdef ALL_STATE
1356         if (sp == NULL)
1357                 return gmtsub(timep, offset, tmp);
1358 #endif /* defined ALL_STATE */
1359         if ((sp->goback && t < sp->ats[0]) ||
1360                 (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1361                         time_t                  newt = t;
1362                         register time_t         seconds;
1363                         register time_t         tcycles;
1364                         register int_fast64_t   icycles;
1365
1366                         if (t < sp->ats[0])
1367                                 seconds = sp->ats[0] - t;
1368                         else    seconds = t - sp->ats[sp->timecnt - 1];
1369                         --seconds;
1370                         tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1371                         ++tcycles;
1372                         icycles = tcycles;
1373                         if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1374                                 return NULL;
1375                         seconds = icycles;
1376                         seconds *= YEARSPERREPEAT;
1377                         seconds *= AVGSECSPERYEAR;
1378                         if (t < sp->ats[0])
1379                                 newt += seconds;
1380                         else    newt -= seconds;
1381                         if (newt < sp->ats[0] ||
1382                                 newt > sp->ats[sp->timecnt - 1])
1383                                         return NULL;    /* "cannot happen" */
1384                         result = localsub(&newt, offset, tmp);
1385                         if (result == tmp) {
1386                                 register time_t newy;
1387
1388                                 newy = tmp->tm_year;
1389                                 if (t < sp->ats[0])
1390                                         newy -= icycles * YEARSPERREPEAT;
1391                                 else    newy += icycles * YEARSPERREPEAT;
1392                                 tmp->tm_year = newy;
1393                                 if (tmp->tm_year != newy)
1394                                         return NULL;
1395                         }
1396                         return result;
1397         }
1398         if (sp->timecnt == 0 || t < sp->ats[0]) {
1399                 i = 0;
1400                 while (sp->ttis[i].tt_isdst)
1401                         if (++i >= sp->typecnt) {
1402                                 i = 0;
1403                                 break;
1404                         }
1405         } else {
1406                 register int    lo = 1;
1407                 register int    hi = sp->timecnt;
1408
1409                 while (lo < hi) {
1410                         register int    mid = (lo + hi) >> 1;
1411
1412                         if (t < sp->ats[mid])
1413                                 hi = mid;
1414                         else    lo = mid + 1;
1415                 }
1416                 i = (int) sp->types[lo - 1];
1417         }
1418         ttisp = &sp->ttis[i];
1419         /*
1420         ** To get (wrong) behavior that's compatible with System V Release 2.0
1421         ** you'd replace the statement below with
1422         **      t += ttisp->tt_gmtoff;
1423         **      timesub(&t, 0L, sp, tmp);
1424         */
1425         result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1426         tmp->tm_isdst = ttisp->tt_isdst;
1427         tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
1428 #ifdef TM_ZONE
1429         tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1430 #endif /* defined TM_ZONE */
1431         return result;
1432 }
1433
1434 static void
1435 localtime_key_init(void)
1436 {
1437
1438         localtime_key_error = _pthread_key_create(&localtime_key, free);
1439 }
1440
1441 struct tm *
1442 localtime(timep)
1443 const time_t * const    timep;
1444 {
1445         struct tm *p_tm;
1446
1447         if (__isthreaded != 0) {
1448                 _pthread_once(&localtime_once, localtime_key_init);
1449                 if (localtime_key_error != 0) {
1450                         errno = localtime_key_error;
1451                         return(NULL);
1452                 }
1453                 p_tm = _pthread_getspecific(localtime_key);
1454                 if (p_tm == NULL) {
1455                         if ((p_tm = (struct tm *)malloc(sizeof(struct tm)))
1456                             == NULL)
1457                                 return(NULL);
1458                         _pthread_setspecific(localtime_key, p_tm);
1459                 }
1460                 _RWLOCK_RDLOCK(&lcl_rwlock);
1461                 tzset_basic(1);
1462                 localsub(timep, 0L, p_tm);
1463                 _RWLOCK_UNLOCK(&lcl_rwlock);
1464                 return(p_tm);
1465         } else {
1466                 tzset_basic(0);
1467                 localsub(timep, 0L, &tm);
1468                 return(&tm);
1469         }
1470 }
1471
1472 /*
1473 ** Re-entrant version of localtime.
1474 */
1475
1476 struct tm *
1477 localtime_r(timep, tmp)
1478 const time_t * const    timep;
1479 struct tm *             tmp;
1480 {
1481         _RWLOCK_RDLOCK(&lcl_rwlock);
1482         tzset_basic(1);
1483         localsub(timep, 0L, tmp);
1484         _RWLOCK_UNLOCK(&lcl_rwlock);
1485         return tmp;
1486 }
1487
1488 static void
1489 gmt_init(void)
1490 {
1491
1492 #ifdef ALL_STATE
1493         gmtptr = (struct state *) calloc(1, sizeof *gmtptr);
1494         if (gmtptr != NULL)
1495 #endif /* defined ALL_STATE */
1496                 gmtload(gmtptr);
1497 }
1498
1499 /*
1500 ** gmtsub is to gmtime as localsub is to localtime.
1501 */
1502
1503 static struct tm *
1504 gmtsub(timep, offset, tmp)
1505 const time_t * const    timep;
1506 const long              offset;
1507 struct tm * const       tmp;
1508 {
1509         register struct tm *    result;
1510
1511         _once(&gmt_once, gmt_init);
1512         result = timesub(timep, offset, gmtptr, tmp);
1513 #ifdef TM_ZONE
1514         /*
1515         ** Could get fancy here and deliver something such as
1516         ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1517         ** but this is no time for a treasure hunt.
1518         */
1519         if (offset != 0)
1520                 tmp->TM_ZONE = wildabbr;
1521         else {
1522 #ifdef ALL_STATE
1523                 if (gmtptr == NULL)
1524                         tmp->TM_ZONE = gmt;
1525                 else    tmp->TM_ZONE = gmtptr->chars;
1526 #endif /* defined ALL_STATE */
1527 #ifndef ALL_STATE
1528                 tmp->TM_ZONE = gmtptr->chars;
1529 #endif /* State Farm */
1530         }
1531 #endif /* defined TM_ZONE */
1532         return result;
1533 }
1534
1535 static void
1536 gmtime_key_init(void)
1537 {
1538
1539         gmtime_key_error = _pthread_key_create(&gmtime_key, free);
1540 }
1541
1542 struct tm *
1543 gmtime(timep)
1544 const time_t * const    timep;
1545 {
1546         struct tm *p_tm;
1547
1548         if (__isthreaded != 0) {
1549                 _pthread_once(&gmtime_once, gmtime_key_init);
1550                 if (gmtime_key_error != 0) {
1551                         errno = gmtime_key_error;
1552                         return(NULL);
1553                 }
1554                 /*
1555                  * Changed to follow POSIX.1 threads standard, which
1556                  * is what BSD currently has.
1557                  */
1558                 if ((p_tm = _pthread_getspecific(gmtime_key)) == NULL) {
1559                         if ((p_tm = (struct tm *)malloc(sizeof(struct tm)))
1560                             == NULL) {
1561                                 return(NULL);
1562                         }
1563                         _pthread_setspecific(gmtime_key, p_tm);
1564                 }
1565                 gmtsub(timep, 0L, p_tm);
1566                 return(p_tm);
1567         }
1568         else {
1569                 gmtsub(timep, 0L, &tm);
1570                 return(&tm);
1571         }
1572 }
1573
1574 /*
1575 * Re-entrant version of gmtime.
1576 */
1577
1578 struct tm *
1579 gmtime_r(timep, tmp)
1580 const time_t * const    timep;
1581 struct tm *             tmp;
1582 {
1583         return gmtsub(timep, 0L, tmp);
1584 }
1585
1586 #ifdef STD_INSPIRED
1587
1588 struct tm *
1589 offtime(timep, offset)
1590 const time_t * const    timep;
1591 const long              offset;
1592 {
1593         return gmtsub(timep, offset, &tm);
1594 }
1595
1596 #endif /* defined STD_INSPIRED */
1597
1598 /*
1599 ** Return the number of leap years through the end of the given year
1600 ** where, to make the math easy, the answer for year zero is defined as zero.
1601 */
1602
1603 static int
1604 leaps_thru_end_of(y)
1605 register const int      y;
1606 {
1607         return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1608                 -(leaps_thru_end_of(-(y + 1)) + 1);
1609 }
1610
1611 static struct tm *
1612 timesub(timep, offset, sp, tmp)
1613 const time_t * const                    timep;
1614 const long                              offset;
1615 const struct state * const      sp;
1616 struct tm * const               tmp;
1617 {
1618         const struct lsinfo *   lp;
1619         time_t                  tdays;
1620         int                     idays;  /* unsigned would be so 2003 */
1621         long                    rem;
1622         int                     y;
1623         const int *             ip;
1624         long                    corr;
1625         int                     hit;
1626         int                     i;
1627
1628         corr = 0;
1629         hit = 0;
1630 #ifdef ALL_STATE
1631         i = (sp == NULL) ? 0 : sp->leapcnt;
1632 #endif /* defined ALL_STATE */
1633 #ifndef ALL_STATE
1634         i = sp->leapcnt;
1635 #endif /* State Farm */
1636         while (--i >= 0) {
1637                 lp = &sp->lsis[i];
1638                 if (*timep >= lp->ls_trans) {
1639                         if (*timep == lp->ls_trans) {
1640                                 hit = ((i == 0 && lp->ls_corr > 0) ||
1641                                         lp->ls_corr > sp->lsis[i - 1].ls_corr);
1642                                 if (hit)
1643                                         while (i > 0 &&
1644                                                 sp->lsis[i].ls_trans ==
1645                                                 sp->lsis[i - 1].ls_trans + 1 &&
1646                                                 sp->lsis[i].ls_corr ==
1647                                                 sp->lsis[i - 1].ls_corr + 1) {
1648                                                         ++hit;
1649                                                         --i;
1650                                         }
1651                         }
1652                         corr = lp->ls_corr;
1653                         break;
1654                 }
1655         }
1656         y = EPOCH_YEAR;
1657         tdays = *timep / SECSPERDAY;
1658         rem = *timep - tdays * SECSPERDAY;
1659         while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1660                 int             newy;
1661                 register time_t tdelta;
1662                 register int    idelta;
1663                 register int    leapdays;
1664
1665                 tdelta = tdays / DAYSPERLYEAR;
1666                 idelta = tdelta;
1667                 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1668                         return NULL;
1669                 if (idelta == 0)
1670                         idelta = (tdays < 0) ? -1 : 1;
1671                 newy = y;
1672                 if (increment_overflow(&newy, idelta))
1673                         return NULL;
1674                 leapdays = leaps_thru_end_of(newy - 1) -
1675                         leaps_thru_end_of(y - 1);
1676                 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1677                 tdays -= leapdays;
1678                 y = newy;
1679         }
1680         {
1681                 register long   seconds;
1682
1683                 seconds = tdays * SECSPERDAY + 0.5;
1684                 tdays = seconds / SECSPERDAY;
1685                 rem += seconds - tdays * SECSPERDAY;
1686         }
1687         /*
1688         ** Given the range, we can now fearlessly cast...
1689         */
1690         idays = tdays;
1691         rem += offset - corr;
1692         while (rem < 0) {
1693                 rem += SECSPERDAY;
1694                 --idays;
1695         }
1696         while (rem >= SECSPERDAY) {
1697                 rem -= SECSPERDAY;
1698                 ++idays;
1699         }
1700         while (idays < 0) {
1701                 if (increment_overflow(&y, -1))
1702                         return NULL;
1703                 idays += year_lengths[isleap(y)];
1704         }
1705         while (idays >= year_lengths[isleap(y)]) {
1706                 idays -= year_lengths[isleap(y)];
1707                 if (increment_overflow(&y, 1))
1708                         return NULL;
1709         }
1710         tmp->tm_year = y;
1711         if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1712                 return NULL;
1713         tmp->tm_yday = idays;
1714         /*
1715         ** The "extra" mods below avoid overflow problems.
1716         */
1717         tmp->tm_wday = EPOCH_WDAY +
1718                 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1719                 (DAYSPERNYEAR % DAYSPERWEEK) +
1720                 leaps_thru_end_of(y - 1) -
1721                 leaps_thru_end_of(EPOCH_YEAR - 1) +
1722                 idays;
1723         tmp->tm_wday %= DAYSPERWEEK;
1724         if (tmp->tm_wday < 0)
1725                 tmp->tm_wday += DAYSPERWEEK;
1726         tmp->tm_hour = (int) (rem / SECSPERHOUR);
1727         rem %= SECSPERHOUR;
1728         tmp->tm_min = (int) (rem / SECSPERMIN);
1729         /*
1730         ** A positive leap second requires a special
1731         ** representation. This uses "... ??:59:60" et seq.
1732         */
1733         tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1734         ip = mon_lengths[isleap(y)];
1735         for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1736                 idays -= ip[tmp->tm_mon];
1737         tmp->tm_mday = (int) (idays + 1);
1738         tmp->tm_isdst = 0;
1739 #ifdef TM_GMTOFF
1740         tmp->TM_GMTOFF = offset;
1741 #endif /* defined TM_GMTOFF */
1742         return tmp;
1743 }
1744
1745 char *
1746 ctime(timep)
1747 const time_t * const    timep;
1748 {
1749 /*
1750 ** Section 4.12.3.2 of X3.159-1989 requires that
1751 **      The ctime function converts the calendar time pointed to by timer
1752 **      to local time in the form of a string. It is equivalent to
1753 **              asctime(localtime(timer))
1754 */
1755         return asctime(localtime(timep));
1756 }
1757
1758 char *
1759 ctime_r(timep, buf)
1760 const time_t * const    timep;
1761 char *                  buf;
1762 {
1763         struct tm       mytm;
1764
1765         return asctime_r(localtime_r(timep, &mytm), buf);
1766 }
1767
1768 /*
1769 ** Adapted from code provided by Robert Elz, who writes:
1770 **      The "best" way to do mktime I think is based on an idea of Bob
1771 **      Kridle's (so its said...) from a long time ago.
1772 **      It does a binary search of the time_t space. Since time_t's are
1773 **      just 32 bits, its a max of 32 iterations (even at 64 bits it
1774 **      would still be very reasonable).
1775 */
1776
1777 #ifndef WRONG
1778 #define WRONG   (-1)
1779 #endif /* !defined WRONG */
1780
1781 /*
1782 ** Simplified normalize logic courtesy Paul Eggert.
1783 */
1784
1785 static int
1786 increment_overflow(number, delta)
1787 int *   number;
1788 int     delta;
1789 {
1790         int     number0;
1791
1792         number0 = *number;
1793         *number += delta;
1794         return (*number < number0) != (delta < 0);
1795 }
1796
1797 static int
1798 long_increment_overflow(number, delta)
1799 long *  number;
1800 int     delta;
1801 {
1802         long    number0;
1803
1804         number0 = *number;
1805         *number += delta;
1806         return (*number < number0) != (delta < 0);
1807 }
1808
1809 static int
1810 normalize_overflow(tensptr, unitsptr, base)
1811 int * const     tensptr;
1812 int * const     unitsptr;
1813 const int       base;
1814 {
1815         int     tensdelta;
1816
1817         tensdelta = (*unitsptr >= 0) ?
1818                 (*unitsptr / base) :
1819                 (-1 - (-1 - *unitsptr) / base);
1820         *unitsptr -= tensdelta * base;
1821         return increment_overflow(tensptr, tensdelta);
1822 }
1823
1824 static int
1825 long_normalize_overflow(tensptr, unitsptr, base)
1826 long * const    tensptr;
1827 int * const     unitsptr;
1828 const int       base;
1829 {
1830         register int    tensdelta;
1831
1832         tensdelta = (*unitsptr >= 0) ?
1833                 (*unitsptr / base) :
1834                 (-1 - (-1 - *unitsptr) / base);
1835         *unitsptr -= tensdelta * base;
1836         return long_increment_overflow(tensptr, tensdelta);
1837 }
1838
1839 static int
1840 tmcomp(atmp, btmp)
1841 const struct tm * const atmp;
1842 const struct tm * const btmp;
1843 {
1844         int     result;
1845
1846         if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1847                 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1848                 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1849                 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1850                 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1851                         result = atmp->tm_sec - btmp->tm_sec;
1852         return result;
1853 }
1854
1855 static time_t
1856 time2sub(tmp, funcp, offset, okayp, do_norm_secs)
1857 struct tm * const       tmp;
1858 struct tm * (* const    funcp)(const time_t*, long, struct tm*);
1859 const long              offset;
1860 int * const             okayp;
1861 const int               do_norm_secs;
1862 {
1863         const struct state *    sp;
1864         int                     dir;
1865         int                     i, j;
1866         int                     saved_seconds;
1867         long                    li;
1868         time_t                  lo;
1869         time_t                  hi;
1870         long                    y;
1871         time_t                  newt;
1872         time_t                  t;
1873         struct tm               yourtm, mytm;
1874
1875         *okayp = FALSE;
1876         yourtm = *tmp;
1877         if (do_norm_secs) {
1878                 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
1879                         SECSPERMIN))
1880                                 return WRONG;
1881         }
1882         if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1883                 return WRONG;
1884         if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1885                 return WRONG;
1886         y = yourtm.tm_year;
1887         if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
1888                 return WRONG;
1889         /*
1890         ** Turn y into an actual year number for now.
1891         ** It is converted back to an offset from TM_YEAR_BASE later.
1892         */
1893         if (long_increment_overflow(&y, TM_YEAR_BASE))
1894                 return WRONG;
1895         while (yourtm.tm_mday <= 0) {
1896                 if (long_increment_overflow(&y, -1))
1897                         return WRONG;
1898                 li = y + (1 < yourtm.tm_mon);
1899                 yourtm.tm_mday += year_lengths[isleap(li)];
1900         }
1901         while (yourtm.tm_mday > DAYSPERLYEAR) {
1902                 li = y + (1 < yourtm.tm_mon);
1903                 yourtm.tm_mday -= year_lengths[isleap(li)];
1904                 if (long_increment_overflow(&y, 1))
1905                         return WRONG;
1906         }
1907         for ( ; ; ) {
1908                 i = mon_lengths[isleap(y)][yourtm.tm_mon];
1909                 if (yourtm.tm_mday <= i)
1910                         break;
1911                 yourtm.tm_mday -= i;
1912                 if (++yourtm.tm_mon >= MONSPERYEAR) {
1913                         yourtm.tm_mon = 0;
1914                         if (long_increment_overflow(&y, 1))
1915                                 return WRONG;
1916                 }
1917         }
1918         if (long_increment_overflow(&y, -TM_YEAR_BASE))
1919                 return WRONG;
1920         yourtm.tm_year = y;
1921         if (yourtm.tm_year != y)
1922                 return WRONG;
1923         /* Don't go below 1900 for POLA */
1924         if (yourtm.tm_year < 0)
1925                 return WRONG;
1926         if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
1927                 saved_seconds = 0;
1928         else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
1929                 /*
1930                 ** We can't set tm_sec to 0, because that might push the
1931                 ** time below the minimum representable time.
1932                 ** Set tm_sec to 59 instead.
1933                 ** This assumes that the minimum representable time is
1934                 ** not in the same minute that a leap second was deleted from,
1935                 ** which is a safer assumption than using 58 would be.
1936                 */
1937                 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1938                         return WRONG;
1939                 saved_seconds = yourtm.tm_sec;
1940                 yourtm.tm_sec = SECSPERMIN - 1;
1941         } else {
1942                 saved_seconds = yourtm.tm_sec;
1943                 yourtm.tm_sec = 0;
1944         }
1945         /*
1946         ** Do a binary search (this works whatever time_t's type is).
1947         */
1948         if (!TYPE_SIGNED(time_t)) {
1949                 lo = 0;
1950                 hi = lo - 1;
1951         } else if (!TYPE_INTEGRAL(time_t)) {
1952                 if (sizeof(time_t) > sizeof(float))
1953                         hi = (time_t) DBL_MAX;
1954                 else    hi = (time_t) FLT_MAX;
1955                 lo = -hi;
1956         } else {
1957                 lo = 1;
1958                 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
1959                         lo *= 2;
1960                 hi = -(lo + 1);
1961         }
1962         for ( ; ; ) {
1963                 t = lo / 2 + hi / 2;
1964                 if (t < lo)
1965                         t = lo;
1966                 else if (t > hi)
1967                         t = hi;
1968                 if ((*funcp)(&t, offset, &mytm) == NULL) {
1969                         /*
1970                         ** Assume that t is too extreme to be represented in
1971                         ** a struct tm; arrange things so that it is less
1972                         ** extreme on the next pass.
1973                         */
1974                         dir = (t > 0) ? 1 : -1;
1975                 } else  dir = tmcomp(&mytm, &yourtm);
1976                 if (dir != 0) {
1977                         if (t == lo) {
1978                                 ++t;
1979                                 if (t <= lo)
1980                                         return WRONG;
1981                                 ++lo;
1982                         } else if (t == hi) {
1983                                 --t;
1984                                 if (t >= hi)
1985                                         return WRONG;
1986                                 --hi;
1987                         }
1988                         if (lo > hi)
1989                                 return WRONG;
1990                         if (dir > 0)
1991                                 hi = t;
1992                         else    lo = t;
1993                         continue;
1994                 }
1995                 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1996                         break;
1997                 /*
1998                 ** Right time, wrong type.
1999                 ** Hunt for right time, right type.
2000                 ** It's okay to guess wrong since the guess
2001                 ** gets checked.
2002                 */
2003                 sp = (const struct state *)
2004                         ((funcp == localsub) ? lclptr : gmtptr);
2005 #ifdef ALL_STATE
2006                 if (sp == NULL)
2007                         return WRONG;
2008 #endif /* defined ALL_STATE */
2009                 for (i = sp->typecnt - 1; i >= 0; --i) {
2010                         if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2011                                 continue;
2012                         for (j = sp->typecnt - 1; j >= 0; --j) {
2013                                 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2014                                         continue;
2015                                 newt = t + sp->ttis[j].tt_gmtoff -
2016                                         sp->ttis[i].tt_gmtoff;
2017                                 if ((*funcp)(&newt, offset, &mytm) == NULL)
2018                                         continue;
2019                                 if (tmcomp(&mytm, &yourtm) != 0)
2020                                         continue;
2021                                 if (mytm.tm_isdst != yourtm.tm_isdst)
2022                                         continue;
2023                                 /*
2024                                 ** We have a match.
2025                                 */
2026                                 t = newt;
2027                                 goto label;
2028                         }
2029                 }
2030                 return WRONG;
2031         }
2032 label:
2033         newt = t + saved_seconds;
2034         if ((newt < t) != (saved_seconds < 0))
2035                 return WRONG;
2036         t = newt;
2037         if ((*funcp)(&t, offset, tmp))
2038                 *okayp = TRUE;
2039         return t;
2040 }
2041
2042 static time_t
2043 time2(tmp, funcp, offset, okayp)
2044 struct tm * const       tmp;
2045 struct tm * (* const    funcp)(const time_t*, long, struct tm*);
2046 const long              offset;
2047 int * const             okayp;
2048 {
2049         time_t  t;
2050
2051         /*
2052         ** First try without normalization of seconds
2053         ** (in case tm_sec contains a value associated with a leap second).
2054         ** If that fails, try with normalization of seconds.
2055         */
2056         t = time2sub(tmp, funcp, offset, okayp, FALSE);
2057         return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
2058 }
2059
2060 static time_t
2061 time1(tmp, funcp, offset)
2062 struct tm * const       tmp;
2063 struct tm * (* const  funcp)(const time_t *, long, struct tm *);
2064 const long              offset;
2065 {
2066         time_t                  t;
2067         const struct state *    sp;
2068         int                     samei, otheri;
2069         int                     sameind, otherind;
2070         int                     i;
2071         int                     nseen;
2072         int                             seen[TZ_MAX_TYPES];
2073         int                             types[TZ_MAX_TYPES];
2074         int                             okay;
2075
2076         if (tmp == NULL) {
2077                 errno = EINVAL;
2078                 return WRONG;
2079         }
2080
2081         if (tmp->tm_isdst > 1)
2082                 tmp->tm_isdst = 1;
2083         t = time2(tmp, funcp, offset, &okay);
2084 #ifdef PCTS
2085         /*
2086         ** PCTS code courtesy Grant Sullivan.
2087         */
2088         if (okay)
2089                 return t;
2090         if (tmp->tm_isdst < 0)
2091                 tmp->tm_isdst = 0;      /* reset to std and try again */
2092 #endif /* defined PCTS */
2093 #ifndef PCTS
2094         if (okay || tmp->tm_isdst < 0)
2095                 return t;
2096 #endif /* !defined PCTS */
2097         /*
2098         ** We're supposed to assume that somebody took a time of one type
2099         ** and did some math on it that yielded a "struct tm" that's bad.
2100         ** We try to divine the type they started from and adjust to the
2101         ** type they need.
2102         */
2103         sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr);
2104 #ifdef ALL_STATE
2105         if (sp == NULL)
2106                 return WRONG;
2107 #endif /* defined ALL_STATE */
2108         for (i = 0; i < sp->typecnt; ++i)
2109                 seen[i] = FALSE;
2110         nseen = 0;
2111         for (i = sp->timecnt - 1; i >= 0; --i)
2112                 if (!seen[sp->types[i]]) {
2113                         seen[sp->types[i]] = TRUE;
2114                         types[nseen++] = sp->types[i];
2115                 }
2116         for (sameind = 0; sameind < nseen; ++sameind) {
2117                 samei = types[sameind];
2118                 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2119                         continue;
2120                 for (otherind = 0; otherind < nseen; ++otherind) {
2121                         otheri = types[otherind];
2122                         if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2123                                 continue;
2124                         tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
2125                                         sp->ttis[samei].tt_gmtoff;
2126                         tmp->tm_isdst = !tmp->tm_isdst;
2127                         t = time2(tmp, funcp, offset, &okay);
2128                         if (okay)
2129                                 return t;
2130                         tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
2131                                         sp->ttis[samei].tt_gmtoff;
2132                         tmp->tm_isdst = !tmp->tm_isdst;
2133                 }
2134         }
2135         return WRONG;
2136 }
2137
2138 time_t
2139 mktime(tmp)
2140 struct tm * const       tmp;
2141 {
2142         time_t mktime_return_value;
2143         _RWLOCK_RDLOCK(&lcl_rwlock);
2144         tzset_basic(1);
2145         mktime_return_value = time1(tmp, localsub, 0L);
2146         _RWLOCK_UNLOCK(&lcl_rwlock);
2147         return(mktime_return_value);
2148 }
2149
2150 #ifdef STD_INSPIRED
2151
2152 time_t
2153 timelocal(tmp)
2154 struct tm * const       tmp;
2155 {
2156         if (tmp != NULL)
2157                 tmp->tm_isdst = -1;     /* in case it wasn't initialized */
2158         return mktime(tmp);
2159 }
2160
2161 time_t
2162 timegm(tmp)
2163 struct tm * const       tmp;
2164 {
2165         if (tmp != NULL)
2166                 tmp->tm_isdst = 0;
2167         return time1(tmp, gmtsub, 0L);
2168 }
2169
2170 time_t
2171 timeoff(tmp, offset)
2172 struct tm * const       tmp;
2173 const long              offset;
2174 {
2175         if (tmp != NULL)
2176                 tmp->tm_isdst = 0;
2177         return time1(tmp, gmtsub, offset);
2178 }
2179
2180 #endif /* defined STD_INSPIRED */
2181
2182 #ifdef CMUCS
2183
2184 /*
2185 ** The following is supplied for compatibility with
2186 ** previous versions of the CMUCS runtime library.
2187 */
2188
2189 long
2190 gtime(tmp)
2191 struct tm * const       tmp;
2192 {
2193         const time_t    t = mktime(tmp);
2194
2195         if (t == WRONG)
2196                 return -1;
2197         return t;
2198 }
2199
2200 #endif /* defined CMUCS */
2201
2202 /*
2203 ** XXX--is the below the right way to conditionalize??
2204 */
2205
2206 #ifdef STD_INSPIRED
2207
2208 /*
2209 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2210 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2211 ** is not the case if we are accounting for leap seconds.
2212 ** So, we provide the following conversion routines for use
2213 ** when exchanging timestamps with POSIX conforming systems.
2214 */
2215
2216 static long
2217 leapcorr(timep)
2218 time_t *        timep;
2219 {
2220         struct state *          sp;
2221         struct lsinfo * lp;
2222         int                     i;
2223
2224         sp = lclptr;
2225         i = sp->leapcnt;
2226         while (--i >= 0) {
2227                 lp = &sp->lsis[i];
2228                 if (*timep >= lp->ls_trans)
2229                         return lp->ls_corr;
2230         }
2231         return 0;
2232 }
2233
2234 time_t
2235 time2posix(t)
2236 time_t  t;
2237 {
2238         tzset();
2239         return t - leapcorr(&t);
2240 }
2241
2242 time_t
2243 posix2time(t)
2244 time_t  t;
2245 {
2246         time_t  x;
2247         time_t  y;
2248
2249         tzset();
2250         /*
2251         ** For a positive leap second hit, the result
2252         ** is not unique. For a negative leap second
2253         ** hit, the corresponding time doesn't exist,
2254         ** so we return an adjacent second.
2255         */
2256         x = t + leapcorr(&t);
2257         y = x - leapcorr(&x);
2258         if (y < t) {
2259                 do {
2260                         x++;
2261                         y = x - leapcorr(&x);
2262                 } while (y < t);
2263                 if (t != y)
2264                         return x - 1;
2265         } else if (y > t) {
2266                 do {
2267                         --x;
2268                         y = x - leapcorr(&x);
2269                 } while (y > t);
2270                 if (t != y)
2271                         return x + 1;
2272         }
2273         return x;
2274 }
2275
2276 #endif /* defined STD_INSPIRED */