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