aboutsummaryrefslogtreecommitdiffstats
path: root/usr.sbin/zic/zic.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/zic/zic.c')
-rw-r--r--usr.sbin/zic/zic.c129
1 files changed, 95 insertions, 34 deletions
diff --git a/usr.sbin/zic/zic.c b/usr.sbin/zic/zic.c
index 0cec89369c3c..040a6053d29a 100644
--- a/usr.sbin/zic/zic.c
+++ b/usr.sbin/zic/zic.c
@@ -1,6 +1,6 @@
#ifndef lint
#ifndef NOID
-static char elsieid[] = "@(#)zic.c 7.77";
+static char elsieid[] = "@(#)zic.c 7.96";
#endif /* !defined NOID */
#endif /* !defined lint */
@@ -79,15 +79,9 @@ struct zone {
extern int getopt P((int argc, char * const 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 void * irealloc P((void * old, int n));
extern int link P((const char * fromname, const char * toname));
extern char * optarg;
extern int optind;
-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,
@@ -136,9 +130,9 @@ static void usage P((void));
static void writezone P((const char * name));
static int yearistype P((int year, const char * type));
-#if !HAVE_STRERROR
+#if !(HAVE_STRERROR - 0)
static char * strerror P((int));
-#endif /* !HAVE_STRERROR */
+#endif /* !(HAVE_STRERROR - 0) */
static int charcnt;
static int errors;
@@ -147,8 +141,10 @@ static int leapcnt;
static int linenum;
static time_t max_time;
static int max_year;
+static int max_year_representable;
static time_t min_time;
static int min_year;
+static int min_year_representable;
static int noise;
static const char * rfilename;
static int rlinenum;
@@ -359,6 +355,7 @@ char * const ptr;
{
if (ptr == NULL) {
const char *e = strerror(errno);
+
(void) fprintf(stderr, _("%s: Memory exhausted: %s\n"),
progname, e);
(void) exit(EXIT_FAILURE);
@@ -375,19 +372,18 @@ char * const ptr;
** Error handling.
*/
-#if ! HAVE_STRERROR
+#if !(HAVE_STRERROR - 0)
static char *
strerror(errnum)
int errnum;
{
- extern char *sys_errlist[];
- extern int sys_nerr;
+ extern char * sys_errlist[];
+ extern int sys_nerr;
- if (errnum > 0 && errnum <= sys_nerr)
- return sys_errlist[errnum];
- return "Unknown system error";
+ return (errnum > 0 && errnum <= sys_nerr) ?
+ sys_errlist[errnum] : _("Unknown system error");
}
-#endif /* ! HAVE_STRERROR */
+#endif /* !(HAVE_STRERROR - 0) */
static void
eats(name, num, rname, rnum)
@@ -434,9 +430,9 @@ const char * const string;
{
char * cp;
- cp = ecpyalloc("warning: ");
+ cp = ecpyalloc(_("warning: "));
cp = ecatalloc(cp, string);
- error(string);
+ error(cp);
ifree(cp);
--errors;
}
@@ -476,7 +472,7 @@ char * argv[];
(void) textdomain(TZ_DOMAIN);
#endif /* HAVE_GETTEXT - 0 */
progname = argv[0];
- while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF)
+ while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
switch (c) {
default:
usage();
@@ -605,10 +601,21 @@ const char * const tofile;
if (!itsdir(toname))
(void) remove(toname);
if (link(fromname, toname) != 0) {
+ int result;
+
if (mkdirs(toname) != 0)
(void) exit(EXIT_FAILURE);
- if (link(fromname, toname) != 0) {
+ result = link(fromname, toname);
+#if (HAVE_SYMLINK - 0)
+ if (result != 0) {
+ result = symlink(fromname, toname);
+ if (result == 0)
+warning(_("hard link failed, symbolic link used"));
+ }
+#endif
+ if (result != 0) {
const char *e = strerror(errno);
+
(void) fprintf(stderr,
_("%s: Can't link from %s to %s: %s\n"),
progname, fromname, toname, e);
@@ -654,6 +661,8 @@ setboundaries P((void))
}
min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
+ min_year_representable = min_year;
+ max_year_representable = max_year;
}
static int
@@ -781,6 +790,7 @@ const char * name;
fp = stdin;
} else if ((fp = fopen(name, "r")) == NULL) {
const char *e = strerror(errno);
+
(void) fprintf(stderr, _("%s: Can't open %s: %s\n"),
progname, name, e);
(void) exit(EXIT_FAILURE);
@@ -849,6 +859,7 @@ _("%s: panic: Invalid l_value %d\n"),
}
if (fp != stdin && fclose(fp)) {
const char *e = strerror(errno);
+
(void) fprintf(stderr, _("%s: Error closing %s: %s\n"),
progname, filename, e);
(void) exit(EXIT_FAILURE);
@@ -890,9 +901,10 @@ const int signable;
error(errstring);
return 0;
}
- if (hh < 0 || hh >= HOURSPERDAY ||
+ if ((hh < 0 || hh >= HOURSPERDAY ||
mm < 0 || mm >= MINSPERHOUR ||
- ss < 0 || ss > SECSPERMIN) {
+ ss < 0 || ss > SECSPERMIN) &&
+ !(hh == HOURSPERDAY && mm == 0 && ss == 0)) {
error(errstring);
return 0;
}
@@ -1019,7 +1031,7 @@ const int iscont;
}
z.z_filename = filename;
z.z_linenum = linenum;
- z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid GMT offset"), TRUE);
+ z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UTC offset"), TRUE);
if ((cp = strchr(fields[i_format], '%')) != 0) {
if (*++cp != 's' || strchr(cp, '%') != 0) {
error(_("invalid abbreviation format"));
@@ -1221,6 +1233,7 @@ const char * const timep;
rp->r_todisstd = FALSE;
rp->r_todisgmt = FALSE;
*ep = '\0';
+ break;
case 'g': /* Greenwich */
case 'u': /* Universal */
case 'z': /* Zulu */
@@ -1252,6 +1265,11 @@ const char * const timep;
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
error(_("invalid starting year"));
return;
+ } else if (noise) {
+ if (rp->r_loyear < min_year_representable)
+ warning(_("starting year too low to be represented"));
+ else if (rp->r_loyear > max_year_representable)
+ warning(_("starting year too high to be represented"));
}
cp = hiyearp;
if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
@@ -1272,6 +1290,11 @@ const char * const timep;
} else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
error(_("invalid ending year"));
return;
+ } else if (noise) {
+ if (rp->r_loyear < min_year_representable)
+ warning(_("starting year too low to be represented"));
+ else if (rp->r_loyear > max_year_representable)
+ warning(_("starting year too high to be represented"));
}
if (rp->r_loyear > rp->r_hiyear) {
error(_("starting year greater than ending year"));
@@ -1286,6 +1309,8 @@ const char * const timep;
}
rp->r_yrtype = ecpyalloc(typep);
}
+ if (rp->r_loyear < min_year && rp->r_loyear > 0)
+ min_year = rp->r_loyear;
/*
** Day work.
** Accept things such as:
@@ -1394,8 +1419,10 @@ const char * const name;
toi = 0;
fromi = 0;
+ while (fromi < timecnt && attypes[fromi].at < min_time)
+ ++fromi;
if (isdsts[0] == 0)
- while (attypes[fromi].type == 0)
+ while (fromi < timecnt && attypes[fromi].type == 0)
++fromi; /* handled by default rule */
for ( ; fromi < timecnt; ++fromi) {
if (toi != 0
@@ -1423,11 +1450,22 @@ const char * const name;
fullname = erealloc(fullname,
(int) (strlen(directory) + 1 + strlen(name) + 1));
(void) sprintf(fullname, "%s/%s", directory, name);
+ /*
+ ** Remove old file, if any, to snap links.
+ */
+ if (!itsdir(fullname) && remove(fullname) != 0 && errno != ENOENT) {
+ const char *e = strerror(errno);
+
+ (void) fprintf(stderr, _("%s: Can't remove %s: %s\n"),
+ progname, fullname, e);
+ (void) exit(EXIT_FAILURE);
+ }
if ((fp = fopen(fullname, "wb")) == NULL) {
if (mkdirs(fullname) != 0)
(void) exit(EXIT_FAILURE);
if ((fp = fopen(fullname, "wb")) == NULL) {
const char *e = strerror(errno);
+
(void) fprintf(stderr, _("%s: Can't create %s: %s\n"),
progname, fullname, e);
(void) exit(EXIT_FAILURE);
@@ -1439,7 +1477,9 @@ const char * const name;
convert(eitol(timecnt), tzh.tzh_timecnt);
convert(eitol(typecnt), tzh.tzh_typecnt);
convert(eitol(charcnt), tzh.tzh_charcnt);
+ (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
#define DO(field) (void) fwrite((void *) tzh.field, (size_t) sizeof tzh.field, (size_t) 1, fp)
+ DO(tzh_magic);
DO(tzh_reserved);
DO(tzh_ttisgmtcnt);
DO(tzh_ttisstdcnt);
@@ -1603,7 +1643,7 @@ const int zonecount;
INITIALIZE(ktime);
if (useuntil) {
/*
- ** Turn untiltime into GMT
+ ** Turn untiltime into UTC
** assuming the current gmtoff and
** stdoff values.
*/
@@ -1683,7 +1723,7 @@ const int zonecount;
(void) strcpy(startbuf, zp->z_format);
eat(zp->z_filename, zp->z_linenum);
if (*startbuf == '\0')
-error(_("can't determine time zone abbrevation to use just after until time"));
+error(_("can't determine time zone abbreviation to use just after until time"));
else addtt(starttime,
addtype(startoff, startbuf,
startoff != zp->z_gmtoff,
@@ -1709,8 +1749,22 @@ error(_("can't determine time zone abbrevation to use just after until time"));
static void
addtt(starttime, type)
const time_t starttime;
-const int type;
+int type;
{
+ if (starttime <= min_time ||
+ (timecnt == 1 && attypes[0].at < min_time)) {
+ gmtoffs[0] = gmtoffs[type];
+ isdsts[0] = isdsts[type];
+ ttisstds[0] = ttisstds[type];
+ ttisgmts[0] = ttisgmts[type];
+ if (abbrinds[type] != 0)
+ (void) strcpy(chars, &chars[abbrinds[type]]);
+ abbrinds[0] = 0;
+ charcnt = strlen(chars) + 1;
+ typecnt = 1;
+ timecnt = 0;
+ type = 0;
+ }
if (timecnt >= TZ_MAX_TIMES) {
error(_("too many transitions?!"));
(void) exit(EXIT_FAILURE);
@@ -1905,10 +1959,11 @@ register const struct lookup * const table;
*/
foundlp = NULL;
for (lp = table; lp->l_word != NULL; ++lp)
- if (itsabbr(word, lp->l_word))
+ if (itsabbr(word, lp->l_word)) {
if (foundlp == NULL)
foundlp = lp;
else return NULL; /* multiple inexact matches */
+ }
return foundlp;
}
@@ -2112,14 +2167,20 @@ char * const argname;
if (!itsdir(name)) {
/*
** It doesn't seem to exist, so we try to create it.
+ ** Creation may fail because of the directory being
+ ** created by some other multiprocessor, so we get
+ ** to do extra checking.
*/
- if (mkdir(name, 0755) != 0) {
+ if (mkdir(name, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0) {
const char *e = strerror(errno);
- (void) fprintf(stderr,
- _("%s: Can't create directory %s: %s\n"),
- progname, name, e);
- ifree(name);
- return -1;
+
+ if (errno != EEXIST || !itsdir(name)) {
+ (void) fprintf(stderr,
+_("%s: Can't create directory %s: %s\n"),
+ progname, name, e);
+ ifree(name);
+ return -1;
+ }
}
}
*cp = '/';