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