xref: /csrg-svn/lib/libc/gen/ctime.c (revision 39720)
1 /*
2  * Copyright (c) 1987, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Arthur Olson.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #if defined(LIBC_SCCS) && !defined(lint)
22 static char sccsid[] = "@(#)ctime.c	5.19 (Berkeley) 12/14/89";
23 #endif /* LIBC_SCCS and not lint */
24 
25 /*
26 ** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
27 ** POSIX-style TZ environment variable handling from Guy Harris
28 ** (guy@auspex.com).
29 */
30 
31 /*LINTLIBRARY*/
32 
33 #include <sys/param.h>
34 #include <fcntl.h>
35 #include <time.h>
36 #include <tzfile.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <stdio.h>
40 
41 #ifdef __STDC__
42 #include <stdlib.h>
43 
44 #define P(s)		s
45 #define alloc_size_t	size_t
46 #define qsort_size_t	size_t
47 #define fread_size_t	size_t
48 #define fwrite_size_t	size_t
49 
50 #else /* !defined __STDC__ */
51 
52 #define P(s)		()
53 #define const
54 #define volatile
55 
56 typedef char *		genericptr_t;
57 typedef unsigned	alloc_size_t;
58 typedef int		qsort_size_t;
59 typedef int		fread_size_t;
60 typedef int		fwrite_size_t;
61 
62 extern char *	calloc();
63 extern char *	malloc();
64 extern char *	realloc();
65 extern char *	getenv();
66 
67 #endif /* !defined __STDC__ */
68 
69 extern time_t	time();
70 
71 #define FILENAME_MAX	MAXPATHLEN
72 #define ACCESS_MODE	O_RDONLY
73 #define OPEN_MODE	O_RDONLY
74 
75 #ifndef WILDABBR
76 /*
77 ** Someone might make incorrect use of a time zone abbreviation:
78 **	1.	They might reference tzname[0] before calling tzset (explicitly
79 **	 	or implicitly).
80 **	2.	They might reference tzname[1] before calling tzset (explicitly
81 **	 	or implicitly).
82 **	3.	They might reference tzname[1] after setting to a time zone
83 **		in which Daylight Saving Time is never observed.
84 **	4.	They might reference tzname[0] after setting to a time zone
85 **		in which Standard Time is never observed.
86 **	5.	They might reference tm.TM_ZONE after calling offtime.
87 ** What's best to do in the above cases is open to debate;
88 ** for now, we just set things up so that in any of the five cases
89 ** WILDABBR is used.  Another possibility:  initialize tzname[0] to the
90 ** string "tzname[0] used before set", and similarly for the other cases.
91 ** And another:  initialize tzname[0] to "ERA", with an explanation in the
92 ** manual page of what this "time zone abbreviation" means (doing this so
93 ** that tzname[0] has the "normal" length of three characters).
94 */
95 #define WILDABBR	"   "
96 #endif /* !defined WILDABBR */
97 
98 #ifndef TRUE
99 #define TRUE		1
100 #define FALSE		0
101 #endif /* !defined TRUE */
102 
103 static const char GMT[] = "GMT";
104 
105 struct ttinfo {				/* time type information */
106 	long		tt_gmtoff;	/* GMT offset in seconds */
107 	int		tt_isdst;	/* used to set tm_isdst */
108 	int		tt_abbrind;	/* abbreviation list index */
109 	int		tt_ttisstd;	/* TRUE if transition is std time */
110 };
111 
112 struct lsinfo {				/* leap second information */
113 	time_t		ls_trans;	/* transition time */
114 	long		ls_corr;	/* correction to apply */
115 };
116 
117 struct state {
118 	int		leapcnt;
119 	int		timecnt;
120 	int		typecnt;
121 	int		charcnt;
122 	time_t		ats[TZ_MAX_TIMES];
123 	unsigned char	types[TZ_MAX_TIMES];
124 	struct ttinfo	ttis[TZ_MAX_TYPES];
125 	char		chars[(TZ_MAX_CHARS + 1 > sizeof GMT) ?
126 				TZ_MAX_CHARS + 1 : sizeof GMT];
127 	struct lsinfo	lsis[TZ_MAX_LEAPS];
128 };
129 
130 struct rule {
131 	int		r_type;		/* type of rule--see below */
132 	int		r_day;		/* day number of rule */
133 	int		r_week;		/* week number of rule */
134 	int		r_mon;		/* month number of rule */
135 	long		r_time;		/* transition time of rule */
136 };
137 
138 #define	JULIAN_DAY		0	/* Jn - Julian day */
139 #define	DAY_OF_YEAR		1	/* n - day of year */
140 #define	MONTH_NTH_DAY_OF_WEEK	2	/* Mm.n.d - month, week, day of week */
141 
142 /*
143 ** Prototypes for static functions.
144 */
145 
146 static long		detzcode P((const char * codep));
147 static const char *	getzname P((const char * strp));
148 static const char *	getnum P((const char * strp, int * nump, int min,
149 				int max));
150 static const char *	getsecs P((const char * strp, long * secsp));
151 static const char *	getoffset P((const char * strp, long * offsetp));
152 static const char *	getrule P((const char * strp, struct rule * rulep));
153 static void		gmtload P((struct state * sp));
154 static void		gmtsub P((const time_t * timep, long offset,
155 				struct tm * tmp));
156 static void		localsub P((const time_t * timep, long offset,
157 				struct tm * tmp));
158 static void		normalize P((int * tensptr, int * unitsptr, int base));
159 static void		settzname P((void));
160 static time_t		time1 P((struct tm * tmp, void (* funcp)(),
161 				long offset));
162 static time_t		time2 P((struct tm *tmp, void (* funcp)(),
163 				long offset, int * okayp));
164 static void		timesub P((const time_t * timep, long offset,
165 				const struct state * sp, struct tm * tmp));
166 static int		tmcomp P((const struct tm * atmp,
167 				const struct tm * btmp));
168 static time_t		transtime P((time_t janfirst, int year,
169 				const struct rule * rulep, long offset));
170 static int		tzload P((const char * name, struct state * sp));
171 static int		tzparse P((const char * name, struct state * sp,
172 				int lastditch));
173 
174 #ifdef ALL_STATE
175 static struct state *	lclptr;
176 static struct state *	gmtptr;
177 #endif /* defined ALL_STATE */
178 
179 #ifndef ALL_STATE
180 static struct state	lclmem;
181 static struct state	gmtmem;
182 #define lclptr		(&lclmem)
183 #define gmtptr		(&gmtmem)
184 #endif /* State Farm */
185 
186 static int		lcl_is_set;
187 static int		gmt_is_set;
188 
189 char *			tzname[2] = {
190 	WILDABBR,
191 	WILDABBR
192 };
193 
194 #ifdef USG_COMPAT
195 time_t			timezone = 0;
196 int			daylight = 0;
197 #endif /* defined USG_COMPAT */
198 
199 #ifdef ALTZONE
200 time_t			altzone = 0;
201 #endif /* defined ALTZONE */
202 
203 static long
204 detzcode(codep)
205 const char * const	codep;
206 {
207 	register long	result;
208 	register int	i;
209 
210 	result = 0;
211 	for (i = 0; i < 4; ++i)
212 		result = (result << 8) | (codep[i] & 0xff);
213 	return result;
214 }
215 
216 static void
217 settzname()
218 {
219 	register const struct state * const	sp = lclptr;
220 	register int				i;
221 
222 	tzname[0] = WILDABBR;
223 	tzname[1] = WILDABBR;
224 #ifdef USG_COMPAT
225 	daylight = 0;
226 	timezone = 0;
227 #endif /* defined USG_COMPAT */
228 #ifdef ALTZONE
229 	altzone = 0;
230 #endif /* defined ALTZONE */
231 #ifdef ALL_STATE
232 	if (sp == NULL) {
233 		tzname[0] = tzname[1] = GMT;
234 		return;
235 	}
236 #endif /* defined ALL_STATE */
237 	for (i = 0; i < sp->typecnt; ++i) {
238 		register const struct ttinfo * const	ttisp = &sp->ttis[i];
239 
240 		tzname[ttisp->tt_isdst] =
241 			(char *) &sp->chars[ttisp->tt_abbrind];
242 #ifdef USG_COMPAT
243 		if (ttisp->tt_isdst)
244 			daylight = 1;
245 		if (i == 0 || !ttisp->tt_isdst)
246 			timezone = -(ttisp->tt_gmtoff);
247 #endif /* defined USG_COMPAT */
248 #ifdef ALTZONE
249 		if (i == 0 || ttisp->tt_isdst)
250 			altzone = -(ttisp->tt_gmtoff);
251 #endif /* defined ALTZONE */
252 	}
253 	/*
254 	** And to get the latest zone names into tzname. . .
255 	*/
256 	for (i = 0; i < sp->timecnt; ++i) {
257 		register const struct ttinfo * const	ttisp =
258 							&sp->ttis[sp->types[i]];
259 
260 		tzname[ttisp->tt_isdst] =
261 			(char *) &sp->chars[ttisp->tt_abbrind];
262 	}
263 }
264 
265 static int
266 tzload(name, sp)
267 register const char *		name;
268 register struct state * const	sp;
269 {
270 	register const char *	p;
271 	register int		i;
272 	register int		fid;
273 
274 	if (name == NULL && (name = TZDEFAULT) == NULL)
275 		return -1;
276 	{
277 		register int 	doaccess;
278 		char		fullname[FILENAME_MAX + 1];
279 
280 		if (name[0] == ':')
281 			++name;
282 		doaccess = name[0] == '/';
283 		if (!doaccess) {
284 			if ((p = TZDIR) == NULL)
285 				return -1;
286 			if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
287 				return -1;
288 			(void) strcpy(fullname, p);
289 			(void) strcat(fullname, "/");
290 			(void) strcat(fullname, name);
291 			/*
292 			** Set doaccess if '.' (as in "../") shows up in name.
293 			*/
294 			if (strchr(name, '.') != NULL)
295 				doaccess = TRUE;
296 			name = fullname;
297 		}
298 		if (doaccess && access(name, ACCESS_MODE) != 0)
299 			return -1;
300 		if ((fid = open(name, OPEN_MODE)) == -1)
301 			return -1;
302 	}
303 	{
304 		register const struct tzhead *	tzhp;
305 		char				buf[sizeof *sp + sizeof *tzhp];
306 		int				ttisstdcnt;
307 
308 		i = read(fid, buf, sizeof buf);
309 		if (close(fid) != 0 || i < sizeof *tzhp)
310 			return -1;
311 		tzhp = (struct tzhead *) buf;
312 		ttisstdcnt = (int) detzcode(tzhp->tzh_ttisstdcnt);
313 		sp->leapcnt = (int) detzcode(tzhp->tzh_leapcnt);
314 		sp->timecnt = (int) detzcode(tzhp->tzh_timecnt);
315 		sp->typecnt = (int) detzcode(tzhp->tzh_typecnt);
316 		sp->charcnt = (int) detzcode(tzhp->tzh_charcnt);
317 		if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
318 			sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
319 			sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
320 			sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
321 			(ttisstdcnt != sp->typecnt && ttisstdcnt != 0))
322 				return -1;
323 		if (i < sizeof *tzhp +
324 			sp->timecnt * (4 + sizeof (char)) +
325 			sp->typecnt * (4 + 2 * sizeof (char)) +
326 			sp->charcnt * sizeof (char) +
327 			sp->leapcnt * 2 * 4 +
328 			ttisstdcnt * sizeof (char))
329 				return -1;
330 		p = buf + sizeof *tzhp;
331 		for (i = 0; i < sp->timecnt; ++i) {
332 			sp->ats[i] = detzcode(p);
333 			p += 4;
334 		}
335 		for (i = 0; i < sp->timecnt; ++i) {
336 			sp->types[i] = (unsigned char) *p++;
337 			if (sp->types[i] >= sp->typecnt)
338 				return -1;
339 		}
340 		for (i = 0; i < sp->typecnt; ++i) {
341 			register struct ttinfo *	ttisp;
342 
343 			ttisp = &sp->ttis[i];
344 			ttisp->tt_gmtoff = detzcode(p);
345 			p += 4;
346 			ttisp->tt_isdst = (unsigned char) *p++;
347 			if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
348 				return -1;
349 			ttisp->tt_abbrind = (unsigned char) *p++;
350 			if (ttisp->tt_abbrind < 0 ||
351 				ttisp->tt_abbrind > sp->charcnt)
352 					return -1;
353 		}
354 		for (i = 0; i < sp->charcnt; ++i)
355 			sp->chars[i] = *p++;
356 		sp->chars[i] = '\0';	/* ensure '\0' at end */
357 		for (i = 0; i < sp->leapcnt; ++i) {
358 			register struct lsinfo *	lsisp;
359 
360 			lsisp = &sp->lsis[i];
361 			lsisp->ls_trans = detzcode(p);
362 			p += 4;
363 			lsisp->ls_corr = detzcode(p);
364 			p += 4;
365 		}
366 		for (i = 0; i < sp->typecnt; ++i) {
367 			register struct ttinfo *	ttisp;
368 
369 			ttisp = &sp->ttis[i];
370 			if (ttisstdcnt == 0)
371 				ttisp->tt_ttisstd = FALSE;
372 			else {
373 				ttisp->tt_ttisstd = *p++;
374 				if (ttisp->tt_ttisstd != TRUE &&
375 					ttisp->tt_ttisstd != FALSE)
376 						return -1;
377 			}
378 		}
379 	}
380 	return 0;
381 }
382 
383 static const int	mon_lengths[2][MONSPERYEAR] = {
384 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
385 	31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
386 };
387 
388 static const int	year_lengths[2] = {
389 	DAYSPERNYEAR, DAYSPERLYEAR
390 };
391 
392 /*
393 ** Given a pointer into a time zone string, scan until a character that is not
394 ** a valid character in a zone name is found.  Return a pointer to that
395 ** character.
396 */
397 
398 static const char *
399 getzname(strp)
400 register const char *	strp;
401 {
402 	register char	c;
403 
404 	while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' &&
405 		c != '+')
406 			++strp;
407 	return strp;
408 }
409 
410 /*
411 ** Given a pointer into a time zone string, extract a number from that string.
412 ** Check that the number is within a specified range; if it is not, return
413 ** NULL.
414 ** Otherwise, return a pointer to the first character not part of the number.
415 */
416 
417 static const char *
418 getnum(strp, nump, min, max)
419 register const char *	strp;
420 int * const		nump;
421 const int		min;
422 const int		max;
423 {
424 	register char	c;
425 	register int	num;
426 
427 	if (strp == NULL || !isdigit(*strp))
428 		return NULL;
429 	num = 0;
430 	while ((c = *strp) != '\0' && isdigit(c)) {
431 		num = num * 10 + (c - '0');
432 		if (num > max)
433 			return NULL;	/* illegal value */
434 		++strp;
435 	}
436 	if (num < min)
437 		return NULL;		/* illegal value */
438 	*nump = num;
439 	return strp;
440 }
441 
442 /*
443 ** Given a pointer into a time zone string, extract a number of seconds,
444 ** in hh[:mm[:ss]] form, from the string.
445 ** If any error occurs, return NULL.
446 ** Otherwise, return a pointer to the first character not part of the number
447 ** of seconds.
448 */
449 
450 static const char *
451 getsecs(strp, secsp)
452 register const char *	strp;
453 long * const		secsp;
454 {
455 	int	num;
456 
457 	strp = getnum(strp, &num, 0, HOURSPERDAY);
458 	if (strp == NULL)
459 		return NULL;
460 	*secsp = num * SECSPERHOUR;
461 	if (*strp == ':') {
462 		++strp;
463 		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
464 		if (strp == NULL)
465 			return NULL;
466 		*secsp += num * SECSPERMIN;
467 		if (*strp == ':') {
468 			++strp;
469 			strp = getnum(strp, &num, 0, SECSPERMIN - 1);
470 			if (strp == NULL)
471 				return NULL;
472 			*secsp += num;
473 		}
474 	}
475 	return strp;
476 }
477 
478 /*
479 ** Given a pointer into a time zone string, extract an offset, in
480 ** [+-]hh[:mm[:ss]] form, from the string.
481 ** If any error occurs, return NULL.
482 ** Otherwise, return a pointer to the first character not part of the time.
483 */
484 
485 static const char *
486 getoffset(strp, offsetp)
487 register const char *	strp;
488 long * const		offsetp;
489 {
490 	register int	neg;
491 
492 	if (*strp == '-') {
493 		neg = 1;
494 		++strp;
495 	} else if (isdigit(*strp) || *strp++ == '+')
496 		neg = 0;
497 	else	return NULL;		/* illegal offset */
498 	strp = getsecs(strp, offsetp);
499 	if (strp == NULL)
500 		return NULL;		/* illegal time */
501 	if (neg)
502 		*offsetp = -*offsetp;
503 	return strp;
504 }
505 
506 /*
507 ** Given a pointer into a time zone string, extract a rule in the form
508 ** date[/time].  See POSIX section 8 for the format of "date" and "time".
509 ** If a valid rule is not found, return NULL.
510 ** Otherwise, return a pointer to the first character not part of the rule.
511 */
512 
513 static const char *
514 getrule(strp, rulep)
515 const char *			strp;
516 register struct rule * const	rulep;
517 {
518 	if (*strp == 'J') {
519 		/*
520 		** Julian day.
521 		*/
522 		rulep->r_type = JULIAN_DAY;
523 		++strp;
524 		strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
525 	} else if (*strp == 'M') {
526 		/*
527 		** Month, week, day.
528 		*/
529 		rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
530 		++strp;
531 		strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
532 		if (strp == NULL)
533 			return NULL;
534 		if (*strp++ != '.')
535 			return NULL;
536 		strp = getnum(strp, &rulep->r_week, 1, 5);
537 		if (strp == NULL)
538 			return NULL;
539 		if (*strp++ != '.')
540 			return NULL;
541 		strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
542 	} else if (isdigit(*strp)) {
543 		/*
544 		** Day of year.
545 		*/
546 		rulep->r_type = DAY_OF_YEAR;
547 		strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
548 	} else	return NULL;		/* invalid format */
549 	if (strp == NULL)
550 		return NULL;
551 	if (*strp == '/') {
552 		/*
553 		** Time specified.
554 		*/
555 		++strp;
556 		strp = getsecs(strp, &rulep->r_time);
557 	} else	rulep->r_time = 2 * SECSPERHOUR;	/* default = 2:00:00 */
558 	return strp;
559 }
560 
561 /*
562 ** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the
563 ** year, a rule, and the offset from GMT at the time that rule takes effect,
564 ** calculate the Epoch-relative time that rule takes effect.
565 */
566 
567 static time_t
568 transtime(janfirst, year, rulep, offset)
569 const time_t				janfirst;
570 const int				year;
571 register const struct rule * const	rulep;
572 const long				offset;
573 {
574 	register int	leapyear;
575 	register time_t	value;
576 	register int	i;
577 	int		d, m1, yy0, yy1, yy2, dow;
578 
579 	leapyear = isleap(year);
580 	switch (rulep->r_type) {
581 
582 	case JULIAN_DAY:
583 		/*
584 		** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
585 		** years.
586 		** In non-leap years, or if the day number is 59 or less, just
587 		** add SECSPERDAY times the day number-1 to the time of
588 		** January 1, midnight, to get the day.
589 		*/
590 		value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
591 		if (leapyear && rulep->r_day >= 60)
592 			value += SECSPERDAY;
593 		break;
594 
595 	case DAY_OF_YEAR:
596 		/*
597 		** n - day of year.
598 		** Just add SECSPERDAY times the day number to the time of
599 		** January 1, midnight, to get the day.
600 		*/
601 		value = janfirst + rulep->r_day * SECSPERDAY;
602 		break;
603 
604 	case MONTH_NTH_DAY_OF_WEEK:
605 		/*
606 		** Mm.n.d - nth "dth day" of month m.
607 		*/
608 		value = janfirst;
609 		for (i = 0; i < rulep->r_mon - 1; ++i)
610 			value += mon_lengths[leapyear][i] * SECSPERDAY;
611 
612 		/*
613 		** Use Zeller's Congruence to get day-of-week of first day of
614 		** month.
615 		*/
616 		m1 = (rulep->r_mon + 9) % 12 + 1;
617 		yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
618 		yy1 = yy0 / 100;
619 		yy2 = yy0 % 100;
620 		dow = ((26 * m1 - 2) / 10 +
621 			1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
622 		if (dow < 0)
623 			dow += DAYSPERWEEK;
624 
625 		/*
626 		** "dow" is the day-of-week of the first day of the month.  Get
627 		** the day-of-month (zero-origin) of the first "dow" day of the
628 		** month.
629 		*/
630 		d = rulep->r_day - dow;
631 		if (d < 0)
632 			d += DAYSPERWEEK;
633 		for (i = 1; i < rulep->r_week; ++i) {
634 			if (d + DAYSPERWEEK >=
635 				mon_lengths[leapyear][rulep->r_mon - 1])
636 					break;
637 			d += DAYSPERWEEK;
638 		}
639 
640 		/*
641 		** "d" is the day-of-month (zero-origin) of the day we want.
642 		*/
643 		value += d * SECSPERDAY;
644 		break;
645 	}
646 
647 	/*
648 	** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
649 	** question.  To get the Epoch-relative time of the specified local
650 	** time on that day, add the transition time and the current offset
651 	** from GMT.
652 	*/
653 	return value + rulep->r_time + offset;
654 }
655 
656 /*
657 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
658 ** appropriate.
659 */
660 
661 static int
662 tzparse(name, sp, lastditch)
663 const char *			name;
664 register struct state * const	sp;
665 const int			lastditch;
666 {
667 	const char *			stdname;
668 	const char *			dstname;
669 	int				stdlen;
670 	int				dstlen;
671 	long				stdoffset;
672 	long				dstoffset;
673 	register time_t *		atp;
674 	register unsigned char *	typep;
675 	register char *			cp;
676 	register int			load_result;
677 
678 	stdname = name;
679 	if (lastditch) {
680 		stdlen = strlen(name);	/* length of standard zone name */
681 		name += stdlen;
682 		if (stdlen >= sizeof sp->chars)
683 			stdlen = (sizeof sp->chars) - 1;
684 	} else {
685 		name = getzname(name);
686 		stdlen = name - stdname;
687 		if (stdlen < 3)
688 			return -1;
689 	}
690 	if (*name == '\0')
691 		return -1;
692 	else {
693 		name = getoffset(name, &stdoffset);
694 		if (name == NULL)
695 			return -1;
696 	}
697 	load_result = tzload(TZDEFRULES, sp);
698 	if (load_result != 0)
699 		sp->leapcnt = 0;		/* so, we're off a little */
700 	if (*name != '\0') {
701 		dstname = name;
702 		name = getzname(name);
703 		dstlen = name - dstname;	/* length of DST zone name */
704 		if (dstlen < 3)
705 			return -1;
706 		if (*name != '\0' && *name != ',' && *name != ';') {
707 			name = getoffset(name, &dstoffset);
708 			if (name == NULL)
709 				return -1;
710 		} else	dstoffset = stdoffset - SECSPERHOUR;
711 		if (*name == ',' || *name == ';') {
712 			struct rule	start;
713 			struct rule	end;
714 			register int	year;
715 			register time_t	janfirst;
716 			time_t		starttime;
717 			time_t		endtime;
718 
719 			++name;
720 			if ((name = getrule(name, &start)) == NULL)
721 				return -1;
722 			if (*name++ != ',')
723 				return -1;
724 			if ((name = getrule(name, &end)) == NULL)
725 				return -1;
726 			if (*name != '\0')
727 				return -1;
728 			sp->typecnt = 2;	/* standard time and DST */
729 			/*
730 			** Two transitions per year, from EPOCH_YEAR to 2037.
731 			*/
732 			sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
733 			if (sp->timecnt > TZ_MAX_TIMES)
734 				return -1;
735 			sp->ttis[0].tt_gmtoff = -dstoffset;
736 			sp->ttis[0].tt_isdst = 1;
737 			sp->ttis[0].tt_abbrind = stdlen + 1;
738 			sp->ttis[1].tt_gmtoff = -stdoffset;
739 			sp->ttis[1].tt_isdst = 0;
740 			sp->ttis[1].tt_abbrind = 0;
741 			atp = sp->ats;
742 			typep = sp->types;
743 			janfirst = 0;
744 			for (year = EPOCH_YEAR; year <= 2037; ++year) {
745 				starttime = transtime(janfirst, year, &start,
746 					stdoffset);
747 				endtime = transtime(janfirst, year, &end,
748 					dstoffset);
749 				if (starttime > endtime) {
750 					*atp++ = endtime;
751 					*typep++ = 1;	/* DST ends */
752 					*atp++ = starttime;
753 					*typep++ = 0;	/* DST begins */
754 				} else {
755 					*atp++ = starttime;
756 					*typep++ = 0;	/* DST begins */
757 					*atp++ = endtime;
758 					*typep++ = 1;	/* DST ends */
759 				}
760 				janfirst +=
761 					year_lengths[isleap(year)] * SECSPERDAY;
762 			}
763 		} else {
764 			int		sawstd;
765 			int		sawdst;
766 			long		stdfix;
767 			long		dstfix;
768 			long		oldfix;
769 			int		isdst;
770 			register int	i;
771 
772 			if (*name != '\0')
773 				return -1;
774 			if (load_result != 0)
775 				return -1;
776 			/*
777 			** Compute the difference between the real and
778 			** prototype standard and summer time offsets
779 			** from GMT, and put the real standard and summer
780 			** time offsets into the rules in place of the
781 			** prototype offsets.
782 			*/
783 			sawstd = FALSE;
784 			sawdst = FALSE;
785 			stdfix = 0;
786 			dstfix = 0;
787 			for (i = 0; i < sp->typecnt; ++i) {
788 				if (sp->ttis[i].tt_isdst) {
789 					oldfix = dstfix;
790 					dstfix =
791 					    sp->ttis[i].tt_gmtoff + dstoffset;
792 					if (sawdst && (oldfix != dstfix))
793 						return -1;
794 					sp->ttis[i].tt_gmtoff = -dstoffset;
795 					sp->ttis[i].tt_abbrind = stdlen + 1;
796 					sawdst = TRUE;
797 				} else {
798 					oldfix = stdfix;
799 					stdfix =
800 					    sp->ttis[i].tt_gmtoff + stdoffset;
801 					if (sawstd && (oldfix != stdfix))
802 						return -1;
803 					sp->ttis[i].tt_gmtoff = -stdoffset;
804 					sp->ttis[i].tt_abbrind = 0;
805 					sawstd = TRUE;
806 				}
807 			}
808 			/*
809 			** Make sure we have both standard and summer time.
810 			*/
811 			if (!sawdst || !sawstd)
812 				return -1;
813 			/*
814 			** Now correct the transition times by shifting
815 			** them by the difference between the real and
816 			** prototype offsets.  Note that this difference
817 			** can be different in standard and summer time;
818 			** the prototype probably has a 1-hour difference
819 			** between standard and summer time, but a different
820 			** difference can be specified in TZ.
821 			*/
822 			isdst = FALSE;	/* we start in standard time */
823 			for (i = 0; i < sp->timecnt; ++i) {
824 				register const struct ttinfo *	ttisp;
825 
826 				/*
827 				** If summer time is in effect, and the
828 				** transition time was not specified as
829 				** standard time, add the summer time
830 				** offset to the transition time;
831 				** otherwise, add the standard time offset
832 				** to the transition time.
833 				*/
834 				ttisp = &sp->ttis[sp->types[i]];
835 				sp->ats[i] +=
836 					(isdst && !ttisp->tt_ttisstd) ?
837 						dstfix : stdfix;
838 				isdst = ttisp->tt_isdst;
839 			}
840 		}
841 	} else {
842 		dstlen = 0;
843 		sp->typecnt = 1;		/* only standard time */
844 		sp->timecnt = 0;
845 		sp->ttis[0].tt_gmtoff = -stdoffset;
846 		sp->ttis[0].tt_isdst = 0;
847 		sp->ttis[0].tt_abbrind = 0;
848 	}
849 	sp->charcnt = stdlen + 1;
850 	if (dstlen != 0)
851 		sp->charcnt += dstlen + 1;
852 	if (sp->charcnt > sizeof sp->chars)
853 		return -1;
854 	cp = sp->chars;
855 	(void) strncpy(cp, stdname, stdlen);
856 	cp += stdlen;
857 	*cp++ = '\0';
858 	if (dstlen != 0) {
859 		(void) strncpy(cp, dstname, dstlen);
860 		*(cp + dstlen) = '\0';
861 	}
862 	return 0;
863 }
864 
865 static void
866 gmtload(sp)
867 struct state * const	sp;
868 {
869 	if (tzload(GMT, sp) != 0)
870 		(void) tzparse(GMT, sp, TRUE);
871 }
872 
873 void
874 tzset()
875 {
876 	register const char *	name;
877 	void tzsetwall();
878 
879 	name = getenv("TZ");
880 	if (name == NULL) {
881 		tzsetwall();
882 		return;
883 	}
884 	lcl_is_set = TRUE;
885 #ifdef ALL_STATE
886 	if (lclptr == NULL) {
887 		lclptr = (struct state *) malloc(sizeof *lclptr);
888 		if (lclptr == NULL) {
889 			settzname();	/* all we can do */
890 			return;
891 		}
892 	}
893 #endif /* defined ALL_STATE */
894 	if (*name == '\0') {
895 		/*
896 		** User wants it fast rather than right.
897 		*/
898 		lclptr->leapcnt = 0;		/* so, we're off a little */
899 		lclptr->timecnt = 0;
900 		lclptr->ttis[0].tt_gmtoff = 0;
901 		lclptr->ttis[0].tt_abbrind = 0;
902 		(void) strcpy(lclptr->chars, GMT);
903 	} else if (tzload(name, lclptr) != 0)
904 		if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
905 			(void) gmtload(lclptr);
906 	settzname();
907 }
908 
909 void
910 tzsetwall()
911 {
912 	lcl_is_set = TRUE;
913 #ifdef ALL_STATE
914 	if (lclptr == NULL) {
915 		lclptr = (struct state *) malloc(sizeof *lclptr);
916 		if (lclptr == NULL) {
917 			settzname();	/* all we can do */
918 			return;
919 		}
920 	}
921 #endif /* defined ALL_STATE */
922 	if (tzload((char *) NULL, lclptr) != 0)
923 		gmtload(lclptr);
924 	settzname();
925 }
926 
927 /*
928 ** The easy way to behave "as if no library function calls" localtime
929 ** is to not call it--so we drop its guts into "localsub", which can be
930 ** freely called.  (And no, the PANS doesn't require the above behavior--
931 ** but it *is* desirable.)
932 **
933 ** The unused offset argument is for the benefit of mktime variants.
934 */
935 
936 /*ARGSUSED*/
937 static void
938 localsub(timep, offset, tmp)
939 const time_t * const	timep;
940 const long		offset;
941 struct tm * const	tmp;
942 {
943 	register const struct state *	sp;
944 	register const struct ttinfo *	ttisp;
945 	register int			i;
946 	const time_t			t = *timep;
947 
948 	if (!lcl_is_set)
949 		tzset();
950 	sp = lclptr;
951 #ifdef ALL_STATE
952 	if (sp == NULL) {
953 		gmtsub(timep, offset, tmp);
954 		return;
955 	}
956 #endif /* defined ALL_STATE */
957 	if (sp->timecnt == 0 || t < sp->ats[0]) {
958 		i = 0;
959 		while (sp->ttis[i].tt_isdst)
960 			if (++i >= sp->typecnt) {
961 				i = 0;
962 				break;
963 			}
964 	} else {
965 		for (i = 1; i < sp->timecnt; ++i)
966 			if (t < sp->ats[i])
967 				break;
968 		i = sp->types[i - 1];
969 	}
970 	ttisp = &sp->ttis[i];
971 	/*
972 	** To get (wrong) behavior that's compatible with System V Release 2.0
973 	** you'd replace the statement below with
974 	**	t += ttisp->tt_gmtoff;
975 	**	timesub(&t, 0L, sp, tmp);
976 	*/
977 	timesub(&t, ttisp->tt_gmtoff, sp, tmp);
978 	tmp->tm_isdst = ttisp->tt_isdst;
979 	tzname[tmp->tm_isdst] = (char *) &sp->chars[ttisp->tt_abbrind];
980 	tmp->tm_zone = &sp->chars[ttisp->tt_abbrind];
981 }
982 
983 struct tm *
984 localtime(timep)
985 const time_t * const	timep;
986 {
987 	static struct tm	tm;
988 
989 	localsub(timep, 0L, &tm);
990 	return &tm;
991 }
992 
993 /*
994 ** gmtsub is to gmtime as localsub is to localtime.
995 */
996 
997 static void
998 gmtsub(timep, offset, tmp)
999 const time_t * const	timep;
1000 const long		offset;
1001 struct tm * const	tmp;
1002 {
1003 	if (!gmt_is_set) {
1004 		gmt_is_set = TRUE;
1005 #ifdef ALL_STATE
1006 		gmtptr = (struct state *) malloc(sizeof *gmtptr);
1007 		if (gmtptr != NULL)
1008 #endif /* defined ALL_STATE */
1009 			gmtload(gmtptr);
1010 	}
1011 	timesub(timep, offset, gmtptr, tmp);
1012 	/*
1013 	** Could get fancy here and deliver something such as
1014 	** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero,
1015 	** but this is no time for a treasure hunt.
1016 	*/
1017 	if (offset != 0)
1018 		tmp->tm_zone = WILDABBR;
1019 	else {
1020 #ifdef ALL_STATE
1021 		if (gmtptr == NULL)
1022 			tmp->TM_ZONE = GMT;
1023 		else	tmp->TM_ZONE = gmtptr->chars;
1024 #endif /* defined ALL_STATE */
1025 #ifndef ALL_STATE
1026 		tmp->tm_zone = gmtptr->chars;
1027 #endif /* State Farm */
1028 	}
1029 }
1030 
1031 struct tm *
1032 gmtime(timep)
1033 const time_t * const	timep;
1034 {
1035 	static struct tm	tm;
1036 
1037 	gmtsub(timep, 0L, &tm);
1038 	return &tm;
1039 }
1040 
1041 static void
1042 timesub(timep, offset, sp, tmp)
1043 const time_t * const			timep;
1044 const long				offset;
1045 register const struct state * const	sp;
1046 register struct tm * const		tmp;
1047 {
1048 	register const struct lsinfo *	lp;
1049 	register long			days;
1050 	register long			rem;
1051 	register int			y;
1052 	register int			yleap;
1053 	register const int *		ip;
1054 	register long			corr;
1055 	register int			hit;
1056 	register int			i;
1057 
1058 	corr = 0;
1059 	hit = FALSE;
1060 #ifdef ALL_STATE
1061 	i = (sp == NULL) ? 0 : sp->leapcnt;
1062 #endif /* defined ALL_STATE */
1063 #ifndef ALL_STATE
1064 	i = sp->leapcnt;
1065 #endif /* State Farm */
1066 	while (--i >= 0) {
1067 		lp = &sp->lsis[i];
1068 		if (*timep >= lp->ls_trans) {
1069 			if (*timep == lp->ls_trans)
1070 				hit = ((i == 0 && lp->ls_corr > 0) ||
1071 					lp->ls_corr > sp->lsis[i - 1].ls_corr);
1072 			corr = lp->ls_corr;
1073 			break;
1074 		}
1075 	}
1076 	days = *timep / SECSPERDAY;
1077 	rem = *timep % SECSPERDAY;
1078 #ifdef mc68k
1079 	if (*timep == 0x80000000) {
1080 		/*
1081 		** A 3B1 muffs the division on the most negative number.
1082 		*/
1083 		days = -24855;
1084 		rem = -11648;
1085 	}
1086 #endif /* mc68k */
1087 	rem += (offset - corr);
1088 	while (rem < 0) {
1089 		rem += SECSPERDAY;
1090 		--days;
1091 	}
1092 	while (rem >= SECSPERDAY) {
1093 		rem -= SECSPERDAY;
1094 		++days;
1095 	}
1096 	tmp->tm_hour = (int) (rem / SECSPERHOUR);
1097 	rem = rem % SECSPERHOUR;
1098 	tmp->tm_min = (int) (rem / SECSPERMIN);
1099 	tmp->tm_sec = (int) (rem % SECSPERMIN);
1100 	if (hit)
1101 		/*
1102 		** A positive leap second requires a special
1103 		** representation.  This uses "... ??:59:60".
1104 		*/
1105 		++(tmp->tm_sec);
1106 	tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
1107 	if (tmp->tm_wday < 0)
1108 		tmp->tm_wday += DAYSPERWEEK;
1109 	y = EPOCH_YEAR;
1110 	if (days >= 0)
1111 		for ( ; ; ) {
1112 			yleap = isleap(y);
1113 			if (days < (long) year_lengths[yleap])
1114 				break;
1115 			++y;
1116 			days = days - (long) year_lengths[yleap];
1117 		}
1118 	else do {
1119 		--y;
1120 		yleap = isleap(y);
1121 		days = days + (long) year_lengths[yleap];
1122 	} while (days < 0);
1123 	tmp->tm_year = y - TM_YEAR_BASE;
1124 	tmp->tm_yday = (int) days;
1125 	ip = mon_lengths[yleap];
1126 	for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
1127 		days = days - (long) ip[tmp->tm_mon];
1128 	tmp->tm_mday = (int) (days + 1);
1129 	tmp->tm_isdst = 0;
1130 #ifdef TM_GMTOFF
1131 	tmp->TM_GMTOFF = offset;
1132 #endif /* defined TM_GMTOFF */
1133 }
1134 
1135 /*
1136 ** A la X3J11
1137 */
1138 
1139 char *
1140 asctime(timeptr)
1141 register const struct tm *	timeptr;
1142 {
1143 	static const char	wday_name[DAYSPERWEEK][3] = {
1144 		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1145 	};
1146 	static const char	mon_name[MONSPERYEAR][3] = {
1147 		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
1148 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1149 	};
1150 	static char	result[26];
1151 
1152 	(void) sprintf(result, "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n",
1153 		wday_name[timeptr->tm_wday],
1154 		mon_name[timeptr->tm_mon],
1155 		timeptr->tm_mday, timeptr->tm_hour,
1156 		timeptr->tm_min, timeptr->tm_sec,
1157 		TM_YEAR_BASE + timeptr->tm_year);
1158 	return result;
1159 }
1160 
1161 char *
1162 ctime(timep)
1163 const time_t * const	timep;
1164 {
1165 	return asctime(localtime(timep));
1166 }
1167 
1168 /*
1169 ** Adapted from code provided by Robert Elz, who writes:
1170 **	The "best" way to do mktime I think is based on an idea of Bob
1171 **	Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
1172 **	It does a binary search of the time_t space.  Since time_t's are
1173 **	just 32 bits, its a max of 32 iterations (even at 64 bits it
1174 **	would still be very reasonable).
1175 */
1176 
1177 #ifndef WRONG
1178 #define WRONG	(-1)
1179 #endif /* !defined WRONG */
1180 
1181 static void
1182 normalize(tensptr, unitsptr, base)
1183 int * const	tensptr;
1184 int * const	unitsptr;
1185 const int	base;
1186 {
1187 	if (*unitsptr >= base) {
1188 		*tensptr += *unitsptr / base;
1189 		*unitsptr %= base;
1190 	} else if (*unitsptr < 0) {
1191 		--*tensptr;
1192 		*unitsptr += base;
1193 		if (*unitsptr < 0) {
1194 			*tensptr -= 1 + (-*unitsptr) / base;
1195 			*unitsptr = base - (-*unitsptr) % base;
1196 		}
1197 	}
1198 }
1199 
1200 static int
1201 tmcomp(atmp, btmp)
1202 register const struct tm * const atmp;
1203 register const struct tm * const btmp;
1204 {
1205 	register int	result;
1206 
1207 	if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1208 		(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1209 		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1210 		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1211 		(result = (atmp->tm_min - btmp->tm_min)) == 0)
1212 			result = atmp->tm_sec - btmp->tm_sec;
1213 	return result;
1214 }
1215 
1216 static time_t
1217 time2(tmp, funcp, offset, okayp)
1218 struct tm * const	tmp;
1219 void (* const		funcp)();
1220 const long		offset;
1221 int * const		okayp;
1222 {
1223 	register const struct state *	sp;
1224 	register int			dir;
1225 	register int			bits;
1226 	register int			i, j ;
1227 	register int			saved_seconds;
1228 	time_t				newt;
1229 	time_t				t;
1230 	struct tm			yourtm, mytm;
1231 
1232 	*okayp = FALSE;
1233 	yourtm = *tmp;
1234 	if (yourtm.tm_sec >= SECSPERMIN + 2 || yourtm.tm_sec < 0)
1235 		normalize(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN);
1236 	normalize(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR);
1237 	normalize(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY);
1238 	normalize(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR);
1239 	while (yourtm.tm_mday <= 0) {
1240 		--yourtm.tm_year;
1241 		yourtm.tm_mday +=
1242 			year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)];
1243 	}
1244 	for ( ; ; ) {
1245 		i = mon_lengths[isleap(yourtm.tm_year +
1246 			TM_YEAR_BASE)][yourtm.tm_mon];
1247 		if (yourtm.tm_mday <= i)
1248 			break;
1249 		yourtm.tm_mday -= i;
1250 		if (++yourtm.tm_mon >= MONSPERYEAR) {
1251 			yourtm.tm_mon = 0;
1252 			++yourtm.tm_year;
1253 		}
1254 	}
1255 	saved_seconds = yourtm.tm_sec;
1256 	yourtm.tm_sec = 0;
1257 	/*
1258 	** Calculate the number of magnitude bits in a time_t
1259 	** (this works regardless of whether time_t is
1260 	** signed or unsigned, though lint complains if unsigned).
1261 	*/
1262 	for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
1263 		;
1264 	/*
1265 	** If time_t is signed, then 0 is the median value,
1266 	** if time_t is unsigned, then 1 << bits is median.
1267 	*/
1268 	t = (t < 0) ? 0 : ((time_t) 1 << bits);
1269 	for ( ; ; ) {
1270 		(*funcp)(&t, offset, &mytm);
1271 		dir = tmcomp(&mytm, &yourtm);
1272 		if (dir != 0) {
1273 			if (bits-- < 0)
1274 				return WRONG;
1275 			if (bits < 0)
1276 				--t;
1277 			else if (dir > 0)
1278 				t -= (time_t) 1 << bits;
1279 			else	t += (time_t) 1 << bits;
1280 			continue;
1281 		}
1282 		if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1283 			break;
1284 		/*
1285 		** Right time, wrong type.
1286 		** Hunt for right time, right type.
1287 		** It's okay to guess wrong since the guess
1288 		** gets checked.
1289 		*/
1290 		sp = (const struct state *)
1291 			((funcp == localsub) ? lclptr : gmtptr);
1292 #ifdef ALL_STATE
1293 		if (sp == NULL)
1294 			return WRONG;
1295 #endif /* defined ALL_STATE */
1296 		for (i = 0; i < sp->typecnt; ++i) {
1297 			if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1298 				continue;
1299 			for (j = 0; j < sp->typecnt; ++j) {
1300 				if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1301 					continue;
1302 				newt = t + sp->ttis[j].tt_gmtoff -
1303 					sp->ttis[i].tt_gmtoff;
1304 				(*funcp)(&newt, offset, &mytm);
1305 				if (tmcomp(&mytm, &yourtm) != 0)
1306 					continue;
1307 				if (mytm.tm_isdst != yourtm.tm_isdst)
1308 					continue;
1309 				/*
1310 				** We have a match.
1311 				*/
1312 				t = newt;
1313 				goto label;
1314 			}
1315 		}
1316 		return WRONG;
1317 	}
1318 label:
1319 	t += saved_seconds;
1320 	(*funcp)(&t, offset, tmp);
1321 	*okayp = TRUE;
1322 	return t;
1323 }
1324 
1325 static time_t
1326 time1(tmp, funcp, offset)
1327 struct tm * const	tmp;
1328 void (* const		funcp)();
1329 const long		offset;
1330 {
1331 	register time_t			t;
1332 	register const struct state *	sp;
1333 	register int			samei, otheri;
1334 	int				okay;
1335 
1336 	if (tmp->tm_isdst > 1)
1337 		tmp->tm_isdst = 1;
1338 	t = time2(tmp, funcp, offset, &okay);
1339 	if (okay || tmp->tm_isdst < 0)
1340 		return t;
1341 	/*
1342 	** We're supposed to assume that somebody took a time of one type
1343 	** and did some math on it that yielded a "struct tm" that's bad.
1344 	** We try to divine the type they started from and adjust to the
1345 	** type they need.
1346 	*/
1347 	sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr);
1348 #ifdef ALL_STATE
1349 	if (sp == NULL)
1350 		return WRONG;
1351 #endif /* defined ALL_STATE */
1352 	for (samei = 0; samei < sp->typecnt; ++samei) {
1353 		if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
1354 			continue;
1355 		for (otheri = 0; otheri < sp->typecnt; ++otheri) {
1356 			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
1357 				continue;
1358 			tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
1359 					sp->ttis[samei].tt_gmtoff;
1360 			tmp->tm_isdst = !tmp->tm_isdst;
1361 			t = time2(tmp, funcp, offset, &okay);
1362 			if (okay)
1363 				return t;
1364 			tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
1365 					sp->ttis[samei].tt_gmtoff;
1366 			tmp->tm_isdst = !tmp->tm_isdst;
1367 		}
1368 	}
1369 	return WRONG;
1370 }
1371 
1372 time_t
1373 mktime(tmp)
1374 struct tm * const	tmp;
1375 {
1376 	return time1(tmp, localsub, 0L);
1377 }
1378