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