ctime.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:34k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 1987, 1989 Regents of the University of California.
  3.  * Copyright (c) 1994 Chris Provenzano, proven@mit.edu
  4.  * All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to Berkeley by
  7.  * Arthur David Olson of the National Cancer Institute.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  * This product includes software developed by the University of
  20.  * California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #if defined(LIBC_SCCS) && !defined(lint)
  38. static char sccsid[] = "@(#)ctime.c 5.26 (Berkeley) 2/23/91";
  39. #endif /* LIBC_SCCS and not lint */
  40. /*
  41. ** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
  42. ** POSIX-style TZ environment variable handling from Guy Harris
  43. ** (guy@auspex.com).
  44. */
  45. /*LINTLIBRARY*/
  46. #include "config.h"
  47. #include <pthread.h>
  48. #include <sys/param.h>
  49. #include <fcntl.h>
  50. #include <time.h>
  51. #include <tzfile.h>
  52. #include <string.h>
  53. #include <ctype.h>
  54. #include <stdio.h>
  55. #include <unistd.h>
  56. #include <stdlib.h>
  57. #ifndef WILDABBR
  58. /*
  59. ** Someone might make incorrect use of a time zone abbreviation:
  60. ** 1. They might reference tzname[0] before calling tzset (explicitly
  61. **   or implicitly).
  62. ** 2. They might reference tzname[1] before calling tzset (explicitly
  63. **   or implicitly).
  64. ** 3. They might reference tzname[1] after setting to a time zone
  65. ** in which Daylight Saving Time is never observed.
  66. ** 4. They might reference tzname[0] after setting to a time zone
  67. ** in which Standard Time is never observed.
  68. ** 5. They might reference tm.TM_ZONE after calling offtime.
  69. ** What's best to do in the above cases is open to debate;
  70. ** for now, we just set things up so that in any of the five cases
  71. ** WILDABBR is used.  Another possibility:  initialize tzname[0] to the
  72. ** string "tzname[0] used before set", and similarly for the other cases.
  73. ** And another:  initialize tzname[0] to "ERA", with an explanation in the
  74. ** manual page of what this "time zone abbreviation" means (doing this so
  75. ** that tzname[0] has the "normal" length of three characters).
  76. */
  77. #define WILDABBR "   "
  78. #endif /* !defined WILDABBR */
  79. #ifndef TRUE
  80. #define TRUE 1
  81. #define FALSE 0
  82. #endif /* !defined TRUE */
  83. static const 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. };
  90. struct lsinfo { /* leap second information */
  91. time_t ls_trans; /* transition time */
  92. long ls_corr; /* correction to apply */
  93. };
  94. struct state {
  95. int leapcnt;
  96. int timecnt;
  97. int typecnt;
  98. int charcnt;
  99. time_t ats[TZ_MAX_TIMES];
  100. unsigned char types[TZ_MAX_TIMES];
  101. struct ttinfo ttis[TZ_MAX_TYPES];
  102. char chars[(TZ_MAX_CHARS + 1 > sizeof GMT) ?
  103. TZ_MAX_CHARS + 1 : sizeof GMT];
  104. struct lsinfo lsis[TZ_MAX_LEAPS];
  105. };
  106. struct rule {
  107. int r_type; /* type of rule--see below */
  108. int r_day; /* day number of rule */
  109. int r_week; /* week number of rule */
  110. int r_mon; /* month number of rule */
  111. long r_time; /* transition time of rule */
  112. };
  113. #define JULIAN_DAY 0 /* Jn - Julian day */
  114. #define DAY_OF_YEAR 1 /* n - day of year */
  115. #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
  116. /*
  117. ** Prototypes for static functions.
  118. */
  119. static int detzcode __P_((const char *));
  120. static const char * getnum __P_((const char *, int *, int, int));
  121. static const char * getsecs __P_((const char *, long *));
  122. static const char * getoffset __P_((const char *, long *));
  123. static const char * getrule __P_((const char *, struct rule *));
  124. static const char * getzname __P_((const char *));
  125. static void gmtload __P_((struct state *));
  126. static void gmtsub __P_((const time_t *, long, struct tm *));
  127. static void localsub __P_((const time_t *, long, struct tm *));
  128. static void normalize __P_((int *, int *, int));
  129. static void settzname __P_((struct state *));
  130. static time_t time1 __P_((struct tm *, long));
  131. static time_t time2 __P_((struct tm *, long, int *));
  132. static void timesub __P_((const time_t *, long, const struct state *,
  133. struct tm *));
  134. static int tmcomp __P_((const struct tm *, const struct tm *));
  135. static time_t transtime __P_((time_t, int, const struct rule *, long));
  136. static int tzload __P_((const char *, struct state *));
  137. static int tzparse __P_((const char *, struct state *, int));
  138. static void tzset_basic __P_((void));
  139. static void tzsetwall_basic __P_((void));
  140. static pthread_mutex_t lcl_mutex  = PTHREAD_MUTEX_INITIALIZER;
  141. static pthread_mutex_t gmt_mutex  = PTHREAD_MUTEX_INITIALIZER;
  142. static int  lcl_is_set  = FALSE;
  143. static int  gmt_is_set  = FALSE;
  144. static struct state lclmem;
  145. static struct state gmtmem;
  146. #define lclptr (&lclmem)
  147. #define gmtptr (&gmtmem)
  148. char * tzname[2] = {
  149. WILDABBR,
  150. WILDABBR
  151. };
  152. #ifdef USG_COMPAT
  153. time_t timezone = 0;
  154. int daylight = 0;
  155. #endif /* defined USG_COMPAT */
  156. #ifdef ALTZONE
  157. time_t altzone = 0;
  158. #endif /* defined ALTZONE */
  159. static int detzcode(const char * codep)
  160. {
  161. long result;
  162. int i;
  163. result = 0;
  164. for (i = 0; i < 4; ++i)
  165. result = (result << 8) | (codep[i] & 0xff);
  166. return result;
  167. }
  168. static void settzname(struct state * sp)
  169. {
  170. register int i;
  171. tzname[0] = WILDABBR;
  172. tzname[1] = WILDABBR;
  173. #ifdef USG_COMPAT
  174. daylight = 0;
  175. timezone = 0;
  176. #endif /* defined USG_COMPAT */
  177. #ifdef ALTZONE
  178. altzone = 0;
  179. #endif /* defined ALTZONE */
  180. for (i = 0; i < sp->typecnt; ++i) {
  181. register const struct ttinfo * const ttisp = &sp->ttis[i];
  182. tzname[ttisp->tt_isdst] =
  183. (char *) &sp->chars[ttisp->tt_abbrind];
  184. #ifdef USG_COMPAT
  185. if (ttisp->tt_isdst)
  186. daylight = 1;
  187. if (i == 0 || !ttisp->tt_isdst)
  188. timezone = -(ttisp->tt_gmtoff);
  189. #endif /* defined USG_COMPAT */
  190. #ifdef ALTZONE
  191. if (i == 0 || ttisp->tt_isdst)
  192. altzone = -(ttisp->tt_gmtoff);
  193. #endif /* defined ALTZONE */
  194. }
  195. /*
  196. ** And to get the latest zone names into tzname. . .
  197. */
  198. for (i = 0; i < sp->timecnt; ++i) {
  199. register const struct ttinfo * const ttisp =
  200. &sp->ttis[sp->types[i]];
  201. tzname[ttisp->tt_isdst] =
  202. (char *) &sp->chars[ttisp->tt_abbrind];
  203. }
  204. }
  205. static int tzload(const char * name, struct state * sp)
  206. {
  207. register const char * p;
  208. register int i;
  209. register int fid;
  210. if (name == NULL && (name = TZDEFAULT) == NULL)
  211. return -1;
  212. {
  213. char fullname[FILENAME_MAX + 1];
  214. if (name[0] == ':')
  215. ++name;
  216. if (name[0] != '/') {
  217. if ((p = TZDIR) == NULL)
  218. return -1;
  219. if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
  220. return -1;
  221. (void) strcpy(fullname, p);
  222. (void) strcat(fullname, "/");
  223. (void) strcat(fullname, name);
  224. name = fullname;
  225. }
  226. if ((fid = open(name, O_RDONLY)) == -1)
  227. return -1;
  228. }
  229. {
  230. register const struct tzhead * tzhp;
  231. char buf[sizeof *sp + sizeof *tzhp];
  232. int ttisstdcnt;
  233. i = read(fid, buf, sizeof buf);
  234. if (close(fid) != 0 || i < sizeof *tzhp)
  235. return -1;
  236. tzhp = (struct tzhead *) buf;
  237. ttisstdcnt = (int) detzcode(tzhp->tzh_ttisstdcnt);
  238. sp->leapcnt = (int) detzcode(tzhp->tzh_leapcnt);
  239. sp->timecnt = (int) detzcode(tzhp->tzh_timecnt);
  240. sp->typecnt = (int) detzcode(tzhp->tzh_typecnt);
  241. sp->charcnt = (int) detzcode(tzhp->tzh_charcnt);
  242. if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
  243. sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
  244. sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
  245. sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
  246. (ttisstdcnt != sp->typecnt && ttisstdcnt != 0))
  247. return -1;
  248. if (i < sizeof *tzhp +
  249. sp->timecnt * (4 + sizeof (char)) +
  250. sp->typecnt * (4 + 2 * sizeof (char)) +
  251. sp->charcnt * sizeof (char) +
  252. sp->leapcnt * 2 * 4 +
  253. ttisstdcnt * sizeof (char))
  254. return -1;
  255. p = buf + sizeof *tzhp;
  256. for (i = 0; i < sp->timecnt; ++i) {
  257. sp->ats[i] = detzcode(p);
  258. p += 4;
  259. }
  260. for (i = 0; i < sp->timecnt; ++i) {
  261. sp->types[i] = (unsigned char) *p++;
  262. if (sp->types[i] >= sp->typecnt)
  263. return -1;
  264. }
  265. for (i = 0; i < sp->typecnt; ++i) {
  266. register struct ttinfo * ttisp;
  267. ttisp = &sp->ttis[i];
  268. ttisp->tt_gmtoff = detzcode(p);
  269. p += 4;
  270. ttisp->tt_isdst = (unsigned char) *p++;
  271. if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
  272. return -1;
  273. ttisp->tt_abbrind = (unsigned char) *p++;
  274. if (ttisp->tt_abbrind < 0 ||
  275. ttisp->tt_abbrind > sp->charcnt)
  276. return -1;
  277. }
  278. for (i = 0; i < sp->charcnt; ++i)
  279. sp->chars[i] = *p++;
  280. sp->chars[i] = ''; /* ensure '' at end */
  281. for (i = 0; i < sp->leapcnt; ++i) {
  282. register struct lsinfo * lsisp;
  283. lsisp = &sp->lsis[i];
  284. lsisp->ls_trans = detzcode(p);
  285. p += 4;
  286. lsisp->ls_corr = detzcode(p);
  287. p += 4;
  288. }
  289. for (i = 0; i < sp->typecnt; ++i) {
  290. register struct ttinfo * ttisp;
  291. ttisp = &sp->ttis[i];
  292. if (ttisstdcnt == 0)
  293. ttisp->tt_ttisstd = FALSE;
  294. else {
  295. ttisp->tt_ttisstd = *p++;
  296. if (ttisp->tt_ttisstd != TRUE &&
  297. ttisp->tt_ttisstd != FALSE)
  298. return -1;
  299. }
  300. }
  301. }
  302. return 0;
  303. }
  304. static const int mon_lengths[2][MONSPERYEAR] = {
  305. 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
  306. 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  307. };
  308. static const int year_lengths[2] = {
  309. DAYSPERNYEAR, DAYSPERLYEAR
  310. };
  311. /*
  312. ** Given a pointer into a time zone string, scan until a character that is not
  313. ** a valid character in a zone name is found.  Return a pointer to that
  314. ** character.
  315. */
  316. static const char * getzname(const char * strp)
  317. {
  318. register char c;
  319. while ((c = *strp) != '' && !isdigit(c) && c != ',' && c != '-' &&
  320. c != '+')
  321. ++strp;
  322. return strp;
  323. }
  324. /*
  325. ** Given a pointer into a time zone string, extract a number from that string.
  326. ** Check that the number is within a specified range; if it is not, return
  327. ** NULL.
  328. ** Otherwise, return a pointer to the first character not part of the number.
  329. */
  330. static const char *getnum(const char * strp, int * nump, int min, int max)
  331. {
  332. char c;
  333. int num;
  334. if (strp == NULL || !isdigit(*strp))
  335. return NULL;
  336. num = 0;
  337. while ((c = *strp) != '' && isdigit(c)) {
  338. num = num * 10 + (c - '0');
  339. if (num > max)
  340. return NULL; /* illegal value */
  341. ++strp;
  342. }
  343. if (num < min)
  344. return NULL; /* illegal value */
  345. *nump = num;
  346. return strp;
  347. }
  348. /*
  349. ** Given a pointer into a time zone string, extract a number of seconds,
  350. ** in hh[:mm[:ss]] form, from the string.
  351. ** If any error occurs, return NULL.
  352. ** Otherwise, return a pointer to the first character not part of the number
  353. ** of seconds.
  354. */
  355. static const char * getsecs(const char * strp, long * secsp)
  356. {
  357. int num;
  358. strp = getnum(strp, &num, 0, HOURSPERDAY);
  359. if (strp == NULL)
  360. return NULL;
  361. *secsp = num * SECSPERHOUR;
  362. if (*strp == ':') {
  363. ++strp;
  364. strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
  365. if (strp == NULL)
  366. return NULL;
  367. *secsp += num * SECSPERMIN;
  368. if (*strp == ':') {
  369. ++strp;
  370. strp = getnum(strp, &num, 0, SECSPERMIN - 1);
  371. if (strp == NULL)
  372. return NULL;
  373. *secsp += num;
  374. }
  375. }
  376. return strp;
  377. }
  378. /*
  379. ** Given a pointer into a time zone string, extract an offset, in
  380. ** [+-]hh[:mm[:ss]] form, from the string.
  381. ** If any error occurs, return NULL.
  382. ** Otherwise, return a pointer to the first character not part of the time.
  383. */
  384. static const char * getoffset(const char * strp, long * offsetp)
  385. {
  386. int neg;
  387. if (*strp == '-') {
  388. neg = 1;
  389. ++strp;
  390. } else if (isdigit(*strp) || *strp++ == '+')
  391. neg = 0;
  392. else return NULL; /* illegal offset */
  393. strp = getsecs(strp, offsetp);
  394. if (strp == NULL)
  395. return NULL; /* illegal time */
  396. if (neg)
  397. *offsetp = -*offsetp;
  398. return strp;
  399. }
  400. /*
  401. ** Given a pointer into a time zone string, extract a rule in the form
  402. ** date[/time].  See POSIX section 8 for the format of "date" and "time".
  403. ** If a valid rule is not found, return NULL.
  404. ** Otherwise, return a pointer to the first character not part of the rule.
  405. */
  406. static const char * getrule(const char * strp, struct rule * rulep)
  407. {
  408. if (*strp == 'J') {
  409. /*
  410. ** Julian day.
  411. */
  412. rulep->r_type = JULIAN_DAY;
  413. ++strp;
  414. strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
  415. } else if (*strp == 'M') {
  416. /*
  417. ** Month, week, day.
  418. */
  419. rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
  420. ++strp;
  421. strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
  422. if (strp == NULL)
  423. return NULL;
  424. if (*strp++ != '.')
  425. return NULL;
  426. strp = getnum(strp, &rulep->r_week, 1, 5);
  427. if (strp == NULL)
  428. return NULL;
  429. if (*strp++ != '.')
  430. return NULL;
  431. strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
  432. } else if (isdigit(*strp)) {
  433. /*
  434. ** Day of year.
  435. */
  436. rulep->r_type = DAY_OF_YEAR;
  437. strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
  438. } else return NULL; /* invalid format */
  439. if (strp == NULL)
  440. return NULL;
  441. if (*strp == '/') {
  442. /*
  443. ** Time specified.
  444. */
  445. ++strp;
  446. strp = getsecs(strp, &rulep->r_time);
  447. } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
  448. return strp;
  449. }
  450. /*
  451. ** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the
  452. ** year, a rule, and the offset from GMT at the time that rule takes effect,
  453. ** calculate the Epoch-relative time that rule takes effect.
  454. */
  455. static time_t transtime(time_t janfirst, int year,
  456.   const struct rule * rulep, long offset)
  457. {
  458. register int leapyear;
  459. register time_t value;
  460. register int i;
  461. int d, m1, yy0, yy1, yy2, dow;
  462. leapyear = isleap(year);
  463. switch (rulep->r_type) {
  464. case JULIAN_DAY:
  465. /*
  466. ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
  467. ** years.
  468. ** In non-leap years, or if the day number is 59 or less, just
  469. ** add SECSPERDAY times the day number-1 to the time of
  470. ** January 1, midnight, to get the day.
  471. */
  472. value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
  473. if (leapyear && rulep->r_day >= 60)
  474. value += SECSPERDAY;
  475. break;
  476. case DAY_OF_YEAR:
  477. /*
  478. ** n - day of year.
  479. ** Just add SECSPERDAY times the day number to the time of
  480. ** January 1, midnight, to get the day.
  481. */
  482. value = janfirst + rulep->r_day * SECSPERDAY;
  483. break;
  484. case MONTH_NTH_DAY_OF_WEEK:
  485. /*
  486. ** Mm.n.d - nth "dth day" of month m.
  487. */
  488. value = janfirst;
  489. for (i = 0; i < rulep->r_mon - 1; ++i)
  490. value += mon_lengths[leapyear][i] * SECSPERDAY;
  491. /*
  492. ** Use Zeller's Congruence to get day-of-week of first day of
  493. ** month.
  494. */
  495. m1 = (rulep->r_mon + 9) % 12 + 1;
  496. yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
  497. yy1 = yy0 / 100;
  498. yy2 = yy0 % 100;
  499. dow = ((26 * m1 - 2) / 10 +
  500. 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
  501. if (dow < 0)
  502. dow += DAYSPERWEEK;
  503. /*
  504. ** "dow" is the day-of-week of the first day of the month.  Get
  505. ** the day-of-month (zero-origin) of the first "dow" day of the
  506. ** month.
  507. */
  508. d = rulep->r_day - dow;
  509. if (d < 0)
  510. d += DAYSPERWEEK;
  511. for (i = 1; i < rulep->r_week; ++i) {
  512. if (d + DAYSPERWEEK >=
  513. mon_lengths[leapyear][rulep->r_mon - 1])
  514. break;
  515. d += DAYSPERWEEK;
  516. }
  517. /*
  518. ** "d" is the day-of-month (zero-origin) of the day we want.
  519. */
  520. value += d * SECSPERDAY;
  521. break;
  522. }
  523. /*
  524. ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
  525. ** question.  To get the Epoch-relative time of the specified local
  526. ** time on that day, add the transition time and the current offset
  527. ** from GMT.
  528. */
  529. return value + rulep->r_time + offset;
  530. }
  531. /*
  532. ** Given a POSIX section 8-style TZ string, fill in the rule tables as
  533. ** appropriate.
  534. */
  535. static int tzparse(const char * name, struct state * sp, int lastditch)
  536. {
  537. const char * stdname;
  538. const char * dstname;
  539. int stdlen;
  540. int dstlen;
  541. long stdoffset;
  542. long dstoffset;
  543. register time_t * atp;
  544. register unsigned char * typep;
  545. register char * cp;
  546. register int load_result;
  547. stdname = name;
  548. if (lastditch) {
  549. stdlen = strlen(name); /* length of standard zone name */
  550. name += stdlen;
  551. if (stdlen >= sizeof sp->chars)
  552. stdlen = (sizeof sp->chars) - 1;
  553. } else {
  554. name = getzname(name);
  555. stdlen = name - stdname;
  556. if (stdlen < 3)
  557. return -1;
  558. }
  559. if (*name == '')
  560. return -1;
  561. else {
  562. name = getoffset(name, &stdoffset);
  563. if (name == NULL)
  564. return -1;
  565. }
  566. load_result = tzload(TZDEFRULES, sp);
  567. if (load_result != 0)
  568. sp->leapcnt = 0; /* so, we're off a little */
  569. if (*name != '') {
  570. dstname = name;
  571. name = getzname(name);
  572. dstlen = name - dstname; /* length of DST zone name */
  573. if (dstlen < 3)
  574. return -1;
  575. if (*name != '' && *name != ',' && *name != ';') {
  576. name = getoffset(name, &dstoffset);
  577. if (name == NULL)
  578. return -1;
  579. } else dstoffset = stdoffset - SECSPERHOUR;
  580. if (*name == ',' || *name == ';') {
  581. struct rule start;
  582. struct rule end;
  583. register int year;
  584. register time_t janfirst;
  585. time_t starttime;
  586. time_t endtime;
  587. ++name;
  588. if ((name = getrule(name, &start)) == NULL)
  589. return -1;
  590. if (*name++ != ',')
  591. return -1;
  592. if ((name = getrule(name, &end)) == NULL)
  593. return -1;
  594. if (*name != '')
  595. return -1;
  596. sp->typecnt = 2; /* standard time and DST */
  597. /*
  598. ** Two transitions per year, from EPOCH_YEAR to 2037.
  599. */
  600. sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
  601. if (sp->timecnt > TZ_MAX_TIMES)
  602. return -1;
  603. sp->ttis[0].tt_gmtoff = -dstoffset;
  604. sp->ttis[0].tt_isdst = 1;
  605. sp->ttis[0].tt_abbrind = stdlen + 1;
  606. sp->ttis[1].tt_gmtoff = -stdoffset;
  607. sp->ttis[1].tt_isdst = 0;
  608. sp->ttis[1].tt_abbrind = 0;
  609. atp = sp->ats;
  610. typep = sp->types;
  611. janfirst = 0;
  612. for (year = EPOCH_YEAR; year <= 2037; ++year) {
  613. starttime = transtime(janfirst, year, &start,
  614. stdoffset);
  615. endtime = transtime(janfirst, year, &end,
  616. dstoffset);
  617. if (starttime > endtime) {
  618. *atp++ = endtime;
  619. *typep++ = 1; /* DST ends */
  620. *atp++ = starttime;
  621. *typep++ = 0; /* DST begins */
  622. } else {
  623. *atp++ = starttime;
  624. *typep++ = 0; /* DST begins */
  625. *atp++ = endtime;
  626. *typep++ = 1; /* DST ends */
  627. }
  628. janfirst +=
  629. year_lengths[isleap(year)] * SECSPERDAY;
  630. }
  631. } else {
  632. int sawstd;
  633. int sawdst;
  634. long stdfix;
  635. long dstfix;
  636. long oldfix;
  637. int isdst;
  638. register int i;
  639. if (*name != '')
  640. return -1;
  641. if (load_result != 0)
  642. return -1;
  643. /*
  644. ** Compute the difference between the real and
  645. ** prototype standard and summer time offsets
  646. ** from GMT, and put the real standard and summer
  647. ** time offsets into the rules in place of the
  648. ** prototype offsets.
  649. */
  650. sawstd = FALSE;
  651. sawdst = FALSE;
  652. stdfix = 0;
  653. dstfix = 0;
  654. for (i = 0; i < sp->typecnt; ++i) {
  655. if (sp->ttis[i].tt_isdst) {
  656. oldfix = dstfix;
  657. dstfix =
  658.     sp->ttis[i].tt_gmtoff + dstoffset;
  659. if (sawdst && (oldfix != dstfix))
  660. return -1;
  661. sp->ttis[i].tt_gmtoff = -dstoffset;
  662. sp->ttis[i].tt_abbrind = stdlen + 1;
  663. sawdst = TRUE;
  664. } else {
  665. oldfix = stdfix;
  666. stdfix =
  667.     sp->ttis[i].tt_gmtoff + stdoffset;
  668. if (sawstd && (oldfix != stdfix))
  669. return -1;
  670. sp->ttis[i].tt_gmtoff = -stdoffset;
  671. sp->ttis[i].tt_abbrind = 0;
  672. sawstd = TRUE;
  673. }
  674. }
  675. /*
  676. ** Make sure we have both standard and summer time.
  677. */
  678. if (!sawdst || !sawstd)
  679. return -1;
  680. /*
  681. ** Now correct the transition times by shifting
  682. ** them by the difference between the real and
  683. ** prototype offsets.  Note that this difference
  684. ** can be different in standard and summer time;
  685. ** the prototype probably has a 1-hour difference
  686. ** between standard and summer time, but a different
  687. ** difference can be specified in TZ.
  688. */
  689. isdst = FALSE; /* we start in standard time */
  690. for (i = 0; i < sp->timecnt; ++i) {
  691. register const struct ttinfo * ttisp;
  692. /*
  693. ** If summer time is in effect, and the
  694. ** transition time was not specified as
  695. ** standard time, add the summer time
  696. ** offset to the transition time;
  697. ** otherwise, add the standard time offset
  698. ** to the transition time.
  699. */
  700. ttisp = &sp->ttis[sp->types[i]];
  701. sp->ats[i] +=
  702. (isdst && !ttisp->tt_ttisstd) ?
  703. dstfix : stdfix;
  704. isdst = ttisp->tt_isdst;
  705. }
  706. }
  707. } else {
  708. dstlen = 0;
  709. sp->typecnt = 1; /* only standard time */
  710. sp->timecnt = 0;
  711. sp->ttis[0].tt_gmtoff = -stdoffset;
  712. sp->ttis[0].tt_isdst = 0;
  713. sp->ttis[0].tt_abbrind = 0;
  714. }
  715. sp->charcnt = stdlen + 1;
  716. if (dstlen != 0)
  717. sp->charcnt += dstlen + 1;
  718. if (sp->charcnt > sizeof sp->chars)
  719. return -1;
  720. cp = sp->chars;
  721. (void) strncpy(cp, stdname, stdlen);
  722. cp += stdlen;
  723. *cp++ = '';
  724. if (dstlen != 0) {
  725. (void) strncpy(cp, dstname, dstlen);
  726. *(cp + dstlen) = '';
  727. }
  728. return 0;
  729. }
  730. static void gmtload(struct state * sp)
  731. {
  732. if (tzload(GMT, sp) != 0)
  733. (void) tzparse(GMT, sp, TRUE);
  734. }
  735. static void tzset_basic()
  736. {
  737. const char * name;
  738. if ((name = getenv("TZ")) == NULL) {
  739. tzsetwall_basic();
  740. return;
  741. }
  742. if (*name == '') {
  743. /*
  744. ** User wants it fast rather than right.
  745. */
  746. lclptr->leapcnt = 0; /* so, we're off a little */
  747. lclptr->timecnt = 0;
  748. lclptr->ttis[0].tt_gmtoff = 0;
  749. lclptr->ttis[0].tt_abbrind = 0;
  750. (void) strcpy(lclptr->chars, GMT);
  751. } else {
  752. if (tzload(name, lclptr) != 0)
  753. if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
  754. (void) gmtload(lclptr);
  755. }
  756. lcl_is_set = TRUE;
  757. settzname(lclptr);
  758. }
  759. void tzset()
  760. {
  761. pthread_mutex_lock(&lcl_mutex);
  762. tzset_basic();
  763. pthread_mutex_unlock(&lcl_mutex);
  764. }
  765. static void tzsetwall_basic()
  766. {
  767. if (tzload((char *) NULL, lclptr) != 0)
  768. gmtload(lclptr);
  769. settzname(lclptr);
  770. lcl_is_set = TRUE;
  771. }
  772. void tzsetwall()
  773. {
  774. pthread_mutex_lock(&lcl_mutex);
  775. tzsetwall_basic();
  776. pthread_mutex_unlock(&lcl_mutex);
  777. }
  778. /*
  779. ** The easy way to behave "as if no library function calls" localtime
  780. ** is to not call it--so we drop its guts into "localsub", which can be
  781. ** freely called.  (And no, the PANS doesn't require the above behavior--
  782. ** but it *is* desirable.)
  783. **
  784. ** The unused offset argument is for the benefit of mktime variants.
  785. */
  786. static void localsub(const time_t * timep, long offset, struct tm * tmp)
  787. {
  788. const struct ttinfo * ttisp;
  789. const time_t t = *timep;
  790. struct state * sp;
  791. int i;
  792. if (!lcl_is_set)
  793. tzset_basic();
  794. sp = lclptr;
  795. if (sp->timecnt == 0 || t < sp->ats[0]) {
  796. i = 0;
  797. while (sp->ttis[i].tt_isdst)
  798. if (++i >= sp->typecnt) {
  799. i = 0;
  800. break;
  801. }
  802. } else {
  803. for (i = 1; i < sp->timecnt; ++i)
  804. if (t < sp->ats[i])
  805. break;
  806. i = sp->types[i - 1];
  807. }
  808. ttisp = &sp->ttis[i];
  809. /*
  810. ** To get (wrong) behavior that's compatible with System V Release 2.0
  811. ** you'd replace the statement below with
  812. ** t += ttisp->tt_gmtoff;
  813. ** timesub(&t, 0L, sp, tmp);
  814. */
  815. timesub(&t, ttisp->tt_gmtoff, sp, tmp);
  816. tzname[tmp->tm_isdst] = (char *) &sp->chars[ttisp->tt_abbrind];
  817. #ifdef BSD_TM
  818. tmp->tm_zone = &sp->chars[ttisp->tt_abbrind];
  819. #endif
  820. tmp->tm_isdst = ttisp->tt_isdst;
  821. pthread_mutex_unlock(&lcl_mutex);
  822. }
  823. struct tm * localtime_r(const time_t * timep, struct tm * tm)
  824. {
  825. pthread_mutex_lock(&lcl_mutex);
  826. localsub(timep, 0L, tm);
  827. pthread_mutex_unlock(&lcl_mutex);
  828. return(tm);
  829. }
  830. struct tm * localtime(const time_t * timep)
  831. {
  832. static pthread_mutex_t localtime_mutex = PTHREAD_MUTEX_INITIALIZER;
  833. static pthread_key_t localtime_key = -1;
  834. struct tm * tm;
  835. pthread_mutex_lock(&localtime_mutex);
  836. if (localtime_key < 0) {
  837. if (pthread_key_create(&localtime_key, free) < 0) {
  838. pthread_mutex_unlock(&localtime_mutex);
  839. return(NULL);
  840. }
  841. }
  842. pthread_mutex_unlock(&localtime_mutex);
  843. if ((tm = pthread_getspecific(localtime_key)) == NULL) {
  844. if ((tm = (struct tm *)malloc(sizeof(struct tm))) == NULL) {
  845. return(NULL);
  846. }
  847. pthread_setspecific(localtime_key, tm);
  848. }
  849. pthread_mutex_lock(&lcl_mutex);
  850. localsub(timep, 0L, tm);
  851. pthread_mutex_unlock(&lcl_mutex);
  852. return tm;
  853. }
  854. /*
  855.  * gmtsub is to gmtime as localsub is to localtime.
  856.  *
  857.  * Once set there is no need to lock the gmt_mutex to view gmtptr 
  858.  */
  859. static void gmtsub(const time_t * timep, long offset, struct tm * tmp)
  860. {
  861. pthread_mutex_lock(&gmt_mutex);
  862. if (gmt_is_set == FALSE) {
  863. gmt_is_set = TRUE;
  864. gmtload(gmtptr);
  865. }
  866. pthread_mutex_unlock(&gmt_mutex);
  867. timesub(timep, offset, gmtptr, tmp);
  868. /*
  869. ** Could get fancy here and deliver something such as
  870. ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero,
  871. ** but this is no time for a treasure hunt.
  872. */
  873. #ifdef BSD_TM
  874. if (offset != 0) {
  875. tmp->tm_zone = WILDABBR;
  876. } else {
  877. tmp->tm_zone = gmtptr->chars;
  878. }
  879. #endif
  880. }
  881. struct tm * gmtime_r(const time_t * timep, struct tm * tm)
  882. {
  883. gmtsub(timep, 0L, tm);
  884. return(tm);
  885. }
  886. struct tm * gmtime(const time_t * timep)
  887. {
  888. static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER;
  889. static pthread_key_t gmtime_key = -1;
  890. struct tm * tm;
  891. pthread_mutex_lock(&gmtime_mutex);
  892. if (gmtime_key < 0) {
  893. if (pthread_key_create(&gmtime_key, free) < 0) {
  894. pthread_mutex_unlock(&gmtime_mutex);
  895. return(NULL);
  896. }
  897. }
  898. pthread_mutex_unlock(&gmtime_mutex);
  899. if ((tm = pthread_getspecific(gmtime_key)) == NULL) {
  900. if ((tm = (struct tm *)malloc(sizeof(struct tm))) == NULL) {
  901. return(NULL);
  902. }
  903. pthread_setspecific(gmtime_key, tm);
  904. }
  905. gmtsub(timep, 0L, tm);
  906. return(tm);
  907. }
  908. static void timesub(const time_t * timep, long offset,
  909.   const struct state * sp, struct tm * tmp)
  910. {
  911. register const struct lsinfo * lp;
  912. register long days;
  913. register long rem;
  914. register int y;
  915. register int yleap;
  916. register const int * ip;
  917. register long corr;
  918. register int hit;
  919. register int i;
  920. corr = 0;
  921. hit = FALSE;
  922. i = sp->leapcnt;
  923. while (--i >= 0) {
  924. lp = &sp->lsis[i];
  925. if (*timep >= lp->ls_trans) {
  926. if (*timep == lp->ls_trans)
  927. hit = ((i == 0 && lp->ls_corr > 0) ||
  928. lp->ls_corr > sp->lsis[i - 1].ls_corr);
  929. corr = lp->ls_corr;
  930. break;
  931. }
  932. }
  933. days = *timep / SECSPERDAY;
  934. rem = *timep % SECSPERDAY;
  935. #ifdef mc68k
  936. if (*timep == 0x80000000) {
  937. /*
  938. ** A 3B1 muffs the division on the most negative number.
  939. */
  940. days = -24855;
  941. rem = -11648;
  942. }
  943. #endif /* mc68k */
  944. rem += (offset - corr);
  945. while (rem < 0) {
  946. rem += SECSPERDAY;
  947. --days;
  948. }
  949. while (rem >= SECSPERDAY) {
  950. rem -= SECSPERDAY;
  951. ++days;
  952. }
  953. tmp->tm_hour = (int) (rem / SECSPERHOUR);
  954. rem = rem % SECSPERHOUR;
  955. tmp->tm_min = (int) (rem / SECSPERMIN);
  956. tmp->tm_sec = (int) (rem % SECSPERMIN);
  957. if (hit)
  958. /*
  959. ** A positive leap second requires a special
  960. ** representation.  This uses "... ??:59:60".
  961. */
  962. ++(tmp->tm_sec);
  963. tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
  964. if (tmp->tm_wday < 0)
  965. tmp->tm_wday += DAYSPERWEEK;
  966. y = EPOCH_YEAR;
  967. if (days >= 0)
  968. for ( ; ; ) {
  969. yleap = isleap(y);
  970. if (days < (long) year_lengths[yleap])
  971. break;
  972. ++y;
  973. days = days - (long) year_lengths[yleap];
  974. }
  975. else do {
  976. --y;
  977. yleap = isleap(y);
  978. days = days + (long) year_lengths[yleap];
  979. } while (days < 0);
  980. tmp->tm_year = y - TM_YEAR_BASE;
  981. tmp->tm_yday = (int) days;
  982. ip = mon_lengths[yleap];
  983. for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
  984. days = days - (long) ip[tmp->tm_mon];
  985. tmp->tm_mday = (int) (days + 1);
  986. tmp->tm_isdst = 0;
  987. #ifdef BSD_TM
  988. tmp->tm_gmtoff = offset;
  989. #endif
  990. }
  991. /*
  992.  * A la X3J11
  993.  *
  994.  * Made thread safe by using thread specific data
  995.  */
  996. char * asctime_r(const struct tm * timeptr, char * result)
  997. {
  998. static const char wday_name[DAYSPERWEEK][3] = {
  999. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  1000. };
  1001. static const char mon_name[MONSPERYEAR][3] = {
  1002. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1003. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  1004. };
  1005. (void) sprintf(result, "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %dn",
  1006. wday_name[timeptr->tm_wday],
  1007. mon_name[timeptr->tm_mon],
  1008. timeptr->tm_mday, timeptr->tm_hour,
  1009. timeptr->tm_min, timeptr->tm_sec,
  1010. TM_YEAR_BASE + timeptr->tm_year);
  1011. return(result);
  1012. }
  1013. char * asctime(const struct tm * timeptr)
  1014. {
  1015. static pthread_mutex_t asctime_mutex = PTHREAD_MUTEX_INITIALIZER;
  1016. static pthread_key_t asctime_key = -1;
  1017. char * result;
  1018. pthread_mutex_lock(&asctime_mutex);
  1019. if (asctime_key < 0) {
  1020. if (pthread_key_create(&asctime_key, free) < 0) {
  1021. pthread_mutex_unlock(&asctime_mutex);
  1022. return(NULL);
  1023. }
  1024. }
  1025. pthread_mutex_unlock(&asctime_mutex);
  1026. if ((result = pthread_getspecific(asctime_key)) == NULL) {
  1027. if ((result = malloc(26)) == NULL) {
  1028. return(NULL);
  1029. }
  1030. pthread_setspecific(asctime_key, result);
  1031. }
  1032. return(asctime_r(timeptr, result));
  1033. }
  1034. char * ctime_r(const time_t * timep, char * buf)
  1035. {
  1036. struct tm tm;
  1037. return asctime_r(localtime_r(timep, &tm), buf);
  1038. }
  1039. char * ctime(const time_t * timep)
  1040. {
  1041. struct tm tm;
  1042. return asctime(localtime_r(timep, &tm));
  1043. }
  1044. /*
  1045. ** Adapted from code provided by Robert Elz, who writes:
  1046. ** The "best" way to do mktime I think is based on an idea of Bob
  1047. ** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
  1048. ** It does a binary search of the time_t space.  Since time_t's are
  1049. ** just 32 bits, its a max of 32 iterations (even at 64 bits it
  1050. ** would still be very reasonable).
  1051. */
  1052. static void normalize(int * tensptr,int *  unitsptr, int base)
  1053. {
  1054. if (*unitsptr >= base) {
  1055. *tensptr += *unitsptr / base;
  1056. *unitsptr %= base;
  1057. } else if (*unitsptr < 0) {
  1058. --*tensptr;
  1059. *unitsptr += base;
  1060. if (*unitsptr < 0) {
  1061. *tensptr -= 1 + (-*unitsptr) / base;
  1062. *unitsptr = base - (-*unitsptr) % base;
  1063. }
  1064. }
  1065. }
  1066. static int tmcomp(const struct tm * atmp, const struct tm * btmp)
  1067. {
  1068. register int result;
  1069. if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
  1070. (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
  1071. (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
  1072. (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
  1073. (result = (atmp->tm_min - btmp->tm_min)) == 0)
  1074. result = atmp->tm_sec - btmp->tm_sec;
  1075. return result;
  1076. }
  1077. static time_t time2(struct tm * tmp, long offset, int * okayp)
  1078. {
  1079. register const struct state * sp;
  1080. register int dir;
  1081. register int bits;
  1082. register int i, j ;
  1083. register int saved_seconds;
  1084. time_t newt;
  1085. time_t t;
  1086. struct tm yourtm, mytm;
  1087. *okayp = FALSE;
  1088. yourtm = *tmp;
  1089. if (yourtm.tm_sec >= SECSPERMIN + 2 || yourtm.tm_sec < 0)
  1090. normalize(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN);
  1091. normalize(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR);
  1092. normalize(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY);
  1093. normalize(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR);
  1094. while (yourtm.tm_mday <= 0) {
  1095. --yourtm.tm_year;
  1096. yourtm.tm_mday +=
  1097. year_lengths[isleap(yourtm.tm_year + TM_YEAR_BASE)];
  1098. }
  1099. for ( ; ; ) {
  1100. i = mon_lengths[isleap(yourtm.tm_year +
  1101. TM_YEAR_BASE)][yourtm.tm_mon];
  1102. if (yourtm.tm_mday <= i)
  1103. break;
  1104. yourtm.tm_mday -= i;
  1105. if (++yourtm.tm_mon >= MONSPERYEAR) {
  1106. yourtm.tm_mon = 0;
  1107. ++yourtm.tm_year;
  1108. }
  1109. }
  1110. saved_seconds = yourtm.tm_sec;
  1111. yourtm.tm_sec = 0;
  1112. /*
  1113. ** Calculate the number of magnitude bits in a time_t
  1114. ** (this works regardless of whether time_t is
  1115. ** signed or unsigned, though lint complains if unsigned).
  1116. */
  1117. for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
  1118. ;
  1119. /*
  1120. ** If time_t is signed, then 0 is the median value,
  1121. ** if time_t is unsigned, then 1 << bits is median.
  1122. */
  1123. t = (t < 0) ? 0 : ((time_t) 1 << bits);
  1124. for ( ; ; ) {
  1125. localsub(&t, offset, &mytm);
  1126. dir = tmcomp(&mytm, &yourtm);
  1127. if (dir != 0) {
  1128. if (bits-- < 0)
  1129. return NOTOK;
  1130. if (bits < 0)
  1131. --t;
  1132. else if (dir > 0)
  1133. t -= (time_t) 1 << bits;
  1134. else t += (time_t) 1 << bits;
  1135. continue;
  1136. }
  1137. if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
  1138. break;
  1139. /*
  1140. ** Right time, wrong type.
  1141. ** Hunt for right time, right type.
  1142. ** It's okay to guess wrong since the guess
  1143. ** gets checked.
  1144. */
  1145. sp = lclptr;
  1146. for (i = 0; i < sp->typecnt; ++i) {
  1147. if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
  1148. continue;
  1149. for (j = 0; j < sp->typecnt; ++j) {
  1150. if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
  1151. continue;
  1152. newt = t + sp->ttis[j].tt_gmtoff -
  1153. sp->ttis[i].tt_gmtoff;
  1154. localsub(&newt, offset, &mytm);
  1155. if (tmcomp(&mytm, &yourtm) != 0)
  1156. continue;
  1157. if (mytm.tm_isdst != yourtm.tm_isdst)
  1158. continue;
  1159. /*
  1160. ** We have a match.
  1161. */
  1162. t = newt;
  1163. goto label;
  1164. }
  1165. }
  1166. return NOTOK;
  1167. }
  1168. label:
  1169. t += saved_seconds;
  1170. localsub(&t, offset, tmp);
  1171. *okayp = TRUE;
  1172. return t;
  1173. }
  1174. static time_t time1(struct tm * tmp, long offset)
  1175. {
  1176. const struct state * sp;
  1177. int samei, otheri, okay;
  1178. time_t t;
  1179. if (tmp->tm_isdst > 1)
  1180. tmp->tm_isdst = 1;
  1181. t = time2(tmp, offset, &okay);
  1182. if (okay || tmp->tm_isdst < 0)
  1183. return t;
  1184. /*
  1185. ** We're supposed to assume that somebody took a time of one type
  1186. ** and did some math on it that yielded a "struct tm" that's bad.
  1187. ** We try to divine the type they started from and adjust to the
  1188. ** type they need.
  1189. */
  1190. sp = lclptr;
  1191. for (samei = 0; samei < sp->typecnt; ++samei) {
  1192. if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
  1193. continue;
  1194. for (otheri = 0; otheri < sp->typecnt; ++otheri) {
  1195. if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
  1196. continue;
  1197. tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
  1198. sp->ttis[samei].tt_gmtoff;
  1199. tmp->tm_isdst = !tmp->tm_isdst;
  1200. t = time2(tmp, offset, &okay);
  1201. if (okay) 
  1202. return t;
  1203. tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
  1204. sp->ttis[samei].tt_gmtoff;
  1205. tmp->tm_isdst = !tmp->tm_isdst;
  1206. }
  1207. }
  1208. return NOTOK;
  1209. }
  1210. time_t mktime(struct tm * tmp)
  1211. {
  1212. time_t mktime_return_value;
  1213. pthread_mutex_lock(&lcl_mutex);
  1214. if (lcl_is_set == FALSE) {
  1215. tzset_basic();
  1216. }
  1217. mktime_return_value = time1(tmp, 0L);
  1218. pthread_mutex_unlock(&lcl_mutex);
  1219. return(mktime_return_value);
  1220. }