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