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