timezone revision 322096
143412Snewton#!/bin/sh
243412Snewton#-
343412Snewton# Copyright (c) 2011-2015 Devin Teske
443412Snewton# All rights reserved.
552333Snewton#
6302097Sbrooks# Redistribution and use in source and binary forms, with or without
743412Snewton# modification, are permitted provided that the following conditions
843412Snewton# are met:
943412Snewton# 1. Redistributions of source code must retain the above copyright
1043412Snewton#    notice, this list of conditions and the following disclaimer.
1143412Snewton# 2. Redistributions in binary form must reproduce the above copyright
1243412Snewton#    notice, this list of conditions and the following disclaimer in the
1365302Sobrien#    documentation and/or other materials provided with the distribution.
1465302Sobrien#
1565302Sobrien# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1665302Sobrien# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1743412Snewton# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1860290Sbde# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1960290Sbde# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2043412Snewton# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2143412Snewton# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22209581Skib# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23225618Skmacy# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24225618Skmacy# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25225618Skmacy# SUCH DAMAGE.
26225618Skmacy#
27209581Skib# $FreeBSD: stable/10/usr.sbin/bsdconfig/timezone/timezone 322096 2017-08-05 12:54:07Z marius $
28225618Skmacy#
29209581Skib############################################################ INCLUDES
30209581Skib
31225618SkmacyBSDCFG_SHARE="/usr/share/bsdconfig"
32225618Skmacy. $BSDCFG_SHARE/common.subr || exit 1
33209581Skibf_dprintf "%s: loading includes..." "$0"
34225618Skmacyf_include $BSDCFG_SHARE/dialog.subr
35209581Skibf_include $BSDCFG_SHARE/mustberoot.subr
36209581Skibf_include $BSDCFG_SHARE/strings.subr
37225618Skmacyf_include $BSDCFG_SHARE/timezone/continents.subr
38225618Skmacyf_include $BSDCFG_SHARE/timezone/countries.subr
39209581Skibf_include $BSDCFG_SHARE/timezone/iso3166.subr
40209581Skibf_include $BSDCFG_SHARE/timezone/menus.subr
41225618Skmacyf_include $BSDCFG_SHARE/timezone/zones.subr
42225618Skmacy
43209581SkibBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
44209581Skibf_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
45225618Skmacy
46225618Skmacyf_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
47209581Skib	pgm="${ipgm:-$pgm}"
48209581Skib
49209581Skib############################################################ CONFIGURATION
50209581Skib
51209581Skib#
52209581Skib# Standard pathnames
53209581Skib#
54209581Skib_PATH_DB="/var/db/zoneinfo"
55209581Skib_PATH_WALL_CMOS_CLOCK="/etc/wall_cmos_clock"
56209581Skib
57209581Skib############################################################ GLOBALS
58225618Skmacy
59209581Skib#
60209581Skib# Options
61209581Skib#
62209581SkibREALLYDOIT=1
63225618SkmacyREINSTALL=
64302097SbrooksUSEDIALOG=1
65209581SkibSKIPUTC= # See MAIN
66209581SkibVERBOSE=
67209581SkibTZ_OR_FAIL=
68225618SkmacyCHROOTENV=
69225618Skmacy
70209581Skib#
71209581Skib# Dummy vars (populated dynamically)
72209581Skib#
73209581SkibCOUNTRIES= # list of 2-character country codes created by f_read_iso3166_table
74209581Skib
75209581Skib############################################################ FUNCTIONS
76209581Skib
77209581Skib# dialog_menu_main
78209581Skib#
79209581Skib# Display the dialog(1)-based application main menu.
80225618Skmacy#
81209581Skibdialog_menu_main()
82225618Skmacy{
83225618Skmacy	local title="$DIALOG_TITLE"
84209581Skib	local btitle="$DIALOG_BACKTITLE"
85209581Skib	local prompt="$msg_select_region"
86209581Skib	local defaultitem= # Calculated below
87209581Skib	local hline=
88209581Skib
89209581Skib	local height width rows
90209581Skib	eval f_dialog_menu_size height width rows \
91209581Skib	                        \"\$title\"  \
92209581Skib	                        \"\$btitle\" \
93209581Skib	                        \"\$prompt\" \
94209581Skib	                        \"\$hline\"  \
95209581Skib	                        $continent_menu_list
96209581Skib
97209581Skib	# Obtain default-item from previously stored selection
98209581Skib	f_dialog_default_fetch defaultitem
99209581Skib
100209581Skib	local menu_choice
101225618Skmacy	menu_choice=$( eval $DIALOG \
102225618Skmacy		--title \"\$title\"              \
103209581Skib		--backtitle \"\$btitle\"         \
104209581Skib		--hline \"\$hline\"              \
105209581Skib		--ok-label \"\$msg_ok\"          \
106209581Skib		--cancel-label \"\$msg_cancel\"  \
107209581Skib		--default-item \"\$defaultitem\" \
108209581Skib		--menu \"\$prompt\"              \
109209581Skib		$height $width $rows             \
110209581Skib		$continent_menu_list             \
111225618Skmacy		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
112225618Skmacy	)
113225618Skmacy	local retval=$?
114225618Skmacy	f_dialog_data_sanitize menu_choice
115225618Skmacy	f_dialog_menutag_store "$menu_choice"
116225618Skmacy	f_dialog_default_store "$menu_choice"
117209581Skib	return $retval
118209581Skib}
119209581Skib
120209581Skib############################################################ MAIN
121209581Skib
122209581Skib# Skip initial question regarding UTC v. Wall-Clock time if run in VM
123209581Skib[ "$( sysctl -n kern.vm_guest 2> /dev/null )" = "none" ] || SKIPUTC=1
124209581Skib
125209581Skib# Incorporate rc-file if it exists
126209581Skib[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
127209581Skib
128209581Skib#
129209581Skib# Process command-line arguments
130209581Skib#
131209581Skibwhile getopts C:ehnrsv$GETOPTS_STDARGS flag; do
132209581Skib	case "$flag" in
133209581Skib	C) CHROOTENV="$OPTARG" ;;
134209581Skib	e) TZ_OR_FAIL=1 ;;
135209581Skib	n) REALLYDOIT= ;;
136209581Skib	r) REINSTALL=1
137209581Skib	   USEDIALOG= ;;
138225618Skmacy	s) SKIPUTC=1 ;;
139225618Skmacy	v) VERBOSE=1 ;;
140209581Skib	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
141225618Skmacy	esac
142225618Skmacydone
143225618Skmacyshift $(( $OPTIND - 1 ))
144225618Skmacy
145209581Skib#
146209581Skib# Initialize
147209581Skib#
148209581Skibf_dialog_title "$msg_time_zone"
149209581Skibf_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
150209581Skibf_mustberoot_init
151209581Skib
152225618Skmacy#
153209581Skib# Process `-C chroot_directory' command-line argument
154209581Skib#
155209581Skibif [ "$CHROOTENV" ]; then
156225618Skmacy	_PATH_ZONETAB="$CHROOTENV$_PATH_ZONETAB"
157209581Skib	_PATH_ISO3166="$CHROOTENV$_PATH_ISO3166"
158225618Skmacy	_PATH_ZONEINFO="$CHROOTENV$_PATH_ZONEINFO"
159209581Skib	_PATH_LOCALTIME="$CHROOTENV$_PATH_LOCALTIME"
160225618Skmacy	_PATH_DB="$CHROOTENV$_PATH_DB"
161209581Skib	_PATH_WALL_CMOS_CLOCK="$CHROOTENV$_PATH_WALL_CMOS_CLOCK"
162209581Skibfi
163225618Skmacy
164209581Skib#
165209581Skib# Process `-r' command-line option
166209581Skib#
167209581Skibif [ "$REINSTALL" ]; then
168209581Skib	[ -f "$_PATH_DB" -a -r "$_PATH_DB" ] ||
169209581Skib		f_die 1 "$msg_cannot_open_for_reading" "$_PATH_DB"
170209581Skib	f_eval_catch -dk zoneinfo "$0" cat 'cat "%s"' "$_PATH_DB" ||
171209581Skib		f_die 1 "$msg_error_reading" "$_PATH_DB"
172209581Skib	[ "$zoneinfo" ] ||
173209581Skib		f_die 1 "$msg_unable_to_determine_name_from_db" "$_PATH_DB"
174209581Skib	f_install_zoneinfo "$zoneinfo"
175209581Skib	exit $?
176209581Skibfi
177209581Skib
178209581Skib#
179225618Skmacy# If the arguments on the command-line do not specify a file,
180225618Skmacy# then interpret it as a zoneinfo name
181209581Skib#
182209581Skibif [ $# -ge 1 ]; then
183209581Skib	zoneinfo="$1"
184209581Skib
185209581Skib	if [ ! -f "$zoneinfo" ]; then
186209581Skib		USEDIALOG=
187209581Skib		f_install_zoneinfo "$zoneinfo"
188209581Skib		exit $?
189209581Skib	fi
190209581Skib
191209581Skib	# FALLTHROUGH
192209581Skibfi
193209581Skib
194209581Skib#
195209581Skib# Process the UTC option
196209581Skib#
197209581Skibif [ "$_PATH_WALL_CMOS_CLOCK" -a ! "$SKIPUTC" ]; then
198209581Skib	f_dialog_title "$msg_select_local_or_utc"
199209581Skib	title="$DIALOG_TITLE"
200209581Skib	btitle="$DIALOG_BACKTITLE"
201209581Skib	f_dialog_title_restore
202209581Skib	msg="$msg_is_machine_clock_utc"
203209581Skib
204209581Skib	if [ "$USE_XDIALOG" ]; then
205209581Skib		defaultno="default-no"
206209581Skib		height=10 width=77
207209581Skib	else
208209581Skib		defaultno="defaultno"
209209581Skib		height=7 width=73
210209581Skib	fi
211209581Skib
212209581Skib	if [ "$USE_XDIALOG" ]; then
213209581Skib		$DIALOG \
214209581Skib			--title "$title"         \
215209581Skib			--backtitle "$btitle"    \
216209581Skib			--$defaultno             \
217209581Skib			--ok-label "$msg_yes"    \
218209581Skib			--cancel-label "$msg_no" \
219209581Skib			--yesno "$msg" $height $width
220209581Skib		result=$?
221225618Skmacy	else
222209581Skib		$DIALOG \
223209581Skib			--title "$title"       \
224225618Skmacy			--backtitle "$btitle"  \
225225618Skmacy			--$defaultno           \
226209581Skib			--yes-label "$msg_yes" \
227209581Skib			--no-label "$msg_no"   \
228209581Skib			--yesno "$msg" $height $width
229209581Skib		result=$?
230209581Skib	fi
231209581Skib
232209581Skib	if [ $result -eq $DIALOG_OK ]; then
233209581Skib		# User chose YES
234209581Skib		[ "$REALLYDOIT" ] &&
235209581Skib			f_quietly rm -f "$_PATH_WALL_CMOS_CLOCK"
236209581Skib	else
237209581Skib		# User chose NO, pressed ESC (or Ctrl-C), or closed box
238209581Skib		[ "$REALLYDOIT" ] &&
239209581Skib			( umask 222 && :> "$_PATH_WALL_CMOS_CLOCK" )
240209581Skib	fi
241209581Skibfi
242209581Skib
243209581Skib#
244209581Skib# Process optional default zone argument
245209581Skib#
246209581Skibif [ $# -ge 1 ]; then
247209581Skib	default="$1"
248209581Skib
249209581Skib	f_dialog_title "$msg_default_zone_provided"
250209581Skib	f_sprintf msg "\n$msg_use_default_zone" "$default"
251209581Skib	hline=
252209581Skib	f_dialog_yesno "$msg" "$hline"
253225618Skmacy	result=$?
254225618Skmacy	f_dialog_title_restore
255225618Skmacy
256225618Skmacy	if [ $result -eq $DIALOG_OK ]; then
257225618Skmacy		# User chose YES
258225618Skmacy		f_install_zoneinfo_file "$default"
259209581Skib		result=$?
260225618Skmacy		[ ! "$USE_XDIALOG" ] && f_dialog_clear
261225618Skmacy		exit $result
262209581Skib	fi
263225618Skmacy
264209581Skib	[ ! "$USE_XDIALOG" ] && f_dialog_clear
265225618Skmacyfi
266225618Skmacy
267225618Skmacy#
268225618Skmacy# Override the user-supplied umask
269209581Skib#
270209581Skibumask 022
271209581Skib
27243412Snewton#
273# Read databases and perform initialization
274#
275f_read_iso3166_table # creates $COUNTRIES and $country_*_name
276f_read_zones         # creates $country_*_{descr,cont,filename}
277f_sort_countries     # sorts the countries listed for each continent
278f_make_menus         # creates $continent_menu_list and $continent_*_menu_list
279
280#
281# Launch application main menu
282#
283defaultctry=
284defaultzone=
285NEED_CONTINENT=1
286NEED_COUNTRY=1
287while :; do
288	if [ "$NEED_CONTINENT" ]; then
289		dialog_menu_main # prompt the user to select a continent/ocean
290		retval=$?
291		f_dialog_menutag_fetch mtag
292
293		if [ $retval -ne $DIALOG_OK ]; then
294			[ "$TZ_OR_FAIL" ] && f_die
295			exit $SUCCESS
296		fi
297
298		NEED_CONTINENT=
299
300		continent=$( eval f_dialog_menutag2item \"\$mtag\" \
301		                  	$continent_menu_list )
302		f_find_continent "$continent" cont
303		f_continent $cont title cont_title
304		f_continent $cont nitems nitems
305		f_OCEANP $cont isocean
306	fi
307
308	if [ "$NEED_COUNTRY" ]; then
309		if [ "$cont_title" = "$continent_utc_title" ]; then
310			if f_set_zone_utc; then
311				break
312			else
313				NEED_CONTINENT=1
314				continue
315			fi
316		fi
317
318		#
319		# Short cut -- if there's only one country, don't post a menu.
320		#
321		if [ $nitems -eq 1 ]; then
322			tag=1
323		else
324			#
325			# It's amazing how much good grammar really matters...
326			#
327			if [ ! "$isocean" ]; then
328				f_sprintf title "$msg_country_title" \
329				                "$cont_title"
330				f_dialog_title "$title"
331				title="$DIALOG_TITLE"
332				btitle="$DIALOG_BACKTITLE"
333				f_dialog_title_restore
334				prompt="$msg_select_country"
335			else
336				f_sprintf title "$msg_island_and_group_title" \
337				                "$cont_title"
338				f_dialog_title "$title"
339				title="$DIALOG_TITLE"
340				btitle="$DIALOG_BACKTITLE"
341				f_dialog_title_restore
342				prompt="$msg_select_island_or_group"
343			fi
344
345			#
346			# Calculate size of menu
347			#
348			f_continent $cont menu_list menu_list
349			eval f_dialog_menu_size height width rows \
350			                        \"\$title\"  \
351			                        \"\$btitle\" \
352			                        \"\$prompt\" \
353			                        \"\"         \
354			                        $menu_list
355
356			#
357			# Launch the country selection menu
358			#
359			tag=$( eval $DIALOG \
360				--title \"\$title\"              \
361				--backtitle \"\$btitle\"         \
362				--ok-label \"\$msg_ok\"          \
363				--cancel-label \"\$msg_cancel\"  \
364				--default-item \"\$defaultctry\" \
365				--menu \"\$prompt\"              \
366				$height $width $rows             \
367				$menu_list                       \
368				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
369			)
370			retval=$?
371			f_dialog_data_sanitize tag
372			defaultctry="$tag"
373
374			if [ $retval -ne $DIALOG_OK ]; then
375				NEED_CONTINENT=1
376				continue # back to main menu
377			fi
378		fi
379
380		# Get the country code from the user's selection 
381		f_continent $cont tlc_$tag tlc
382
383		NEED_COUNTRY=
384	fi
385
386	#
387	# If the selection has only one zone (nzones == -1),
388	# just set it.
389	#
390	f_country $tlc nzones nzones
391	if [ $nzones -lt 0 ]; then
392		f_country $tlc cont real_cont
393		f_continent $real_cont name real_continent
394		f_country $tlc name name
395		f_country $tlc filename filename
396
397		if ! f_confirm_zone "$real_continent/$filename"; then
398			[ $nitems -eq 1 ] && NEED_CONTINENT=1
399			NEED_COUNTRY=1
400			continue
401		fi
402	else
403		f_country $tlc name name
404		f_sprintf title "$msg_country_time_zones" "$name"
405		f_dialog_title "$title"
406		title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
407		f_dialog_title_restore
408		prompt="$msg_select_zone"
409		f_country $tlc menu_list menu_list
410		eval f_dialog_menu_size height width rows \
411			\"\$title\"  \"\$btitle\" \"\$prompt\" \"\" $menu_list
412
413		#
414		# Launch the zone selection menu
415		# NOTE: This is as deep as we go
416		#
417		n=$( eval $DIALOG \
418			--title \"\$title\"              \
419			--backtitle \"\$btitle\"         \
420			--ok-label \"\$msg_ok\"          \
421			--cancel-label \"\$msg_cancel\"  \
422			--default-item \"\$defaultzone\" \
423			--menu \"\$prompt\"              \
424			$height $width $rows             \
425			$menu_list                       \
426			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
427		)
428		retval=$?
429		f_dialog_data_sanitize n
430		defaultzone="$n"
431
432		if [ $retval -ne $DIALOG_OK ]; then
433			[ $nitems -eq 1 ] && NEED_CONTINENT=1
434			NEED_COUNTRY=1
435			continue
436		fi
437
438		f_country $tlc cont_$n real_cont
439		f_continent $real_cont name real_continent
440		f_country $tlc name name
441		f_country $tlc filename_$n filename
442
443		f_confirm_zone "$real_continent/$filename" || continue
444	fi
445
446	[ $retval -eq $DIALOG_OK ] || continue # back to main menu
447
448	if ! f_install_zoneinfo "$real_continent/$filename"; then
449		[ $nzones -lt 0 ] && NEED_COUNTRY=1
450	else
451		break
452	fi
453done
454
455################################################################################
456# END
457################################################################################
458