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