localtime.c 37 KB

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