freebsd-dev/usr.sbin/bsdconfig/timezone/timezone
Devin Teske 052f89691c Standardize the way functions build their arguments leading up to a dialog
invocation. Specifically, "top-load" your arguments and in the order in-
which they will be displayed. For example, many [if not all] widgets display
information in the following order, top-to-bottom (visually):

+ backtitle (displayed behind the widget at top-left)
+ title (at the top of the `window')
+ prompt text (just below the title and above whatever widget you choose)
+ Depending on widget, _one_ of the following:
  - menu list
  - radio list
  - check list
  - text input box with initial text
  - [Xdialog(1)] 2x or 3x text input boxes
  - [dialog(1)] a multi-part form
  - progress bar
  - etc. (many more widget choices)
+ buttons (right below the selected widget)
+ [dialog(1)] the hline (displayed at bottom of `window')

NOTE: Xdialog(1) accepts and silently ignores --hline

When building local arguments for your dialog invocation, if the value can't
be cleanly loaded into a local, add "# Calculated below" to the end of the
local declaration while retaining the block order of argument declarations.

Move other local declarations that are not associated with this top-loading
the dialog arguments to right-above where they are first-used.

Also, standardize on the names of the arguments. For example, always use
$prompt (instead of sometimes $msg and sometimes $prompt); use $menu_list
or $shell_list or $radio_list for those respective widgets; ad nauseum.

While we're doing this, flush-out full arguments for many invocations that
were passing NULL strings (making it unapparent if you were staring at this
one invocation what argument that NULL string was supposed to represent).

Last, while we're in startup/rcconf let's remove the unnecessary use of a
GLOBAL (RCCONF_MENU_LIST) for the menu_list.
2013-06-02 20:02:50 +00:00

474 lines
12 KiB
Bash
Executable File

#!/bin/sh
#-
# 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 (INLUDING, 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
ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
############################################################ CONFIGURATION
#
# Standard pathnames
#
_PATH_DB="/var/db/zoneinfo"
_PATH_WALL_CMOS_CLOCK="/etc/wall_cmos_clock"
############################################################ GLOBALS
#
# Options
#
REALLYDOIT=1
REINSTALL=
USEDIALOG=1
SKIPUTC=
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
# 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"
zoneinfo=$( cat "$_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 0 ]; 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"
title="$DIALOG_TITLE"
btitle="$DIALOG_BACKTITLE"
f_dialog_title_restore
msg=$( printf "\n$msg_use_default_zone" "$default" )
f_dialog_buttonbox_size height width "$title" "$btitle" "$msg"
if [ "$USE_XDIALOG" ]; then
eval $DIALOG \
--title \"\$title\" \
--backtitle \"\$btitle\" \
--ok-label \"\$msg_yes\" \
--cancel-label \"\$msg_no\" \
--yesno \"\$msg\" $height $width
result=$?
else
eval $DIALOG \
--title \"\$title\" \
--backtitle \"\$btitle\" \
--yes-label \"\$msg_yes\" \
--no-label \"\$msg_no\" \
--yesno \"\$msg\" $height $width
result=$?
fi
if [ $result -eq 0 ]; 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 0 ]; then
[ "$TZ_OR_FAIL" ] && f_die
exit $SUCCESS
fi
NEED_CONTINENT=
continent=$( eval f_dialog_menutag2item \"\$mtag\" \
$continent_menu_list )
cont=$( f_find_continent "$continent" )
cont_title=$( f_continent $cont title )
nitems=$( f_continent $cont nitems )
isocean=$( f_OCEANP $cont )
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
title=$( printf "$msg_country_title" \
"$cont_title" )
f_dialog_title "$title"
title="$DIALOG_TITLE"
btitle="$DIALOG_BACKTITLE"
f_dialog_title_restore
prompt="$msg_select_country"
else
title=$( printf "$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
#
menu_list=$( f_continent $cont 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 0 ]; then
NEED_CONTINENT=1
continue # back to main menu
fi
fi
# Get the country code from the user's selection
tlc=$( f_continent $cont tlc_$tag )
NEED_COUNTRY=
fi
#
# If the selection has only one zone (nzones == -1),
# just set it.
#
nzones=$( f_country $tlc nzones )
if [ $nzones -lt 0 ]; then
real_cont=$( f_country $tlc cont )
real_continent=$( f_continent $real_cont name )
name=$( f_country $tlc name )
filename=$( f_country $tlc filename )
if ! f_confirm_zone "$real_continent/$filename"; then
[ $nitems -eq 1 ] && NEED_CONTINENT=1
NEED_COUNTRY=1
continue
fi
else
title=$( printf "$msg_country_time_zones" \
"$( f_country $tlc name )" )
f_dialog_title "$title"
title="$DIALOG_TITLE"
btitle="$DIALOG_BACKTITLE"
f_dialog_title_restore
prompt="$msg_select_zone"
menu_list=$( f_country $tlc 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 0 ]; then
[ $nitems -eq 1 ] && NEED_CONTINENT=1
NEED_COUNTRY=1
continue
fi
real_cont=$( f_country $tlc cont_$n )
real_continent=$( f_continent $real_cont name )
name=$( f_country $tlc name )
filename=$( f_country $tlc filename_$n )
f_confirm_zone "$real_continent/$filename" || continue
fi
[ $retval -eq 0 ] || continue # back to main menu
if ! f_install_zoneinfo "$real_continent/$filename"; then
[ $nzones -lt 0 ] && NEED_COUNTRY=1
else
break
fi
done
################################################################################
# END
################################################################################