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