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