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