localtime.c 37 KB

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