aboutsummaryrefslogtreecommitdiff
path: root/bsdconfig/timezone
diff options
context:
space:
mode:
Diffstat (limited to 'bsdconfig/timezone')
-rw-r--r--bsdconfig/timezone/INDEX57
-rw-r--r--bsdconfig/timezone/Makefile11
-rw-r--r--bsdconfig/timezone/Makefile.depend11
-rw-r--r--bsdconfig/timezone/USAGE46
-rw-r--r--bsdconfig/timezone/include/Makefile6
-rw-r--r--bsdconfig/timezone/include/Makefile.depend11
-rw-r--r--bsdconfig/timezone/include/messages.subr78
-rw-r--r--bsdconfig/timezone/share/Makefile7
-rw-r--r--bsdconfig/timezone/share/Makefile.depend11
-rw-r--r--bsdconfig/timezone/share/continents.subr166
-rw-r--r--bsdconfig/timezone/share/countries.subr105
-rw-r--r--bsdconfig/timezone/share/iso3166.subr202
-rw-r--r--bsdconfig/timezone/share/menus.subr225
-rw-r--r--bsdconfig/timezone/share/zones.subr523
-rwxr-xr-xbsdconfig/timezone/timezone457
15 files changed, 1916 insertions, 0 deletions
diff --git a/bsdconfig/timezone/INDEX b/bsdconfig/timezone/INDEX
new file mode 100644
index 000000000000..67fc50b0dcb6
--- /dev/null
+++ b/bsdconfig/timezone/INDEX
@@ -0,0 +1,57 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 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.
+#
+# $FreeBSD$
+
+#
+# Title that will be shown in the bsdconfig menu.
+#
+menu_title="Timezone"
+
+#
+# A short descriptive line shown at the bottom of the bsdconfig menu. keep it
+# short because any line longer than the terminal width will be truncated.
+#
+menu_help="Set up Time Zone"
+
+#
+# Two-part variable that defines an action to take when `keyword' is passed on
+# a bsdconfig command line. Variable takes the form "keyword|command" and
+# multiple occurrences of the variable (with different `keyword's, or different
+# `keyword's AND `command's) are allowed. If `command' begins with a '/' then
+# the full path to the program is needed. If `command' begins with anything
+# else it is a path relative to the directory this INDEX file is in. `keyword'
+# can be i18n'ed but `command' is the name of a script.
+#
+menu_selection="timezone|timezone"
+
+#
+# ------------ Items below this line do NOT need i18n translation ------------
+#
+# Name of the program to be run when this menu choice is selected. If it begins
+# with a '/' then the full path to the program is needed. If it begins with
+# anything else it is a path relative to the directory this INDEX file is in.
+#
+menu_program="timezone"
diff --git a/bsdconfig/timezone/Makefile b/bsdconfig/timezone/Makefile
new file mode 100644
index 000000000000..1569e7e49569
--- /dev/null
+++ b/bsdconfig/timezone/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include share
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/090.timezone
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= timezone
+
+.include <bsd.prog.mk>
diff --git a/bsdconfig/timezone/Makefile.depend b/bsdconfig/timezone/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/bsdconfig/timezone/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# 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/bsdconfig/timezone/USAGE b/bsdconfig/timezone/USAGE
new file mode 100644
index 000000000000..6dbe96d3997d
--- /dev/null
+++ b/bsdconfig/timezone/USAGE
@@ -0,0 +1,46 @@
+# Copyright (c) 2011-2013 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.
+#
+# $FreeBSD$
+
+Usage: bsdconfig @PROGRAM_NAME@ [-ehnrSsvX] [-C chroot_dir] [zinfo_file | zinfo_name]
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -e Only return success on exit if user selects a timezone AND
+ the selected timezone was successfully installed. By default
+ (without this flag), success is always returned unless an
+ error has occurred.
+ -h Print this usage statement and exit.
+ -n Do not create or copy files.
+ -r Reinstall the zoneinfo file installed last time. The name is
+ obtained from /var/db/zoneinfo.
+ -S Secure X11 mode (implies `-X'). As root, always prompt-for
+ and validate sudo(8) username/password before starting.
+ -s Skip the initial question about adjusting the clock if
+ not set to UTC.
+ -v Verbose. Enable extra output when installing the zone file.
+ -X Enable the use of Xdialog(1) instead of dialog(1).
diff --git a/bsdconfig/timezone/include/Makefile b/bsdconfig/timezone/include/Makefile
new file mode 100644
index 000000000000..8fc6dfc84535
--- /dev/null
+++ b/bsdconfig/timezone/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/090.timezone/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/bsdconfig/timezone/include/Makefile.depend b/bsdconfig/timezone/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/bsdconfig/timezone/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# 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/bsdconfig/timezone/include/messages.subr b/bsdconfig/timezone/include/messages.subr
new file mode 100644
index 000000000000..6a7f045cd4f2
--- /dev/null
+++ b/bsdconfig/timezone/include/messages.subr
@@ -0,0 +1,78 @@
+# Copyright (c) 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.
+#
+# $FreeBSD$
+
+continent_africa_title="Africa"
+continent_america_title="America -- North and South"
+continent_antarctica_title="Antarctica"
+continent_arctic_title="Arctic Ocean"
+continent_asia_title="Asia"
+continent_atlantic_title="Atlantic Ocean"
+continent_australia_title="Australia"
+continent_europe_title="Europe"
+continent_indian_title="Indian Ocean"
+continent_pacific_title="Pacific Ocean"
+continent_utc_title="UTC"
+msg_cancel="Cancel"
+msg_cannot_open_for_reading="Cannot open %s for reading. Does it exist?"
+msg_confirmation="Confirmation"
+msg_conflicting_zone_definition="%s:%d: conflicting zone definition"
+msg_copied_timezone_file="Copied timezone file from %s to %s"
+msg_copying_file="Copying %s to %s"
+msg_country_code_invalid="%s:%d: country code \`%s' invalid"
+msg_country_code_multiply_defined="%s:%d: country code \`%s' multiply defined: %s"
+msg_country_code_unknown="%s:%d: country code \`%s' unknown"
+msg_country_time_zones="%s Time Zones"
+msg_country_title="Countries in %s"
+msg_created_symlink="Created symbolic link from %s to %s"
+msg_creating_symlink="Creating symbolic link %s to %s"
+msg_default_zone_provided="Default timezone provided"
+msg_done="Done"
+msg_error="Error"
+msg_error_reading="Error reading %s."
+msg_info="Info"
+msg_invalid_code="%s:%d: invalid code \`%s'"
+msg_invalid_country_code="%s:%d: invalid country code \`%s'"
+msg_invalid_format="%s:%d: invalid format"
+msg_invalid_region="%s:%d: invalid region \`%s'"
+msg_invalid_zone_name="%s:%d: invalid zone name \`%s'"
+msg_is_machine_clock_utc="Is the machine's CMOS clock set to UTC? If it is set to local time,\nor you don't know, please choose NO here!"
+msg_island_and_group_title="Islands and groups in the %s"
+msg_look_reasonable="Does the abbreviation \`%s' look reasonable?"
+msg_no="No"
+msg_ok="OK"
+msg_removed_file="Removed %s"
+msg_removing_file="Removing %s"
+msg_select_country="Select a country"
+msg_select_island_or_group="Select an island or group"
+msg_select_local_or_utc="Select local or UTC (Greenwhich Mean Time) clock"
+msg_select_region="Select a region"
+msg_select_zone="Select a zone which observes the same time as your locality."
+msg_time_zone="Time Zone"
+msg_unable_to_determine_name_from_db="Unable to determine earlier installed zoneinfo name. Check %s"
+msg_use_default_zone="Use the default \`%s' zone?"
+msg_yes="Yes"
+msg_zone_multiply_defined="%s:%d: zone multiply defined"
+msg_zone_must_have_description="%s:%d: zone must have description"
diff --git a/bsdconfig/timezone/share/Makefile b/bsdconfig/timezone/share/Makefile
new file mode 100644
index 000000000000..166fb1020d29
--- /dev/null
+++ b/bsdconfig/timezone/share/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+FILESDIR= ${SHAREDIR}/bsdconfig/timezone
+FILES= continents.subr countries.subr iso3166.subr menus.subr \
+ zones.subr
+
+.include <bsd.prog.mk>
diff --git a/bsdconfig/timezone/share/Makefile.depend b/bsdconfig/timezone/share/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/bsdconfig/timezone/share/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# 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/bsdconfig/timezone/share/continents.subr b/bsdconfig/timezone/share/continents.subr
new file mode 100644
index 000000000000..764f33fc6c50
--- /dev/null
+++ b/bsdconfig/timezone/share/continents.subr
@@ -0,0 +1,166 @@
+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.
+#
+# $FreeBSD$
+#
+############################################################ 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/bsdconfig/timezone/share/countries.subr b/bsdconfig/timezone/share/countries.subr
new file mode 100644
index 000000000000..8958e877c3d8
--- /dev/null
+++ b/bsdconfig/timezone/share/countries.subr
@@ -0,0 +1,105 @@
+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.
+#
+# $FreeBSD$
+#
+############################################################ 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/bsdconfig/timezone/share/iso3166.subr b/bsdconfig/timezone/share/iso3166.subr
new file mode 100644
index 000000000000..205d5f5046fd
--- /dev/null
+++ b/bsdconfig/timezone/share/iso3166.subr
@@ -0,0 +1,202 @@
+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.
+#
+# $FreeBSD$
+#
+############################################################ 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/bsdconfig/timezone/share/menus.subr b/bsdconfig/timezone/share/menus.subr
new file mode 100644
index 000000000000..ef3979be49a5
--- /dev/null
+++ b/bsdconfig/timezone/share/menus.subr
@@ -0,0 +1,225 @@
+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.
+#
+# $FreeBSD$
+#
+############################################################ 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/bsdconfig/timezone/share/zones.subr b/bsdconfig/timezone/share/zones.subr
new file mode 100644
index 000000000000..59a933013e57
--- /dev/null
+++ b/bsdconfig/timezone/share/zones.subr
@@ -0,0 +1,523 @@
+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.
+#
+# $FreeBSD$
+#
+############################################################ 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
diff --git a/bsdconfig/timezone/timezone b/bsdconfig/timezone/timezone
new file mode 100755
index 000000000000..a2914429846e
--- /dev/null
+++ b/bsdconfig/timezone/timezone
@@ -0,0 +1,457 @@
+#!/bin/sh
+#-
+# 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.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/timezone/continents.subr
+f_include $BSDCFG_SHARE/timezone/countries.subr
+f_include $BSDCFG_SHARE/timezone/iso3166.subr
+f_include $BSDCFG_SHARE/timezone/menus.subr
+f_include $BSDCFG_SHARE/timezone/zones.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames
+#
+_PATH_DB="/var/db/zoneinfo"
+_PATH_WALL_CMOS_CLOCK="/etc/wall_cmos_clock"
+
+############################################################ GLOBALS
+
+#
+# Options
+#
+REALLYDOIT=1
+REINSTALL=
+USEDIALOG=1
+SKIPUTC= # See MAIN
+VERBOSE=
+TZ_OR_FAIL=
+CHROOTENV=
+
+#
+# Dummy vars (populated dynamically)
+#
+COUNTRIES= # list of 2-character country codes created by f_read_iso3166_table
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local prompt="$msg_select_region"
+ local defaultitem= # Calculated below
+ local hline=
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $continent_menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $continent_menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ f_dialog_default_store "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Skip initial question regarding UTC v. Wall-Clock time if run in VM
+[ "$( sysctl -n kern.vm_guest 2> /dev/null )" = "none" ] || SKIPUTC=1
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts C:ehnrsv$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ C) CHROOTENV="$OPTARG" ;;
+ e) TZ_OR_FAIL=1 ;;
+ n) REALLYDOIT= ;;
+ r) REINSTALL=1
+ USEDIALOG= ;;
+ s) SKIPUTC=1 ;;
+ v) VERBOSE=1 ;;
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_time_zone"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Process `-C chroot_directory' command-line argument
+#
+if [ "$CHROOTENV" ]; then
+ _PATH_ZONETAB="$CHROOTENV$_PATH_ZONETAB"
+ _PATH_ISO3166="$CHROOTENV$_PATH_ISO3166"
+ _PATH_ZONEINFO="$CHROOTENV$_PATH_ZONEINFO"
+ _PATH_LOCALTIME="$CHROOTENV$_PATH_LOCALTIME"
+ _PATH_DB="$CHROOTENV$_PATH_DB"
+ _PATH_WALL_CMOS_CLOCK="$CHROOTENV$_PATH_WALL_CMOS_CLOCK"
+fi
+
+#
+# Process `-r' command-line option
+#
+if [ "$REINSTALL" ]; then
+ [ -f "$_PATH_DB" -a -r "$_PATH_DB" ] ||
+ f_die 1 "$msg_cannot_open_for_reading" "$_PATH_DB"
+ f_eval_catch -dk zoneinfo "$0" cat 'cat "%s"' "$_PATH_DB" ||
+ f_die 1 "$msg_error_reading" "$_PATH_DB"
+ [ "$zoneinfo" ] ||
+ f_die 1 "$msg_unable_to_determine_name_from_db" "$_PATH_DB"
+ f_install_zoneinfo "$zoneinfo"
+ exit $?
+fi
+
+#
+# If the arguments on the command-line do not specify a file,
+# then interpret it as a zoneinfo name
+#
+if [ $# -ge 1 ]; then
+ zoneinfo="$1"
+
+ if [ ! -f "$zoneinfo" ]; then
+ USEDIALOG=
+ f_install_zoneinfo "$zoneinfo"
+ exit $?
+ fi
+
+ # FALLTHROUGH
+fi
+
+#
+# Process the UTC option
+#
+if [ "$_PATH_WALL_CMOS_CLOCK" -a ! "$SKIPUTC" ]; then
+ f_dialog_title "$msg_select_local_or_utc"
+ title="$DIALOG_TITLE"
+ btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ msg="$msg_is_machine_clock_utc"
+
+ if [ "$USE_XDIALOG" ]; then
+ defaultno="default-no"
+ height=10 width=77
+ else
+ defaultno="defaultno"
+ height=7 width=73
+ fi
+
+ if [ "$USE_XDIALOG" ]; then
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --$defaultno \
+ --ok-label "$msg_yes" \
+ --cancel-label "$msg_no" \
+ --yesno "$msg" $height $width
+ result=$?
+ else
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --$defaultno \
+ --yes-label "$msg_yes" \
+ --no-label "$msg_no" \
+ --yesno "$msg" $height $width
+ result=$?
+ fi
+
+ if [ $result -eq $DIALOG_OK ]; then
+ # User chose YES
+ [ "$REALLYDOIT" ] &&
+ f_quietly rm -f "$_PATH_WALL_CMOS_CLOCK"
+ else
+ # User chose NO, pressed ESC (or Ctrl-C), or closed box
+ [ "$REALLYDOIT" ] &&
+ ( umask 222 && :> "$_PATH_WALL_CMOS_CLOCK" )
+ fi
+fi
+
+#
+# Process optional default zone argument
+#
+if [ $# -ge 1 ]; then
+ default="$1"
+
+ f_dialog_title "$msg_default_zone_provided"
+ f_sprintf msg "\n$msg_use_default_zone" "$default"
+ hline=
+ f_dialog_yesno "$msg" "$hline"
+ result=$?
+ f_dialog_title_restore
+
+ if [ $result -eq $DIALOG_OK ]; then
+ # User chose YES
+ f_install_zoneinfo_file "$default"
+ result=$?
+ [ ! "$USE_XDIALOG" ] && f_dialog_clear
+ exit $result
+ fi
+
+ [ ! "$USE_XDIALOG" ] && f_dialog_clear
+fi
+
+#
+# Override the user-supplied umask
+#
+umask 022
+
+#
+# Read databases and perform initialization
+#
+f_read_iso3166_table # creates $COUNTRIES and $country_*_name
+f_read_zones # creates $country_*_{descr,cont,filename}
+f_sort_countries # sorts the countries listed for each continent
+f_make_menus # creates $continent_menu_list and $continent_*_menu_list
+
+#
+# Launch application main menu
+#
+defaultctry=
+defaultzone=
+NEED_CONTINENT=1
+NEED_COUNTRY=1
+while :; do
+ if [ "$NEED_CONTINENT" ]; then
+ dialog_menu_main # prompt the user to select a continent/ocean
+ retval=$?
+ f_dialog_menutag_fetch mtag
+
+ if [ $retval -ne $DIALOG_OK ]; then
+ [ "$TZ_OR_FAIL" ] && f_die
+ exit $SUCCESS
+ fi
+
+ NEED_CONTINENT=
+
+ continent=$( eval f_dialog_menutag2item \"\$mtag\" \
+ $continent_menu_list )
+ f_find_continent "$continent" cont
+ f_continent $cont title cont_title
+ f_continent $cont nitems nitems
+ f_OCEANP $cont isocean
+ fi
+
+ if [ "$NEED_COUNTRY" ]; then
+ if [ "$cont_title" = "$continent_utc_title" ]; then
+ if f_set_zone_utc; then
+ break
+ else
+ NEED_CONTINENT=1
+ continue
+ fi
+ fi
+
+ #
+ # Short cut -- if there's only one country, don't post a menu.
+ #
+ if [ $nitems -eq 1 ]; then
+ tag=1
+ else
+ #
+ # It's amazing how much good grammar really matters...
+ #
+ if [ ! "$isocean" ]; then
+ f_sprintf title "$msg_country_title" \
+ "$cont_title"
+ f_dialog_title "$title"
+ title="$DIALOG_TITLE"
+ btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ prompt="$msg_select_country"
+ else
+ f_sprintf title "$msg_island_and_group_title" \
+ "$cont_title"
+ f_dialog_title "$title"
+ title="$DIALOG_TITLE"
+ btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ prompt="$msg_select_island_or_group"
+ fi
+
+ #
+ # Calculate size of menu
+ #
+ f_continent $cont menu_list menu_list
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\" \
+ $menu_list
+
+ #
+ # Launch the country selection menu
+ #
+ tag=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultctry\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ retval=$?
+ f_dialog_data_sanitize tag
+ defaultctry="$tag"
+
+ if [ $retval -ne $DIALOG_OK ]; then
+ NEED_CONTINENT=1
+ continue # back to main menu
+ fi
+ fi
+
+ # Get the country code from the user's selection
+ f_continent $cont tlc_$tag tlc
+
+ NEED_COUNTRY=
+ fi
+
+ #
+ # If the selection has only one zone (nzones == -1),
+ # just set it.
+ #
+ f_country $tlc nzones nzones
+ if [ $nzones -lt 0 ]; then
+ f_country $tlc cont real_cont
+ f_continent $real_cont name real_continent
+ f_country $tlc name name
+ f_country $tlc filename filename
+
+ if ! f_confirm_zone "$real_continent/$filename"; then
+ [ $nitems -eq 1 ] && NEED_CONTINENT=1
+ NEED_COUNTRY=1
+ continue
+ fi
+ else
+ f_country $tlc name name
+ f_sprintf title "$msg_country_time_zones" "$name"
+ f_dialog_title "$title"
+ title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ prompt="$msg_select_zone"
+ f_country $tlc menu_list menu_list
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \"\$btitle\" \"\$prompt\" \"\" $menu_list
+
+ #
+ # Launch the zone selection menu
+ # NOTE: This is as deep as we go
+ #
+ n=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultzone\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ retval=$?
+ f_dialog_data_sanitize n
+ defaultzone="$n"
+
+ if [ $retval -ne $DIALOG_OK ]; then
+ [ $nitems -eq 1 ] && NEED_CONTINENT=1
+ NEED_COUNTRY=1
+ continue
+ fi
+
+ f_country $tlc cont_$n real_cont
+ f_continent $real_cont name real_continent
+ f_country $tlc name name
+ f_country $tlc filename_$n filename
+
+ f_confirm_zone "$real_continent/$filename" || continue
+ fi
+
+ [ $retval -eq $DIALOG_OK ] || continue # back to main menu
+
+ if ! f_install_zoneinfo "$real_continent/$filename"; then
+ [ $nzones -lt 0 ] && NEED_COUNTRY=1
+ else
+ break
+ fi
+done
+
+################################################################################
+# END
+################################################################################