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