0,0 → 1,193 |
#include <_ansi.h> |
#include <reent.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <sys/types.h> |
#include <sys/time.h> |
#include "local.h" |
|
#define sscanf siscanf /* avoid to pull in FP functions. */ |
|
static char __tzname_std[11]; |
static char __tzname_dst[11]; |
static char *prev_tzenv = NULL; |
|
_VOID |
_DEFUN (_tzset_unlocked_r, (reent_ptr), |
struct _reent *reent_ptr) |
{ |
char *tzenv; |
unsigned short hh, mm, ss, m, w, d; |
int sign, n; |
int i, ch; |
__tzinfo_type *tz = __gettzinfo (); |
|
if ((tzenv = _getenv_r (reent_ptr, "TZ")) == NULL) |
{ |
_timezone = 0; |
_daylight = 0; |
_tzname[0] = "GMT"; |
_tzname[1] = "GMT"; |
free(prev_tzenv); |
prev_tzenv = NULL; |
return; |
} |
|
if (prev_tzenv != NULL && strcmp(tzenv, prev_tzenv) == 0) |
return; |
|
free(prev_tzenv); |
prev_tzenv = _malloc_r (reent_ptr, strlen(tzenv) + 1); |
if (prev_tzenv != NULL) |
strcpy (prev_tzenv, tzenv); |
|
/* ignore implementation-specific format specifier */ |
if (*tzenv == ':') |
++tzenv; |
|
if (sscanf (tzenv, "%10[^0-9,+-]%n", __tzname_std, &n) <= 0) |
return; |
|
tzenv += n; |
|
sign = 1; |
if (*tzenv == '-') |
{ |
sign = -1; |
++tzenv; |
} |
else if (*tzenv == '+') |
++tzenv; |
|
mm = 0; |
ss = 0; |
|
if (sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n) < 1) |
return; |
|
tz->__tzrule[0].offset = sign * (ss + SECSPERMIN * mm + SECSPERHOUR * hh); |
_tzname[0] = __tzname_std; |
tzenv += n; |
|
if (sscanf (tzenv, "%10[^0-9,+-]%n", __tzname_dst, &n) <= 0) |
{ /* No dst */ |
_tzname[1] = _tzname[0]; |
_timezone = tz->__tzrule[0].offset; |
_daylight = 0; |
return; |
} |
else |
_tzname[1] = __tzname_dst; |
|
tzenv += n; |
|
/* otherwise we have a dst name, look for the offset */ |
sign = 1; |
if (*tzenv == '-') |
{ |
sign = -1; |
++tzenv; |
} |
else if (*tzenv == '+') |
++tzenv; |
|
hh = 0; |
mm = 0; |
ss = 0; |
|
n = 0; |
if (sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n) <= 0) |
tz->__tzrule[1].offset = tz->__tzrule[0].offset - 3600; |
else |
tz->__tzrule[1].offset = sign * (ss + SECSPERMIN * mm + SECSPERHOUR * hh); |
|
tzenv += n; |
|
for (i = 0; i < 2; ++i) |
{ |
if (*tzenv == ',') |
++tzenv; |
|
if (*tzenv == 'M') |
{ |
if (sscanf (tzenv, "M%hu%n.%hu%n.%hu%n", &m, &n, &w, &n, &d, &n) != 3 || |
m < 1 || m > 12 || w < 1 || w > 5 || d > 6) |
return; |
|
tz->__tzrule[i].ch = 'M'; |
tz->__tzrule[i].m = m; |
tz->__tzrule[i].n = w; |
tz->__tzrule[i].d = d; |
|
tzenv += n; |
} |
else |
{ |
char *end; |
if (*tzenv == 'J') |
{ |
ch = 'J'; |
++tzenv; |
} |
else |
ch = 'D'; |
|
d = strtoul (tzenv, &end, 10); |
|
/* if unspecified, default to US settings */ |
/* From 1987-2006, US was M4.1.0,M10.5.0, but starting in 2007 is |
* M3.2.0,M11.1.0 (2nd Sunday March through 1st Sunday November) */ |
if (end == tzenv) |
{ |
if (i == 0) |
{ |
tz->__tzrule[0].ch = 'M'; |
tz->__tzrule[0].m = 3; |
tz->__tzrule[0].n = 2; |
tz->__tzrule[0].d = 0; |
} |
else |
{ |
tz->__tzrule[1].ch = 'M'; |
tz->__tzrule[1].m = 11; |
tz->__tzrule[1].n = 1; |
tz->__tzrule[1].d = 0; |
} |
} |
else |
{ |
tz->__tzrule[i].ch = ch; |
tz->__tzrule[i].d = d; |
} |
|
tzenv = end; |
} |
|
/* default time is 02:00:00 am */ |
hh = 2; |
mm = 0; |
ss = 0; |
n = 0; |
|
if (*tzenv == '/') |
sscanf (tzenv, "/%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n); |
|
tz->__tzrule[i].s = ss + SECSPERMIN * mm + SECSPERHOUR * hh; |
|
tzenv += n; |
} |
|
__tzcalc_limits (tz->__tzyear); |
_timezone = tz->__tzrule[0].offset; |
_daylight = tz->__tzrule[0].offset != tz->__tzrule[1].offset; |
} |
|
_VOID |
_DEFUN (_tzset_r, (reent_ptr), |
struct _reent *reent_ptr) |
{ |
TZ_LOCK; |
_tzset_unlocked_r (reent_ptr); |
TZ_UNLOCK; |
} |