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