git: cfd0217aa9a9 - main - tzsetup: adopt zone1970.tab changes
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 27 Apr 2023 17:40:04 UTC
The branch main has been updated by yuripv:
URL: https://cgit.FreeBSD.org/src/commit/?id=cfd0217aa9a929ac625db90828a56dfe4dc1dbd2
commit cfd0217aa9a929ac625db90828a56dfe4dc1dbd2
Author: Yuri Pankov <yuripv@FreeBSD.org>
AuthorDate: 2023-04-27 17:31:48 +0000
Commit: Yuri Pankov <yuripv@FreeBSD.org>
CommitDate: 2023-04-27 17:31:48 +0000
tzsetup: adopt zone1970.tab changes
- assumption that single-zone countries do not have description
is no longer correct; do not try to optimize this case as it's
only going to make the code more confusing and we now have menus
with a single zone selection because of this
- remove the single-country continent short cut, it also only serves
to confuse users as we now have such a continent
- instead add a single-zone contry short cut (see above), now all
single-zone countries fall here
- use the #@ continent overrides that zone1970.tab introduces (this is
visible at least fixing Iceland being currently listed under Africa)
- add Arctic Ocean "continent" coming only from the overrides at the
moment
- update baseline with the changes
Reviewed by: bapt, philip
Differential Revision: https://reviews.freebsd.org/D39606
---
usr.sbin/tzsetup/baseline | 24 ++--
usr.sbin/tzsetup/tzsetup.c | 310 +++++++++++++++++++++++----------------------
2 files changed, 169 insertions(+), 165 deletions(-)
diff --git a/usr.sbin/tzsetup/baseline b/usr.sbin/tzsetup/baseline
index 79a7f2a869b6..de9b5f638d09 100644
--- a/usr.sbin/tzsetup/baseline
+++ b/usr.sbin/tzsetup/baseline
@@ -19,10 +19,10 @@ AQ:Antarctica
Antarctica:Antarctica/Palmer
Antarctica:Antarctica/Rothera
Antarctica:Antarctica/Troll
- Asia:Asia/Urumqi
- Pacific:Pacific/Auckland
- Pacific:Pacific/Port_Moresby
- Asia:Asia/Riyadh
+ Antarctica:Asia/Urumqi
+ Antarctica:Pacific/Auckland
+ Antarctica:Pacific/Port_Moresby
+ Antarctica:Asia/Riyadh
AG:Antigua and Barbuda
America:America/Puerto_Rico
AR:Argentina
@@ -159,13 +159,13 @@ CN:China
Asia:Asia/Shanghai
Asia:Asia/Urumqi
CX:Christmas Island
- Asia:Asia/Bangkok
+ Indian:Asia/Bangkok
CC:Cocos (Keeling) Islands
- Asia:Asia/Yangon
+ Indian:Asia/Yangon
CO:Colombia
America:America/Bogota
KM:Comoros
- Africa:Africa/Nairobi
+ Indian:Africa/Nairobi
CG:Congo
Africa:Africa/Lagos
CD:Congo, Democratic Republic of the
@@ -280,7 +280,7 @@ HK:Hong Kong
HU:Hungary
Europe:Europe/Budapest
IS:Iceland
- Africa:Africa/Abidjan
+ Atlantic:Africa/Abidjan
IN:India
Asia:Asia/Kolkata
ID:Indonesia
@@ -353,7 +353,7 @@ MO:Macao
MK:Macedonia (the former Yugoslav Republic of)
Europe:Europe/Belgrade
MG:Madagascar
- Africa:Africa/Nairobi
+ Indian:Africa/Nairobi
MW:Malawi
Africa:Africa/Maputo
MY:Malaysia
@@ -375,7 +375,7 @@ MR:Mauritania
MU:Mauritius
Indian:Indian/Mauritius
YT:Mayotte
- Africa:Africa/Nairobi
+ Indian:Africa/Nairobi
MX:Mexico
America:America/Mexico_City
America:America/Cancun
@@ -507,7 +507,7 @@ RE:Réunion
BL:Saint Barthélemy
America:America/Puerto_Rico
SH:Saint Helena Ascension and Tristan da Cunha
- Africa:Africa/Abidjan
+ Atlantic:Africa/Abidjan
KN:Saint Kitts and Nevis
America:America/Puerto_Rico
LC:Saint Lucia
@@ -563,7 +563,7 @@ SD:Sudan
SR:Suriname
America:America/Paramaribo
SJ:Svalbard and Jan Mayen
- Europe:Europe/Berlin
+ Arctic:Europe/Berlin
SE:Sweden
Europe:Europe/Berlin
CH:Switzerland
diff --git a/usr.sbin/tzsetup/tzsetup.c b/usr.sbin/tzsetup/tzsetup.c
index b4d906d90b7e..a20c0730c48e 100644
--- a/usr.sbin/tzsetup/tzsetup.c
+++ b/usr.sbin/tzsetup/tzsetup.c
@@ -157,8 +157,7 @@ static int usedialog = 1;
static int confirm_zone(const char *filename);
static int continent_country_menu(dialogMenuItem *);
-static int set_zone_multi(dialogMenuItem *);
-static int set_zone_whole_country(dialogMenuItem *);
+static int set_zone(dialogMenuItem *);
static int set_zone_menu(dialogMenuItem *);
static int set_zone_utc(void);
@@ -167,7 +166,7 @@ struct continent {
int nitems;
};
-static struct continent africa, america, antarctica, asia, atlantic;
+static struct continent africa, america, antarctica, arctic, asia, atlantic;
static struct continent australia, europe, indian, pacific, utc;
static struct continent_names {
@@ -177,6 +176,7 @@ static struct continent_names {
{ "Africa", &africa },
{ "America", &america },
{ "Antarctica", &antarctica },
+ { "Arctic", &arctic },
{ "Asia", &asia },
{ "Atlantic", &atlantic },
{ "Australia", &australia },
@@ -187,26 +187,27 @@ static struct continent_names {
};
static struct continent_items {
- char prompt[2];
+ char prompt[3];
char title[30];
} continent_items[] = {
{ "1", "Africa" },
{ "2", "America -- North and South" },
{ "3", "Antarctica" },
- { "4", "Asia" },
- { "5", "Atlantic Ocean" },
- { "6", "Australia" },
- { "7", "Europe" },
- { "8", "Indian Ocean" },
- { "9", "Pacific Ocean" },
- { "0", "UTC" }
+ { "4", "Arctic Ocean" },
+ { "5", "Asia" },
+ { "6", "Atlantic Ocean" },
+ { "7", "Australia" },
+ { "8", "Europe" },
+ { "9", "Indian Ocean" },
+ { "10", "Pacific Ocean" },
+ { "11", "UTC" }
};
#define NCONTINENTS \
(int)((sizeof(continent_items)) / (sizeof(continent_items[0])))
static dialogMenuItem continents[NCONTINENTS];
-#define OCEANP(x) ((x) == 4 || (x) == 7 || (x) == 8)
+#define OCEANP(x) ((x) == 3 || (x) == 5 || (x) == 8 || (x) == 9)
static int
continent_country_menu(dialogMenuItem *continent)
@@ -219,10 +220,6 @@ continent_country_menu(dialogMenuItem *continent)
if (strcmp(continent->title, "UTC") == 0)
return (set_zone_utc());
- /* Short cut -- if there's only one country, don't post a menu. */
- if (contp->nitems == 1)
- return (contp->menu[0].fire(&contp->menu[0]));
-
/* It's amazing how much good grammar really matters... */
if (!isocean) {
snprintf(title, sizeof(title), "Countries in %s",
@@ -239,14 +236,30 @@ continent_country_menu(dialogMenuItem *continent)
}
static struct continent *
-find_continent(const char *name)
+find_continent(int lineno, const char *name)
{
+ char *cname, *cp;
int i;
+ /*
+ * Both normal (the ones in zone filename, e.g. Europe/Andorra) and
+ * override (e.g. Atlantic/) entries should contain '/'.
+ */
+ cp = strdup(name);
+ if (cp == NULL)
+ err(1, "strdup");
+ cname = strsep(&cp, "/");
+ if (cp == NULL)
+ errx(1, "%s:%d: invalid entry `%s'", path_zonetab, lineno,
+ cname);
+
for (i = 0; i < NCONTINENTS; i++)
- if (strcmp(name, continent_names[i].name) == 0)
+ if (strcmp(cname, continent_names[i].name) == 0) {
+ free(cname);
return (continent_names[i].continent);
- return (0);
+ }
+
+ errx(1, "%s:%d: continent `%s' unknown", path_zonetab, lineno, cname);
}
static const char *
@@ -264,10 +277,9 @@ struct country {
char *name;
char *tlc;
int nzones;
- char *filename; /* use iff nzones < 0 */
- struct continent *continent; /* use iff nzones < 0 */
- TAILQ_HEAD(, zone) zones; /* use iff nzones > 0 */
- dialogMenuItem *submenu; /* use iff nzones > 0 */
+ struct continent *override; /* continent override */
+ TAILQ_HEAD(, zone) zones;
+ dialogMenuItem *submenu;
};
struct zone {
@@ -346,56 +358,50 @@ read_iso3166_table(void)
fclose(fp);
}
-static void
-add_zone_to_country(int lineno, const char *tlc, const char *descr,
- const char *file, struct continent *cont)
+static struct country *
+find_country(int lineno, const char *tlc)
{
- struct zone *zp;
struct country *cp;
- if (tlc[0] < 'A' || tlc[0] > 'Z' || tlc[1] < 'A' || tlc[1] > 'Z')
+ if (strlen(tlc) != 2 ||
+ tlc[0] < 'A' || tlc[0] > 'Z' || tlc[1] < 'A' || tlc[1] > 'Z')
errx(1, "%s:%d: country code `%s' invalid", path_zonetab,
lineno, tlc);
cp = &countries[CODE2INT(tlc)];
- if (cp->name == 0)
+ if (cp->name == NULL)
errx(1, "%s:%d: country code `%s' unknown", path_zonetab,
lineno, tlc);
- if (descr) {
- if (cp->nzones < 0)
- errx(1, "%s:%d: conflicting zone definition",
- path_zonetab, lineno);
+ return (cp);
+}
+
+static void
+add_zone_to_country(int lineno, struct country *cp, const char *descr,
+ const char *file, struct continent *cont)
+{
+ struct zone *zp;
- zp = malloc(sizeof(*zp));
- if (zp == NULL)
- errx(1, "malloc(%zu)", sizeof(*zp));
+ zp = malloc(sizeof(*zp));
+ if (zp == NULL)
+ errx(1, "malloc(%zu)", sizeof(*zp));
- if (cp->nzones == 0)
- TAILQ_INIT(&cp->zones);
+ if (cp->nzones == 0)
+ TAILQ_INIT(&cp->zones);
+ if (descr != NULL) {
zp->descr = strdup(descr);
if (zp->descr == NULL)
errx(1, "malloc failed");
- zp->filename = strdup(file);
- if (zp->filename == NULL)
- errx(1, "malloc failed");
- zp->continent = cont;
- TAILQ_INSERT_TAIL(&cp->zones, zp, link);
- cp->nzones++;
} else {
- if (cp->nzones > 0)
- errx(1, "%s:%d: zone must have description",
- path_zonetab, lineno);
- if (cp->nzones < 0)
- errx(1, "%s:%d: zone multiply defined",
- path_zonetab, lineno);
- cp->nzones = -1;
- cp->filename = strdup(file);
- if (cp->filename == NULL)
- errx(1, "malloc failed");
- cp->continent = cont;
+ zp->descr = NULL;
}
+ zp->filename = strdup(file);
+ if (zp->filename == NULL)
+ errx(1, "malloc failed");
+ zp->continent = cp->override != NULL ? cp->override : cont;
+ TAILQ_INSERT_TAIL(&cp->zones, zp, link);
+ cp->nzones++;
}
/*
@@ -432,54 +438,79 @@ sort_countries(void)
static void
read_zones(void)
{
- char contbuf[16];
FILE *fp;
struct continent *cont;
- size_t len, contlen;
- char *line, *country_list, *tlc, *file, *descr, *p;
+ struct country *cp;
+ size_t len;
+ char *line, *country_list, *tlc, *file, *descr;
int lineno;
+ bool pass1;
fp = fopen(path_zonetab, "r");
if (!fp)
err(1, "%s", path_zonetab);
- lineno = 0;
+ pass1 = true;
+again:
+ lineno = 0;
while ((line = fgetln(fp, &len)) != NULL) {
lineno++;
if (line[len - 1] != '\n')
errx(1, "%s:%d: invalid format", path_zonetab, lineno);
line[len - 1] = '\0';
- if (line[0] == '#')
- continue;
- country_list = strsep(&line, "\t");
- /* coord = */ strsep(&line, "\t"); /* Unused */
- file = strsep(&line, "\t");
- /* get continent portion from continent/country */
- p = strchr(file, '/');
- if (p == NULL)
- errx(1, "%s:%d: invalid zone name `%s'", path_zonetab,
- lineno, file);
- contlen = p - file + 1; /* trailing nul */
- if (contlen > sizeof(contbuf))
- errx(1, "%s:%d: continent name in zone name `%s' too long",
- path_zonetab, lineno, file);
- strlcpy(contbuf, file, contlen);
- cont = find_continent(contbuf);
- if (!cont)
- errx(1, "%s:%d: invalid region `%s'", path_zonetab,
- lineno, contbuf);
-
- descr = (line != NULL && *line != '\0') ? line : NULL;
-
- while (country_list != NULL) {
- tlc = strsep(&country_list, ",");
- if (strlen(tlc) != 2)
- errx(1, "%s:%d: invalid country code `%s'",
- path_zonetab, lineno, tlc);
- add_zone_to_country(lineno, tlc, descr, file, cont);
+ if (pass1) {
+ /*
+ * First pass: collect overrides, only looking for
+ * single continent ones for the moment.
+ *
+ * zone1970.tab introduced continent overrides in the
+ * following format:
+ *
+ * #@TLC[,TLC...]<tab>CONTINENT/[,CONTINENT/...]
+ */
+ if (strncmp(line, "#@", strlen("#@")) != 0)
+ continue;
+ line += 2;
+ country_list = strsep(&line, "\t");
+ /* Skip multi-continent overrides */
+ if (strchr(line, ',') != NULL)
+ continue;
+ cont = find_continent(lineno, line);
+ /* Parse and store overrides */
+ while (country_list != NULL) {
+ tlc = strsep(&country_list, ",");
+ cp = find_country(lineno, tlc);
+ cp->override = cont;
+ }
+ } else {
+ /* Second pass: parse actual data */
+ if (line[0] == '#')
+ continue;
+
+ country_list = strsep(&line, "\t");
+ /* coord = */ strsep(&line, "\t"); /* Unused */
+ file = strsep(&line, "\t");
+ cont = find_continent(lineno, file);
+ descr = (line != NULL && *line != '\0') ? line : NULL;
+
+ while (country_list != NULL) {
+ tlc = strsep(&country_list, ",");
+ cp = find_country(lineno, tlc);
+ add_zone_to_country(lineno, cp, descr, file,
+ cont);
+ }
}
}
+
+ if (pass1) {
+ pass1 = false;
+ errno = 0;
+ rewind(fp);
+ if (errno != 0)
+ err(1, "failed to rewind %s", path_zonetab);
+ goto again;
+ }
fclose(fp);
}
@@ -492,14 +523,9 @@ dump_zonetab(void)
for (cp = countries; cp->name != NULL; cp++) {
printf("%s:%s\n", cp->tlc, cp->name);
- if (cp->nzones < 0) {
- cont = find_continent_name(cp->continent);
- printf(" %s:%s\n", cont, cp->filename);
- } else {
- TAILQ_FOREACH(zp, &cp->zones, link) {
- cont = find_continent_name(zp->continent);
- printf(" %s:%s\n", cont, zp->filename);
- }
+ TAILQ_FOREACH(zp, &cp->zones, link) {
+ cont = find_continent_name(zp->continent);
+ printf(" %s:%s\n", cont, zp->filename);
}
}
}
@@ -522,18 +548,14 @@ make_menus(void)
for (cp = countries; cp->name; cp++) {
if (cp->nzones == 0)
continue;
- if (cp->nzones < 0) {
- cp->continent->nitems++;
- } else {
- TAILQ_FOREACH(zp, &cp->zones, link) {
- cont = zp->continent;
- for (zp2 = TAILQ_FIRST(&cp->zones);
- zp2->continent != cont;
- zp2 = TAILQ_NEXT(zp2, link))
- ;
- if (zp2 == zp)
- zp->continent->nitems++;
- }
+ TAILQ_FOREACH(zp, &cp->zones, link) {
+ cont = zp->continent;
+ for (zp2 = TAILQ_FIRST(&cp->zones);
+ zp2->continent != cont;
+ zp2 = TAILQ_NEXT(zp2, link))
+ ;
+ if (zp2 == zp)
+ zp->continent->nitems++;
}
}
@@ -564,41 +586,32 @@ make_menus(void)
for (cp = countries; cp->name; cp++) {
if (cp->nzones == 0)
continue;
- if (cp->nzones < 0) {
- dmi = &cp->continent->menu[cp->continent->nitems];
+ cp->submenu = malloc(cp->nzones * sizeof(*dmi));
+ if (cp->submenu == 0)
+ errx(1, "malloc for submenu");
+ cp->nzones = 0;
+ TAILQ_FOREACH(zp, &cp->zones, link) {
+ cont = zp->continent;
+ dmi = &cp->submenu[cp->nzones];
+ memset(dmi, 0, sizeof(*dmi));
+ asprintf(&dmi->prompt, "%d", ++cp->nzones);
+ dmi->title = zp->descr;
+ dmi->fire = set_zone;
+ dmi->data = zp;
+
+ for (zp2 = TAILQ_FIRST(&cp->zones);
+ zp2->continent != cont;
+ zp2 = TAILQ_NEXT(zp2, link))
+ ;
+ if (zp2 != zp)
+ continue;
+
+ dmi = &cont->menu[cont->nitems];
memset(dmi, 0, sizeof(*dmi));
- asprintf(&dmi->prompt, "%d", ++cp->continent->nitems);
+ asprintf(&dmi->prompt, "%d", ++cont->nitems);
dmi->title = cp->name;
- dmi->fire = set_zone_whole_country;
+ dmi->fire = set_zone_menu;
dmi->data = cp;
- } else {
- cp->submenu = malloc(cp->nzones * sizeof(*dmi));
- if (cp->submenu == 0)
- errx(1, "malloc for submenu");
- cp->nzones = 0;
- TAILQ_FOREACH(zp, &cp->zones, link) {
- cont = zp->continent;
- dmi = &cp->submenu[cp->nzones];
- memset(dmi, 0, sizeof(*dmi));
- asprintf(&dmi->prompt, "%d", ++cp->nzones);
- dmi->title = zp->descr;
- dmi->fire = set_zone_multi;
- dmi->data = zp;
-
- for (zp2 = TAILQ_FIRST(&cp->zones);
- zp2->continent != cont;
- zp2 = TAILQ_NEXT(zp2, link))
- ;
- if (zp2 != zp)
- continue;
-
- dmi = &cont->menu[cont->nitems];
- memset(dmi, 0, sizeof(*dmi));
- asprintf(&dmi->prompt, "%d", ++cont->nitems);
- dmi->title = cp->name;
- dmi->fire = set_zone_menu;
- dmi->data = cp;
- }
}
}
}
@@ -610,6 +623,10 @@ set_zone_menu(dialogMenuItem *dmi)
struct country *cp = dmi->data;
int rv;
+ /* Short cut -- if there's only one zone, don't post a menu. */
+ if (cp->nzones == 1)
+ return (cp->submenu[0].fire(&cp->submenu[0]));
+
snprintf(title, sizeof(title), "%s Time Zones", cp->name);
snprintf(prompt, sizeof(prompt),
"Select a zone which observes the same time as your locality.");
@@ -646,7 +663,7 @@ confirm_zone(const char *filename)
}
static int
-set_zone_multi(dialogMenuItem *dmi)
+set_zone(dialogMenuItem *dmi)
{
struct zone *zp = dmi->data;
int rv;
@@ -658,19 +675,6 @@ set_zone_multi(dialogMenuItem *dmi)
return (rv);
}
-static int
-set_zone_whole_country(dialogMenuItem *dmi)
-{
- struct country *cp = dmi->data;
- int rv;
-
- if (!confirm_zone(cp->filename))
- return (DITEM_FAILURE | DITEM_RECREATE);
-
- rv = install_zoneinfo(cp->filename);
- return (rv);
-}
-
#endif
static void message_zoneinfo_file(const char *title, char *prompt)