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