📄 zic.c
字号:
/*- * Copyright (c) 1991, 1993 * 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. */#ifndef lintstatic char sccsid[] = "@(#)zic.c 8.1 (Berkeley) 7/19/93";#endif /* not lint */#ifdef notdefstatic 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 TRUE#define TRUE 1#define FALSE 0#endif /* !defined TRUE */struct rule { const char * r_filename; int r_linenum; const char * r_name; int r_loyear; /* for example, 1986 */ int r_hiyear; /* for example, 1986 */ const char * r_yrtype; int r_month; /* 0..11 */ int r_dycode; /* see below */ int r_dayofmonth; int r_wday; long r_tod; /* time from midnight */ int r_todisstd; /* above is standard time if TRUE */ /* or wall clock time if FALSE */ long r_stdoff; /* offset from standard time */ const char * r_abbrvar; /* variable part of abbreviation */ int r_todo; /* a rule to do (used in outzone) */ time_t r_temp; /* used in outzone */};/*** r_dycode r_dayofmonth r_wday*/#define DC_DOM 0 /* 1..31 */ /* unused */#define DC_DOWGEQ 1 /* 1..31 */ /* 0..6 (Sun..Sat) */#define DC_DOWLEQ 2 /* 1..31 */ /* 0..6 (Sun..Sat) */struct zone { const char * z_filename; int z_linenum; const char * z_name; long z_gmtoff; const char * z_rule; const char * z_format; long z_stdoff; struct rule * z_rules; int z_nrules; struct rule z_untilrule; 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 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));static int charcnt;static int errors;static const char * filename;static int leapcnt;static int linenum;static time_t max_time;static int max_year;static time_t min_time;static int min_year;static int noise;static const char * rfilename;static int rlinenum;static const char * progname;static int timecnt;static int typecnt;static int tt_signed;/*** Line codes.*/#define LC_RULE 0#define LC_ZONE 1#define LC_LINK 2#define LC_LEAP 3/*** Which fields are which on a Zone line.*/#define ZF_NAME 1#define ZF_GMTOFF 2#define ZF_RULE 3#define ZF_FORMAT 4#define ZF_TILYEAR 5#define ZF_TILMONTH 6#define ZF_TILDAY 7#define ZF_TILTIME 8#define ZONE_MINFIELDS 5#define ZONE_MAXFIELDS 9/*** Which fields are which on a Zone continuation line.*/#define ZFC_GMTOFF 0#define ZFC_RULE 1#define ZFC_FORMAT 2#define ZFC_TILYEAR 3#define ZFC_TILMONTH 4#define ZFC_TILDAY 5#define ZFC_TILTIME 6#define ZONEC_MINFIELDS 3#define ZONEC_MAXFIELDS 7/*** Which files are which on a Rule line.*/#define RF_NAME 1#define RF_LOYEAR 2#define RF_HIYEAR 3#define RF_COMMAND 4#define RF_MONTH 5#define RF_DAY 6#define RF_TOD 7#define RF_STDOFF 8#define RF_ABBRVAR 9#define RULE_FIELDS 10/*** Which fields are which on a Link line.*/#define LF_FROM 1#define LF_TO 2#define LINK_FIELDS 3/*** Which fields are which on a Leap line.*/#define LP_YEAR 1#define LP_MONTH 2#define LP_DAY 3#define LP_TIME 4#define LP_CORR 5#define LP_ROLL 6#define LEAP_FIELDS 7/*** Year synonyms.*/#define YR_MINIMUM 0#define YR_MAXIMUM 1#define YR_ONLY 2static struct rule * rules;static int nrules; /* number of rules */static struct zone * zones;static int nzones; /* number of zones */struct link { const char * l_filename; int l_linenum; const char * l_from; const char * l_to;};static struct link * links;static int nlinks;struct lookup { const char * l_word; const int l_value;};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};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};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};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};static struct lookup const begin_years[] = { "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};static struct lookup const leap_types[] = { "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};static const int len_years[2] = { DAYSPERNYEAR, DAYSPERLYEAR};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 char ttisstds[TZ_MAX_TYPES];static char chars[TZ_MAX_CHARS];static time_t trans[TZ_MAX_LEAPS];static long corr[TZ_MAX_LEAPS];static char roll[TZ_MAX_LEAPS];/*** Memory allocation.*/static char *memcheck(ptr)char * const ptr;{ if (ptr == NULL) { (void) perror(progname); (void) exit(EXIT_FAILURE); } return ptr;}#define emalloc(size) memcheck(imalloc(size))#define erealloc(ptr, size) memcheck(irealloc(ptr, size))#define ecpyalloc(ptr) memcheck(icpyalloc(ptr))#define ecatalloc(oldp, newp) memcheck(icatalloc(oldp, newp))/*** Error handling.*/static voideats(name, num, rname, rnum)const char * const name;const int num;const char * const rname;const int rnum;{ filename = name; linenum = num; rfilename = rname; rlinenum = rnum;}static voideat(name, num)const char * const name;const int num;{ eats(name, num, (char *) NULL, -1);}static voiderror(string)const char * const string;{ /* ** Match the format of "cc" to allow sh users to ** zic ... 2>&1 | error -t "*" -v ** on BSD systems. */ (void) fprintf(stderr, "\"%s\", line %d: %s", filename, linenum, string); if (rfilename != NULL) (void) fprintf(stderr, " (rule from \"%s\", line %d)", rfilename, rlinenum); (void) fprintf(stderr, "\n"); ++errors;}static voidusage(){ (void) fprintf(stderr,"%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ]\n\\t[ -L leapseconds ] [ 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 int sflag = FALSE;intmain(argc, argv)int argc;char * argv[];{ register int i, j; register int c; (void) umask(umask(022) | 022); progname = argv[0]; while ((c = getopt(argc, argv, "d:l:p:L:vs")) != EOF) switch (c) { default: usage(); case 'd': if (directory == NULL) directory = optarg; else { (void) fprintf(stderr,"%s: More than one -d option specified\n", progname); (void) exit(EXIT_FAILURE); } break; case 'l': if (lcltime == NULL) lcltime = optarg; else { (void) fprintf(stderr,"%s: More than one -l option specified\n", progname); (void) exit(EXIT_FAILURE); } break; case 'p': if (psxrules == NULL) psxrules = optarg; else { (void) fprintf(stderr,"%s: More than one -p option specified\n", progname); (void) exit(EXIT_FAILURE); } break; case 'L': if (leapsec == NULL) leapsec = optarg; else { (void) fprintf(stderr,"%s: More than one -L option specified\n", progname); (void) exit(EXIT_FAILURE); } break; case 'v': noise = TRUE; break; case 's': sflag = TRUE; break; } if (optind == argc - 1 && strcmp(argv[optind], "=") == 0) usage(); /* usage message by request */ if (directory == NULL) directory = TZDIR; setboundaries(); if (optind < argc && leapsec != NULL) { infile(leapsec); adjleap(); } zones = (struct zone *) emalloc(0); rules = (struct rule *) emalloc(0); links = (struct link *) emalloc(0); for (i = optind; i < argc; ++i) infile(argv[i]); if (errors) (void) exit(EXIT_FAILURE); associate(); for (i = 0; i < nzones; i = j) { /* ** Find the next non-continuation zone entry. */ for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j) ; outzone(&zones[i], j - i); } /* ** Make links. */ for (i = 0; i < nlinks; ++i) dolink(links[i].l_from, links[i].l_to); if (lcltime != NULL) dolink(lcltime, TZDEFAULT); if (psxrules != NULL) dolink(psxrules, TZDEFRULES); return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;}static voiddolink(fromfile, tofile)const char * const fromfile;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); /* ** We get to be careful here since ** there's a fair chance of root running us. */ 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); } ifree(fromname); ifree(toname);}static voidsetboundaries(){ register time_t bit; for (bit = 1; bit > 0; bit <<= 1) ; if (bit == 0) { /* time_t is an unsigned type */ tt_signed = FALSE; min_time = 0; max_time = ~(time_t) 0; if (sflag) max_time >>= 1; } else { tt_signed = TRUE; min_time = bit; max_time = bit; ++max_time; max_time = -max_time; if (sflag) min_time = 0; } min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year; max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;}static intitsdir(name)const char * const name;{ struct stat s; return (stat(name, &s) == 0 && S_ISDIR(s.st_mode));}/*** Associate sets of rules with zones.*//*** Sort by rule name.*/static intrcomp(cp1, cp2)const void * cp1;const void * cp2;{ return strcmp(((struct rule *) cp1)->r_name, ((struct rule *) cp2)->r_name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -