localtime.c revision 1.63
1/*	$NetBSD: localtime.c,v 1.63 2011/11/07 19:42: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.63 2011/11/07 19:42: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);
159static const char *	getqzname(const char * strp, const int delim);
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);
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, 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);
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	int			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] = (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 = (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(strp)
663const char *	strp;
664{
665	char	c;
666
667	while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
668		c != '+')
669			++strp;
670	return strp;
671}
672
673/*
674** Given a pointer into an extended time zone string, scan until the ending
675** delimiter of the zone name is located. Return a pointer to the delimiter.
676**
677** As with getzname above, the legal character set is actually quite
678** restricted, with other characters producing undefined results.
679** We don't do any checking here; checking is done later in common-case code.
680*/
681
682static const char *
683getqzname(const char *strp, const int delim)
684{
685	int	c;
686
687	while ((c = *strp) != '\0' && c != delim)
688		++strp;
689	return strp;
690}
691
692/*
693** Given a pointer into a time zone string, extract a number from that string.
694** Check that the number is within a specified range; if it is not, return
695** NULL.
696** Otherwise, return a pointer to the first character not part of the number.
697*/
698
699static const char *
700getnum(strp, nump, min, max)
701const char *	strp;
702int * const		nump;
703const int		min;
704const int		max;
705{
706	char	c;
707	int	num;
708
709	if (strp == NULL || !is_digit(c = *strp)) {
710		errno = EINVAL;
711		return NULL;
712	}
713	num = 0;
714	do {
715		num = num * 10 + (c - '0');
716		if (num > max) {
717			errno = EOVERFLOW;
718			return NULL;	/* illegal value */
719		}
720		c = *++strp;
721	} while (is_digit(c));
722	if (num < min) {
723		errno = EINVAL;
724		return NULL;		/* illegal value */
725	}
726	*nump = num;
727	return strp;
728}
729
730/*
731** Given a pointer into a time zone string, extract a number of seconds,
732** in hh[:mm[:ss]] form, from the string.
733** If any error occurs, return NULL.
734** Otherwise, return a pointer to the first character not part of the number
735** of seconds.
736*/
737
738static const char *
739getsecs(const char *strp, long *const secsp)
740{
741	int	num;
742
743	/*
744	** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
745	** "M10.4.6/26", which does not conform to Posix,
746	** but which specifies the equivalent of
747	** ``02:00 on the first Sunday on or after 23 Oct''.
748	*/
749	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
750	if (strp == NULL)
751		return NULL;
752	*secsp = num * (long) SECSPERHOUR;
753	if (*strp == ':') {
754		++strp;
755		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
756		if (strp == NULL)
757			return NULL;
758		*secsp += num * SECSPERMIN;
759		if (*strp == ':') {
760			++strp;
761			/* `SECSPERMIN' allows for leap seconds. */
762			strp = getnum(strp, &num, 0, SECSPERMIN);
763			if (strp == NULL)
764				return NULL;
765			*secsp += num;
766		}
767	}
768	return strp;
769}
770
771/*
772** Given a pointer into a time zone string, extract an offset, in
773** [+-]hh[:mm[:ss]] form, from the string.
774** If any error occurs, return NULL.
775** Otherwise, return a pointer to the first character not part of the time.
776*/
777
778static const char *
779getoffset(const char *strp, long *const offsetp)
780{
781	int	neg = 0;
782
783	if (*strp == '-') {
784		neg = 1;
785		++strp;
786	} else if (*strp == '+')
787		++strp;
788	strp = getsecs(strp, offsetp);
789	if (strp == NULL)
790		return NULL;		/* illegal time */
791	if (neg)
792		*offsetp = -*offsetp;
793	return strp;
794}
795
796/*
797** Given a pointer into a time zone string, extract a rule in the form
798** date[/time]. See POSIX section 8 for the format of "date" and "time".
799** If a valid rule is not found, return NULL.
800** Otherwise, return a pointer to the first character not part of the rule.
801*/
802
803static const char *
804getrule(const char *strp, struct rule *const rulep)
805{
806	if (*strp == 'J') {
807		/*
808		** Julian day.
809		*/
810		rulep->r_type = JULIAN_DAY;
811		++strp;
812		strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
813	} else if (*strp == 'M') {
814		/*
815		** Month, week, day.
816		*/
817		rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
818		++strp;
819		strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
820		if (strp == NULL)
821			return NULL;
822		if (*strp++ != '.')
823			return NULL;
824		strp = getnum(strp, &rulep->r_week, 1, 5);
825		if (strp == NULL)
826			return NULL;
827		if (*strp++ != '.')
828			return NULL;
829		strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
830	} else if (is_digit(*strp)) {
831		/*
832		** Day of year.
833		*/
834		rulep->r_type = DAY_OF_YEAR;
835		strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
836	} else	return NULL;		/* invalid format */
837	if (strp == NULL)
838		return NULL;
839	if (*strp == '/') {
840		/*
841		** Time specified.
842		*/
843		++strp;
844		strp = getsecs(strp, &rulep->r_time);
845	} else	rulep->r_time = 2 * SECSPERHOUR;	/* default = 2:00:00 */
846	return strp;
847}
848
849/*
850** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
851** year, a rule, and the offset from UTC at the time that rule takes effect,
852** calculate the Epoch-relative time that rule takes effect.
853*/
854
855static time_t
856transtime(const time_t janfirst, const int year, const struct rule *const rulep,
857    const long offset)
858{
859	int	leapyear;
860	time_t	value;
861	int	i;
862	int		d, m1, yy0, yy1, yy2, dow;
863
864	INITIALIZE(value);
865	leapyear = isleap(year);
866	switch (rulep->r_type) {
867
868	case JULIAN_DAY:
869		/*
870		** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
871		** years.
872		** In non-leap years, or if the day number is 59 or less, just
873		** add SECSPERDAY times the day number-1 to the time of
874		** January 1, midnight, to get the day.
875		*/
876		value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
877		if (leapyear && rulep->r_day >= 60)
878			value += SECSPERDAY;
879		break;
880
881	case DAY_OF_YEAR:
882		/*
883		** n - day of year.
884		** Just add SECSPERDAY times the day number to the time of
885		** January 1, midnight, to get the day.
886		*/
887		value = janfirst + rulep->r_day * SECSPERDAY;
888		break;
889
890	case MONTH_NTH_DAY_OF_WEEK:
891		/*
892		** Mm.n.d - nth "dth day" of month m.
893		*/
894		value = janfirst;
895		for (i = 0; i < rulep->r_mon - 1; ++i)
896			value += mon_lengths[leapyear][i] * SECSPERDAY;
897
898		/*
899		** Use Zeller's Congruence to get day-of-week of first day of
900		** month.
901		*/
902		m1 = (rulep->r_mon + 9) % 12 + 1;
903		yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
904		yy1 = yy0 / 100;
905		yy2 = yy0 % 100;
906		dow = ((26 * m1 - 2) / 10 +
907			1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
908		if (dow < 0)
909			dow += DAYSPERWEEK;
910
911		/*
912		** "dow" is the day-of-week of the first day of the month. Get
913		** the day-of-month (zero-origin) of the first "dow" day of the
914		** month.
915		*/
916		d = rulep->r_day - dow;
917		if (d < 0)
918			d += DAYSPERWEEK;
919		for (i = 1; i < rulep->r_week; ++i) {
920			if (d + DAYSPERWEEK >=
921				mon_lengths[leapyear][rulep->r_mon - 1])
922					break;
923			d += DAYSPERWEEK;
924		}
925
926		/*
927		** "d" is the day-of-month (zero-origin) of the day we want.
928		*/
929		value += d * SECSPERDAY;
930		break;
931	}
932
933	/*
934	** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
935	** question. To get the Epoch-relative time of the specified local
936	** time on that day, add the transition time and the current offset
937	** from UTC.
938	*/
939	return value + rulep->r_time + offset;
940}
941
942/*
943** Given a POSIX section 8-style TZ string, fill in the rule tables as
944** appropriate.
945*/
946
947static int
948tzparse(timezone_t sp, const char *name, const int lastditch)
949{
950	const char *			stdname;
951	const char *			dstname;
952	size_t				stdlen;
953	size_t				dstlen;
954	long				stdoffset;
955	long				dstoffset;
956	time_t *		atp;
957	unsigned char *	typep;
958	char *			cp;
959	int			load_result;
960
961	INITIALIZE(dstname);
962	stdname = name;
963	if (lastditch) {
964		stdlen = strlen(name);	/* length of standard zone name */
965		name += stdlen;
966		if (stdlen >= sizeof sp->chars)
967			stdlen = (sizeof sp->chars) - 1;
968		stdoffset = 0;
969	} else {
970		if (*name == '<') {
971			name++;
972			stdname = name;
973			name = getqzname(name, '>');
974			if (*name != '>')
975				return (-1);
976			stdlen = name - stdname;
977			name++;
978		} else {
979			name = getzname(name);
980			stdlen = name - stdname;
981		}
982		if (*name == '\0')
983			return -1;
984		name = getoffset(name, &stdoffset);
985		if (name == NULL)
986			return -1;
987	}
988	load_result = tzload(sp, TZDEFRULES, FALSE);
989	if (load_result != 0)
990		sp->leapcnt = 0;		/* so, we're off a little */
991	if (*name != '\0') {
992		if (*name == '<') {
993			dstname = ++name;
994			name = getqzname(name, '>');
995			if (*name != '>')
996				return -1;
997			dstlen = name - dstname;
998			name++;
999		} else {
1000			dstname = name;
1001			name = getzname(name);
1002			dstlen = name - dstname; /* length of DST zone name */
1003		}
1004		if (*name != '\0' && *name != ',' && *name != ';') {
1005			name = getoffset(name, &dstoffset);
1006			if (name == NULL)
1007				return -1;
1008		} else	dstoffset = stdoffset - SECSPERHOUR;
1009		if (*name == '\0' && load_result != 0)
1010			name = TZDEFRULESTRING;
1011		if (*name == ',' || *name == ';') {
1012			struct rule	start;
1013			struct rule	end;
1014			int	year;
1015			time_t	janfirst;
1016			time_t		starttime;
1017			time_t		endtime;
1018
1019			++name;
1020			if ((name = getrule(name, &start)) == NULL)
1021				return -1;
1022			if (*name++ != ',')
1023				return -1;
1024			if ((name = getrule(name, &end)) == NULL)
1025				return -1;
1026			if (*name != '\0')
1027				return -1;
1028			sp->typecnt = 2;	/* standard time and DST */
1029			/*
1030			** Two transitions per year, from EPOCH_YEAR forward.
1031			*/
1032			memset(sp->ttis, 0, sizeof(sp->ttis));
1033			sp->ttis[0].tt_gmtoff = -dstoffset;
1034			sp->ttis[0].tt_isdst = 1;
1035			sp->ttis[0].tt_abbrind = stdlen + 1;
1036			sp->ttis[1].tt_gmtoff = -stdoffset;
1037			sp->ttis[1].tt_isdst = 0;
1038			sp->ttis[1].tt_abbrind = 0;
1039			atp = sp->ats;
1040			typep = sp->types;
1041			janfirst = 0;
1042			sp->timecnt = 0;
1043			for (year = EPOCH_YEAR;
1044			    sp->timecnt + 2 <= TZ_MAX_TIMES;
1045			    ++year) {
1046			    	time_t	newfirst;
1047
1048				starttime = transtime(janfirst, year, &start,
1049					stdoffset);
1050				endtime = transtime(janfirst, year, &end,
1051					dstoffset);
1052				if (starttime > endtime) {
1053					*atp++ = endtime;
1054					*typep++ = 1;	/* DST ends */
1055					*atp++ = starttime;
1056					*typep++ = 0;	/* DST begins */
1057				} else {
1058					*atp++ = starttime;
1059					*typep++ = 0;	/* DST begins */
1060					*atp++ = endtime;
1061					*typep++ = 1;	/* DST ends */
1062				}
1063				sp->timecnt += 2;
1064				newfirst = janfirst;
1065				newfirst += year_lengths[isleap(year)] *
1066					SECSPERDAY;
1067				if (newfirst <= janfirst)
1068					break;
1069				janfirst = newfirst;
1070			}
1071		} else {
1072			long	theirstdoffset;
1073			long	theirdstoffset;
1074			long	theiroffset;
1075			int	isdst;
1076			int	i;
1077			int	j;
1078
1079			if (*name != '\0')
1080				return -1;
1081			/*
1082			** Initial values of theirstdoffset
1083			*/
1084			theirstdoffset = 0;
1085			for (i = 0; i < sp->timecnt; ++i) {
1086				j = sp->types[i];
1087				if (!sp->ttis[j].tt_isdst) {
1088					theirstdoffset =
1089						-sp->ttis[j].tt_gmtoff;
1090					break;
1091				}
1092			}
1093			theirdstoffset = 0;
1094			for (i = 0; i < sp->timecnt; ++i) {
1095				j = sp->types[i];
1096				if (sp->ttis[j].tt_isdst) {
1097					theirdstoffset =
1098						-sp->ttis[j].tt_gmtoff;
1099					break;
1100				}
1101			}
1102			/*
1103			** Initially we're assumed to be in standard time.
1104			*/
1105			isdst = FALSE;
1106			theiroffset = theirstdoffset;
1107			/*
1108			** Now juggle transition times and types
1109			** tracking offsets as you do.
1110			*/
1111			for (i = 0; i < sp->timecnt; ++i) {
1112				j = sp->types[i];
1113				sp->types[i] = sp->ttis[j].tt_isdst;
1114				if (sp->ttis[j].tt_ttisgmt) {
1115					/* No adjustment to transition time */
1116				} else {
1117					/*
1118					** If summer time is in effect, and the
1119					** transition time was not specified as
1120					** standard time, add the summer time
1121					** offset to the transition time;
1122					** otherwise, add the standard time
1123					** offset to the transition time.
1124					*/
1125					/*
1126					** Transitions from DST to DDST
1127					** will effectively disappear since
1128					** POSIX provides for only one DST
1129					** offset.
1130					*/
1131					if (isdst && !sp->ttis[j].tt_ttisstd) {
1132						sp->ats[i] += dstoffset -
1133							theirdstoffset;
1134					} else {
1135						sp->ats[i] += stdoffset -
1136							theirstdoffset;
1137					}
1138				}
1139				theiroffset = -sp->ttis[j].tt_gmtoff;
1140				if (!sp->ttis[j].tt_isdst)
1141					theirstdoffset = theiroffset;
1142				else	theirdstoffset = theiroffset;
1143			}
1144			/*
1145			** Finally, fill in ttis.
1146			*/
1147			memset(sp->ttis, 0, sizeof(sp->ttis));
1148			sp->ttis[0].tt_gmtoff = -stdoffset;
1149			sp->ttis[0].tt_isdst = FALSE;
1150			sp->ttis[0].tt_abbrind = 0;
1151			sp->ttis[1].tt_gmtoff = -dstoffset;
1152			sp->ttis[1].tt_isdst = TRUE;
1153			sp->ttis[1].tt_abbrind = stdlen + 1;
1154			sp->typecnt = 2;
1155		}
1156	} else {
1157		dstlen = 0;
1158		sp->typecnt = 1;		/* only standard time */
1159		sp->timecnt = 0;
1160		memset(sp->ttis, 0, sizeof(sp->ttis));
1161		sp->ttis[0].tt_gmtoff = -stdoffset;
1162		sp->ttis[0].tt_isdst = 0;
1163		sp->ttis[0].tt_abbrind = 0;
1164	}
1165	sp->charcnt = stdlen + 1;
1166	if (dstlen != 0)
1167		sp->charcnt += dstlen + 1;
1168	if ((size_t) sp->charcnt > sizeof sp->chars)
1169		return -1;
1170	cp = sp->chars;
1171	(void) strncpy(cp, stdname, stdlen);
1172	cp += stdlen;
1173	*cp++ = '\0';
1174	if (dstlen != 0) {
1175		(void) strncpy(cp, dstname, dstlen);
1176		*(cp + dstlen) = '\0';
1177	}
1178	return 0;
1179}
1180
1181static void
1182gmtload(timezone_t sp)
1183{
1184	if (tzload(sp, gmt, TRUE) != 0)
1185		(void) tzparse(sp, gmt, TRUE);
1186}
1187
1188timezone_t
1189tzalloc(const char *name)
1190{
1191	timezone_t sp = calloc(1, sizeof *sp);
1192	if (sp == NULL)
1193		return NULL;
1194	if (tzload(sp, name, TRUE) != 0) {
1195		free(sp);
1196		return NULL;
1197	}
1198	settzname_z(sp);
1199	return sp;
1200}
1201
1202void
1203tzfree(const timezone_t sp)
1204{
1205	free(sp);
1206}
1207
1208static void
1209tzsetwall_unlocked(void)
1210{
1211	if (lcl_is_set < 0)
1212		return;
1213	lcl_is_set = -1;
1214
1215	if (lclptr == NULL) {
1216		int saveerrno = errno;
1217		lclptr = calloc(1, sizeof *lclptr);
1218		errno = saveerrno;
1219		if (lclptr == NULL) {
1220			settzname();	/* all we can do */
1221			return;
1222		}
1223	}
1224	if (tzload(lclptr, NULL, TRUE) != 0)
1225		gmtload(lclptr);
1226	settzname();
1227}
1228
1229#ifndef STD_INSPIRED
1230/*
1231** A non-static declaration of tzsetwall in a system header file
1232** may cause a warning about this upcoming static declaration...
1233*/
1234static
1235#endif /* !defined STD_INSPIRED */
1236void
1237tzsetwall(void)
1238{
1239	rwlock_wrlock(&lcl_lock);
1240	tzsetwall_unlocked();
1241	rwlock_unlock(&lcl_lock);
1242}
1243
1244#ifndef STD_INSPIRED
1245/*
1246** A non-static declaration of tzsetwall in a system header file
1247** may cause a warning about this upcoming static declaration...
1248*/
1249static
1250#endif /* !defined STD_INSPIRED */
1251void
1252tzset_unlocked(void)
1253{
1254	const char *	name;
1255	int saveerrno;
1256
1257	saveerrno = errno;
1258	name = getenv("TZ");
1259	errno = saveerrno;
1260	if (name == NULL) {
1261		tzsetwall_unlocked();
1262		return;
1263	}
1264
1265	if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
1266		return;
1267	lcl_is_set = strlen(name) < sizeof lcl_TZname;
1268	if (lcl_is_set)
1269		(void)strlcpy(lcl_TZname, name, sizeof(lcl_TZname));
1270
1271	if (lclptr == NULL) {
1272		saveerrno = errno;
1273		lclptr = calloc(1, sizeof *lclptr);
1274		errno = saveerrno;
1275		if (lclptr == NULL) {
1276			settzname();	/* all we can do */
1277			return;
1278		}
1279	}
1280	if (*name == '\0') {
1281		/*
1282		** User wants it fast rather than right.
1283		*/
1284		lclptr->leapcnt = 0;		/* so, we're off a little */
1285		lclptr->timecnt = 0;
1286		lclptr->typecnt = 0;
1287		lclptr->ttis[0].tt_isdst = 0;
1288		lclptr->ttis[0].tt_gmtoff = 0;
1289		lclptr->ttis[0].tt_abbrind = 0;
1290		(void) strlcpy(lclptr->chars, gmt, sizeof(lclptr->chars));
1291	} else if (tzload(lclptr, name, TRUE) != 0)
1292		if (name[0] == ':' || tzparse(lclptr, name, FALSE) != 0)
1293			(void) gmtload(lclptr);
1294	settzname();
1295}
1296
1297void
1298tzset(void)
1299{
1300	rwlock_wrlock(&lcl_lock);
1301	tzset_unlocked();
1302	rwlock_unlock(&lcl_lock);
1303}
1304
1305/*
1306** The easy way to behave "as if no library function calls" localtime
1307** is to not call it--so we drop its guts into "localsub", which can be
1308** freely called. (And no, the PANS doesn't require the above behavior--
1309** but it *is* desirable.)
1310**
1311** The unused offset argument is for the benefit of mktime variants.
1312*/
1313
1314/*ARGSUSED*/
1315static struct tm *
1316localsub(const timezone_t sp, const time_t * const timep, const long offset,
1317    struct tm *const tmp)
1318{
1319	const struct ttinfo *	ttisp;
1320	int			i;
1321	struct tm *		result;
1322	const time_t			t = *timep;
1323
1324	if ((sp->goback && t < sp->ats[0]) ||
1325		(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1326			time_t			newt = t;
1327			time_t		seconds;
1328			time_t		tcycles;
1329			int_fast64_t	icycles;
1330
1331			if (t < sp->ats[0])
1332				seconds = sp->ats[0] - t;
1333			else	seconds = t - sp->ats[sp->timecnt - 1];
1334			--seconds;
1335			tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1336			++tcycles;
1337			icycles = tcycles;
1338			if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1339				return NULL;
1340			seconds = (time_t) icycles;
1341			seconds *= YEARSPERREPEAT;
1342			seconds *= AVGSECSPERYEAR;
1343			if (t < sp->ats[0])
1344				newt += seconds;
1345			else	newt -= seconds;
1346			if (newt < sp->ats[0] ||
1347				newt > sp->ats[sp->timecnt - 1])
1348					return NULL;	/* "cannot happen" */
1349			result = localsub(sp, &newt, offset, tmp);
1350			if (result == tmp) {
1351				time_t	newy;
1352
1353				newy = tmp->tm_year;
1354				if (t < sp->ats[0])
1355					newy -= (time_t)icycles * YEARSPERREPEAT;
1356				else	newy += (time_t)icycles * YEARSPERREPEAT;
1357				tmp->tm_year = (int)newy;
1358				if (tmp->tm_year != newy)
1359					return NULL;
1360			}
1361			return result;
1362	}
1363	if (sp->timecnt == 0 || t < sp->ats[0]) {
1364		i = 0;
1365		while (sp->ttis[i].tt_isdst)
1366			if (++i >= sp->typecnt) {
1367				i = 0;
1368				break;
1369			}
1370	} else {
1371		int	lo = 1;
1372		int	hi = sp->timecnt;
1373
1374		while (lo < hi) {
1375			int	mid = (lo + hi) / 2;
1376
1377			if (t < sp->ats[mid])
1378				hi = mid;
1379			else	lo = mid + 1;
1380		}
1381		i = (int) sp->types[lo - 1];
1382	}
1383	ttisp = &sp->ttis[i];
1384	/*
1385	** To get (wrong) behavior that's compatible with System V Release 2.0
1386	** you'd replace the statement below with
1387	**	t += ttisp->tt_gmtoff;
1388	**	timesub(&t, 0L, sp, tmp);
1389	*/
1390	result = timesub(sp, &t, ttisp->tt_gmtoff, tmp);
1391	tmp->tm_isdst = ttisp->tt_isdst;
1392	if (sp == lclptr)
1393		tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
1394#ifdef TM_ZONE
1395	tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1396#endif /* defined TM_ZONE */
1397	return result;
1398}
1399
1400/*
1401** Re-entrant version of localtime.
1402*/
1403
1404struct tm *
1405localtime_r(const time_t * __restrict timep, struct tm *tmp)
1406{
1407	rwlock_rdlock(&lcl_lock);
1408	tzset_unlocked();
1409	tmp = localtime_rz(lclptr, timep, tmp);
1410	rwlock_unlock(&lcl_lock);
1411	return tmp;
1412}
1413
1414struct tm *
1415localtime(const time_t *const timep)
1416{
1417	return localtime_r(timep, &tm);
1418}
1419
1420struct tm *
1421localtime_rz(const timezone_t sp, const time_t * __restrict timep, struct tm *tmp)
1422{
1423	if (sp == NULL)
1424		tmp = gmtsub(NULL, timep, 0L, tmp);
1425	else
1426		tmp = localsub(sp, timep, 0L, tmp);
1427	if (tmp == NULL)
1428		errno = EOVERFLOW;
1429	return tmp;
1430}
1431
1432/*
1433** gmtsub is to gmtime as localsub is to localtime.
1434*/
1435
1436static struct tm *
1437gmtsub(const timezone_t sp, const time_t * const timep, const long offset,
1438    struct tm *const tmp)
1439{
1440	struct tm *	result;
1441#ifdef _REENTRANT
1442	static mutex_t gmt_mutex = MUTEX_INITIALIZER;
1443#endif
1444
1445	mutex_lock(&gmt_mutex);
1446	if (!gmt_is_set) {
1447		int saveerrno;
1448		gmt_is_set = TRUE;
1449		saveerrno = errno;
1450		gmtptr = calloc(1, sizeof *gmtptr);
1451		errno = saveerrno;
1452		if (gmtptr != NULL)
1453			gmtload(gmtptr);
1454	}
1455	mutex_unlock(&gmt_mutex);
1456	result = timesub(gmtptr, timep, offset, tmp);
1457#ifdef TM_ZONE
1458	/*
1459	** Could get fancy here and deliver something such as
1460	** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1461	** but this is no time for a treasure hunt.
1462	*/
1463	if (offset != 0)
1464		tmp->TM_ZONE = (__aconst char *)__UNCONST(wildabbr);
1465	else {
1466		if (gmtptr == NULL)
1467			tmp->TM_ZONE = (__aconst char *)__UNCONST(gmt);
1468		else	tmp->TM_ZONE = gmtptr->chars;
1469	}
1470#endif /* defined TM_ZONE */
1471	return result;
1472}
1473
1474struct tm *
1475gmtime(const time_t *const timep)
1476{
1477	struct tm *tmp = gmtsub(NULL, timep, 0L, &tm);
1478
1479	if (tmp == NULL)
1480		errno = EOVERFLOW;
1481
1482	return tmp;
1483}
1484
1485/*
1486** Re-entrant version of gmtime.
1487*/
1488
1489struct tm *
1490gmtime_r(const time_t * const timep, struct tm *tmp)
1491{
1492	tmp = gmtsub(NULL, timep, 0L, tmp);
1493
1494	if (tmp == NULL)
1495		errno = EOVERFLOW;
1496
1497	return tmp;
1498}
1499
1500#ifdef STD_INSPIRED
1501
1502struct tm *
1503offtime(const time_t *const timep, long offset)
1504{
1505	struct tm *tmp = gmtsub(NULL, timep, offset, &tm);
1506
1507	if (tmp == NULL)
1508		errno = EOVERFLOW;
1509
1510	return tmp;
1511}
1512
1513struct tm *
1514offtime_r(const time_t *timep, long offset, struct tm *tmp)
1515{
1516	tmp = gmtsub(NULL, timep, offset, tmp);
1517
1518	if (tmp == NULL)
1519		errno = EOVERFLOW;
1520
1521	return tmp;
1522}
1523
1524#endif /* defined STD_INSPIRED */
1525
1526/*
1527** Return the number of leap years through the end of the given year
1528** where, to make the math easy, the answer for year zero is defined as zero.
1529*/
1530
1531static int
1532leaps_thru_end_of(const int y)
1533{
1534	return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1535		-(leaps_thru_end_of(-(y + 1)) + 1);
1536}
1537
1538static struct tm *
1539timesub(const timezone_t sp, const time_t *const timep, const long offset,
1540    struct tm *const tmp)
1541{
1542	const struct lsinfo *	lp;
1543	time_t			tdays;
1544	int			idays;	/* unsigned would be so 2003 */
1545	long			rem;
1546	int			y;
1547	const int *		ip;
1548	long			corr;
1549	int			hit;
1550	int			i;
1551
1552	corr = 0;
1553	hit = 0;
1554	i = (sp == NULL) ? 0 : sp->leapcnt;
1555	while (--i >= 0) {
1556		lp = &sp->lsis[i];
1557		if (*timep >= lp->ls_trans) {
1558			if (*timep == lp->ls_trans) {
1559				hit = ((i == 0 && lp->ls_corr > 0) ||
1560					lp->ls_corr > sp->lsis[i - 1].ls_corr);
1561				if (hit)
1562					while (i > 0 &&
1563						sp->lsis[i].ls_trans ==
1564						sp->lsis[i - 1].ls_trans + 1 &&
1565						sp->lsis[i].ls_corr ==
1566						sp->lsis[i - 1].ls_corr + 1) {
1567							++hit;
1568							--i;
1569					}
1570			}
1571			corr = lp->ls_corr;
1572			break;
1573		}
1574	}
1575	y = EPOCH_YEAR;
1576	tdays = *timep / SECSPERDAY;
1577	rem = (long) (*timep - tdays * SECSPERDAY);
1578	while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1579		int		newy;
1580		time_t	tdelta;
1581		int	idelta;
1582		int	leapdays;
1583
1584		tdelta = tdays / DAYSPERLYEAR;
1585		idelta = (int) tdelta;
1586		if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1587			return NULL;
1588		if (idelta == 0)
1589			idelta = (tdays < 0) ? -1 : 1;
1590		newy = y;
1591		if (increment_overflow(&newy, idelta))
1592			return NULL;
1593		leapdays = leaps_thru_end_of(newy - 1) -
1594			leaps_thru_end_of(y - 1);
1595		tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1596		tdays -= leapdays;
1597		y = newy;
1598	}
1599	{
1600		long	seconds;
1601
1602		seconds = tdays * SECSPERDAY + 0.5;
1603		tdays = seconds / SECSPERDAY;
1604		rem += (long) (seconds - tdays * SECSPERDAY);
1605	}
1606	/*
1607	** Given the range, we can now fearlessly cast...
1608	*/
1609	idays = (int) tdays;
1610	rem += offset - corr;
1611	while (rem < 0) {
1612		rem += SECSPERDAY;
1613		--idays;
1614	}
1615	while (rem >= SECSPERDAY) {
1616		rem -= SECSPERDAY;
1617		++idays;
1618	}
1619	while (idays < 0) {
1620		if (increment_overflow(&y, -1))
1621			return NULL;
1622		idays += year_lengths[isleap(y)];
1623	}
1624	while (idays >= year_lengths[isleap(y)]) {
1625		idays -= year_lengths[isleap(y)];
1626		if (increment_overflow(&y, 1))
1627			return NULL;
1628	}
1629	tmp->tm_year = y;
1630	if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1631		return NULL;
1632	tmp->tm_yday = idays;
1633	/*
1634	** The "extra" mods below avoid overflow problems.
1635	*/
1636	tmp->tm_wday = EPOCH_WDAY +
1637		((y - EPOCH_YEAR) % DAYSPERWEEK) *
1638		(DAYSPERNYEAR % DAYSPERWEEK) +
1639		leaps_thru_end_of(y - 1) -
1640		leaps_thru_end_of(EPOCH_YEAR - 1) +
1641		idays;
1642	tmp->tm_wday %= DAYSPERWEEK;
1643	if (tmp->tm_wday < 0)
1644		tmp->tm_wday += DAYSPERWEEK;
1645	tmp->tm_hour = (int) (rem / SECSPERHOUR);
1646	rem %= SECSPERHOUR;
1647	tmp->tm_min = (int) (rem / SECSPERMIN);
1648	/*
1649	** A positive leap second requires a special
1650	** representation. This uses "... ??:59:60" et seq.
1651	*/
1652	tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1653	ip = mon_lengths[isleap(y)];
1654	for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1655		idays -= ip[tmp->tm_mon];
1656	tmp->tm_mday = (int) (idays + 1);
1657	tmp->tm_isdst = 0;
1658#ifdef TM_GMTOFF
1659	tmp->TM_GMTOFF = offset;
1660#endif /* defined TM_GMTOFF */
1661	return tmp;
1662}
1663
1664char *
1665ctime(const time_t *const timep)
1666{
1667/*
1668** Section 4.12.3.2 of X3.159-1989 requires that
1669**	The ctime function converts the calendar time pointed to by timer
1670**	to local time in the form of a string. It is equivalent to
1671**		asctime(localtime(timer))
1672*/
1673	struct tm *rtm = localtime(timep);
1674	if (rtm == NULL)
1675		return NULL;
1676	return asctime(rtm);
1677}
1678
1679char *
1680ctime_r(const time_t *const timep, char *buf)
1681{
1682	struct tm	mytm, *rtm;
1683
1684	rtm = localtime_r(timep, &mytm);
1685	if (rtm == NULL)
1686		return NULL;
1687	return asctime_r(rtm, buf);
1688}
1689
1690char *
1691ctime_rz(const timezone_t sp, const time_t * timep, char *buf)
1692{
1693	struct tm	mytm, *rtm;
1694
1695	rtm = localtime_rz(sp, timep, &mytm);
1696	if (rtm == NULL)
1697		return NULL;
1698	return asctime_r(rtm, buf);
1699}
1700
1701/*
1702** Adapted from code provided by Robert Elz, who writes:
1703**	The "best" way to do mktime I think is based on an idea of Bob
1704**	Kridle's (so its said...) from a long time ago.
1705**	It does a binary search of the time_t space. Since time_t's are
1706**	just 32 bits, its a max of 32 iterations (even at 64 bits it
1707**	would still be very reasonable).
1708*/
1709
1710#ifndef WRONG
1711#define WRONG	((time_t)-1)
1712#endif /* !defined WRONG */
1713
1714/*
1715** Simplified normalize logic courtesy Paul Eggert.
1716*/
1717
1718static int
1719increment_overflow(int *ip, int j)
1720{
1721	int	i = *ip;
1722
1723	/*
1724	** If i >= 0 there can only be overflow if i + j > INT_MAX
1725	** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1726	** If i < 0 there can only be overflow if i + j < INT_MIN
1727	** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1728	*/
1729	if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1730		return TRUE;
1731	*ip += j;
1732	return FALSE;
1733}
1734
1735static int
1736long_increment_overflow(long *lp, int m)
1737{
1738	long l = *lp;
1739
1740	if ((l >= 0) ? (m > LONG_MAX - l) : (m < LONG_MIN - l))
1741		return TRUE;
1742	*lp += m;
1743	return FALSE;
1744}
1745
1746static int
1747normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
1748{
1749	int	tensdelta;
1750
1751	tensdelta = (*unitsptr >= 0) ?
1752		(*unitsptr / base) :
1753		(-1 - (-1 - *unitsptr) / base);
1754	*unitsptr -= tensdelta * base;
1755	return increment_overflow(tensptr, tensdelta);
1756}
1757
1758static int
1759long_normalize_overflow(long *const tensptr, int *const unitsptr,
1760    const int base)
1761{
1762	int	tensdelta;
1763
1764	tensdelta = (*unitsptr >= 0) ?
1765		(*unitsptr / base) :
1766		(-1 - (-1 - *unitsptr) / base);
1767	*unitsptr -= tensdelta * base;
1768	return long_increment_overflow(tensptr, tensdelta);
1769}
1770
1771static int
1772tmcomp(const struct tm *const atmp, const struct tm *const btmp)
1773{
1774	int	result;
1775
1776	if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1777		(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1778		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1779		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1780		(result = (atmp->tm_min - btmp->tm_min)) == 0)
1781			result = atmp->tm_sec - btmp->tm_sec;
1782	return result;
1783}
1784
1785static time_t
1786time2sub(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
1787    const long offset, int *const okayp, const int do_norm_secs)
1788{
1789	int			dir;
1790	int			i, j;
1791	int			saved_seconds;
1792	long			li;
1793	time_t			lo;
1794	time_t			hi;
1795#ifdef NO_ERROR_IN_DST_GAP
1796	time_t			ilo;
1797#endif
1798	long				y;
1799	time_t				newt;
1800	time_t				t;
1801	struct tm			yourtm, mytm;
1802
1803	*okayp = FALSE;
1804	yourtm = *tmp;
1805	if (do_norm_secs) {
1806		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
1807		    SECSPERMIN))
1808			goto overflow;
1809	}
1810	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1811		goto overflow;
1812	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1813		goto overflow;
1814	y = yourtm.tm_year;
1815	if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
1816		goto overflow;
1817	/*
1818	** Turn y into an actual year number for now.
1819	** It is converted back to an offset from TM_YEAR_BASE later.
1820	*/
1821	if (long_increment_overflow(&y, TM_YEAR_BASE))
1822		goto overflow;
1823	while (yourtm.tm_mday <= 0) {
1824		if (long_increment_overflow(&y, -1))
1825			goto overflow;
1826		li = y + (1 < yourtm.tm_mon);
1827		yourtm.tm_mday += year_lengths[isleap(li)];
1828	}
1829	while (yourtm.tm_mday > DAYSPERLYEAR) {
1830		li = y + (1 < yourtm.tm_mon);
1831		yourtm.tm_mday -= year_lengths[isleap(li)];
1832		if (long_increment_overflow(&y, 1))
1833			goto overflow;
1834	}
1835	for ( ; ; ) {
1836		i = mon_lengths[isleap(y)][yourtm.tm_mon];
1837		if (yourtm.tm_mday <= i)
1838			break;
1839		yourtm.tm_mday -= i;
1840		if (++yourtm.tm_mon >= MONSPERYEAR) {
1841			yourtm.tm_mon = 0;
1842			if (long_increment_overflow(&y, 1))
1843				goto overflow;
1844		}
1845	}
1846	if (long_increment_overflow(&y, -TM_YEAR_BASE))
1847		goto overflow;
1848	yourtm.tm_year = y;
1849	if (yourtm.tm_year != y)
1850		goto overflow;
1851	if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
1852		saved_seconds = 0;
1853	else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
1854		/*
1855		** We can't set tm_sec to 0, because that might push the
1856		** time below the minimum representable time.
1857		** Set tm_sec to 59 instead.
1858		** This assumes that the minimum representable time is
1859		** not in the same minute that a leap second was deleted from,
1860		** which is a safer assumption than using 58 would be.
1861		*/
1862		if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1863			goto overflow;
1864		saved_seconds = yourtm.tm_sec;
1865		yourtm.tm_sec = SECSPERMIN - 1;
1866	} else {
1867		saved_seconds = yourtm.tm_sec;
1868		yourtm.tm_sec = 0;
1869	}
1870	/*
1871	** Do a binary search (this works whatever time_t's type is).
1872	*/
1873/* LINTED constant */
1874	if (!TYPE_SIGNED(time_t)) {
1875		lo = 0;
1876		hi = lo - 1;
1877/* LINTED constant */
1878	} else if (!TYPE_INTEGRAL(time_t)) {
1879/* CONSTCOND */
1880		if (sizeof(time_t) > sizeof(float))
1881/* LINTED assumed double */
1882			hi = (time_t) DBL_MAX;
1883/* LINTED assumed float */
1884		else	hi = (time_t) FLT_MAX;
1885		lo = -hi;
1886	} else {
1887		lo = 1;
1888		for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
1889			lo *= 2;
1890		hi = -(lo + 1);
1891	}
1892#ifdef NO_ERROR_IN_DST_GAP
1893	ilo = lo;
1894#endif
1895	for ( ; ; ) {
1896		t = lo / 2 + hi / 2;
1897		if (t < lo)
1898			t = lo;
1899		else if (t > hi)
1900			t = hi;
1901		if ((*funcp)(sp, &t, offset, &mytm) == NULL) {
1902			/*
1903			** Assume that t is too extreme to be represented in
1904			** a struct tm; arrange things so that it is less
1905			** extreme on the next pass.
1906			*/
1907			dir = (t > 0) ? 1 : -1;
1908		} else	dir = tmcomp(&mytm, &yourtm);
1909		if (dir != 0) {
1910			if (t == lo) {
1911				++t;
1912				if (t <= lo)
1913					goto overflow;
1914				++lo;
1915			} else if (t == hi) {
1916				--t;
1917				if (t >= hi)
1918					goto overflow;
1919				--hi;
1920			}
1921#ifdef NO_ERROR_IN_DST_GAP
1922			if (ilo != lo && lo - 1 == hi && yourtm.tm_isdst < 0) {
1923				time_t off = 0;
1924				for (i = sp->typecnt - 1; i >= 0; --i) {
1925					for (j = sp->typecnt - 1; j >= 0; --j) {
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						break;
1932					}
1933					if (j >= 0)
1934						break;
1935				}
1936				if (off) {
1937					t = hi;
1938					break;
1939				}
1940			}
1941#endif
1942			if (lo > hi)
1943				goto invalid;
1944			if (dir > 0)
1945				hi = t;
1946			else	lo = t;
1947			continue;
1948		}
1949		if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1950			break;
1951		/*
1952		** Right time, wrong type.
1953		** Hunt for right time, right type.
1954		** It's okay to guess wrong since the guess
1955		** gets checked.
1956		*/
1957		if (sp == NULL)
1958			goto invalid;
1959		for (i = sp->typecnt - 1; i >= 0; --i) {
1960			if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1961				continue;
1962			for (j = sp->typecnt - 1; j >= 0; --j) {
1963				if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1964					continue;
1965				newt = t + sp->ttis[j].tt_gmtoff -
1966					sp->ttis[i].tt_gmtoff;
1967				if ((*funcp)(sp, &newt, offset, &mytm) == NULL)
1968					continue;
1969				if (tmcomp(&mytm, &yourtm) != 0)
1970					continue;
1971				if (mytm.tm_isdst != yourtm.tm_isdst)
1972					continue;
1973				/*
1974				** We have a match.
1975				*/
1976				t = newt;
1977				goto label;
1978			}
1979		}
1980		goto invalid;
1981	}
1982label:
1983	newt = t + saved_seconds;
1984	if ((newt < t) != (saved_seconds < 0))
1985		goto overflow;
1986	t = newt;
1987	if ((*funcp)(sp, &t, offset, tmp)) {
1988		*okayp = TRUE;
1989		return t;
1990	}
1991overflow:
1992	errno = EOVERFLOW;
1993	return WRONG;
1994invalid:
1995	errno = EINVAL;
1996	return WRONG;
1997}
1998
1999static time_t
2000time2(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
2001    const long offset, int *const okayp)
2002{
2003	time_t	t;
2004
2005	/*
2006	** First try without normalization of seconds
2007	** (in case tm_sec contains a value associated with a leap second).
2008	** If that fails, try with normalization of seconds.
2009	*/
2010	t = time2sub(sp, tmp, funcp, offset, okayp, FALSE);
2011	return *okayp ? t : time2sub(sp, tmp, funcp, offset, okayp, TRUE);
2012}
2013
2014static time_t
2015time1(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
2016    long offset)
2017{
2018	time_t			t;
2019	int			samei, otheri;
2020	int			sameind, otherind;
2021	int			i;
2022	int			nseen;
2023	int				seen[TZ_MAX_TYPES];
2024	int				types[TZ_MAX_TYPES];
2025	int				okay;
2026
2027	if (tmp == NULL) {
2028		errno = EINVAL;
2029		return WRONG;
2030	}
2031	if (tmp->tm_isdst > 1)
2032		tmp->tm_isdst = 1;
2033	t = time2(sp, tmp, funcp, offset, &okay);
2034#ifdef PCTS
2035	/*
2036	** PCTS code courtesy Grant Sullivan.
2037	*/
2038	if (okay)
2039		return t;
2040	if (tmp->tm_isdst < 0)
2041		tmp->tm_isdst = 0;	/* reset to std and try again */
2042#endif /* defined PCTS */
2043#ifndef PCTS
2044	if (okay || tmp->tm_isdst < 0)
2045		return t;
2046#endif /* !defined PCTS */
2047	/*
2048	** We're supposed to assume that somebody took a time of one type
2049	** and did some math on it that yielded a "struct tm" that's bad.
2050	** We try to divine the type they started from and adjust to the
2051	** type they need.
2052	*/
2053	if (sp == NULL) {
2054		errno = EINVAL;
2055		return WRONG;
2056	}
2057	for (i = 0; i < sp->typecnt; ++i)
2058		seen[i] = FALSE;
2059	nseen = 0;
2060	for (i = sp->timecnt - 1; i >= 0; --i)
2061		if (!seen[sp->types[i]]) {
2062			seen[sp->types[i]] = TRUE;
2063			types[nseen++] = sp->types[i];
2064		}
2065	for (sameind = 0; sameind < nseen; ++sameind) {
2066		samei = types[sameind];
2067		if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2068			continue;
2069		for (otherind = 0; otherind < nseen; ++otherind) {
2070			otheri = types[otherind];
2071			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2072				continue;
2073			tmp->tm_sec += (int)(sp->ttis[otheri].tt_gmtoff -
2074					sp->ttis[samei].tt_gmtoff);
2075			tmp->tm_isdst = !tmp->tm_isdst;
2076			t = time2(sp, tmp, funcp, offset, &okay);
2077			if (okay)
2078				return t;
2079			tmp->tm_sec -= (int)(sp->ttis[otheri].tt_gmtoff -
2080					sp->ttis[samei].tt_gmtoff);
2081			tmp->tm_isdst = !tmp->tm_isdst;
2082		}
2083	}
2084	errno = EOVERFLOW;
2085	return WRONG;
2086}
2087
2088time_t
2089mktime_z(const timezone_t sp, struct tm *tmp)
2090{
2091	time_t t;
2092	if (sp == NULL)
2093		t = time1(NULL, tmp, gmtsub, 0L);
2094	else
2095		t = time1(sp, tmp, localsub, 0L);
2096	return t;
2097}
2098
2099time_t
2100mktime(struct tm * const	tmp)
2101{
2102	time_t result;
2103
2104	rwlock_wrlock(&lcl_lock);
2105	tzset_unlocked();
2106	result = mktime_z(lclptr, tmp);
2107	rwlock_unlock(&lcl_lock);
2108	return result;
2109}
2110
2111#ifdef STD_INSPIRED
2112
2113time_t
2114timelocal_z(const timezone_t sp, struct tm *tmp)
2115{
2116	if (tmp != NULL)
2117		tmp->tm_isdst = -1;	/* in case it wasn't initialized */
2118	return mktime_z(sp, tmp);
2119}
2120
2121time_t
2122timelocal(struct tm *const tmp)
2123{
2124	if (tmp != NULL)
2125		tmp->tm_isdst = -1;	/* in case it wasn't initialized */
2126	return mktime(tmp);
2127}
2128
2129time_t
2130timegm(struct tm *const tmp)
2131{
2132	time_t t;
2133
2134	if (tmp != NULL)
2135		tmp->tm_isdst = 0;
2136	t = time1(gmtptr, tmp, gmtsub, 0L);
2137	if (t == WRONG)
2138		errno = EOVERFLOW;
2139	return t;
2140}
2141
2142time_t
2143timeoff(struct tm *const tmp, const long offset)
2144{
2145	time_t t;
2146
2147	if (tmp != NULL)
2148		tmp->tm_isdst = 0;
2149	t = time1(gmtptr, tmp, gmtsub, offset);
2150	if (t == WRONG)
2151		errno = EOVERFLOW;
2152	return t;
2153}
2154
2155#endif /* defined STD_INSPIRED */
2156
2157#ifdef CMUCS
2158
2159/*
2160** The following is supplied for compatibility with
2161** previous versions of the CMUCS runtime library.
2162*/
2163
2164long
2165gtime(struct tm *const tmp)
2166{
2167	const time_t t = mktime(tmp);
2168
2169	if (t == WRONG)
2170		return -1;
2171	return t;
2172}
2173
2174#endif /* defined CMUCS */
2175
2176/*
2177** XXX--is the below the right way to conditionalize??
2178*/
2179
2180#ifdef STD_INSPIRED
2181
2182/*
2183** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2184** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2185** is not the case if we are accounting for leap seconds.
2186** So, we provide the following conversion routines for use
2187** when exchanging timestamps with POSIX conforming systems.
2188*/
2189
2190static long
2191leapcorr(const timezone_t sp, time_t *timep)
2192{
2193	struct lsinfo * lp;
2194	int		i;
2195
2196	i = sp->leapcnt;
2197	while (--i >= 0) {
2198		lp = &sp->lsis[i];
2199		if (*timep >= lp->ls_trans)
2200			return lp->ls_corr;
2201	}
2202	return 0;
2203}
2204
2205time_t
2206time2posix_z(const timezone_t sp, time_t t)
2207{
2208	return t - leapcorr(sp, &t);
2209}
2210
2211time_t
2212time2posix(time_t t)
2213{
2214	time_t result;
2215	rwlock_wrlock(&lcl_lock);
2216	tzset_unlocked();
2217	result = t - leapcorr(lclptr, &t);
2218	rwlock_unlock(&lcl_lock);
2219	return (result);
2220}
2221
2222time_t
2223posix2time_z(const timezone_t sp, time_t t)
2224{
2225	time_t	x;
2226	time_t	y;
2227
2228	/*
2229	** For a positive leap second hit, the result
2230	** is not unique. For a negative leap second
2231	** hit, the corresponding time doesn't exist,
2232	** so we return an adjacent second.
2233	*/
2234	x = t + leapcorr(sp, &t);
2235	y = x - leapcorr(sp, &x);
2236	if (y < t) {
2237		do {
2238			x++;
2239			y = x - leapcorr(sp, &x);
2240		} while (y < t);
2241		if (t != y) {
2242			return x - 1;
2243		}
2244	} else if (y > t) {
2245		do {
2246			--x;
2247			y = x - leapcorr(sp, &x);
2248		} while (y > t);
2249		if (t != y) {
2250			return x + 1;
2251		}
2252	}
2253	return x;
2254}
2255
2256
2257
2258time_t
2259posix2time(time_t t)
2260{
2261	time_t result;
2262
2263	rwlock_wrlock(&lcl_lock);
2264	tzset_unlocked();
2265	result = posix2time_z(lclptr, t);
2266	rwlock_unlock(&lcl_lock);
2267	return result;
2268}
2269
2270#endif /* defined STD_INSPIRED */
2271