diff --git a/usr.sbin/tzsetup/tzsetup.c b/usr.sbin/tzsetup/tzsetup.c --- a/usr.sbin/tzsetup/tzsetup.c +++ b/usr.sbin/tzsetup/tzsetup.c @@ -162,7 +162,7 @@ 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 { @@ -172,6 +172,7 @@ { "Africa", &africa }, { "America", &america }, { "Antarctica", &antarctica }, + { "Arctic", &arctic }, { "Asia", &asia }, { "Atlantic", &atlantic }, { "Australia", &australia }, @@ -182,26 +183,27 @@ }; 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) @@ -214,10 +216,6 @@ 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", @@ -250,6 +248,7 @@ int nzones; char *filename; /* use iff nzones < 0 */ struct continent *continent; /* use iff nzones < 0 */ + struct continent *override; /* continent override */ TAILQ_HEAD(, zone) zones; /* use iff nzones > 0 */ dialogMenuItem *submenu; /* use iff nzones > 0 */ }; @@ -330,6 +329,29 @@ fclose(fp); } +static void +add_override_to_country(int lineno, const char *tlc, const char *continent) +{ + struct country *cp; + struct continent *cont; + + if (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 == NULL) + errx(1, "%s:%d: country code `%s' unknown", path_zonetab, + lineno, tlc); + + cont = find_continent(continent); + if (cont == NULL) + errx(1, "%s:%d: continent `%s' unknown", path_zonetab, + lineno, continent); + + cp->override = cont; +} + static void add_zone_to_country(int lineno, const char *tlc, const char *descr, const char *file, struct continent *cont) @@ -364,7 +386,7 @@ zp->filename = strdup(file); if (zp->filename == NULL) errx(1, "malloc failed"); - zp->continent = cont; + zp->continent = cp->override != NULL ? cp->override : cont; TAILQ_INSERT_TAIL(&cp->zones, zp, link); cp->nzones++; } else { @@ -378,7 +400,7 @@ cp->filename = strdup(file); if (cp->filename == NULL) errx(1, "malloc failed"); - cp->continent = cont; + cp->continent = cp->override != NULL ? cp->override : cont; } } @@ -426,8 +448,42 @@ fp = fopen(path_zonetab, "r"); if (!fp) err(1, "%s", path_zonetab); + + /* + * zone1970.tab introduced continent overrides in the following format: + * + * #@TLC[,TLC...]CONTINENT/[,CONTINENT/...] + * + * First pass: collect overrides, only looking for single continent ones + * for the moment. + */ lineno = 0; + while ((line = fgetln(fp, &len)) != NULL) { + lineno++; + if (strncmp(line, "#@", strlen("#@")) != 0) + continue; + line[len - 1] = '\0'; + line += 2; + country_list = strsep(&line, "\t"); + /* Skip multi-continent overrides */ + if (strchr(line, ',') != NULL) + continue; + line[strlen(line) - 1] = '\0'; + /* Parse and store overrides */ + while (country_list != NULL) { + tlc = strsep(&country_list, ","); + add_override_to_country(lineno, tlc, line); + } + } + /* + * Second pass: read actual data. + */ + errno = 0; + rewind(fp); + if (errno != 0) + err(1, "failed to rewind %s", path_zonetab); + lineno = 0; while ((line = fgetln(fp, &len)) != NULL) { lineno++; if (line[len - 1] != '\n')