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