Here are changes (relative to what's currently available via ftp) to deal with time zone
abbreviation issues.
1. The use of "??" as an abbreviation in the solar* files is eliminated.
2. The zic command warns about non-POSIX abbreviations.
3. The zdump command warns about non-POSIX abbreviations if its "-v" flag is used.
4. localtime.c is changed to restrict characters in abbreviations to [a-zA-Z0-9 :+-]
(replacing other characters with 'X'), and to restrict abbreviation lengths to 16
(truncating longer abbreviations).
Both zic.c and localtime.c have the long Factory "abbreviation" grandparented in.
--ado
diff -r -c old/Makefile new/Makefile
*** old/Makefile Mon Apr 4 11:24:31 2005
--- new/Makefile Thu May 26 12:42:13 2005
***************
*** 1,4 ****
! # @(#)Makefile 7.108
# Change the line below for your time zone (after finding the zone you want in
# the time zone files, or adding it to a time zone file).
--- 1,4 ----
! # @(#)Makefile 7.109
# Change the line below for your time zone (after finding the zone you want in
# the time zone files, or adding it to a time zone file).
***************
*** 111,117 ****
# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1
# if you do not want run time warnings about formats that may cause
# year 2000 grief
! #
GCC_DEBUG_FLAGS = -Dlint -g -O -fno-common \
-Wall -Wcast-qual -Wconversion -Wmissing-prototypes \
-Wnested-externs -Wpointer-arith -Wshadow \
--- 111,119 ----
# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1
# if you do not want run time warnings about formats that may cause
# year 2000 grief
! # -DZIC_MAX_ABBR_LEN_WO_WARN=3
! # (or some other number) to set the maximum time zone abbreviation length
! # that zic will accept without a warning (the default is 6)
GCC_DEBUG_FLAGS = -Dlint -g -O -fno-common \
-Wall -Wcast-qual -Wconversion -Wmissing-prototypes \
-Wnested-externs -Wpointer-arith -Wshadow \
diff -r -c old/localtime.c new/localtime.c
*** old/localtime.c Mon Apr 4 11:24:32 2005
--- new/localtime.c Thu May 26 15:02:36 2005
***************
*** 5,11 ****
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.91";
#endif /* !defined NOID */
#endif /* !defined lint */
--- 5,11 ----
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.93";
#endif /* !defined NOID */
#endif /* !defined lint */
***************
*** 22,27 ****
--- 22,40 ----
#include "fcntl.h"
#include "float.h" /* for FLT_MAX and DBL_MAX */
+ #ifndef TZ_ABBR_MAX_LEN
+ #define TZ_ABBR_MAX_LEN 16
+ #endif /* !defined TZ_ABBR_MAX_LEN */
+
+ #ifndef TZ_ABBR_CHAR_SET
+ #define TZ_ABBR_CHAR_SET \
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-"
+ #endif /* !defined TZ_ABBR_CHAR_SET */
+
+ #ifndef TZ_ABBR_ERR_CHAR
+ #define TZ_ABBR_ERR_CHAR 'X'
+ #endif /* !defined TZ_ABBR_ERR_CHAR */
+
/*
** SunOS 4.1.1 headers lack O_BINARY.
*/
***************
*** 124,129 ****
--- 137,143 ----
static long detzcode P((const char * codep));
static const char * getzname P((const char * strp));
+ static const char * getqzname P((const char * strp, const char delim));
static const char * getnum P((const char * strp, int * nump, int min,
int max));
static const char * getsecs P((const char * strp, long * secsp));
***************
*** 269,274 ****
--- 283,306 ----
tzname[ttisp->tt_isdst] =
&sp->chars[ttisp->tt_abbrind];
}
+ /*
+ ** Finally, scrub the abbreviations.
+ ** First, replace bogus characters.
+ */
+ for (i = 0; i < sp->charcnt; ++i)
+ if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
+ sp->chars[i] = TZ_ABBR_ERR_CHAR;
+ /*
+ ** Second, truncate long abbreviations.
+ */
+ for (i = 0; i < sp->typecnt; ++i) {
+ register const struct ttinfo * const ttisp = &sp->ttis[i];
+ register char * cp = &sp->chars[ttisp->tt_abbrind];
+
+ if (strlen(cp) > TZ_ABBR_MAX_LEN &&
+ strcmp(cp, GRANDPARENTED) != 0)
+ *(cp + TZ_ABBR_MAX_LEN) = '\0';
+ }
}
static int
***************
*** 470,475 ****
--- 502,528 ----
}
/*
+ ** Given a pointer into an extended time zone string, scan until the ending
+ ** delimiter of the zone name is located. Return a pointer to the delimiter.
+ **
+ ** As with getzname above, the legal character set is actually quite
+ ** restricted, with other characters producing undefined results.
+ ** We choose not to care - allowing almost anything to be in the zone abbrev.
+ */
+
+ static const char *
+ getqzname(strp, delim)
+ register const char * strp;
+ const char delim;
+ {
+ register char c;
+
+ while ((c = *strp) != '\0' && c != delim)
+ ++strp;
+ return strp;
+ }
+
+ /*
** Given a pointer into a time zone string, extract a number from that string.
** Check that the number is within a specified range; if it is not, return
** NULL.
***************
*** 753,760 ****
stdlen = (sizeof sp->chars) - 1;
stdoffset = 0;
} else {
! name = getzname(name);
! stdlen = name - stdname;
if (stdlen < 3)
return -1;
if (*name == '\0')
--- 806,823 ----
stdlen = (sizeof sp->chars) - 1;
stdoffset = 0;
} else {
! if (*name == '<') {
! name++;
! stdname = name;
! name = getqzname(name, '>');
! if (*name != '>')
! return (-1);
! stdlen = name - stdname;
! name++;
! } else {
! name = getzname(name);
! stdlen = name - stdname;
! }
if (stdlen < 3)
return -1;
if (*name == '\0')
***************
*** 767,775 ****
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
! dstname = name;
! name = getzname(name);
! dstlen = name - dstname; /* length of DST zone name */
if (dstlen < 3)
return -1;
if (*name != '\0' && *name != ',' && *name != ';') {
--- 830,847 ----
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
! if (*name == '<') {
! dstname = ++name;
! name = getqzname(name, '>');
! if (*name != '>')
! return -1;
! dstlen = name - dstname;
! name++;
! } else {
! dstname = name;
! name = getzname(name);
! dstlen = name - dstname; /* length of DST zone name */
! }
if (dstlen < 3)
return -1;
if (*name != '\0' && *name != ',' && *name != ';') {
diff -r -c old/private.h new/private.h
*** old/private.h Mon Apr 4 11:24:32 2005
--- new/private.h Thu May 26 14:54:07 2005
***************
*** 25,30 ****
--- 25,32 ----
#endif /* !defined NOID */
#endif /* !defined lint */
+ #define GRANDPARENTED "Local time zone must be set--see zic manual page"
+
/*
** Defaults for preprocessor symbols.
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
diff -r -c old/solar87 new/solar87
*** old/solar87 Thu Apr 21 15:04:16 2005
--- new/solar87 Thu May 26 12:42:35 2005
***************
*** 1,4 ****
! # @(#)solar87 7.3
# So much for footnotes about Saudi Arabia.
# Apparent noon times below are for Riyadh; your mileage will vary.
--- 1,4 ----
! # @(#)solar87 7.4
# So much for footnotes about Saudi Arabia.
# Apparent noon times below are for Riyadh; your mileage will vary.
***************
*** 381,388 ****
# Before and after 1987, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh87 3:07:04 - ?? 1987
! 3:07:04 sol87 ?? 1988
! 3:07:04 - ??
# For backward compatibility...
Link Asia/Riyadh87 Mideast/Riyadh87
--- 381,388 ----
# Before and after 1987, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh87 3:07:04 - zzz 1987
! 3:07:04 sol87 zzz 1988
! 3:07:04 - zzz
# For backward compatibility...
Link Asia/Riyadh87 Mideast/Riyadh87
diff -r -c old/solar88 new/solar88
*** old/solar88 Thu Apr 21 15:04:16 2005
--- new/solar88 Thu May 26 12:42:35 2005
***************
*** 1,4 ****
! # @(#)solar88 7.3
# Apparent noon times below are for Riyadh; they're a bit off for other places.
# Times were computed using formulas in the U.S. Naval Observatory's
--- 1,4 ----
! # @(#)solar88 7.4
# Apparent noon times below are for Riyadh; they're a bit off for other places.
# Times were computed using formulas in the U.S. Naval Observatory's
***************
*** 381,388 ****
# Before and after 1988, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh88 3:07:04 - ?? 1988
! 3:07:04 sol88 ?? 1989
! 3:07:04 - ??
# For backward compatibility...
Link Asia/Riyadh88 Mideast/Riyadh88
--- 381,388 ----
# Before and after 1988, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh88 3:07:04 - zzz 1988
! 3:07:04 sol88 zzz 1989
! 3:07:04 - zzz
# For backward compatibility...
Link Asia/Riyadh88 Mideast/Riyadh88
diff -r -c old/solar89 new/solar89
*** old/solar89 Thu Apr 21 15:04:16 2005
--- new/solar89 Thu May 26 12:42:35 2005
***************
*** 1,4 ****
! # @(#)solar89 7.4
# Apparent noon times below are for Riyadh; they're a bit off for other places.
# Times were computed using a formula provided by the U. S. Naval Observatory:
--- 1,4 ----
! # @(#)solar89 7.5
# Apparent noon times below are for Riyadh; they're a bit off for other places.
# Times were computed using a formula provided by the U. S. Naval Observatory:
***************
*** 386,393 ****
# Before and after 1989, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh89 3:07:04 - ?? 1989
! 3:07:04 sol89 ?? 1990
! 3:07:04 - ??
# For backward compatibility...
Link Asia/Riyadh89 Mideast/Riyadh89
--- 386,393 ----
# Before and after 1989, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh89 3:07:04 - zzz 1989
! 3:07:04 sol89 zzz 1990
! 3:07:04 - zzz
# For backward compatibility...
Link Asia/Riyadh89 Mideast/Riyadh89
diff -r -c old/zdump.c new/zdump.c
*** old/zdump.c Mon Apr 4 11:24:32 2005
--- new/zdump.c Thu May 26 12:48:56 2005
***************
*** 1,4 ****
! static char elsieid[] = "@(#)zdump.c 7.64";
/*
** This code has been made independent of the rest of the time
--- 1,4 ----
! static char elsieid[] = "@(#)zdump.c 7.65";
/*
** This code has been made independent of the rest of the time
***************
*** 144,151 ****
--- 144,153 ----
static time_t absolute_max_time;
static size_t longest;
static char * progname;
+ static int warned;
static char * abbr P((struct tm * tmp));
+ static void abbrok P((const char * abbr, const char * zone));
static long delta P((struct tm * newp, struct tm * oldp));
static void dumptime P((const struct tm * tmp));
static time_t hunt P((char * name, time_t lot, time_t hit));
***************
*** 191,196 ****
--- 193,236 ----
}
#endif /* !defined TYPECHECK */
+ static void
+ abbrok(abbr, zone)
+ const char * const abbr;
+ const char * const zone;
+ {
+ register int i;
+ register const char * cp;
+ register char * wp;
+
+ if (warned)
+ return;
+ cp = abbr;
+ wp = NULL;
+ while (isascii(*cp) && isalpha(*cp))
+ ++cp;
+ if (cp - abbr == 0)
+ wp = _("lacks alphabetic at start");
+ if (cp - abbr < 3)
+ wp = _("has fewer than 3 alphabetics");
+ if (cp - abbr > 6)
+ wp = _("has more than 6 alphabetics");
+ if (wp == NULL && (*cp == '+' || *cp == '-')) {
+ ++cp;
+ if (isascii(*cp) && isdigit(*cp))
+ if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
+ ++cp;
+ }
+ if (*cp != '\0')
+ wp = _("differs from POSIX standard");
+ if (wp == NULL)
+ return;
+ (void) fflush(stdout);
+ (void) fprintf(stderr,
+ "%s: warning: zone \"%s\" abbreviation \"%s\" %s\n",
+ progname, zone, abbr, wp);
+ warned = TRUE;
+ }
+
int
main(argc, argv)
int argc;
***************
*** 297,302 ****
--- 337,343 ----
show(argv[i], now, FALSE);
continue;
}
+ warned = FALSE;
t = absolute_min_time;
show(argv[i], t, TRUE);
t += SECSPERHOUR * HOURSPERDAY;
***************
*** 527,532 ****
--- 568,575 ----
}
}
(void) printf("\n");
+ if (tmp != NULL && *abbr(tmp) != '\0')
+ abbrok(abbr(tmp), zone);
}
static char *
diff -r -c old/zic.c new/zic.c
*** old/zic.c Mon Apr 4 11:24:32 2005
--- new/zic.c Thu May 26 14:54:07 2005
***************
*** 1,4 ****
! static char elsieid[] = "@(#)zic.c 7.122";
/*
** Regardless of the type of time_t, we do our work using this type.
--- 1,4 ----
! static char elsieid[] = "@(#)zic.c 7.124";
/*
** Regardless of the type of time_t, we do our work using this type.
***************
*** 10,15 ****
--- 10,19 ----
#include "locale.h"
#include "tzfile.h"
+ #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
+ #define ZIC_MAX_ABBR_LEN_WO_WARN 6
+ #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
+
#if HAVE_SYS_STAT_H
#include "sys/stat.h"
#endif
***************
*** 2196,2201 ****
--- 2200,2240 ----
{
register int i;
+ if (strcmp(string, GRANDPARENTED) != 0) {
+ register const char * cp;
+ register char * wp;
+
+ /*
+ ** Want one to ZIC_MAX_ABBR_LEN_WO_WARN alphabetics
+ ** optionally followed by a + or - and a number from 1 to 14.
+ */
+ cp = string;
+ wp = NULL;
+ while (isascii(*cp) && isalpha(*cp))
+ ++cp;
+ if (cp - string == 0)
+ wp = _("time zone abbreviation lacks alphabetic at start");
+ if (noise && cp - string > 3)
+ wp = _("time zone abbreviation has more than 3 alphabetics");
+ if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
+ wp = _("time zone abbreviation has too many alphabetics");
+ if (wp == NULL && (*cp == '+' || *cp == '-')) {
+ ++cp;
+ if (isascii(*cp) && isdigit(*cp))
+ if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
+ ++cp;
+ }
+ if (*cp != '\0')
+ wp = _("time zone abbreviation differs from POSIX standard");
+ if (wp != NULL) {
+ wp = ecpyalloc(wp);
+ wp = ecatalloc(wp, " (");
+ wp = ecatalloc(wp, string);
+ wp = ecatalloc(wp, ")");
+ warning(wp);
+ ifree(wp);
+ }
+ }
i = strlen(string) + 1;
if (charcnt + i > TZ_MAX_CHARS) {
error(_("too many, or too long, time zone abbreviations"));