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