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