aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/bsdconfig/timezone/share
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bsdconfig/timezone/share')
-rw-r--r--usr.sbin/bsdconfig/timezone/share/Makefile5
-rw-r--r--usr.sbin/bsdconfig/timezone/share/Makefile.depend10
-rw-r--r--usr.sbin/bsdconfig/timezone/share/continents.subr165
-rw-r--r--usr.sbin/bsdconfig/timezone/share/countries.subr104
-rw-r--r--usr.sbin/bsdconfig/timezone/share/iso3166.subr201
-rw-r--r--usr.sbin/bsdconfig/timezone/share/menus.subr224
-rw-r--r--usr.sbin/bsdconfig/timezone/share/zones.subr522
7 files changed, 1231 insertions, 0 deletions
diff --git a/usr.sbin/bsdconfig/timezone/share/Makefile b/usr.sbin/bsdconfig/timezone/share/Makefile
new file mode 100644
index 000000000000..8a4ba14b3a8f
--- /dev/null
+++ b/usr.sbin/bsdconfig/timezone/share/Makefile
@@ -0,0 +1,5 @@
+FILESDIR= ${SHAREDIR}/bsdconfig/timezone
+FILES= continents.subr countries.subr iso3166.subr menus.subr \
+ zones.subr
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdconfig/timezone/share/Makefile.depend b/usr.sbin/bsdconfig/timezone/share/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/usr.sbin/bsdconfig/timezone/share/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.sbin/bsdconfig/timezone/share/continents.subr b/usr.sbin/bsdconfig/timezone/share/continents.subr
new file mode 100644
index 000000000000..8cdf4bf1645d
--- /dev/null
+++ b/usr.sbin/bsdconfig/timezone/share/continents.subr
@@ -0,0 +1,165 @@
+if [ ! "$_TIMEZONE_CONTINENTS_SUBR" ]; then _TIMEZONE_CONTINENTS_SUBR=1
+#
+# Copyright (c) 2011-2015 Devin Teske
+# All rights reserved.
+#
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." timezone/continents.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# List of worldly continents/oceans (export'ed for awk(1) ENVIRON visibility)
+#
+export CONTINENTS="
+ africa
+ america
+ antarctica
+ arctic
+ asia
+ atlantic
+ australia
+ europe
+ indian
+ pacific
+ utc
+"
+
+#
+# Directory name of each continent/ocean (in _PATH_ZONEINFO)
+#
+export continent_africa_name="Africa"
+export continent_america_name="America"
+export continent_antarctica_name="Antarctica"
+export continent_arctic_name="Arctic"
+export continent_asia_name="Asia"
+export continent_atlantic_name="Atlantic"
+export continent_australia_name="Australia"
+export continent_europe_name="Europe"
+export continent_indian_name="Indian"
+export continent_pacific_name="Pacific"
+export continent_utc_name="UTC"
+
+#
+# Export i18n menu texts of continents/oceans for awk(1) ENVIRON visibility
+# NOTE: These are defined in messages.subr included above.
+#
+export continent_africa_title
+export continent_america_title
+export continent_antarctica_title
+export continent_arctic_title
+export continent_asia_title
+export continent_atlantic_title
+export continent_australia_title
+export continent_europe_title
+export continent_indian_title
+export continent_pacific_title
+export continent_utc_title
+
+############################################################ FUNCTIONS
+
+# f_continent $cont $property [$var_to_set]
+#
+# Returns a single property of a given continent. Available properties are:
+#
+# name Directory name of continent/ocean as it appears in
+# _PATH_ZONEINFO.
+# title Menu text of this continent/ocean to be displayed in the
+# continent-selection menu.
+# nitems Number of submenu items associated with this
+# continent/ocean.
+# tlc_N 2-character country code of the Nth submenu item associated
+# with this continent displayed in the country-selection menu
+# (which appears after continent selection).
+# menu_list Menu-list of regions for this continent.
+#
+# If $var_to_set is missing or NULL, the value of $var_to_get is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_continent()
+{
+ f_getvar "continent_${1}_$2" $3
+}
+
+# f_find_continent $title [$var_to_set]
+#
+# Returns continent identifier given continent title.
+#
+# If $var_to_set is missing or NULL, the value of $var_to_get is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_find_continent()
+{
+ local __cont __title
+ for __cont in $CONTINENTS; do
+ f_continent $__cont title __title
+ if [ "$1" = "$__title" ]; then
+ if [ "$2" ]; then
+ setvar "$2" $__cont
+ else
+ echo "$__cont"
+ fi
+ return $SUCCESS
+ fi
+ done
+ return $FAILURE
+}
+
+# f_OCEANP $cont [$var_to_set]
+#
+# Returns "1" if the first argument is an ocean, otherwise NULL.
+#
+# If $var_to_set is missing or NULL, the value of $var_to_get is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_OCEANP()
+{
+ case "$1" in
+ arctic|atlantic|indian|pacific)
+ if [ "$2" ]; then
+ setvar "$2" 1
+ else
+ echo 1
+ fi
+ ;;
+ *)
+ [ "$2" ] && setvar "$2" ""
+ esac
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/continents.subr
+
+fi # ! $_TIMEZONE_CONTINENTS_SUBR
diff --git a/usr.sbin/bsdconfig/timezone/share/countries.subr b/usr.sbin/bsdconfig/timezone/share/countries.subr
new file mode 100644
index 000000000000..1eaf34354736
--- /dev/null
+++ b/usr.sbin/bsdconfig/timezone/share/countries.subr
@@ -0,0 +1,104 @@
+if [ ! "$_TIMEZONE_COUNTRIES_SUBR" ]; then _TIMEZONE_COUNTRIES_SUBR=1
+#
+# Copyright (c) 2011-2015 Devin Teske
+# All rights reserved.
+#
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+#
+############################################################ FUNCTIONS
+
+# f_country $code $property [$var_to_set]
+#
+# Returns a single property of a given country. Available properties are:
+#
+# name Name of the country as read from _PATH_ISO3166.
+# nzones Number of zones within the country (-1 if country has
+# only a single zone).
+# filename The filename portion of the TZ field (after the `/') as
+# read from _PATH_ZONETAB.
+# cont The principal continent in which the country lies (appears
+# before the `/' in the TZ field of _PATH_ZONETAB).
+# filename_N Like filename, but for the Nth zone when the country has
+# multiple zones (nzones > 0).
+# cont_N Like cont, but for the Nth zone when the country has
+# multiple zones (nzones > 0).
+# descr_N Like name, but for the Nth zone when the country has
+# multiple zones (nzones > 0)
+#
+# If $var_to_set is missing or NULL, the value of $var_to_get is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_country()
+{
+ f_getvar "country_${1}_$2" $3
+}
+
+# f_sort_countries
+#
+# Sorts alphabetically the 2-character country codes listed in $COUNTRIES based
+# on the name of each country.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_sort_countries_awk='
+function _asorti(src, dest)
+{
+ k = nitems = 0
+ for (i in src) dest[++nitems] = i
+ for (i = 1; i <= nitems; k = i++) {
+ idx = dest[i]
+ while ((k > 0) && (dest[k] > idx)) {
+ dest[k+1] = dest[k]; k--
+ }
+ dest[k+1] = idx
+ }
+ return nitems
+}
+BEGIN {
+ split(ENVIRON["COUNTRIES"], array, /[[:space:]]+/)
+ for (item in array)
+ {
+ tlc = array[item]
+ name = ENVIRON["country_" tlc "_name"]
+ countries[name] = tlc
+ }
+ n = _asorti(countries, sorted_countries)
+ for (i = 1; i <= n; i++)
+ print countries[sorted_countries[i]]
+ exit
+}
+'
+f_sort_countries()
+{
+ export COUNTRIES # for awk(1) ENVIRON[] visibility
+ COUNTRIES=$( awk "$f_sort_countries_awk" )
+ export COUNTRIES # Pedantic
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/countries.subr
+
+fi # ! $_TIMEZONE_COUNTRIES_SUBR
diff --git a/usr.sbin/bsdconfig/timezone/share/iso3166.subr b/usr.sbin/bsdconfig/timezone/share/iso3166.subr
new file mode 100644
index 000000000000..d68ed141b19d
--- /dev/null
+++ b/usr.sbin/bsdconfig/timezone/share/iso3166.subr
@@ -0,0 +1,201 @@
+if [ ! "$_TIMEZONE_ISO3166_SUBR" ]; then _TIMEZONE_ISO3166_SUBR=1
+#
+# Copyright (c) 2011-2012 Devin Teske
+# All rights reserved.
+#
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." timezone/iso3166.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames
+#
+_PATH_ISO3166="/usr/share/misc/iso3166"
+
+#
+# Export required i18n messages for awk(1) ENVIRON visibility
+#
+export msg_country_code_multiply_defined
+export msg_invalid_code
+export msg_invalid_format
+
+############################################################ FUNCTIONS
+
+# f_read_iso3166_table
+#
+# Read the ISO 3166 country code database in _PATH_ISO3166:
+# /usr/share/misc/iso3166 on FreeBSD
+# /usr/share/zoneinfo/iso3166.tab on Linux, Mac OS X, and Cygwin
+#
+# The format of this file on FreeBSD is:
+# two three number name
+#
+# The format of this file on Linux, Mac OS X, and Cygwin is:
+# two name
+#
+# With each of the following elements (described below) being separated by a
+# single tab character:
+#
+# two ISO 3166 2-character country code
+# three ISO 3166 3-character country code (if provided)
+# number ISO 3166 numeric country code (if provided)
+# name Human-readable country name (may contain spaces)
+#
+# Variables created by this function:
+#
+# COUNTRIES
+# A space-separated list of 2-character country codes.
+# country_CODE_name
+# The country `name' (as described above).
+#
+# where CODE is the 2-character country code.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_read_iso3166_table_awk='
+# Variables that should be defined on the invocation line:
+# -v progname="progname"
+#
+BEGIN {
+ lineno = 0
+ failed = 0
+}
+function die(fmt, argc, argv)
+{
+ printf "f_die 1 \"%%s: %s\" \"%s\"", fmt, progname
+ for (n = 1; n <= argc; n++)
+ printf " \"%s\"", argv[n]
+ print ""
+ failed++
+ exit 1
+}
+function add_country(tlc, name)
+{
+ if (country_name[tlc])
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ argv[3] = tlc
+ argv[4] = name
+ die(ENVIRON["msg_country_code_multiply_defined"], 4, argv)
+ }
+
+ country_name[tlc] = name
+}
+function print_country_name(tlc)
+{
+ name = country_name[tlc]
+ gsub(/"/, "\\\"", name)
+ printf "country_%s_name=\"%s\"\n", tlc, name
+ printf "export country_%s_name\n", tlc
+}
+/^#/ {
+ lineno++
+ next
+}
+!/^#/ {
+ lineno++
+
+ # Split the current record (on TAB) into an array
+ split($0, line, /\t/)
+
+ # Get the ISO3166-1 (Alpha 1) 2-letter country code
+ tlc = line[1]
+
+ #
+ # Validate the two-character country code
+ #
+ if (length(tlc) != 2)
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ die(ENVIRON["msg_invalid_format"], 2, argv)
+ }
+ if (!match(tlc, /^[A-Z][A-Z]$/))
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ argv[3] = tlc
+ die(ENVIRON["msg_invalid_code"], 3, argv)
+ }
+
+ #
+ # Calculate the substr start-position of the name
+ #
+ name_start = 0
+ n = 4
+ if (FILENAME ~ /\.tab$/)
+ n = 2
+ while (--n)
+ {
+ #
+ # Validate field-length of 2nd/3rd columns while we are here
+ #
+ if (n > 1 && length(line[n]) != 3)
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ die(ENVIRON["msg_invalid_format"], 2, argv)
+ }
+
+ name_start += length(line[n]) + 1
+ }
+
+ # Get the name field
+ name = substr($0, name_start + 1)
+
+ add_country(tlc, name)
+}
+END {
+ list = ""
+ for (tlc in country_name)
+ {
+ list = list (length(list) > 0 ? " " : "") tlc
+ print_country_name(tlc)
+ }
+ printf "COUNTRIES=\"%s\"\n", list
+ print "export COUNTRIES"
+}
+'
+f_read_iso3166_table()
+{
+ eval $( awk -v progname="$pgm" \
+ "$f_read_iso3166_table_awk" \
+ "$_PATH_ISO3166" )
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/iso3166.subr
+
+fi # ! $_TIMEZONE_ISO3166_SUBR
diff --git a/usr.sbin/bsdconfig/timezone/share/menus.subr b/usr.sbin/bsdconfig/timezone/share/menus.subr
new file mode 100644
index 000000000000..268945a73a59
--- /dev/null
+++ b/usr.sbin/bsdconfig/timezone/share/menus.subr
@@ -0,0 +1,224 @@
+if [ ! "$_TIMEZONE_MENUS_SUBR" ]; then _TIMEZONE_MENUS_SUBR=1
+#
+# Copyright (c) 2011-2012 Devin Teske
+# All rights reserved.
+#
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." timezone/menus.subr
+f_include $BSDCFG_SHARE/dialog.subr
+
+############################################################ GLOBALS
+
+#
+# Export special included variables required by awk(1) for `ENVIRON' visibility
+#
+export DIALOG_MENU_TAGS
+
+############################################################ FUNCTIONS
+
+# f_make_menus
+#
+# Creates the tag/item ordered-pair list environment variables for the
+# continent and country menus.
+#
+# Required variables [from continents.subr]:
+#
+# CONTINENTS
+# Space-separated list of continents.
+# continent_*_title
+# Desired menu text for the continent represented by *.
+#
+# Required variables [created by f_read_iso3166_table from iso3166.subr]:
+#
+# COUNTRIES
+# Space-separated list of 2-character country codes.
+# country_*_name :: when country_*_nzones < 0
+# Desired menu text for the country-zone represented by *, the 2-
+# character country code.
+#
+# Required variables [created by f_read_zones from zones.subr]:
+#
+# country_*_nzones
+# Number of zones for the country represented by *, the 2-
+# character country code. Should be -1 if the country has only
+# one single zone, otherwise 1 or greater to indicate how many
+# zones the country has.
+# country_*_cont :: when country_*_nzones < 0
+# Principal continent (or ocean) in which the country-zone
+# represented by *, the 2-character country code, resides.
+# country_*_cont_N :: when country_*_nzones > 0
+# Principal continent (or ocean) in which zone-N of the country
+# represented by * resides, the 2-character country code.
+# country_*_descr_N :: when country_*_nzones > 0
+# Desired submenu text for zone-N of the country represented by
+# *, the 2-character country code.
+#
+# Variables created by this function:
+#
+# continent_menu_list
+# Menu-list of continents.
+# continent_*_nitems
+# Number of items associated with the continent represented by *,
+# the continent identifier.
+# continent_*_tlc_N
+# 2-character country code of the Nth item in the continent menu
+# for the continent represented by *, the continent identifier.
+# continent_*_menu_list
+# Menu-list of countries/zones for each continent represented by
+# *, the continent identifier.
+# country_*_menu_list
+# For countries that have multiple zones, this is the submenu-
+# list of zones for said country represented by *, the 2-
+# character country code.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_make_menus_awk='
+function add_zone_n_to_country_menu(tlc, n)
+{
+ zone_title = ENVIRON["country_" tlc "_descr_" n]
+ gsub(/'\''/, "'\''\\'\'\''", zone_title)
+ country_menu_list[tlc] = country_menu_list[tlc] \
+ ( length(country_menu_list[tlc]) > 0 ? "\n" : "" ) \
+ n " '\''" zone_title "'\''"
+}
+BEGIN {
+ #
+ # First, count up all the countries in each continent/ocean.
+ # Be careful to count those countries which have multiple zones
+ # only once for each. NB: some countries are in multiple
+ # continents/oceans.
+ #
+ i = split(ENVIRON["COUNTRIES"], countries, /[[:space:]]+/)
+ for (cp = 1; cp <= i; cp++)
+ {
+ tlc = countries[cp]
+ title = ENVIRON["country_" tlc "_name"]
+ gsub(/'\''/, "'\''\\'\'\''", title)
+ nzones = ENVIRON["country_" tlc "_nzones"]
+ if (!nzones)
+ {
+ # Country has no zones
+ continue
+ }
+ else if (nzones < 0)
+ {
+ # Country has only one zone
+ cont = ENVIRON["country_" tlc "_cont"]
+ nitems = ++continent_nitems[cont]
+ continent_tlc[cont,nitems] = tlc
+ continent_title[cont,nitems] = title
+ }
+ else
+ {
+ # Country has one or more zones
+ for (n = 1; n <= nzones; n++)
+ {
+ add_zone_n_to_country_menu(tlc, n)
+ cont = ENVIRON["country_" tlc "_cont_" n]
+ for (x = 1; x < n; x++)
+ {
+ contx = ENVIRON["country_"tlc"_cont_"x]
+ if (cont == contx) break
+ }
+ if (x == n)
+ {
+ nitems = ++continent_nitems[cont]
+ continent_tlc[cont,nitems] = tlc
+ continent_title[cont,nitems] = title
+ }
+ }
+ }
+ }
+}
+END {
+ tags = ENVIRON["DIALOG_MENU_TAGS"]
+ cont_menu_list = ""
+ tagn = 0
+
+ #
+ # Assemble the menu items in the menu list for each continent/ocean.
+ #
+ i = split(ENVIRON["CONTINENTS"], array, /[[:space:]]+/)
+ for (item = 1; item <= i; item++)
+ {
+ cont = array[item]
+ if (!cont) continue
+
+ if (++tagn >= length(tags)) break
+ tag = substr(tags, tagn, 1)
+ cont_menu_list = cont_menu_list \
+ ( length(cont_menu_list) > 0 ? "\n" : "" ) \
+ "'\''" tag "'\'' '\''" \
+ ENVIRON["continent_" cont "_title"] "'\''"
+
+ nitems = continent_nitems[cont]
+ printf "continent_%s_nitems=%d\n", cont, nitems
+
+ menu_list = ""
+ for (n = 1; n <= nitems; n++)
+ {
+ printf "continent_%s_tlc_%d=%s\n",
+ cont, n, continent_tlc[cont,n]
+
+ title = continent_title[cont,n]
+ menu_list = menu_list \
+ ( length(menu_list) > 0 ? "\n" : "" ) \
+ n " '\''" title "'\''"
+ }
+
+ gsub(/"/, "\\\"", menu_list)
+ printf "continent_%s_menu_list=\"%s\"\n", cont, menu_list
+ }
+
+ gsub(/"/, "\\\"", continent_menu_list)
+ printf "continent_menu_list=\"%s\"\n", cont_menu_list
+ print "export continent_menu_list"
+
+ #
+ # Dump the submenus of countries with multiple zones
+ #
+ for (tlc in country_menu_list)
+ {
+ menu_list = country_menu_list[tlc]
+ gsub(/"/, "\\\"", menu_list)
+ printf "country_%s_menu_list=\"%s\"\n", tlc, menu_list
+ }
+}
+'
+f_make_menus()
+{
+ eval $( :| awk "$f_make_menus_awk" )
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/menus.subr
+
+fi # ! $_TIMEZONE_MENUS_SUBR
diff --git a/usr.sbin/bsdconfig/timezone/share/zones.subr b/usr.sbin/bsdconfig/timezone/share/zones.subr
new file mode 100644
index 000000000000..4cad5ef02425
--- /dev/null
+++ b/usr.sbin/bsdconfig/timezone/share/zones.subr
@@ -0,0 +1,522 @@
+if [ ! "$_TIMEZONE_ZONES_SUBR" ]; then _TIMEZONE_ZONES_SUBR=1
+#
+# Copyright (c) 2011-2012 Devin Teske
+# All rights reserved.
+#
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." timezone/zones.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/timezone/continents.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames
+#
+_PATH_ZONETAB="/usr/share/zoneinfo/zone.tab"
+_PATH_ZONEINFO="/usr/share/zoneinfo"
+_PATH_LOCALTIME="/etc/localtime"
+_PATH_DB="/var/db/zoneinfo"
+
+#
+# Export required i18n messages for awk(1) ENVIRON visibility
+#
+export msg_conflicting_zone_definition
+export msg_country_code_invalid
+export msg_country_code_unknown
+export msg_invalid_country_code
+export msg_invalid_format
+export msg_invalid_region
+export msg_invalid_zone_name
+export msg_zone_multiply_defined
+export msg_zone_must_have_description
+
+############################################################ FUNCTIONS
+
+# f_read_zones
+#
+# Read the zone descriptions database in _PATH_ZONETAB:
+# /usr/share/zoneinfo/zone.tab on all OSes
+#
+# The format of this file (on all OSes) is:
+# code coordinates TZ comments
+#
+# With each of the following elements (described below) being separated by a
+# single tab character:
+#
+# code
+# The ISO 3166 2-character country code.
+# coordinates
+# Latitude and logitude of the zone's principal location in ISO
+# 6709 sign-degrees-minutes-seconds format, either +-DDMM+-DDDMM
+# or +-DDMMSS+-DDDMMSS, first latitude (+ is north), then long-
+# itude (+ is east).
+# TZ
+# Zone name used in value of TZ environment variable.
+# comments
+# Comments; present if and only if the country has multiple rows.
+#
+# Required variables [from continents.subr]:
+#
+# CONTINENTS
+# Space-separated list of continents.
+# continent_*_name
+# Directory element in _PATH_ZONEINFO for the continent
+# represented by *.
+#
+# Required variables [created by f_read_iso3166_table from iso3166.subr]:
+#
+# country_CODE_name
+# Country name of the country represented by CODE, the 2-
+# character country code.
+#
+# Variables created by this function:
+#
+# country_CODE_nzones
+# Either set to `-1' to indicate that the 2-character country
+# code has only a single zone associated with it (and therefore
+# you should query the `country_CODE_*' environment variables),
+# or set to `0' or higher to indicate how many zones are assoc-
+# iated with the given country code. When multiple zones are
+# configured for a single code, you should instead query the
+# `country_CODE_*_N' environment variables (e.g., `echo
+# $country_AQ_descr_1' prints the description of the first
+# timezone in Antarctica).
+# country_CODE_filename
+# The ``filename'' portion of the TZ value that appears after the
+# `/' (e.g., `Hong_Kong' from `Asia/Hong_Kong' or `Isle_of_Man'
+# from `Europe/Isle_of_Man').
+# country_CODE_cont
+# The ``continent'' portion of the TZ value that appears before
+# the `/' (e.g., `Asia' from `Asia/Hong_Kong' or `Europe' from
+# `Europe/Isle_of_Man').
+# country_CODE_descr
+# The comments associated with the ISO 3166 code entry (if any).
+#
+# NOTE: CODE is the 2-character country code.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_read_zones_awk='
+# Variables that should be defined on the invocation line:
+# -v progname="progname"
+#
+BEGIN {
+ lineno = 0
+ failed = 0
+
+ #
+ # Initialize continents array/map (name => id)
+ #
+ split(ENVIRON["CONTINENTS"], array, /[[:space:]]+/)
+ for (item in array)
+ {
+ cont = array[item]
+ if (!cont) continue
+ name = ENVIRON["continent_" cont "_name"]
+ continents[name] = cont
+ }
+}
+function die(fmt, argc, argv)
+{
+ printf "f_die 1 \"%%s: %s\" \"%s\"", fmt, progname
+ for (n = 1; n <= argc; n++)
+ printf " \"%s\"", argv[n]
+ print ""
+ failed++
+ exit 1
+}
+function find_continent(name)
+{
+ return continents[name]
+}
+function add_zone_to_country(lineno, tlc, descr, file, cont)
+{
+ #
+ # Validate the two-character country code
+ #
+ if (!match(tlc, /^[A-Z][A-Z]$/))
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ argv[3] = tlc
+ die(ENVRION["msg_country_code_invalid"], 3, argv)
+ }
+ if (!ENVIRON["country_" tlc "_name"])
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ argv[3] = tlc
+ die(ENVIRON["msg_country_code_unknown"], 3, argv)
+ }
+
+ #
+ # Add Zone to an array that we will parse at the end
+ #
+ if (length(descr) > 0)
+ {
+ if (country_nzones[tlc] < 0)
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ die(ENVIRON["msg_conflicting_zone_definition"], 2, argv)
+ }
+
+ n = ++country_nzones[tlc]
+ country_cont[tlc,n] = cont
+ country_filename[tlc,n] = file
+ country_descr[tlc,n] = descr
+ }
+ else
+ {
+ if (country_nzones[tlc] > 0)
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ die(ENVIRON["msg_zone_must_have_description"], 2, argv)
+ }
+ if (country_nzones[tlc] < 0)
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ die(ENVIRON["msg_zone_multiply_defined"], 2, argv)
+ }
+
+ country_nzones[tlc] = -1
+ country_cont[tlc] = cont
+ country_filename[tlc] = file
+ }
+}
+function print_country_code(tlc)
+{
+ nz = country_nzones[tlc]
+
+ printf "country_%s_nzones=%d\n", tlc, nz
+ printf "export country_%s_nzones\n", tlc
+
+ if (nz < 0)
+ {
+ printf "country_%s_cont=\"%s\"\n", tlc, country_cont[tlc]
+ printf "export country_%s_cont\n", tlc
+ printf "country_%s_filename=\"%s\"\n",
+ tlc, country_filename[tlc]
+ }
+ else
+ {
+ n = 0
+ while ( ++n <= nz )
+ {
+ printf "country_%s_cont_%d=\"%s\"\n",
+ tlc, n, country_cont[tlc,n]
+ printf "export country_%s_cont_%d\n", tlc, n
+ printf "country_%s_filename_%d=\"%s\"\n",
+ tlc, n, country_filename[tlc,n]
+ printf "country_%s_descr_%d=\"%s\"\n",
+ tlc, n, country_descr[tlc,n]
+ }
+ }
+}
+/^#/ {
+ lineno++
+ next
+}
+!/^#/ {
+ lineno++
+
+ #
+ # Split the current record (on TAB) into an array
+ #
+ if (split($0, line, /\t/) < 2)
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ die(ENVIRON["msg_invalid_format"], 2, argv)
+ }
+
+ # Get the ISO3166-1 (Alpha 1) 2-letter country code
+ tlc = line[1]
+
+ #
+ # Validate the two-character country code
+ #
+ if (length(tlc) != 2)
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ argv[3] = tlc
+ die(ENVIRON["msg_invalid_country_code"], 3, argv)
+ }
+
+ # Get the TZ field
+ tz = line[3]
+
+ #
+ # Validate the TZ field
+ #
+ if (!match(tz, "/"))
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ argv[3] = tz
+ die(ENVIRON["msg_invalid_zone_name"], 3, argv)
+ }
+
+ #
+ # Get the continent portion of the TZ field
+ #
+ contbuf = tz
+ sub("/.*$", "", contbuf)
+
+ #
+ # Validate the continent
+ #
+ cont = find_continent(contbuf)
+ if (!cont)
+ {
+ argv[1] = FILENAME
+ argv[2] = lineno
+ argv[3] = contbuf
+ die(ENVIRON["msg_invalid_region"], 3, argv)
+ }
+
+ #
+ # Get the filename portion of the TZ field
+ #
+ filename = tz
+ sub("^[^/]*/", "", filename)
+
+ #
+ # Calculate the substr start-position of the comment
+ #
+ descr_start = 0
+ n = 4
+ while (--n)
+ descr_start += length(line[n]) + 1
+
+ # Get the comment field
+ descr = substr($0, descr_start + 1)
+
+ add_zone_to_country(lineno, tlc, descr, filename, cont)
+}
+END {
+ if (failed) exit failed
+ for (tlc in country_nzones)
+ print_country_code(tlc)
+}
+'
+f_read_zones()
+{
+ eval $( awk -v progname="$pgm" \
+ "$f_read_zones_awk" \
+ "$_PATH_ZONETAB" )
+}
+
+# f_install_zoneinfo_file $filename
+#
+# Installs a zone file to _PATH_LOCALTIME.
+#
+f_install_zoneinfo_file()
+{
+ local funcname=f_install_zoneinfo_file
+ local zoneinfo_file="$1"
+ local copymode title msg height width
+
+ if [ -L "$_PATH_LOCALTIME" ]; then
+ copymode=
+ elif [ ! -e "$_PATH_LOCALTIME" ]; then
+ # Nothing there yet...
+ copymode=1
+ else
+ copymode=1
+ fi
+
+ if [ "$VERBOSE" ]; then
+ if [ ! "$zoneinfo_file" ]; then
+ f_sprintf msg "$msg_removing_file" "$_PATH_LOCALTIME"
+ elif [ "$copymode" ]; then
+ f_sprintf msg "$msg_copying_file" \
+ "$zoneinfo_file" "$_PATH_LOCALTIME"
+ else
+ f_sprintf msg "$msg_creating_symlink" \
+ "$_PATH_LOCALTIME" "$zoneinfo_file"
+ fi
+ if [ "$USEDIALOG" ]; then
+ f_dialog_title "$msg_info"
+ f_dialog_msgbox "$msg"
+ f_dialog_title_restore
+ else
+ printf "%s\n" "$msg"
+ fi
+ fi
+
+ [ "$REALLYDOIT" ] || return $SUCCESS
+
+ local catch_args="-de"
+ [ "$USEDIALOG" ] && catch_args=
+
+ if [ ! "$zoneinfo_file" ]; then
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_LOCALTIME" || return $FAILURE
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_DB" || return $FAILURE
+
+ if [ "$VERBOSE" ]; then
+ f_sprintf msg "$msg_removed_file" "$_PATH_LOCALTIME"
+ if [ "$USEDIALOG" ]; then
+ f_dialog_title "$msg_done"
+ f_dialog_msgbox "$msg"
+ f_dialog_title_restore
+ else
+ printf "%s\n" "$msg"
+ fi
+ fi
+ return $SUCCESS
+ fi # ! zoneinfo_file
+
+ if [ "$copymode" ]; then
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_LOCALTIME" || return $FAILURE
+ f_eval_catch $catch_args $funcname sh \
+ 'umask 222 && :> "%s"' "$_PATH_LOCALTIME" ||
+ return $FAILURE
+ f_eval_catch $catch_args $funcname sh \
+ 'cat "%s" > "%s"' \
+ "$zoneinfo_file" "$_PATH_LOCALTIME" || return $FAILURE
+ else
+ f_eval_catch $catch_args $funcname sh \
+ '( :< "%s" )' "$zoneinfo_file" || return $FAILURE
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_LOCALTIME" || return $FAILURE
+ f_eval_catch $catch_args $funcname ln \
+ 'ln -s "%s" "%s"' \
+ "$zoneinfo_file" "$_PATH_LOCALTIME" || return $FAILURE
+ fi # copymode
+
+ if [ "$VERBOSE" ]; then
+ if [ "$copymode" ]; then
+ f_sprintf msg "$msg_copied_timezone_file" \
+ "$zoneinfo_file" "$_PATH_LOCALTIME"
+ else
+ f_sprintf msg "$msg_created_symlink" \
+ "$_PATH_LOCALTIME" "$zoneinfo_file"
+ fi
+ if [ "$USEDIALOG" ]; then
+ f_dialog_title "$msg_done"
+ f_dialog_msgbox "$msg"
+ f_dialog_title_restore
+ else
+ printf "%s\n" "$msg"
+ fi
+ fi
+
+ return $SUCCESS
+}
+
+# f_install_zoneinfo $zoneinfo
+#
+# Install a zoneinfo file relative to _PATH_ZONEINFO. The given $zoneinfo
+# will be written to _PATH_DB (usable later with the `-r' flag).
+#
+f_install_zoneinfo()
+{
+ local zoneinfo="$1"
+ local rv
+
+ f_install_zoneinfo_file "$_PATH_ZONEINFO/$zoneinfo"
+ rv=$?
+
+ # Save knowledge for later
+ if [ "$REALLYDOIT" -a $rv -eq $SUCCESS ]; then
+ if true 2> /dev/null > "$_PATH_DB"; then
+ cat <<-EOF > "$_PATH_DB"
+ $zoneinfo
+ EOF
+ fi
+ fi
+
+ return $rv
+}
+
+# f_confirm_zone $filename
+#
+# Prompt the user to confirm the new timezone data. The first (and only)
+# argument should be the pathname to the zoneinfo file, either absolute or
+# relative to `/usr/share/zoneinfo' (e.g., "America/Los_Angeles").
+#
+# The return status is 0 if "Yes" is chosen, 1 if "No", and 255 if Esc is
+# pressed (see dialog(1) for additional details).
+#
+f_confirm_zone()
+{
+ local filename="$1"
+ f_dialog_title "$msg_confirmation"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ local tm_zone="$( TZ="$filename" date +%Z )"
+ local prompt # Calculated below
+ local height=5 width=72
+
+ f_sprintf prompt "$msg_look_reasonable" "$tm_zone"
+ if [ "$USE_XDIALOG" ]; then
+ height=$(( $height + 4 ))
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --ok-label "$msg_yes" \
+ --cancel-label "$msg_no" \
+ --yesno "$prompt" $height $width
+ else
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --yes-label "$msg_yes" \
+ --no-label "$msg_no" \
+ --yesno "$prompt" $height $width
+ fi
+}
+
+# f_set_zone_utc
+#
+# Resets to the UTC timezone.
+#
+f_set_zone_utc()
+{
+ f_confirm_zone "" || return $FAILURE
+ f_install_zoneinfo_file ""
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/zones.subr
+
+fi # ! $_TIMEZONE_ZONES_SUBR