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