00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef _THREAD_SAFE
00041 #define _THREAD_SAFE
00042 #endif
00043 #define TZ_STRLEN_MAX 255
00044
00045
00046
00047
00048
00049 #include <sys/types.h>
00050 #include <sys/stat.h>
00051 #include <fcntl.h>
00052 #ifdef DEBUG
00053 #include <stdio.h>
00054 #endif
00055 #include "private.h"
00056 #include "tzfile.h"
00057 #include "asterisk/lock.h"
00058 #include "asterisk/localtime.h"
00059
00060
00061 #ifndef lint
00062 #ifndef NOID
00063 static const char elsieid[] = "@(#)localtime.c 7.57";
00064 #endif
00065 #endif
00066
00067
00068
00069
00070
00071
00072
00073 #ifdef O_BINARY
00074 #define OPEN_MODE (O_RDONLY | O_BINARY)
00075 #endif
00076 #ifndef O_BINARY
00077 #define OPEN_MODE O_RDONLY
00078 #endif
00079
00080 #ifdef SOLARIS
00081 #undef TM_ZONE
00082 #undef TM_GMTOFF
00083 #endif
00084
00085 #ifdef TM_ZONE
00086 #ifndef WILDABBR
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 #define WILDABBR " "
00107 #endif
00108
00109 static char wildabbr[] = "WILDABBR";
00110 #endif
00111
00112
00113
00114 static char gmt[] = "GMT";
00115
00116
00117 struct ttinfo {
00118 long tt_gmtoff;
00119 int tt_isdst;
00120 int tt_abbrind;
00121 int tt_ttisstd;
00122 int tt_ttisgmt;
00123 };
00124
00125
00126 struct lsinfo {
00127 time_t ls_trans;
00128 long ls_corr;
00129 };
00130
00131 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
00132
00133 #ifdef TZNAME_MAX
00134 #define MY_TZNAME_MAX TZNAME_MAX
00135 #endif
00136 #ifndef TZNAME_MAX
00137 #define MY_TZNAME_MAX 255
00138 #endif
00139
00140 struct state {
00141 char name[TZ_STRLEN_MAX + 1];
00142 int leapcnt;
00143 int timecnt;
00144 int typecnt;
00145 int charcnt;
00146 time_t ats[TZ_MAX_TIMES];
00147 unsigned char types[TZ_MAX_TIMES];
00148 struct ttinfo ttis[TZ_MAX_TYPES];
00149 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
00150 (2 * (MY_TZNAME_MAX + 1)))];
00151 struct lsinfo lsis[TZ_MAX_LEAPS];
00152 struct state *next;
00153 };
00154
00155 struct rule {
00156 int r_type;
00157 int r_day;
00158 int r_week;
00159 int r_mon;
00160 long r_time;
00161 };
00162
00163 #define JULIAN_DAY 0
00164 #define DAY_OF_YEAR 1
00165 #define MONTH_NTH_DAY_OF_WEEK 2
00166
00167
00168
00169
00170
00171 static long detzcode P((const char * codep));
00172 static const char * getnum P((const char * strp, int * nump, int min,
00173 int max));
00174 static const char * getsecs P((const char * strp, long * secsp));
00175 static const char * getoffset P((const char * strp, long * offsetp));
00176 static const char * getrule P((const char * strp, struct rule * rulep));
00177 static void gmtload P((struct state * sp));
00178 static void gmtsub P((const time_t * timep, long offset,
00179 struct tm * tmp, const char * zone));
00180 static void localsub P((const time_t * timep, long offset,
00181 struct tm * tmp, const char * zone));
00182 static int increment_overflow P((int * number, int delta));
00183 static int normalize_overflow P((int * tensptr, int * unitsptr,
00184 int base));
00185 static time_t time1 P((struct tm * tmp,
00186 void(*funcp) P((const time_t *,
00187 long, struct tm *, const char*)),
00188 long offset, const char * zone));
00189 static time_t time2 P((struct tm *tmp,
00190 void(*funcp) P((const time_t *,
00191 long, struct tm*, const char*)),
00192 long offset, int * okayp, const char * zone));
00193 static void timesub P((const time_t * timep, long offset,
00194 const struct state * sp, struct tm * tmp));
00195 static int tmcomp P((const struct tm * atmp,
00196 const struct tm * btmp));
00197 static time_t transtime P((time_t janfirst, int year,
00198 const struct rule * rulep, long offset));
00199 static int tzload P((const char * name, struct state * sp));
00200 static int tzparse P((const char * name, struct state * sp,
00201 int lastditch));
00202
00203 static struct state * lclptr = NULL;
00204 static struct state * last_lclptr = NULL;
00205 static struct state * gmtptr = NULL;
00206
00207 #ifndef TZ_STRLEN_MAX
00208 #define TZ_STRLEN_MAX 255
00209 #endif
00210
00211 static int gmt_is_set;
00212 #ifdef _THREAD_SAFE
00213 AST_MUTEX_DEFINE_STATIC(lcl_mutex);
00214 AST_MUTEX_DEFINE_STATIC(tzset_mutex);
00215 AST_MUTEX_DEFINE_STATIC(tzsetwall_mutex);
00216 AST_MUTEX_DEFINE_STATIC(gmt_mutex);
00217 #endif
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 static long detzcode(const char * const codep)
00228 {
00229 register long result;
00230 register int i;
00231
00232 result = (codep[0] & 0x80) ? ~0L : 0L;
00233 for (i = 0; i < 4; ++i)
00234 result = (result << 8) | (codep[i] & 0xff);
00235 return result;
00236 }
00237
00238 static int tzload(register const char *name, register struct state *const sp)
00239 {
00240 register const char * p;
00241 register int i;
00242 register int fid;
00243
00244 #ifdef DEBUG
00245 fprintf(stderr,"tzload called with name=%s, sp=%d\n", name, sp);
00246 #endif
00247 if (name == NULL && (name = TZDEFAULT) == NULL)
00248 return -1;
00249 {
00250 register int doaccess;
00251 struct stat stab;
00252
00253
00254
00255
00256
00257
00258
00259 char fullname[FILENAME_MAX + 1] = "";
00260
00261 if (name[0] == ':')
00262 ++name;
00263 doaccess = name[0] == '/';
00264 if (!doaccess) {
00265 if ((p = TZDIR) == NULL)
00266 return -1;
00267 if ((strlen(p) + 1 + strlen(name) + 1) >= sizeof fullname)
00268 return -1;
00269 (void) strncpy(fullname, p, sizeof(fullname) - 1);
00270 (void) strncat(fullname, "/", sizeof(fullname) - strlen(fullname) - 1);
00271 (void) strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
00272
00273
00274
00275 if (strchr(name, '.') != NULL)
00276 doaccess = TRUE;
00277 name = fullname;
00278 }
00279 if (doaccess && access(name, R_OK) != 0)
00280 return -1;
00281 if ((fid = open(name, OPEN_MODE)) == -1)
00282 return -1;
00283 if ((fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) {
00284 close(fid);
00285 return -1;
00286 }
00287 }
00288 {
00289 struct tzhead * tzhp;
00290 char buf[sizeof *sp + sizeof *tzhp];
00291 int ttisstdcnt;
00292 int ttisgmtcnt;
00293
00294 i = read(fid, buf, sizeof buf);
00295 if (close(fid) != 0)
00296 return -1;
00297 p = buf;
00298 p += (sizeof tzhp->tzh_magic) + (sizeof tzhp->tzh_reserved);
00299 ttisstdcnt = (int) detzcode(p);
00300 p += 4;
00301 ttisgmtcnt = (int) detzcode(p);
00302 p += 4;
00303 sp->leapcnt = (int) detzcode(p);
00304 p += 4;
00305 sp->timecnt = (int) detzcode(p);
00306 p += 4;
00307 sp->typecnt = (int) detzcode(p);
00308 p += 4;
00309 sp->charcnt = (int) detzcode(p);
00310 p += 4;
00311 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00312 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00313 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00314 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00315 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00316 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00317 return -1;
00318 if (i - (p - buf) < sp->timecnt * 4 +
00319 sp->timecnt +
00320 sp->typecnt * (4 + 2) +
00321 sp->charcnt +
00322 sp->leapcnt * (4 + 4) +
00323 ttisstdcnt +
00324 ttisgmtcnt)
00325 return -1;
00326 for (i = 0; i < sp->timecnt; ++i) {
00327 sp->ats[i] = detzcode(p);
00328 p += 4;
00329 }
00330 for (i = 0; i < sp->timecnt; ++i) {
00331 sp->types[i] = (unsigned char) *p++;
00332 if (sp->types[i] >= sp->typecnt)
00333 return -1;
00334 }
00335 for (i = 0; i < sp->typecnt; ++i) {
00336 register struct ttinfo * ttisp;
00337
00338 ttisp = &sp->ttis[i];
00339 ttisp->tt_gmtoff = detzcode(p);
00340 p += 4;
00341 ttisp->tt_isdst = (unsigned char) *p++;
00342 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00343 return -1;
00344 ttisp->tt_abbrind = (unsigned char) *p++;
00345 if (ttisp->tt_abbrind < 0 ||
00346 ttisp->tt_abbrind > sp->charcnt)
00347 return -1;
00348 }
00349 for (i = 0; i < sp->charcnt; ++i)
00350 sp->chars[i] = *p++;
00351 sp->chars[i] = '\0';
00352 for (i = 0; i < sp->leapcnt; ++i) {
00353 register struct lsinfo * lsisp;
00354
00355 lsisp = &sp->lsis[i];
00356 lsisp->ls_trans = detzcode(p);
00357 p += 4;
00358 lsisp->ls_corr = detzcode(p);
00359 p += 4;
00360 }
00361 for (i = 0; i < sp->typecnt; ++i) {
00362 register struct ttinfo * ttisp;
00363
00364 ttisp = &sp->ttis[i];
00365 if (ttisstdcnt == 0)
00366 ttisp->tt_ttisstd = FALSE;
00367 else {
00368 ttisp->tt_ttisstd = *p++;
00369 if (ttisp->tt_ttisstd != TRUE &&
00370 ttisp->tt_ttisstd != FALSE)
00371 return -1;
00372 }
00373 }
00374 for (i = 0; i < sp->typecnt; ++i) {
00375 register struct ttinfo * ttisp;
00376
00377 ttisp = &sp->ttis[i];
00378 if (ttisgmtcnt == 0)
00379 ttisp->tt_ttisgmt = FALSE;
00380 else {
00381 ttisp->tt_ttisgmt = *p++;
00382 if (ttisp->tt_ttisgmt != TRUE &&
00383 ttisp->tt_ttisgmt != FALSE)
00384 return -1;
00385 }
00386 }
00387 }
00388 return 0;
00389 }
00390
00391 static const int mon_lengths[2][MONSPERYEAR] = {
00392 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00393 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
00394 };
00395
00396 static const int year_lengths[2] = {
00397 DAYSPERNYEAR, DAYSPERLYEAR
00398 };
00399
00400
00401
00402
00403
00404
00405
00406
00407 static const char *getnum(register const char *strp, int * const nump, const int min, const int max)
00408 {
00409 register char c;
00410 register int num;
00411
00412 if (strp == NULL || !is_digit(c = *strp))
00413 return NULL;
00414 num = 0;
00415 do {
00416 num = num * 10 + (c - '0');
00417 if (num > max)
00418 return NULL;
00419 c = *++strp;
00420 } while (is_digit(c));
00421 if (num < min)
00422 return NULL;
00423 *nump = num;
00424 return strp;
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 static const char *getsecs(register const char *strp, long * const secsp)
00436 {
00437 int num;
00438
00439
00440
00441
00442
00443
00444
00445 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00446 if (strp == NULL)
00447 return NULL;
00448 *secsp = num * (long) SECSPERHOUR;
00449 if (*strp == ':') {
00450 ++strp;
00451 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00452 if (strp == NULL)
00453 return NULL;
00454 *secsp += num * SECSPERMIN;
00455 if (*strp == ':') {
00456 ++strp;
00457
00458 strp = getnum(strp, &num, 0, SECSPERMIN);
00459 if (strp == NULL)
00460 return NULL;
00461 *secsp += num;
00462 }
00463 }
00464 return strp;
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474 static const char * getoffset(register const char *strp, long * const offsetp)
00475 {
00476 register int neg = 0;
00477
00478 if (*strp == '-') {
00479 neg = 1;
00480 ++strp;
00481 } else if (*strp == '+')
00482 ++strp;
00483 strp = getsecs(strp, offsetp);
00484 if (strp == NULL)
00485 return NULL;
00486 if (neg)
00487 *offsetp = -*offsetp;
00488 return strp;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498 static const char *getrule(const char *strp, register struct rule * const rulep)
00499 {
00500 if (*strp == 'J') {
00501
00502
00503
00504 rulep->r_type = JULIAN_DAY;
00505 ++strp;
00506 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
00507 } else if (*strp == 'M') {
00508
00509
00510
00511 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
00512 ++strp;
00513 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
00514 if (strp == NULL)
00515 return NULL;
00516 if (*strp++ != '.')
00517 return NULL;
00518 strp = getnum(strp, &rulep->r_week, 1, 5);
00519 if (strp == NULL)
00520 return NULL;
00521 if (*strp++ != '.')
00522 return NULL;
00523 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
00524 } else if (is_digit(*strp)) {
00525
00526
00527
00528 rulep->r_type = DAY_OF_YEAR;
00529 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
00530 } else return NULL;
00531 if (strp == NULL)
00532 return NULL;
00533 if (*strp == '/') {
00534
00535
00536
00537 ++strp;
00538 strp = getsecs(strp, &rulep->r_time);
00539 } else rulep->r_time = 2 * SECSPERHOUR;
00540 return strp;
00541 }
00542
00543
00544
00545
00546
00547
00548
00549 static time_t transtime(janfirst, year, rulep, offset)
00550 const time_t janfirst;
00551 const int year;
00552 register const struct rule * const rulep;
00553 const long offset;
00554 {
00555 register int leapyear;
00556 register time_t value = 0;
00557 register int i;
00558 int d, m1, yy0, yy1, yy2, dow;
00559
00560 leapyear = isleap(year);
00561 switch (rulep->r_type) {
00562
00563 case JULIAN_DAY:
00564
00565
00566
00567
00568
00569
00570
00571 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
00572 if (leapyear && rulep->r_day >= 60)
00573 value += SECSPERDAY;
00574 break;
00575
00576 case DAY_OF_YEAR:
00577
00578
00579
00580
00581
00582 value = janfirst + rulep->r_day * SECSPERDAY;
00583 break;
00584
00585 case MONTH_NTH_DAY_OF_WEEK:
00586
00587
00588
00589 value = janfirst;
00590 for (i = 0; i < rulep->r_mon - 1; ++i)
00591 value += mon_lengths[leapyear][i] * SECSPERDAY;
00592
00593
00594
00595
00596
00597 m1 = (rulep->r_mon + 9) % 12 + 1;
00598 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
00599 yy1 = yy0 / 100;
00600 yy2 = yy0 % 100;
00601 dow = ((26 * m1 - 2) / 10 +
00602 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
00603 if (dow < 0)
00604 dow += DAYSPERWEEK;
00605
00606
00607
00608
00609
00610
00611 d = rulep->r_day - dow;
00612 if (d < 0)
00613 d += DAYSPERWEEK;
00614 for (i = 1; i < rulep->r_week; ++i) {
00615 if (d + DAYSPERWEEK >=
00616 mon_lengths[leapyear][rulep->r_mon - 1])
00617 break;
00618 d += DAYSPERWEEK;
00619 }
00620
00621
00622
00623
00624 value += d * SECSPERDAY;
00625 break;
00626 }
00627
00628
00629
00630
00631
00632
00633
00634 return value + rulep->r_time + offset;
00635 }
00636
00637
00638
00639
00640
00641
00642 static int
00643 tzparse(name, sp, lastditch)
00644 const char * name;
00645 register struct state * const sp;
00646 const int lastditch;
00647 {
00648 const char * stdname;
00649 const char * dstname = NULL;
00650 size_t stdlen = 0;
00651 size_t dstlen = 0;
00652 long stdoffset = 0L;
00653 long dstoffset = 0L;
00654 register time_t * atp;
00655 register unsigned char * typep;
00656 register char * cp;
00657 register int load_result;
00658
00659 stdname = name;
00660 #ifdef DEBUG
00661 fprintf(stderr, "tzparse(): loading default rules\n");
00662 #endif
00663 load_result = tzload(TZDEFRULES, sp);
00664 if (load_result != 0)
00665 sp->leapcnt = 0;
00666 if (*name != '\0') {
00667 if (*name != '\0' && *name != ',' && *name != ';') {
00668 name = getoffset(name, &dstoffset);
00669 if (name == NULL)
00670 return -1;
00671 } else dstoffset = stdoffset - SECSPERHOUR;
00672 if (*name == ',' || *name == ';') {
00673 struct rule start;
00674 struct rule end;
00675 register int year;
00676 register time_t janfirst;
00677 time_t starttime;
00678 time_t endtime;
00679
00680 ++name;
00681 if ((name = getrule(name, &start)) == NULL)
00682 return -1;
00683 if (*name++ != ',')
00684 return -1;
00685 if ((name = getrule(name, &end)) == NULL)
00686 return -1;
00687 if (*name != '\0')
00688 return -1;
00689 sp->typecnt = 2;
00690
00691
00692
00693 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
00694 if (sp->timecnt > TZ_MAX_TIMES)
00695 return -1;
00696 sp->ttis[0].tt_gmtoff = -dstoffset;
00697 sp->ttis[0].tt_isdst = 1;
00698 sp->ttis[0].tt_abbrind = stdlen + 1;
00699 sp->ttis[1].tt_gmtoff = -stdoffset;
00700 sp->ttis[1].tt_isdst = 0;
00701 sp->ttis[1].tt_abbrind = 0;
00702 atp = sp->ats;
00703 typep = sp->types;
00704 janfirst = 0;
00705 for (year = EPOCH_YEAR; year <= 2037; ++year) {
00706 starttime = transtime(janfirst, year, &start,
00707 stdoffset);
00708 endtime = transtime(janfirst, year, &end,
00709 dstoffset);
00710 if (starttime > endtime) {
00711 *atp++ = endtime;
00712 *typep++ = 1;
00713 *atp++ = starttime;
00714 *typep++ = 0;
00715 } else {
00716 *atp++ = starttime;
00717 *typep++ = 0;
00718 *atp++ = endtime;
00719 *typep++ = 1;
00720 }
00721 janfirst += year_lengths[isleap(year)] *
00722 SECSPERDAY;
00723 }
00724 } else {
00725 register long theirstdoffset;
00726 register long theirdstoffset;
00727 register long theiroffset;
00728 register int isdst;
00729 register int i;
00730 register int j;
00731
00732 if (*name != '\0')
00733 return -1;
00734 if (load_result != 0)
00735 return -1;
00736
00737
00738
00739 theirstdoffset = 0;
00740 for (i = 0; i < sp->timecnt; ++i) {
00741 j = sp->types[i];
00742 if (!sp->ttis[j].tt_isdst) {
00743 theirstdoffset =
00744 -sp->ttis[j].tt_gmtoff;
00745 break;
00746 }
00747 }
00748 theirdstoffset = 0;
00749 for (i = 0; i < sp->timecnt; ++i) {
00750 j = sp->types[i];
00751 if (sp->ttis[j].tt_isdst) {
00752 theirdstoffset =
00753 -sp->ttis[j].tt_gmtoff;
00754 break;
00755 }
00756 }
00757
00758
00759
00760 isdst = FALSE;
00761 theiroffset = theirstdoffset;
00762
00763
00764
00765
00766 for (i = 0; i < sp->timecnt; ++i) {
00767 j = sp->types[i];
00768 sp->types[i] = sp->ttis[j].tt_isdst;
00769 if (sp->ttis[j].tt_ttisgmt) {
00770
00771 } else {
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786 if (isdst && !sp->ttis[j].tt_ttisstd) {
00787 sp->ats[i] += dstoffset -
00788 theirdstoffset;
00789 } else {
00790 sp->ats[i] += stdoffset -
00791 theirstdoffset;
00792 }
00793 }
00794 theiroffset = -sp->ttis[j].tt_gmtoff;
00795 if (sp->ttis[j].tt_isdst)
00796 theirdstoffset = theiroffset;
00797 else theirstdoffset = theiroffset;
00798 }
00799
00800
00801
00802
00803 sp->ttis[0].tt_gmtoff = -stdoffset;
00804 sp->ttis[0].tt_isdst = FALSE;
00805 sp->ttis[0].tt_abbrind = 0;
00806 sp->ttis[1].tt_gmtoff = -dstoffset;
00807 sp->ttis[1].tt_isdst = TRUE;
00808 sp->ttis[1].tt_abbrind = stdlen + 1;
00809 }
00810 } else {
00811 dstlen = 0;
00812 sp->typecnt = 1;
00813 sp->timecnt = 0;
00814 sp->ttis[0].tt_gmtoff = -stdoffset;
00815 sp->ttis[0].tt_isdst = 0;
00816 sp->ttis[0].tt_abbrind = 0;
00817 }
00818 sp->charcnt = stdlen + 1;
00819 if (dstlen != 0)
00820 sp->charcnt += dstlen + 1;
00821 if (sp->charcnt > sizeof sp->chars)
00822 return -1;
00823 cp = sp->chars;
00824 (void) strncpy(cp, stdname, stdlen);
00825 cp += stdlen;
00826 *cp++ = '\0';
00827 if (dstlen != 0) {
00828 (void) strncpy(cp, dstname, dstlen);
00829 *(cp + dstlen) = '\0';
00830 }
00831 return 0;
00832 }
00833
00834 static void
00835 gmtload(sp)
00836 struct state * const sp;
00837 {
00838 if (tzload(gmt, sp) != 0)
00839 (void) tzparse(gmt, sp, TRUE);
00840 }
00841
00842
00843
00844
00845
00846 static
00847 #ifdef _THREAD_SAFE
00848 int
00849 ast_tzsetwall_basic P((void))
00850 #else
00851 int
00852 ast_tzsetwall P((void))
00853 #endif
00854 {
00855 struct state *cur_state = lclptr;
00856
00857
00858 while (cur_state != NULL) {
00859 if (cur_state->name[0] == '\0')
00860 break;
00861 cur_state = cur_state->next;
00862 }
00863 if (cur_state != NULL)
00864 return 0;
00865 cur_state = malloc(sizeof(struct state));
00866 if (cur_state == NULL) {
00867 return -1;
00868 }
00869 memset(cur_state,0,sizeof(struct state));
00870 if (tzload((char *) NULL, cur_state) != 0)
00871 #ifdef DEBUG
00872 {
00873 fprintf(stderr, "ast_tzsetwall: calling gmtload()\n");
00874 #endif
00875 gmtload(cur_state);
00876 #ifdef DEBUG
00877 }
00878 #endif
00879
00880 if (last_lclptr)
00881 last_lclptr->next = cur_state;
00882 else
00883 lclptr = cur_state;
00884 last_lclptr = cur_state;
00885 return 0;
00886 }
00887
00888 #ifdef _THREAD_SAFE
00889 int
00890 ast_tzsetwall P((void))
00891 {
00892 ast_mutex_lock(&tzsetwall_mutex);
00893 ast_tzsetwall_basic();
00894 ast_mutex_unlock(&tzsetwall_mutex);
00895 return 0;
00896 }
00897 #endif
00898
00899 #ifdef _THREAD_SAFE
00900 static int
00901 ast_tzset_basic P((const char *name))
00902 #else
00903 int
00904 ast_tzset P((const char *name))
00905 #endif
00906 {
00907 struct state *cur_state = lclptr;
00908
00909
00910 if (name == NULL) {
00911 return ast_tzsetwall();
00912 }
00913
00914
00915 while (cur_state != NULL) {
00916 if (!strcmp(cur_state->name,name))
00917 break;
00918 cur_state = cur_state->next;
00919 }
00920 if (cur_state != NULL)
00921 return 0;
00922
00923 cur_state = malloc(sizeof(struct state));
00924 if (cur_state == NULL) {
00925 return -1;
00926 }
00927 memset(cur_state,0,sizeof(*cur_state));
00928
00929
00930 if (name[0] == '\0') {
00931
00932
00933
00934 cur_state->leapcnt = 0;
00935 cur_state->timecnt = 0;
00936 cur_state->ttis[0].tt_gmtoff = 0;
00937 cur_state->ttis[0].tt_abbrind = 0;
00938 (void) strncpy(cur_state->chars, gmt, sizeof(cur_state->chars) - 1);
00939 } else if (tzload(name, cur_state) != 0) {
00940 if (name[0] == ':') {
00941 (void) gmtload(cur_state);
00942 } else if (tzparse(name, cur_state, FALSE) != 0) {
00943
00944 if (tzload("/etc/localtime", cur_state) != 0)
00945
00946 (void) gmtload(cur_state);
00947 }
00948 }
00949 strncpy(cur_state->name, name, sizeof(cur_state->name) - 1);
00950 if (last_lclptr)
00951 last_lclptr->next = cur_state;
00952 else
00953 lclptr = cur_state;
00954 last_lclptr = cur_state;
00955 return 0;
00956 }
00957
00958 #ifdef _THREAD_SAFE
00959 void
00960 ast_tzset P((const char *name))
00961 {
00962 ast_mutex_lock(&tzset_mutex);
00963 ast_tzset_basic(name);
00964 ast_mutex_unlock(&tzset_mutex);
00965 }
00966 #endif
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 static void
00979 localsub(timep, offset, tmp, zone)
00980 const time_t * const timep;
00981 const long offset;
00982 struct tm * const tmp;
00983 const char * const zone;
00984 {
00985 register struct state * sp;
00986 register const struct ttinfo * ttisp;
00987 register int i;
00988 const time_t t = *timep;
00989
00990 sp = lclptr;
00991
00992 if (zone == NULL)
00993 sp = NULL;
00994 else
00995 while (sp != NULL) {
00996 if (!strcmp(sp->name,zone))
00997 break;
00998 sp = sp->next;
00999 }
01000
01001 if (sp == NULL) {
01002 ast_tzsetwall();
01003 sp = lclptr;
01004
01005 while (sp != NULL) {
01006 if (sp->name[0] == '\0')
01007 break;
01008 sp = sp->next;
01009 }
01010 }
01011
01012
01013 if (sp == NULL) {
01014 gmtsub(timep, offset, tmp, zone);
01015 return;
01016 }
01017 if (sp->timecnt == 0 || t < sp->ats[0]) {
01018 i = 0;
01019 while (sp->ttis[i].tt_isdst)
01020 if (++i >= sp->typecnt) {
01021 i = 0;
01022 break;
01023 }
01024 } else {
01025 for (i = 1; i < sp->timecnt; ++i)
01026 if (t < sp->ats[i])
01027 break;
01028 i = sp->types[i - 1];
01029 }
01030 ttisp = &sp->ttis[i];
01031
01032
01033
01034
01035
01036
01037 timesub(&t, ttisp->tt_gmtoff, sp, tmp);
01038 tmp->tm_isdst = ttisp->tt_isdst;
01039 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
01040 #ifdef TM_ZONE
01041 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
01042 #endif
01043 }
01044
01045 struct tm *
01046 ast_localtime(timep, p_tm, zone)
01047 const time_t * const timep;
01048 struct tm *p_tm;
01049 const char * const zone;
01050 {
01051 #ifdef _THREAD_SAFE
01052 ast_mutex_lock(&lcl_mutex);
01053 #endif
01054 ast_tzset(zone);
01055 localsub(timep, 0L, p_tm, zone);
01056 #ifdef _THREAD_SAFE
01057 ast_mutex_unlock(&lcl_mutex);
01058 #endif
01059 return(p_tm);
01060 }
01061
01062
01063
01064
01065
01066 static void
01067 gmtsub(timep, offset, tmp, zone)
01068 const time_t * const timep;
01069 const long offset;
01070 struct tm * const tmp;
01071 const char * const zone;
01072 {
01073 #ifdef _THREAD_SAFE
01074 ast_mutex_lock(&gmt_mutex);
01075 #endif
01076 if (!gmt_is_set) {
01077 gmt_is_set = TRUE;
01078 gmtptr = (struct state *) malloc(sizeof *gmtptr);
01079 if (gmtptr != NULL)
01080 gmtload(gmtptr);
01081 }
01082 ast_mutex_unlock(&gmt_mutex);
01083 timesub(timep, offset, gmtptr, tmp);
01084 #ifdef TM_ZONE
01085
01086
01087
01088
01089
01090 if (offset != 0)
01091 tmp->TM_ZONE = wildabbr;
01092 else {
01093 if (gmtptr == NULL)
01094 tmp->TM_ZONE = gmt;
01095 else tmp->TM_ZONE = gmtptr->chars;
01096 }
01097 #endif
01098 }
01099
01100 static void
01101 timesub(timep, offset, sp, tmp)
01102 const time_t * const timep;
01103 const long offset;
01104 register const struct state * const sp;
01105 register struct tm * const tmp;
01106 {
01107 register const struct lsinfo * lp;
01108 register long days;
01109 register long rem;
01110 register int y;
01111 register int yleap;
01112 register const int * ip;
01113 register long corr;
01114 register int hit;
01115 register int i;
01116
01117 corr = 0;
01118 hit = 0;
01119 i = (sp == NULL) ? 0 : sp->leapcnt;
01120 while (--i >= 0) {
01121 lp = &sp->lsis[i];
01122 if (*timep >= lp->ls_trans) {
01123 if (*timep == lp->ls_trans) {
01124 hit = ((i == 0 && lp->ls_corr > 0) ||
01125 lp->ls_corr > sp->lsis[i - 1].ls_corr);
01126 if (hit)
01127 while (i > 0 &&
01128 sp->lsis[i].ls_trans ==
01129 sp->lsis[i - 1].ls_trans + 1 &&
01130 sp->lsis[i].ls_corr ==
01131 sp->lsis[i - 1].ls_corr + 1) {
01132 ++hit;
01133 --i;
01134 }
01135 }
01136 corr = lp->ls_corr;
01137 break;
01138 }
01139 }
01140 days = *timep / SECSPERDAY;
01141 rem = *timep % SECSPERDAY;
01142 #ifdef mc68k
01143 if (*timep == 0x80000000) {
01144
01145
01146
01147 days = -24855;
01148 rem = -11648;
01149 }
01150 #endif
01151 rem += (offset - corr);
01152 while (rem < 0) {
01153 rem += SECSPERDAY;
01154 --days;
01155 }
01156 while (rem >= SECSPERDAY) {
01157 rem -= SECSPERDAY;
01158 ++days;
01159 }
01160 tmp->tm_hour = (int) (rem / SECSPERHOUR);
01161 rem = rem % SECSPERHOUR;
01162 tmp->tm_min = (int) (rem / SECSPERMIN);
01163
01164
01165
01166
01167 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01168 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
01169 if (tmp->tm_wday < 0)
01170 tmp->tm_wday += DAYSPERWEEK;
01171 y = EPOCH_YEAR;
01172 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
01173 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
01174 register int newy;
01175
01176 newy = y + days / DAYSPERNYEAR;
01177 if (days < 0)
01178 --newy;
01179 days -= (newy - y) * DAYSPERNYEAR +
01180 LEAPS_THRU_END_OF(newy - 1) -
01181 LEAPS_THRU_END_OF(y - 1);
01182 y = newy;
01183 }
01184 tmp->tm_year = y - TM_YEAR_BASE;
01185 tmp->tm_yday = (int) days;
01186 ip = mon_lengths[yleap];
01187 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
01188 days = days - (long) ip[tmp->tm_mon];
01189 tmp->tm_mday = (int) (days + 1);
01190 tmp->tm_isdst = 0;
01191 #ifdef TM_GMTOFF
01192 tmp->TM_GMTOFF = offset;
01193 #endif
01194 }
01195
01196 char *
01197 ast_ctime(timep)
01198 const time_t * const timep;
01199 {
01200
01201
01202
01203
01204
01205
01206 return asctime(localtime(timep));
01207 }
01208
01209 char *
01210 ast_ctime_r(timep, buf)
01211 const time_t * const timep;
01212 char *buf;
01213 {
01214 struct tm tm;
01215 #ifdef SOLARIS
01216 return asctime_r(localtime_r(timep, &tm), buf, 256);
01217 #else
01218 return asctime_r(localtime_r(timep, &tm), buf);
01219 #endif
01220 }
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232 #ifndef WRONG
01233 #define WRONG (-1)
01234 #endif
01235
01236
01237
01238
01239
01240 static int
01241 increment_overflow(number, delta)
01242 int * number;
01243 int delta;
01244 {
01245 int number0;
01246
01247 number0 = *number;
01248 *number += delta;
01249 return (*number < number0) != (delta < 0);
01250 }
01251
01252 static int
01253 normalize_overflow(tensptr, unitsptr, base)
01254 int * const tensptr;
01255 int * const unitsptr;
01256 const int base;
01257 {
01258 register int tensdelta;
01259
01260 tensdelta = (*unitsptr >= 0) ?
01261 (*unitsptr / base) :
01262 (-1 - (-1 - *unitsptr) / base);
01263 *unitsptr -= tensdelta * base;
01264 return increment_overflow(tensptr, tensdelta);
01265 }
01266
01267 static int
01268 tmcomp(atmp, btmp)
01269 register const struct tm * const atmp;
01270 register const struct tm * const btmp;
01271 {
01272 register int result;
01273
01274 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01275 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01276 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01277 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01278 (result = (atmp->tm_min - btmp->tm_min)) == 0)
01279 result = atmp->tm_sec - btmp->tm_sec;
01280 return result;
01281 }
01282
01283 static time_t
01284 time2(tmp, funcp, offset, okayp, zone)
01285 struct tm * const tmp;
01286 void (* const funcp) P((const time_t*, long, struct tm*, const char*));
01287 const long offset;
01288 int * const okayp;
01289 const char * const zone;
01290 {
01291 register const struct state * sp;
01292 register int dir;
01293 register int bits;
01294 register int i, j ;
01295 register int saved_seconds;
01296 time_t newt;
01297 time_t t;
01298 struct tm yourtm, mytm;
01299
01300 *okayp = FALSE;
01301 yourtm = *tmp;
01302 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01303 return WRONG;
01304 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01305 return WRONG;
01306 if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
01307 return WRONG;
01308
01309
01310
01311
01312 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
01313 return WRONG;
01314 while (yourtm.tm_mday <= 0) {
01315 if (increment_overflow(&yourtm.tm_year, -1))
01316 return WRONG;
01317 i = yourtm.tm_year + (1 < yourtm.tm_mon);
01318 yourtm.tm_mday += year_lengths[isleap(i)];
01319 }
01320 while (yourtm.tm_mday > DAYSPERLYEAR) {
01321 i = yourtm.tm_year + (1 < yourtm.tm_mon);
01322 yourtm.tm_mday -= year_lengths[isleap(i)];
01323 if (increment_overflow(&yourtm.tm_year, 1))
01324 return WRONG;
01325 }
01326 for ( ; ; ) {
01327 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
01328 if (yourtm.tm_mday <= i)
01329 break;
01330 yourtm.tm_mday -= i;
01331 if (++yourtm.tm_mon >= MONSPERYEAR) {
01332 yourtm.tm_mon = 0;
01333 if (increment_overflow(&yourtm.tm_year, 1))
01334 return WRONG;
01335 }
01336 }
01337 if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
01338 return WRONG;
01339 if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
01340
01341
01342
01343
01344
01345
01346
01347
01348 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
01349 return WRONG;
01350 saved_seconds = yourtm.tm_sec;
01351 yourtm.tm_sec = SECSPERMIN - 1;
01352 } else {
01353 saved_seconds = yourtm.tm_sec;
01354 yourtm.tm_sec = 0;
01355 }
01356
01357
01358
01359
01360 bits = TYPE_BIT(time_t) - 1;
01361
01362
01363
01364
01365
01366 t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
01367 for ( ; ; ) {
01368 (*funcp)(&t, offset, &mytm, zone);
01369 dir = tmcomp(&mytm, &yourtm);
01370 if (dir != 0) {
01371 if (bits-- < 0)
01372 return WRONG;
01373 if (bits < 0)
01374 --t;
01375 else if (dir > 0)
01376 t -= ((time_t) 1) << bits;
01377 else t += ((time_t) 1) << bits;
01378 continue;
01379 }
01380 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
01381 break;
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391 sp = (const struct state *)
01392 (((void *) funcp == (void *) localsub) ?
01393 lclptr : gmtptr);
01394 if (sp == NULL)
01395 return WRONG;
01396 for (i = sp->typecnt - 1; i >= 0; --i) {
01397 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
01398 continue;
01399 for (j = sp->typecnt - 1; j >= 0; --j) {
01400 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
01401 continue;
01402 newt = t + sp->ttis[j].tt_gmtoff -
01403 sp->ttis[i].tt_gmtoff;
01404 (*funcp)(&newt, offset, &mytm, zone);
01405 if (tmcomp(&mytm, &yourtm) != 0)
01406 continue;
01407 if (mytm.tm_isdst != yourtm.tm_isdst)
01408 continue;
01409
01410
01411
01412 t = newt;
01413 goto label;
01414 }
01415 }
01416 return WRONG;
01417 }
01418 label:
01419 newt = t + saved_seconds;
01420 if ((newt < t) != (saved_seconds < 0))
01421 return WRONG;
01422 t = newt;
01423 (*funcp)(&t, offset, tmp, zone);
01424 *okayp = TRUE;
01425 return t;
01426 }
01427
01428 static time_t
01429 time1(tmp, funcp, offset, zone)
01430 struct tm * const tmp;
01431 void (* const funcp) P((const time_t *, long, struct tm *, const char*));
01432 const long offset;
01433 const char * const zone;
01434 {
01435 register time_t t;
01436 register const struct state * sp;
01437 register int samei, otheri;
01438 int okay;
01439
01440 if (tmp->tm_isdst > 1)
01441 tmp->tm_isdst = 1;
01442 t = time2(tmp, funcp, offset, &okay, zone);
01443 #ifdef PCTS
01444
01445
01446
01447 if (okay)
01448 return t;
01449 if (tmp->tm_isdst < 0)
01450 tmp->tm_isdst = 0;
01451 #endif
01452 #ifndef PCTS
01453 if (okay || tmp->tm_isdst < 0)
01454 return t;
01455 #endif
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465 sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
01466 lclptr : gmtptr);
01467 if (sp == NULL)
01468 return WRONG;
01469 for (samei = sp->typecnt - 1; samei >= 0; --samei) {
01470 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
01471 continue;
01472 for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) {
01473 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
01474 continue;
01475 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
01476 sp->ttis[samei].tt_gmtoff;
01477 tmp->tm_isdst = !tmp->tm_isdst;
01478 t = time2(tmp, funcp, offset, &okay, zone);
01479 if (okay)
01480 return t;
01481 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
01482 sp->ttis[samei].tt_gmtoff;
01483 tmp->tm_isdst = !tmp->tm_isdst;
01484 }
01485 }
01486 return WRONG;
01487 }
01488
01489 time_t
01490 ast_mktime(tmp,zone)
01491 struct tm * const tmp;
01492 const char * const zone;
01493 {
01494 time_t mktime_return_value;
01495 #ifdef _THREAD_SAFE
01496 ast_mutex_lock(&lcl_mutex);
01497 #endif
01498 ast_tzset(zone);
01499 mktime_return_value = time1(tmp, localsub, 0L, zone);
01500 #ifdef _THREAD_SAFE
01501 ast_mutex_unlock(&lcl_mutex);
01502 #endif
01503 return(mktime_return_value);
01504 }
01505