1 | #include <_ansi.h> |
---|
2 | #include <reent.h> |
---|
3 | #include <stdio.h> |
---|
4 | #include <stdlib.h> |
---|
5 | #include <string.h> |
---|
6 | #include <sys/types.h> |
---|
7 | #include <sys/time.h> |
---|
8 | #include "local.h" |
---|
9 | |
---|
10 | #define sscanf siscanf /* avoid to pull in FP functions. */ |
---|
11 | |
---|
12 | static char __tzname_std[11]; |
---|
13 | static char __tzname_dst[11]; |
---|
14 | static char *prev_tzenv = NULL; |
---|
15 | |
---|
16 | void |
---|
17 | _tzset_unlocked_r (struct _reent *reent_ptr) |
---|
18 | { |
---|
19 | char *tzenv; |
---|
20 | unsigned short hh, mm, ss, m, w, d; |
---|
21 | int sign, n; |
---|
22 | int i, ch; |
---|
23 | __tzinfo_type *tz = __gettzinfo (); |
---|
24 | |
---|
25 | if ((tzenv = _getenv_r (reent_ptr, "TZ")) == NULL) |
---|
26 | { |
---|
27 | _timezone = 0; |
---|
28 | _daylight = 0; |
---|
29 | _tzname[0] = "GMT"; |
---|
30 | _tzname[1] = "GMT"; |
---|
31 | free(prev_tzenv); |
---|
32 | prev_tzenv = NULL; |
---|
33 | return; |
---|
34 | } |
---|
35 | |
---|
36 | if (prev_tzenv != NULL && strcmp(tzenv, prev_tzenv) == 0) |
---|
37 | return; |
---|
38 | |
---|
39 | free(prev_tzenv); |
---|
40 | prev_tzenv = _malloc_r (reent_ptr, strlen(tzenv) + 1); |
---|
41 | if (prev_tzenv != NULL) |
---|
42 | strcpy (prev_tzenv, tzenv); |
---|
43 | |
---|
44 | /* ignore implementation-specific format specifier */ |
---|
45 | if (*tzenv == ':') |
---|
46 | ++tzenv; |
---|
47 | |
---|
48 | if (sscanf (tzenv, "%10[^0-9,+-]%n", __tzname_std, &n) <= 0) |
---|
49 | return; |
---|
50 | |
---|
51 | tzenv += n; |
---|
52 | |
---|
53 | sign = 1; |
---|
54 | if (*tzenv == '-') |
---|
55 | { |
---|
56 | sign = -1; |
---|
57 | ++tzenv; |
---|
58 | } |
---|
59 | else if (*tzenv == '+') |
---|
60 | ++tzenv; |
---|
61 | |
---|
62 | mm = 0; |
---|
63 | ss = 0; |
---|
64 | |
---|
65 | if (sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n) < 1) |
---|
66 | return; |
---|
67 | |
---|
68 | tz->__tzrule[0].offset = sign * (ss + SECSPERMIN * mm + SECSPERHOUR * hh); |
---|
69 | _tzname[0] = __tzname_std; |
---|
70 | tzenv += n; |
---|
71 | |
---|
72 | if (sscanf (tzenv, "%10[^0-9,+-]%n", __tzname_dst, &n) <= 0) |
---|
73 | { /* No dst */ |
---|
74 | _tzname[1] = _tzname[0]; |
---|
75 | _timezone = tz->__tzrule[0].offset; |
---|
76 | _daylight = 0; |
---|
77 | return; |
---|
78 | } |
---|
79 | else |
---|
80 | _tzname[1] = __tzname_dst; |
---|
81 | |
---|
82 | tzenv += n; |
---|
83 | |
---|
84 | /* otherwise we have a dst name, look for the offset */ |
---|
85 | sign = 1; |
---|
86 | if (*tzenv == '-') |
---|
87 | { |
---|
88 | sign = -1; |
---|
89 | ++tzenv; |
---|
90 | } |
---|
91 | else if (*tzenv == '+') |
---|
92 | ++tzenv; |
---|
93 | |
---|
94 | hh = 0; |
---|
95 | mm = 0; |
---|
96 | ss = 0; |
---|
97 | |
---|
98 | n = 0; |
---|
99 | if (sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n) <= 0) |
---|
100 | tz->__tzrule[1].offset = tz->__tzrule[0].offset - 3600; |
---|
101 | else |
---|
102 | tz->__tzrule[1].offset = sign * (ss + SECSPERMIN * mm + SECSPERHOUR * hh); |
---|
103 | |
---|
104 | tzenv += n; |
---|
105 | |
---|
106 | for (i = 0; i < 2; ++i) |
---|
107 | { |
---|
108 | if (*tzenv == ',') |
---|
109 | ++tzenv; |
---|
110 | |
---|
111 | if (*tzenv == 'M') |
---|
112 | { |
---|
113 | if (sscanf (tzenv, "M%hu%n.%hu%n.%hu%n", &m, &n, &w, &n, &d, &n) != 3 || |
---|
114 | m < 1 || m > 12 || w < 1 || w > 5 || d > 6) |
---|
115 | return; |
---|
116 | |
---|
117 | tz->__tzrule[i].ch = 'M'; |
---|
118 | tz->__tzrule[i].m = m; |
---|
119 | tz->__tzrule[i].n = w; |
---|
120 | tz->__tzrule[i].d = d; |
---|
121 | |
---|
122 | tzenv += n; |
---|
123 | } |
---|
124 | else |
---|
125 | { |
---|
126 | char *end; |
---|
127 | if (*tzenv == 'J') |
---|
128 | { |
---|
129 | ch = 'J'; |
---|
130 | ++tzenv; |
---|
131 | } |
---|
132 | else |
---|
133 | ch = 'D'; |
---|
134 | |
---|
135 | d = strtoul (tzenv, &end, 10); |
---|
136 | |
---|
137 | /* if unspecified, default to US settings */ |
---|
138 | /* From 1987-2006, US was M4.1.0,M10.5.0, but starting in 2007 is |
---|
139 | * M3.2.0,M11.1.0 (2nd Sunday March through 1st Sunday November) */ |
---|
140 | if (end == tzenv) |
---|
141 | { |
---|
142 | if (i == 0) |
---|
143 | { |
---|
144 | tz->__tzrule[0].ch = 'M'; |
---|
145 | tz->__tzrule[0].m = 3; |
---|
146 | tz->__tzrule[0].n = 2; |
---|
147 | tz->__tzrule[0].d = 0; |
---|
148 | } |
---|
149 | else |
---|
150 | { |
---|
151 | tz->__tzrule[1].ch = 'M'; |
---|
152 | tz->__tzrule[1].m = 11; |
---|
153 | tz->__tzrule[1].n = 1; |
---|
154 | tz->__tzrule[1].d = 0; |
---|
155 | } |
---|
156 | } |
---|
157 | else |
---|
158 | { |
---|
159 | tz->__tzrule[i].ch = ch; |
---|
160 | tz->__tzrule[i].d = d; |
---|
161 | } |
---|
162 | |
---|
163 | tzenv = end; |
---|
164 | } |
---|
165 | |
---|
166 | /* default time is 02:00:00 am */ |
---|
167 | hh = 2; |
---|
168 | mm = 0; |
---|
169 | ss = 0; |
---|
170 | n = 0; |
---|
171 | |
---|
172 | if (*tzenv == '/') |
---|
173 | sscanf (tzenv, "/%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n); |
---|
174 | |
---|
175 | tz->__tzrule[i].s = ss + SECSPERMIN * mm + SECSPERHOUR * hh; |
---|
176 | |
---|
177 | tzenv += n; |
---|
178 | } |
---|
179 | |
---|
180 | __tzcalc_limits (tz->__tzyear); |
---|
181 | _timezone = tz->__tzrule[0].offset; |
---|
182 | _daylight = tz->__tzrule[0].offset != tz->__tzrule[1].offset; |
---|
183 | } |
---|
184 | |
---|
185 | void |
---|
186 | _tzset_r (struct _reent *reent_ptr) |
---|
187 | { |
---|
188 | TZ_LOCK; |
---|
189 | _tzset_unlocked_r (reent_ptr); |
---|
190 | TZ_UNLOCK; |
---|
191 | } |
---|