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