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