diff options
Diffstat (limited to 'share/zoneinfo/zic.c')
| -rw-r--r-- | share/zoneinfo/zic.c | 621 |
1 files changed, 322 insertions, 299 deletions
diff --git a/share/zoneinfo/zic.c b/share/zoneinfo/zic.c index 677fb2e9a3e3..125543a0a5e9 100644 --- a/share/zoneinfo/zic.c +++ b/share/zoneinfo/zic.c @@ -1,61 +1,18 @@ -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Arthur David Olson of the National Cancer Institute. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. +/* + * This file provided by Arthur David Olson of the National Cancer + * Institute. Because it was created by the United States government, + * it is in the public domain with the United States, and freely distributable + * outside. (Comment added by G. Wollman, FreeBSD Project.) */ - +/* $Id: zic.c,v 1.5 1994/02/20 15:51:36 rgrimes Exp $ */ #ifndef lint -static char sccsid[] = "@(#)zic.c 5.3 (Berkeley) 4/20/91"; -#endif /* not lint */ - -#ifdef notdef -static char elsieid[] = "@(#)zic.c 4.12"; -#endif - -#include <sys/types.h> -#include <sys/cdefs.h> -#include <sys/stat.h> -#include <time.h> -#include <tzfile.h> -#include <stdio.h> -#include <ctype.h> -#include <string.h> -#include <stdlib.h> +#ifndef NOID +static char elsieid[] = "@(#)zic.c 7.19"; +#endif /* !defined NOID */ +#endif /* !defined lint */ -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif /* !defined TRUE */ +#include "private.h" +#include "tzfile.h" struct rule { const char * r_filename; @@ -108,59 +65,61 @@ struct zone { time_t z_untiltime; }; -extern char * icatalloc __P((char * old, const char * new)); -extern char * icpyalloc __P((const char * string)); -extern void ifree __P((char * p)); -extern char * imalloc __P((int n)); -extern char * irealloc __P((char * old, int n)); -extern int link __P((const char * fromname, const char * toname)); +extern int getopt P((int argc, char * argv[], const char * options)); +extern char * icatalloc P((char * old, const char * new)); +extern char * icpyalloc P((const char * string)); +extern void ifree P((char * p)); +extern char * imalloc P((int n)); +extern char * irealloc P((char * old, int n)); +extern int link P((const char * fromname, const char * toname)); extern char * optarg; extern int optind; -extern void perror __P((const char * string)); -extern char * scheck __P((const char * string, const char * format)); -static void addtt __P((time_t starttime, int type)); -static int addtype - __P((long gmtoff, const char * abbr, int isdst, - int ttisstd)); -static void addleap __P((time_t t, int positive, int rolling)); -static void adjleap __P((void)); -static void associate __P((void)); -static int ciequal __P((const char * ap, const char * bp)); -static void convert __P((long val, char * buf)); -static void dolink __P((const char * fromfile, const char * tofile)); -static void eat __P((const char * name, int num)); -static void eats __P((const char * name, int num, - const char * rname, int rnum)); -static long eitol __P((int i)); -static void error __P((const char * message)); -static char ** getfields __P((char * buf)); -static long gethms __P((char * string, const char * errstrng, - int signable)); -static void infile __P((const char * filename)); -static void inleap __P((char ** fields, int nfields)); -static void inlink __P((char ** fields, int nfields)); -static void inrule __P((char ** fields, int nfields)); -static int inzcont __P((char ** fields, int nfields)); -static int inzone __P((char ** fields, int nfields)); -static int inzsub __P((char ** fields, int nfields, int iscont)); -static int itsabbr __P((const char * abbr, const char * word)); -static int itsdir __P((const char * name)); -static int lowerit __P((int c)); -static char * memcheck __P((char * tocheck)); -static int mkdirs __P((char * filename)); -static void newabbr __P((const char * abbr)); -static long oadd __P((long t1, long t2)); -static void outzone __P((const struct zone * zp, int ntzones)); -static void puttzcode __P((long code, FILE * fp)); -static int rcomp __P((const void *leftp, const void *rightp)); -static time_t rpytime __P((const struct rule * rp, int wantedy)); -static void rulesub __P((struct rule * rp, char * loyearp, char * hiyearp, - char * typep, char * monthp, char * dayp, char * timep)); -static void setboundaries __P((void)); -static time_t tadd __P((time_t t1, long t2)); -static void usage __P((void)); -static void writezone __P((const char * name)); -static int yearistype __P((int year, const char * type)); +extern char * scheck P((const char * string, const char * format)); + +static void addtt P((time_t starttime, int type)); +static int addtype P((long gmtoff, const char * abbr, int isdst, + int ttisstd)); +static void leapadd P((time_t t, int positive, int rolling, int count)); +static void adjleap P((void)); +static void associate P((void)); +static int ciequal P((const char * ap, const char * bp)); +static void convert P((long val, char * buf)); +static void dolink P((const char * fromfile, const char * tofile)); +static void eat P((const char * name, int num)); +static void eats P((const char * name, int num, + const char * rname, int rnum)); +static long eitol P((int i)); +static void error P((const char * message)); +static char ** getfields P((char * buf)); +static long gethms P((const char * string, const char * errstrng, + int signable)); +static void infile P((const char * filename)); +static void inleap P((char ** fields, int nfields)); +static void inlink P((char ** fields, int nfields)); +static void inrule P((char ** fields, int nfields)); +static int inzcont P((char ** fields, int nfields)); +static int inzone P((char ** fields, int nfields)); +static int inzsub P((char ** fields, int nfields, int iscont)); +static int itsabbr P((const char * abbr, const char * word)); +static int itsdir P((const char * name)); +static int lowerit P((int c)); +static char * memcheck P((char * tocheck)); +static int mkdirs P((char * filename)); +static void newabbr P((const char * abbr)); +static long oadd P((long t1, long t2)); +static void outzone P((const struct zone * zp, int ntzones)); +static void puttzcode P((long code, FILE * fp)); +static int rcomp P((const genericptr_t leftp, const genericptr_t rightp)); +static time_t rpytime P((const struct rule * rp, int wantedy)); +static void rulesub P((struct rule * rp, + char * loyearp, char * hiyearp, + char * typep, char * monthp, + char * dayp, char * timep)); +static void setboundaries P((void)); +static time_t tadd P((time_t t1, long t2)); +static void usage P((void)); +static void writezone P((const char * name)); +static int yearistype P((int year, const char * type)); static int charcnt; static int errors; @@ -281,77 +240,77 @@ struct lookup { const int l_value; }; -static struct lookup const * byword __P((const char * string, +static struct lookup const * byword P((const char * string, const struct lookup * lp)); static struct lookup const line_codes[] = { - "Rule", LC_RULE, - "Zone", LC_ZONE, - "Link", LC_LINK, - "Leap", LC_LEAP, - NULL, 0 + { "Rule", LC_RULE }, + { "Zone", LC_ZONE }, + { "Link", LC_LINK }, + { "Leap", LC_LEAP }, + { NULL, 0} }; static struct lookup const mon_names[] = { - "January", TM_JANUARY, - "February", TM_FEBRUARY, - "March", TM_MARCH, - "April", TM_APRIL, - "May", TM_MAY, - "June", TM_JUNE, - "July", TM_JULY, - "August", TM_AUGUST, - "September", TM_SEPTEMBER, - "October", TM_OCTOBER, - "November", TM_NOVEMBER, - "December", TM_DECEMBER, - NULL, 0 + { "January", TM_JANUARY }, + { "February", TM_FEBRUARY }, + { "March", TM_MARCH }, + { "April", TM_APRIL }, + { "May", TM_MAY }, + { "June", TM_JUNE }, + { "July", TM_JULY }, + { "August", TM_AUGUST }, + { "September", TM_SEPTEMBER }, + { "October", TM_OCTOBER }, + { "November", TM_NOVEMBER }, + { "December", TM_DECEMBER }, + { NULL, 0 } }; static struct lookup const wday_names[] = { - "Sunday", TM_SUNDAY, - "Monday", TM_MONDAY, - "Tuesday", TM_TUESDAY, - "Wednesday", TM_WEDNESDAY, - "Thursday", TM_THURSDAY, - "Friday", TM_FRIDAY, - "Saturday", TM_SATURDAY, - NULL, 0 + { "Sunday", TM_SUNDAY }, + { "Monday", TM_MONDAY }, + { "Tuesday", TM_TUESDAY }, + { "Wednesday", TM_WEDNESDAY }, + { "Thursday", TM_THURSDAY }, + { "Friday", TM_FRIDAY }, + { "Saturday", TM_SATURDAY }, + { NULL, 0 } }; static struct lookup const lasts[] = { - "last-Sunday", TM_SUNDAY, - "last-Monday", TM_MONDAY, - "last-Tuesday", TM_TUESDAY, - "last-Wednesday", TM_WEDNESDAY, - "last-Thursday", TM_THURSDAY, - "last-Friday", TM_FRIDAY, - "last-Saturday", TM_SATURDAY, - NULL, 0 + { "last-Sunday", TM_SUNDAY }, + { "last-Monday", TM_MONDAY }, + { "last-Tuesday", TM_TUESDAY }, + { "last-Wednesday", TM_WEDNESDAY }, + { "last-Thursday", TM_THURSDAY }, + { "last-Friday", TM_FRIDAY }, + { "last-Saturday", TM_SATURDAY }, + { NULL, 0 } }; static struct lookup const begin_years[] = { - "minimum", YR_MINIMUM, - "maximum", YR_MAXIMUM, - NULL, 0 + { "minimum", YR_MINIMUM }, + { "maximum", YR_MAXIMUM }, + { NULL, 0 } }; static struct lookup const end_years[] = { - "minimum", YR_MINIMUM, - "maximum", YR_MAXIMUM, - "only", YR_ONLY, - NULL, 0 + { "minimum", YR_MINIMUM }, + { "maximum", YR_MAXIMUM }, + { "only", YR_ONLY }, + { NULL, 0 } }; static struct lookup const leap_types[] = { - "Rolling", TRUE, - "Stationary", FALSE, - NULL, 0 + { "Rolling", TRUE }, + { "Stationary", FALSE }, + { NULL, 0 } }; static const int len_months[2][MONSPERYEAR] = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, - 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; static const int len_years[2] = { @@ -362,7 +321,7 @@ static time_t ats[TZ_MAX_TIMES]; static unsigned char types[TZ_MAX_TIMES]; static long gmtoffs[TZ_MAX_TYPES]; static char isdsts[TZ_MAX_TYPES]; -static char abbrinds[TZ_MAX_TYPES]; +static unsigned char abbrinds[TZ_MAX_TYPES]; static char ttisstds[TZ_MAX_TYPES]; static char chars[TZ_MAX_CHARS]; static time_t trans[TZ_MAX_LEAPS]; @@ -436,16 +395,17 @@ static void usage() { (void) fprintf(stderr, -"%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ]\n\ -\t[ -L leapseconds ] [ filename ... ]\n", +"%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ] \n\ +\t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n", progname, progname); (void) exit(EXIT_FAILURE); } -static const char * psxrules = NULL; -static const char * lcltime = NULL; -static const char * directory = NULL; -static const char * leapsec = NULL; +static const char * psxrules; +static const char * lcltime; +static const char * directory; +static const char * leapsec; +static const char * yitcommand; static int sflag = FALSE; int @@ -458,7 +418,7 @@ char * argv[]; (void) umask(umask(022) | 022); progname = argv[0]; - while ((c = getopt(argc, argv, "d:l:p:L:vs")) != EOF) + while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF) switch (c) { default: usage(); @@ -492,6 +452,16 @@ char * argv[]; (void) exit(EXIT_FAILURE); } break; + case 'y': + if (yitcommand == NULL) + yitcommand = optarg; + else { + (void) fprintf(stderr, +"%s: More than one -y option specified\n", + progname); + (void) exit(EXIT_FAILURE); + } + break; case 'L': if (leapsec == NULL) leapsec = optarg; @@ -513,6 +483,8 @@ char * argv[]; usage(); /* usage message by request */ if (directory == NULL) directory = TZDIR; + if (yitcommand == NULL) + yitcommand = "sh ./yearistype"; setboundaries(); @@ -557,12 +529,20 @@ const char * const tofile; register char * fromname; register char * toname; - fromname = ecpyalloc(directory); - fromname = ecatalloc(fromname, "/"); - fromname = ecatalloc(fromname, fromfile); - toname = ecpyalloc(directory); - toname = ecatalloc(toname, "/"); - toname = ecatalloc(toname, tofile); + if (fromfile[0] == '/') + fromname = (char *)fromfile; + else { + fromname = ecpyalloc(directory); + fromname = ecatalloc(fromname, "/"); + fromname = ecatalloc(fromname, fromfile); + } + if (tofile[0] == '/') + toname = (char *)tofile; + else { + toname = ecpyalloc(directory); + toname = ecatalloc(toname, "/"); + toname = ecatalloc(toname, tofile); + } /* ** We get to be careful here since ** there's a fair chance of root running us. @@ -570,13 +550,19 @@ const char * const tofile; if (!itsdir(toname)) (void) remove(toname); if (link(fromname, toname) != 0) { - (void) fprintf(stderr, "%s: Can't link from %s to ", - progname, fromname); - (void) perror(toname); - (void) exit(EXIT_FAILURE); + if (mkdirs(toname) != 0) + (void) exit(EXIT_FAILURE); + if (link(fromname, toname) != 0) { + (void) fprintf(stderr, "%s: Can't link from %s to ", + progname, fromname); + (void) perror(toname); + (void) exit(EXIT_FAILURE); + } } - ifree(fromname); - ifree(toname); + if (fromname != fromfile) + ifree(fromname); + if (toname != tofile) + ifree(toname); } static void @@ -609,9 +595,14 @@ static int itsdir(name) const char * const name; { - struct stat s; + register char * myname; + register int accres; - return (stat(name, &s) == 0 && S_ISDIR(s.st_mode)); + myname = ecpyalloc(name); + myname = ecatalloc(myname, "/."); + accres = access(myname, 0); + ifree(myname); + return accres == 0; } /* @@ -624,8 +615,8 @@ const char * const name; static int rcomp(cp1, cp2) -const void * cp1; -const void * cp2; +const genericptr_t cp1; +const genericptr_t cp2; { return strcmp(((struct rule *) cp1)->r_name, ((struct rule *) cp2)->r_name); @@ -640,8 +631,9 @@ associate() register int i; if (nrules != 0) - (void) qsort((void *) rules, (size_t) nrules, - (size_t) sizeof *rules, rcomp); + (void) qsort((genericptr_t) rules, + (qsort_size_t) nrules, + (qsort_size_t) sizeof *rules, rcomp); for (i = 0; i < nzones; ++i) { zp = &zones[i]; zp->z_rules = NULL; @@ -667,8 +659,7 @@ associate() ** Maybe we have a local standard time offset. */ eat(zp->z_filename, zp->z_linenum); - zp->z_stdoff = - gethms((char *)zp->z_rule, "unruly zone", TRUE); + zp->z_stdoff = gethms(zp->z_rule, "unruly zone", TRUE); /* ** Note, though, that if there's no rule, ** a '%s' in the format is a bad thing. @@ -716,8 +707,10 @@ const char * name; fields = getfields(buf); nfields = 0; while (fields[nfields] != NULL) { + static char nada[1]; + if (ciequal(fields[nfields], "-")) - fields[nfields] = ""; + fields[nfields] = nada; ++nfields; } if (nfields == 0) { @@ -781,7 +774,7 @@ const char * name; static long gethms(string, errstring, signable) -char * string; +const char * string; const char * const errstring; const int signable; { @@ -848,22 +841,24 @@ register char ** const fields; const int nfields; { register int i; - char buf[132]; + static char * buf; if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) { error("wrong number of fields on Zone line"); return FALSE; } if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) { + buf = erealloc(buf, 132 + strlen(TZDEFAULT)); (void) sprintf(buf, - "\"Zone %s\" line and -l option are mutually exclusive", +"\"Zone %s\" line and -l option are mutually exclusive", TZDEFAULT); error(buf); return FALSE; } if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) { + buf = erealloc(buf, 132 + strlen(TZDEFRULES)); (void) sprintf(buf, - "\"Zone %s\" line and -p option are mutually exclusive", +"\"Zone %s\" line and -p option are mutually exclusive", TZDEFRULES); error(buf); return FALSE; @@ -871,6 +866,9 @@ const int nfields; for (i = 0; i < nzones; ++i) if (zones[i].z_name != NULL && strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) { + buf = erealloc(buf, 132 + + strlen(fields[ZF_NAME]) + + strlen(zones[i].z_filename)); (void) sprintf(buf, "duplicate zone name %s (file \"%s\", line %d)", fields[ZF_NAME], @@ -945,15 +943,20 @@ const int iscont; fields[i_untilyear], "only", "", - (nfields > i_untilmonth) ? fields[i_untilmonth] : "Jan", + (nfields > i_untilmonth) ? + fields[i_untilmonth] : "Jan", (nfields > i_untilday) ? fields[i_untilday] : "1", (nfields > i_untiltime) ? fields[i_untiltime] : "0"); - z.z_untiltime = rpytime(&z.z_untilrule, z.z_untilrule.r_loyear); - if (iscont && nzones > 0 && z.z_untiltime < max_time && + z.z_untiltime = rpytime(&z.z_untilrule, + z.z_untilrule.r_loyear); + if (iscont && nzones > 0 && z.z_untiltime > min_time && + z.z_untiltime < max_time && + zones[nzones - 1].z_untiltime > min_time && + zones[nzones - 1].z_untiltime < max_time && zones[nzones - 1].z_untiltime >= z.z_untiltime) { error("Zone continuation line end time is not after end time of previous line"); - return FALSE; + return FALSE; } } zones = (struct zone *) erealloc((char *) zones, @@ -984,8 +987,7 @@ const int nfields; } dayoff = 0; cp = fields[LP_YEAR]; - if (sscanf((char *)cp, scheck(cp, "%d"), &year) != 1 || - year < min_year || year > max_year) { + if (sscanf(cp, scheck(cp, "%d"), &year) != 1) { /* * Leapin' Lizards! */ @@ -1015,7 +1017,7 @@ const int nfields; ++j; } cp = fields[LP_DAY]; - if (sscanf((char *)cp, scheck(cp, "%d"), &day) != 1 || + if (sscanf(cp, scheck(cp, "%d"), &day) != 1 || day <= 0 || day > len_months[isleap(year)][month]) { error("invalid day of month"); return; @@ -1035,16 +1037,32 @@ const int nfields; } tod = gethms(fields[LP_TIME], "invalid time of day", FALSE); cp = fields[LP_CORR]; - if (strcmp(cp, "+") != 0 && strcmp(cp, "") != 0) { - /* infile() turned "-" into "" */ - error("illegal CORRECTION field on Leap line"); - return; - } - if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) { - error("illegal Rolling/Stationary field on Leap line"); - return; + { + register int positive; + int count; + + if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */ + positive = FALSE; + count = 1; + } else if (strcmp(cp, "--") == 0) { + positive = FALSE; + count = 2; + } else if (strcmp(cp, "+") == 0) { + positive = TRUE; + count = 1; + } else if (strcmp(cp, "++") == 0) { + positive = TRUE; + count = 2; + } else { + error("illegal CORRECTION field on Leap line"); + return; + } + if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) { + error("illegal Rolling/Stationary field on Leap line"); + return; + } + leapadd(tadd(t, tod), positive, lp->l_value, count); } - addleap(tadd(t, tod), *cp == '+', lp->l_value); } static void @@ -1125,12 +1143,9 @@ char * const timep; "%s: panic: Invalid l_value %d\n", progname, lp->l_value); (void) exit(EXIT_FAILURE); - } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1 || - rp->r_loyear < min_year || rp->r_loyear > max_year) { - if (noise) - error("invalid starting year"); - if (rp->r_loyear > max_year) - return; + } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) { + error("invalid starting year"); + return; } cp = hiyearp; if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) { @@ -1148,19 +1163,10 @@ char * const timep; "%s: panic: Invalid l_value %d\n", progname, lp->l_value); (void) exit(EXIT_FAILURE); - } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1 || - rp->r_hiyear < min_year || rp->r_hiyear > max_year) { - if (noise) - error("invalid ending year"); - if (rp->r_hiyear < min_year) - return; + } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) { + error("invalid ending year"); + return; } - if (rp->r_hiyear < min_year) - return; - if (rp->r_loyear < min_year) - rp->r_loyear = min_year; - if (rp->r_hiyear > max_year) - rp->r_hiyear = max_year; if (rp->r_loyear > rp->r_hiyear) { error("starting year greater than ending year"); return; @@ -1236,7 +1242,9 @@ FILE * const fp; char buf[4]; convert(val, buf); - (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp); + (void) fwrite((genericptr_t) buf, + (fwrite_size_t) sizeof buf, + (fwrite_size_t) 1, fp); } static void @@ -1245,15 +1253,11 @@ const char * const name; { register FILE * fp; register int i, j; - char fullname[BUFSIZ]; + static char * fullname; static struct tzhead tzh; - if (strlen(directory) + 1 + strlen(name) >= sizeof fullname) { - (void) fprintf(stderr, - "%s: File name %s/%s too long\n", progname, - directory, name); - (void) exit(EXIT_FAILURE); - } + fullname = erealloc(fullname, + strlen(directory) + 1 + strlen(name) + 1); (void) sprintf(fullname, "%s/%s", directory, name); if ((fp = fopen(fullname, "wb")) == NULL) { if (mkdirs(fullname) != 0) @@ -1269,7 +1273,9 @@ const char * const name; convert(eitol(timecnt), tzh.tzh_timecnt); convert(eitol(typecnt), tzh.tzh_typecnt); convert(eitol(charcnt), tzh.tzh_charcnt); - (void) fwrite((void *) &tzh, (size_t) sizeof tzh, (size_t) 1, fp); + (void) fwrite((genericptr_t) &tzh, + (fwrite_size_t) sizeof tzh, + (fwrite_size_t) 1, fp); for (i = 0; i < timecnt; ++i) { j = leapcnt; while (--j >= 0) @@ -1280,16 +1286,18 @@ const char * const name; puttzcode((long) ats[i], fp); } if (timecnt > 0) - (void) fwrite((void *) types, (size_t) sizeof types[0], - (size_t) timecnt, fp); + (void) fwrite((genericptr_t) types, + (fwrite_size_t) sizeof types[0], + (fwrite_size_t) timecnt, fp); for (i = 0; i < typecnt; ++i) { puttzcode((long) gmtoffs[i], fp); (void) putc(isdsts[i], fp); (void) putc(abbrinds[i], fp); } if (charcnt != 0) - (void) fwrite((void *) chars, (size_t) sizeof chars[0], - (size_t) charcnt, fp); + (void) fwrite((genericptr_t) chars, + (fwrite_size_t) sizeof chars[0], + (fwrite_size_t) charcnt, fp); for (i = 0; i < leapcnt; ++i) { if (roll[i]) { if (timecnt == 0 || trans[i] < ats[0]) { @@ -1344,28 +1352,35 @@ const int zonecount; typecnt = 0; charcnt = 0; /* - ** Two guesses. . .the second may well be corrected later. + ** A guess that may well be corrected later. */ - gmtoff = zpfirst->z_gmtoff; stdoff = 0; + /* + ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au) + ** for noting the need to unconditionally initialize startttisstd. + */ + startttisstd = FALSE; #ifdef lint starttime = 0; - startttisstd = FALSE; #endif /* defined lint */ for (i = 0; i < zonecount; ++i) { - usestart = i > 0; - useuntil = i < (zonecount - 1); zp = &zpfirst[i]; + usestart = i > 0 && (zp - 1)->z_untiltime > min_time; + useuntil = i < (zonecount - 1); + if (useuntil && zp->z_untiltime <= min_time) + continue; + gmtoff = zp->z_gmtoff; eat(zp->z_filename, zp->z_linenum); startisdst = -1; if (zp->z_nrules == 0) { - type = addtype(oadd(zp->z_gmtoff, zp->z_stdoff), - zp->z_format, zp->z_stdoff != 0, - startttisstd); + stdoff = zp->z_stdoff; + (void) strcpy(startbuf, zp->z_format); + type = addtype(oadd(zp->z_gmtoff, stdoff), + startbuf, stdoff != 0, startttisstd); if (usestart) addtt(starttime, type); - gmtoff = zp->z_gmtoff; - stdoff = zp->z_stdoff; + else if (stdoff != 0) + addtt(min_time, type); } else for (year = min_year; year <= max_year; ++year) { if (useuntil && year > zp->z_untilrule.r_hiyear) break; @@ -1395,11 +1410,11 @@ const int zonecount; ** assuming the current gmtoff and ** stdoff values. */ - offset = gmtoff; - if (!zp->z_untilrule.r_todisstd) - offset = oadd(offset, stdoff); untiltime = tadd(zp->z_untiltime, - -offset); + -gmtoff); + if (!zp->z_untilrule.r_todisstd) + untiltime = tadd(untiltime, + -stdoff); } /* ** Find the rule (of those to do, if any) @@ -1435,21 +1450,33 @@ const int zonecount; if (useuntil && ktime >= untiltime) break; if (usestart) { - if (ktime < starttime) { - stdoff = rp->r_stdoff; - startoff = oadd(zp->z_gmtoff, - rp->r_stdoff); - (void) sprintf(startbuf, - zp->z_format, - rp->r_abbrvar); - startisdst = - rp->r_stdoff != 0; - continue; + if (ktime < starttime) { + stdoff = rp->r_stdoff; + startoff = oadd(zp->z_gmtoff, + rp->r_stdoff); + (void) sprintf(startbuf, zp->z_format, + rp->r_abbrvar); + startisdst = rp->r_stdoff != 0; + continue; + } + usestart = FALSE; + if (ktime != starttime) { + if (startisdst < 0 && + zp->z_gmtoff != + (zp - 1)->z_gmtoff) { + type = (timecnt == 0) ? 0 : + types[timecnt - 1]; + startoff = oadd(gmtoffs[type], + -(zp - 1)->z_gmtoff); + startisdst = startoff != 0; + startoff = oadd(startoff, + zp->z_gmtoff); + (void) strcpy(startbuf, + &chars[abbrinds[type]]); } - if (ktime != starttime && - startisdst >= 0) + if (startisdst >= 0) addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd)); - usestart = FALSE; + } } eats(zp->z_filename, zp->z_linenum, rp->r_filename, rp->r_linenum); @@ -1458,9 +1485,7 @@ addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd)); offset = oadd(zp->z_gmtoff, rp->r_stdoff); type = addtype(offset, buf, rp->r_stdoff != 0, rp->r_todisstd); - if (timecnt != 0 || rp->r_stdoff != 0) - addtt(ktime, type); - gmtoff = zp->z_gmtoff; + addtt(ktime, type); stdoff = rp->r_stdoff; } } @@ -1468,9 +1493,10 @@ addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd)); ** Now we may get to set starttime for the next zone line. */ if (useuntil) { - starttime = tadd(zp->z_untiltime, - -gmtoffs[types[timecnt - 1]]); + starttime = tadd(zp->z_untiltime, -gmtoff); startttisstd = zp->z_untilrule.r_todisstd; + if (!startttisstd) + starttime = tadd(starttime, -stdoff); } } writezone(zpfirst->z_name); @@ -1483,6 +1509,8 @@ const int type; { if (timecnt != 0 && type == types[timecnt - 1]) return; /* easy enough! */ + if (timecnt == 0 && type == 0 && isdsts[0] == 0) + return; /* handled by default rule */ if (timecnt >= TZ_MAX_TIMES) { error("too many transitions?!"); (void) exit(EXIT_FAILURE); @@ -1534,14 +1562,15 @@ const int ttisstd; } static void -addleap(t, positive, rolling) +leapadd(t, positive, rolling, count) const time_t t; const int positive; const int rolling; +int count; { register int i, j; - if (leapcnt >= TZ_MAX_LEAPS) { + if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) { error("too many leap seconds"); (void) exit(EXIT_FAILURE); } @@ -1553,15 +1582,17 @@ const int rolling; } break; } - for (j = leapcnt; j > i; --j) { - trans[j] = trans[j-1]; - corr[j] = corr[j-1]; - roll[j] = roll[j-1]; - } - trans[i] = t; - corr[i] = (positive ? 1L : -1L); - roll[i] = rolling; - ++leapcnt; + do { + for (j = leapcnt; j > i; --j) { + trans[j] = trans[j - 1]; + corr[j] = corr[j - 1]; + roll[j] = roll[j - 1]; + } + trans[i] = t; + corr[i] = positive ? 1L : eitol(-count); + roll[i] = rolling; + ++leapcnt; + } while (positive && --count != 0); } static void @@ -1584,8 +1615,8 @@ yearistype(year, type) const int year; const char * const type; { - char buf[BUFSIZ]; - int result; + static char * buf; + int result; if (type == NULL || *type == '\0') return TRUE; @@ -1593,7 +1624,8 @@ const char * const type; return (year % 4) == 0; if (strcmp(type, "nonpres") == 0) return (year % 4) != 0; - (void) sprintf(buf, "yearistype %d %s", year, type); + buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type)); + (void) sprintf(buf, "%s %d %s", yitcommand, year, type); result = system(buf); if (result == 0) return TRUE; @@ -1710,7 +1742,7 @@ const long t2; register long t; t = t1 + t2; - if (t2 > 0 && t <= t1 || t2 < 0 && t >= t1) { + if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { error("time overflow"); (void) exit(EXIT_FAILURE); } @@ -1729,7 +1761,7 @@ const long t2; if (t1 == min_time && t2 < 0) return min_time; t = t1 + t2; - if (t2 > 0 && t <= t1 || t2 < 0 && t >= t1) { + if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) { error("time overflow"); (void) exit(EXIT_FAILURE); } @@ -1803,7 +1835,7 @@ register const int wantedy; } else { dayoff = oadd(dayoff, (long) -1); if (--wday < 0) - wday = LDAYSPERWEEK; + wday = LDAYSPERWEEK - 1; --i; } if (i < 0 || i >= len_months[isleap(y)][m]) { @@ -1811,24 +1843,14 @@ register const int wantedy; (void) exit(EXIT_FAILURE); } } - if (dayoff < 0 && !tt_signed) { - if (wantedy == rp->r_loyear) - return min_time; - error("time before zero"); - (void) exit(EXIT_FAILURE); - } + if (dayoff < 0 && !tt_signed) + return min_time; t = (time_t) dayoff * SECSPERDAY; /* ** Cheap overflow check. */ - if (t / SECSPERDAY != dayoff) { - if (wantedy == rp->r_hiyear) - return max_time; - if (wantedy == rp->r_loyear) - return min_time; - error("time overflow"); - (void) exit(EXIT_FAILURE); - } + if (t / SECSPERDAY != dayoff) + return (dayoff > 0) ? max_time : min_time; return tadd(t, rp->r_tod); } @@ -1839,7 +1861,7 @@ const char * const string; register int i; i = strlen(string) + 1; - if (charcnt + i >= TZ_MAX_CHARS) { + if (charcnt + i > TZ_MAX_CHARS) { error("too many, or too long, time zone abbreviations"); (void) exit(EXIT_FAILURE); } @@ -1881,8 +1903,9 @@ const int i; long l; l = i; - if (i < 0 && l >= 0 || i == 0 && l != 0 || i > 0 && l <= 0) { - (void) fprintf(stderr, "%s: %d did not sign extend correctly\n", + if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) { + (void) fprintf(stderr, + "%s: %d did not sign extend correctly\n", progname, i); (void) exit(EXIT_FAILURE); } |
