1986-01-13 17:21:20 -05:00
|
|
|
#
|
|
|
|
|
|
|
|
|
|
/*LINTLIBRARY*/
|
|
|
|
|
|
1986-03-02 22:03:44 -05:00
|
|
|
/*
|
|
|
|
|
** Should there be any built-in rules other than GMT?
|
|
|
|
|
** In particular, should zones such as "EST5" (abbreviation is always "EST",
|
|
|
|
|
** GMT offset is always 5 hours) be built in?
|
|
|
|
|
*/
|
|
|
|
|
|
1986-02-15 15:23:29 -05:00
|
|
|
#include "tzfile.h"
|
1986-01-13 17:21:20 -05:00
|
|
|
#include "time.h"
|
|
|
|
|
|
|
|
|
|
#ifdef OBJECTID
|
|
|
|
|
static char sccsid[] = "%W%";
|
|
|
|
|
#endif
|
|
|
|
|
|
1986-03-02 22:03:44 -05:00
|
|
|
#ifndef TRUE
|
1986-03-04 10:43:24 -05:00
|
|
|
#define TRUE 1
|
|
|
|
|
#define FALSE 0
|
1986-03-02 22:03:44 -05:00
|
|
|
#endif
|
|
|
|
|
|
1986-03-04 09:49:44 -05:00
|
|
|
#ifndef MAXPATHLEN
|
|
|
|
|
#define MAXPATHLEN 1024
|
|
|
|
|
#endif
|
|
|
|
|
|
1986-01-15 08:27:06 -05:00
|
|
|
extern char * asctime();
|
|
|
|
|
extern struct tm * gmtime();
|
|
|
|
|
extern char * strcpy();
|
|
|
|
|
extern char * strcat();
|
|
|
|
|
extern char * getenv();
|
1986-01-13 17:21:20 -05:00
|
|
|
|
1986-07-27 12:35:10 -04:00
|
|
|
struct state {
|
|
|
|
|
struct tzhead h;
|
|
|
|
|
long ats[TZ_MAX_TIMES];
|
|
|
|
|
unsigned char types[TZ_MAX_TIMES];
|
|
|
|
|
struct ttinfo ttis[TZ_MAX_TYPES];
|
|
|
|
|
char chars[TZ_MAX_CHARS + 1];
|
|
|
|
|
};
|
1986-03-04 09:49:44 -05:00
|
|
|
|
1986-07-27 12:35:10 -04:00
|
|
|
static struct state s;
|
1986-03-04 09:49:44 -05:00
|
|
|
|
1986-03-02 22:03:44 -05:00
|
|
|
static char isset;
|
1986-01-13 17:21:20 -05:00
|
|
|
|
1986-01-16 08:50:51 -05:00
|
|
|
char * tz_abbr; /* set by localtime; available to all */
|
|
|
|
|
|
1986-08-28 10:05:22 -04:00
|
|
|
#define GETSHORT(val, p) { \
|
|
|
|
|
register int shortval; \
|
|
|
|
|
shortval = *p++; \
|
|
|
|
|
shortval = (shortval << 8) | *p++; \
|
|
|
|
|
val = shortval; \
|
|
|
|
|
}
|
1986-03-04 09:49:44 -05:00
|
|
|
|
1986-08-28 10:05:22 -04:00
|
|
|
#define GETLONG(val, p) { \
|
|
|
|
|
register long longval; \
|
|
|
|
|
longval = *p++; \
|
|
|
|
|
longval = (longval << 8) | *p++; \
|
|
|
|
|
longval = (longval << 8) | *p++; \
|
|
|
|
|
longval = (longval << 8) | *p++; \
|
|
|
|
|
val = longval; \
|
|
|
|
|
}
|
|
|
|
|
|
1986-03-01 17:07:13 -05:00
|
|
|
static
|
1986-07-27 12:35:10 -04:00
|
|
|
tzload(tzname, sp)
|
|
|
|
|
register char * tzname;
|
|
|
|
|
register struct state * sp;
|
1986-01-13 17:21:20 -05:00
|
|
|
{
|
1986-03-02 22:03:44 -05:00
|
|
|
register int i;
|
1986-08-28 10:05:22 -04:00
|
|
|
register int fid;
|
1986-03-04 09:49:44 -05:00
|
|
|
|
|
|
|
|
if (tzname == 0 && (tzname = TZDEFAULT) == 0)
|
|
|
|
|
return -1;
|
1986-07-27 12:35:10 -04:00
|
|
|
{
|
1986-08-28 10:05:22 -04:00
|
|
|
register char * p;
|
|
|
|
|
register int doaccess;
|
|
|
|
|
char fullname[MAXPATHLEN];
|
1986-07-27 12:35:10 -04:00
|
|
|
|
1986-08-28 10:05:22 -04:00
|
|
|
doaccess = tzname[0] == '/';
|
1986-07-27 12:35:10 -04:00
|
|
|
if (!doaccess) {
|
|
|
|
|
if ((p = TZDIR) == 0)
|
|
|
|
|
return -1;
|
|
|
|
|
if ((strlen(p) + strlen(tzname) + 1) >= sizeof fullname)
|
|
|
|
|
return -1;
|
|
|
|
|
(void) strcpy(fullname, p);
|
|
|
|
|
(void) strcat(fullname, "/");
|
|
|
|
|
(void) strcat(fullname, tzname);
|
|
|
|
|
/*
|
|
|
|
|
** Set doaccess if '.' (as in "../") shows up in name.
|
|
|
|
|
*/
|
|
|
|
|
while (*tzname != '\0')
|
|
|
|
|
if (*tzname++ == '.')
|
|
|
|
|
doaccess = TRUE;
|
|
|
|
|
tzname = fullname;
|
|
|
|
|
}
|
|
|
|
|
if (doaccess && access(tzname, 4) != 0)
|
1986-03-04 09:49:44 -05:00
|
|
|
return -1;
|
1986-07-27 12:35:10 -04:00
|
|
|
if ((fid = open(tzname, 0)) == -1)
|
1986-03-04 09:49:44 -05:00
|
|
|
return -1;
|
1986-01-13 20:30:59 -05:00
|
|
|
}
|
1986-07-27 12:35:10 -04:00
|
|
|
{
|
1986-08-28 10:05:22 -04:00
|
|
|
register unsigned char * p;
|
|
|
|
|
unsigned char buf[sizeof s];
|
1986-07-27 12:35:10 -04:00
|
|
|
|
|
|
|
|
p = buf;
|
1986-08-28 10:05:22 -04:00
|
|
|
i = read(fid, (char *) p, sizeof buf);
|
1986-07-27 12:35:10 -04:00
|
|
|
if (close(fid) != 0 || i < sizeof sp->h)
|
1986-03-04 09:49:44 -05:00
|
|
|
return -1;
|
1986-08-28 10:38:34 -04:00
|
|
|
p += sizeof sp->h.tzh_reserved;
|
1986-08-28 10:05:22 -04:00
|
|
|
GETSHORT(sp->h.tzh_timecnt, p);
|
|
|
|
|
GETSHORT(sp->h.tzh_typecnt, p);
|
|
|
|
|
GETSHORT(sp->h.tzh_charcnt, p);
|
1986-07-27 12:35:10 -04:00
|
|
|
if (sp->h.tzh_timecnt > TZ_MAX_TIMES ||
|
|
|
|
|
sp->h.tzh_typecnt == 0 ||
|
|
|
|
|
sp->h.tzh_typecnt > TZ_MAX_TYPES ||
|
|
|
|
|
sp->h.tzh_charcnt > TZ_MAX_CHARS)
|
|
|
|
|
return -1;
|
1986-08-28 10:38:34 -04:00
|
|
|
if (i < sizeof sp->h.tzh_reserved + 3 * sizeof (short) +
|
1986-08-28 10:05:22 -04:00
|
|
|
sp->h.tzh_timecnt * (sizeof (long) + sizeof (char)) +
|
|
|
|
|
sp->h.tzh_typecnt * (sizeof (long) + 2*sizeof (char)) +
|
|
|
|
|
sp->h.tzh_charcnt * sizeof (char))
|
1986-07-27 12:35:10 -04:00
|
|
|
return -1;
|
1986-08-28 10:05:22 -04:00
|
|
|
for (i = 0; i < sp->h.tzh_timecnt; ++i)
|
|
|
|
|
GETLONG(sp->ats[i], p);
|
|
|
|
|
for (i = 0; i < sp->h.tzh_timecnt; ++i)
|
|
|
|
|
sp->types[i] = *p++;
|
1986-08-28 10:38:34 -04:00
|
|
|
for (i = 0; i < sp->h.tzh_typecnt; ++i) {
|
|
|
|
|
register struct ttinfo * ttisp;
|
|
|
|
|
|
|
|
|
|
ttisp = &sp->ttis[i];
|
1986-08-28 10:05:22 -04:00
|
|
|
GETLONG(ttisp->tt_gmtoff, p);
|
1986-08-28 11:07:02 -04:00
|
|
|
ttisp->tt_isdst = *p++;
|
1986-08-28 10:05:22 -04:00
|
|
|
ttisp->tt_abbrind = *p++;
|
1986-07-27 12:35:10 -04:00
|
|
|
}
|
1986-08-28 10:05:22 -04:00
|
|
|
for (i = 0; i < sp->h.tzh_charcnt; ++i)
|
|
|
|
|
sp->chars[i] = *p++;
|
|
|
|
|
sp->chars[sp->h.tzh_charcnt] = '\0'; /* ensure '\0' at end */
|
1986-03-04 09:49:44 -05:00
|
|
|
}
|
1986-08-28 10:05:22 -04:00
|
|
|
/*
|
|
|
|
|
** Check that all the local time type indices are valid.
|
|
|
|
|
*/
|
1986-07-27 12:35:10 -04:00
|
|
|
for (i = 0; i < sp->h.tzh_timecnt; ++i)
|
|
|
|
|
if (sp->types[i] >= sp->h.tzh_typecnt)
|
1986-03-04 09:49:44 -05:00
|
|
|
return -1;
|
1986-08-28 10:05:22 -04:00
|
|
|
/*
|
|
|
|
|
** Check that all the abbreviation indices are valid.
|
|
|
|
|
*/
|
1986-07-27 12:35:10 -04:00
|
|
|
for (i = 0; i < sp->h.tzh_typecnt; ++i)
|
|
|
|
|
if (sp->ttis[i].tt_abbrind >= sp->h.tzh_charcnt)
|
1986-03-04 09:49:44 -05:00
|
|
|
return -1;
|
1986-01-13 17:21:20 -05:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1986-01-16 08:50:51 -05:00
|
|
|
/*
|
1986-03-01 17:07:13 -05:00
|
|
|
** settz("") Use built-in GMT.
|
1986-03-05 18:49:16 -05:00
|
|
|
** settz((char *) 0) Use TZDEFAULT.
|
1986-03-01 17:07:13 -05:00
|
|
|
** settz(otherwise) Use otherwise.
|
1986-01-16 08:50:51 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
settz(tzname)
|
|
|
|
|
char * tzname;
|
|
|
|
|
{
|
|
|
|
|
register int answer;
|
|
|
|
|
|
1986-03-02 22:03:44 -05:00
|
|
|
isset = TRUE;
|
1986-02-28 21:29:14 -05:00
|
|
|
if (tzname != 0 && *tzname == '\0')
|
1986-01-16 08:50:51 -05:00
|
|
|
answer = 0; /* Use built-in GMT */
|
|
|
|
|
else {
|
1986-07-27 12:35:10 -04:00
|
|
|
if (tzload(tzname, &s) == 0)
|
1986-01-16 08:50:51 -05:00
|
|
|
return 0;
|
|
|
|
|
/*
|
1986-02-28 21:29:14 -05:00
|
|
|
** If we want to try for local time on errors. . .
|
1986-07-27 12:35:10 -04:00
|
|
|
if (tzload((char *) 0, &s) == 0)
|
1986-01-16 08:50:51 -05:00
|
|
|
return -1;
|
1986-02-28 21:29:14 -05:00
|
|
|
*/
|
1986-01-16 08:50:51 -05:00
|
|
|
answer = -1;
|
|
|
|
|
}
|
1986-07-27 12:35:10 -04:00
|
|
|
s.h.tzh_timecnt = 0;
|
|
|
|
|
s.ttis[0].tt_gmtoff = 0;
|
|
|
|
|
s.ttis[0].tt_abbrind = 0;
|
|
|
|
|
(void) strcpy(s.chars, "GMT");
|
1986-01-16 08:50:51 -05:00
|
|
|
return answer;
|
|
|
|
|
}
|
|
|
|
|
|
1986-07-27 12:35:10 -04:00
|
|
|
static struct tm *
|
|
|
|
|
newsub(timep, sp)
|
|
|
|
|
register long * timep;
|
|
|
|
|
register struct state * sp;
|
1986-01-13 17:21:20 -05:00
|
|
|
{
|
1986-08-28 10:05:22 -04:00
|
|
|
register struct ttinfo * ttisp;
|
1986-03-05 18:49:16 -05:00
|
|
|
register struct tm * tmp;
|
1986-01-13 20:30:59 -05:00
|
|
|
register int i;
|
1986-01-16 08:50:51 -05:00
|
|
|
long t;
|
1986-01-13 17:21:20 -05:00
|
|
|
|
1986-01-16 08:50:51 -05:00
|
|
|
t = *timep;
|
1986-07-27 12:35:10 -04:00
|
|
|
if (sp->h.tzh_timecnt == 0 || t < sp->ats[0])
|
1986-03-02 22:03:44 -05:00
|
|
|
i = 0;
|
1986-01-16 08:50:51 -05:00
|
|
|
else {
|
1986-07-27 12:35:10 -04:00
|
|
|
for (i = 1; i < sp->h.tzh_timecnt; ++i)
|
|
|
|
|
if (t < sp->ats[i])
|
1986-01-16 08:50:51 -05:00
|
|
|
break;
|
1986-07-27 12:35:10 -04:00
|
|
|
i = sp->types[i - 1];
|
1986-01-16 08:50:51 -05:00
|
|
|
}
|
1986-08-28 10:05:22 -04:00
|
|
|
ttisp = &sp->ttis[i];
|
|
|
|
|
t += ttisp->tt_gmtoff;
|
1986-03-05 18:49:16 -05:00
|
|
|
tmp = gmtime(&t);
|
1986-08-28 10:05:22 -04:00
|
|
|
tmp->tm_isdst = ttisp->tt_isdst;
|
|
|
|
|
tz_abbr = &sp->chars[ttisp->tt_abbrind];
|
1986-03-05 18:49:16 -05:00
|
|
|
return tmp;
|
1986-01-13 17:21:20 -05:00
|
|
|
}
|
|
|
|
|
|
1986-07-27 12:35:10 -04:00
|
|
|
struct tm *
|
|
|
|
|
newlocaltime(timep)
|
|
|
|
|
long * timep;
|
|
|
|
|
{
|
|
|
|
|
if (!isset)
|
|
|
|
|
(void) settz(getenv("TZ"));
|
|
|
|
|
return newsub(timep, &s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct tm *
|
|
|
|
|
zonetime(timep, zone)
|
|
|
|
|
long * timep;
|
|
|
|
|
char * zone;
|
|
|
|
|
{
|
|
|
|
|
struct state st;
|
|
|
|
|
|
|
|
|
|
return (tzload(zone, &st) == 0) ? newsub(timep, &st) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
1986-01-13 17:21:20 -05:00
|
|
|
char *
|
1986-01-15 08:27:06 -05:00
|
|
|
newctime(timep)
|
1986-03-01 17:07:13 -05:00
|
|
|
long * timep;
|
1986-01-13 17:21:20 -05:00
|
|
|
{
|
1986-03-02 22:03:44 -05:00
|
|
|
return asctime(newlocaltime(timep));
|
1986-01-13 17:21:20 -05:00
|
|
|
}
|