205 lines
3.5 KiB
C
205 lines
3.5 KiB
C
#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"
|
|
|
|
static char __tzname_std[11];
|
|
static char __tzname_dst[11];
|
|
static char *prev_tzenv = NULL;
|
|
|
|
/* default to GMT */
|
|
char *_tzname[2] = {"GMT" "GMT"};
|
|
int _daylight = 0;
|
|
time_t _timezone = (time_t)0;
|
|
|
|
int __tzyear = 0;
|
|
|
|
int __tznorth = 1;
|
|
|
|
__tzrule_type __tzrule[2] = { {'J', 0, 0, 0, 0, (time_t)0, 0 },
|
|
{'J', 0, 0, 0, 0, (time_t)0, 0 } };
|
|
|
|
_VOID
|
|
_DEFUN (_tzset_r, (reent_ptr),
|
|
struct _reent *reent_ptr)
|
|
{
|
|
char *tzenv;
|
|
int hh, mm, ss, sign, m, w, d, n;
|
|
int i, ch;
|
|
|
|
if ((tzenv = _getenv_r (reent_ptr, "TZ")) == NULL)
|
|
{
|
|
TZ_LOCK;
|
|
_timezone = (time_t)0;
|
|
_daylight = 0;
|
|
_tzname[0] = "GMT";
|
|
_tzname[1] = "GMT";
|
|
TZ_UNLOCK;
|
|
return;
|
|
}
|
|
|
|
TZ_LOCK;
|
|
|
|
if (prev_tzenv != NULL && strcmp(tzenv, prev_tzenv) == 0)
|
|
{
|
|
TZ_UNLOCK;
|
|
return;
|
|
}
|
|
|
|
free(prev_tzenv);
|
|
prev_tzenv = _strdup_r (reent_ptr, tzenv);
|
|
|
|
/* ignore implementation-specific format specifier */
|
|
if (*tzenv == ':')
|
|
++tzenv;
|
|
|
|
if (sscanf (tzenv, "%10[^0-9,+-]%n", __tzname_std, &n) <= 0)
|
|
{
|
|
TZ_UNLOCK;
|
|
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)
|
|
{
|
|
TZ_UNLOCK;
|
|
return;
|
|
}
|
|
|
|
__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)
|
|
{
|
|
_tzname[1] = _tzname[0];
|
|
TZ_UNLOCK;
|
|
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;
|
|
|
|
if (sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n) <= 0)
|
|
__tzrule[1].offset = __tzrule[0].offset - 3600;
|
|
else
|
|
__tzrule[1].offset = sign * (ss + SECSPERMIN * mm + SECSPERHOUR * hh);
|
|
|
|
tzenv += n;
|
|
|
|
if (*tzenv == ',')
|
|
++tzenv;
|
|
|
|
for (i = 0; i < 2; ++i)
|
|
{
|
|
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)
|
|
{
|
|
TZ_UNLOCK;
|
|
return;
|
|
}
|
|
|
|
__tzrule[i].ch = 'M';
|
|
__tzrule[i].m = m;
|
|
__tzrule[i].n = w;
|
|
__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 */
|
|
if (end == tzenv)
|
|
{
|
|
if (i == 0)
|
|
{
|
|
__tzrule[0].ch = 'M';
|
|
__tzrule[0].m = 4;
|
|
__tzrule[0].n = 1;
|
|
__tzrule[0].d = 0;
|
|
}
|
|
else
|
|
{
|
|
__tzrule[1].ch = 'M';
|
|
__tzrule[1].m = 10;
|
|
__tzrule[1].n = 5;
|
|
__tzrule[1].d = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
__tzrule[i].ch = ch;
|
|
__tzrule[i].d = d;
|
|
}
|
|
|
|
tzenv = end;
|
|
}
|
|
|
|
/* default time is 02:00:00 am */
|
|
hh = 2;
|
|
mm = 0;
|
|
ss = 0;
|
|
|
|
if (*tzenv == '/')
|
|
sscanf (tzenv, "%hu%n:%hu%n:%hu%n", &hh, &n, &mm, &n, &ss, &n);
|
|
|
|
__tzrule[i].s = ss + SECSPERMIN * mm + SECSPERHOUR * hh;
|
|
}
|
|
|
|
__tzcalc_limits (__tzyear);
|
|
_timezone = (time_t)(__tzrule[0].offset);
|
|
_daylight = __tzrule[0].offset != __tzrule[1].offset;
|
|
|
|
TZ_UNLOCK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|