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