1238438Sdteske#!/bin/sh
2238438Sdteske#-
3278489Sdteske# Copyright (c) 2011-2015 Devin Teske
4252980Sdteske# All rights reserved.
5238438Sdteske#
6238438Sdteske# Redistribution and use in source and binary forms, with or without
7238438Sdteske# modification, are permitted provided that the following conditions
8238438Sdteske# are met:
9238438Sdteske# 1. Redistributions of source code must retain the above copyright
10238438Sdteske#    notice, this list of conditions and the following disclaimer.
11238438Sdteske# 2. Redistributions in binary form must reproduce the above copyright
12238438Sdteske#    notice, this list of conditions and the following disclaimer in the
13238438Sdteske#    documentation and/or other materials provided with the distribution.
14238438Sdteske#
15238438Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16252987Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17238438Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18238438Sdteske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19238438Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20252987Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21238438Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22238438Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23238438Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24238438Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25238438Sdteske# SUCH DAMAGE.
26238438Sdteske#
27238438Sdteske# $FreeBSD$
28238438Sdteske#
29238438Sdteske############################################################ INCLUDES
30238438Sdteske
31240684SdteskeBSDCFG_SHARE="/usr/share/bsdconfig"
32240684Sdteske. $BSDCFG_SHARE/common.subr || exit 1
33244675Sdteskef_dprintf "%s: loading includes..." "$0"
34240684Sdteskef_include $BSDCFG_SHARE/dialog.subr
35240684Sdteskef_include $BSDCFG_SHARE/mustberoot.subr
36240684Sdteskef_include $BSDCFG_SHARE/strings.subr
37240684Sdteskef_include $BSDCFG_SHARE/timezone/continents.subr
38240684Sdteskef_include $BSDCFG_SHARE/timezone/countries.subr
39240684Sdteskef_include $BSDCFG_SHARE/timezone/iso3166.subr
40240684Sdteskef_include $BSDCFG_SHARE/timezone/menus.subr
41240684Sdteskef_include $BSDCFG_SHARE/timezone/zones.subr
42238438Sdteske
43240684SdteskeBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
44238438Sdteskef_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
45238438Sdteske
46259054Sdteskef_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
47259054Sdteske	pgm="${ipgm:-$pgm}"
48238438Sdteske
49238438Sdteske############################################################ CONFIGURATION
50238438Sdteske
51238438Sdteske#
52238438Sdteske# Standard pathnames
53238438Sdteske#
54238438Sdteske_PATH_DB="/var/db/zoneinfo"
55238438Sdteske_PATH_WALL_CMOS_CLOCK="/etc/wall_cmos_clock"
56238438Sdteske
57238438Sdteske############################################################ GLOBALS
58238438Sdteske
59238438Sdteske#
60238438Sdteske# Options
61238438Sdteske#
62238438SdteskeREALLYDOIT=1
63238438SdteskeREINSTALL=
64238438SdteskeUSEDIALOG=1
65274394SdteskeSKIPUTC= # See MAIN
66238438SdteskeVERBOSE=
67238438SdteskeTZ_OR_FAIL=
68238438SdteskeCHROOTENV=
69238438Sdteske
70238438Sdteske#
71238438Sdteske# Dummy vars (populated dynamically)
72238438Sdteske#
73238438SdteskeCOUNTRIES= # list of 2-character country codes created by f_read_iso3166_table
74238438Sdteske
75238438Sdteske############################################################ FUNCTIONS
76238438Sdteske
77238438Sdteske# dialog_menu_main
78238438Sdteske#
79238438Sdteske# Display the dialog(1)-based application main menu.
80238438Sdteske#
81238438Sdteskedialog_menu_main()
82238438Sdteske{
83238438Sdteske	local title="$DIALOG_TITLE"
84238438Sdteske	local btitle="$DIALOG_BACKTITLE"
85238438Sdteske	local prompt="$msg_select_region"
86251244Sdteske	local defaultitem= # Calculated below
87251264Sdteske	local hline=
88238438Sdteske
89251190Sdteske	local height width rows
90251190Sdteske	eval f_dialog_menu_size height width rows \
91251190Sdteske	                        \"\$title\"  \
92251190Sdteske	                        \"\$btitle\" \
93251190Sdteske	                        \"\$prompt\" \
94251264Sdteske	                        \"\$hline\"  \
95251190Sdteske	                        $continent_menu_list
96238438Sdteske
97251244Sdteske	# Obtain default-item from previously stored selection
98251244Sdteske	f_dialog_default_fetch defaultitem
99251244Sdteske
100251236Sdteske	local menu_choice
101251236Sdteske	menu_choice=$( eval $DIALOG \
102251244Sdteske		--title \"\$title\"              \
103251244Sdteske		--backtitle \"\$btitle\"         \
104251264Sdteske		--hline \"\$hline\"              \
105251244Sdteske		--ok-label \"\$msg_ok\"          \
106251244Sdteske		--cancel-label \"\$msg_cancel\"  \
107251244Sdteske		--default-item \"\$defaultitem\" \
108251244Sdteske		--menu \"\$prompt\"              \
109251244Sdteske		$height $width $rows             \
110251244Sdteske		$continent_menu_list             \
111240768Sdteske		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
112240768Sdteske	)
113240768Sdteske	local retval=$?
114251236Sdteske	f_dialog_data_sanitize menu_choice
115251236Sdteske	f_dialog_menutag_store "$menu_choice"
116251244Sdteske	f_dialog_default_store "$menu_choice"
117240768Sdteske	return $retval
118238438Sdteske}
119238438Sdteske
120238438Sdteske############################################################ MAIN
121238438Sdteske
122274394Sdteske# Skip initial question regarding UTC v. Wall-Clock time if run in VM
123274394Sdteske[ "$( sysctl -n kern.vm_guest 2> /dev/null )" = "none" ] || SKIPUTC=1
124274394Sdteske
125238438Sdteske# Incorporate rc-file if it exists
126238438Sdteske[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
127238438Sdteske
128238438Sdteske#
129238438Sdteske# Process command-line arguments
130238438Sdteske#
131250633Sdteskewhile getopts C:ehnrsv$GETOPTS_STDARGS flag; do
132238438Sdteske	case "$flag" in
133252178Sdteske	C) CHROOTENV="$OPTARG" ;;
134252178Sdteske	e) TZ_OR_FAIL=1 ;;
135252178Sdteske	n) REALLYDOIT= ;;
136238438Sdteske	r) REINSTALL=1
137252178Sdteske	   USEDIALOG= ;;
138252178Sdteske	s) SKIPUTC=1 ;;
139252178Sdteske	v) VERBOSE=1 ;;
140252178Sdteske	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
141238438Sdteske	esac
142238438Sdteskedone
143238438Sdteskeshift $(( $OPTIND - 1 ))
144238438Sdteske
145238438Sdteske#
146238438Sdteske# Initialize
147238438Sdteske#
148238438Sdteskef_dialog_title "$msg_time_zone"
149238438Sdteskef_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
150238438Sdteskef_mustberoot_init
151238438Sdteske
152238438Sdteske#
153238438Sdteske# Process `-C chroot_directory' command-line argument
154238438Sdteske#
155238438Sdteskeif [ "$CHROOTENV" ]; then
156238438Sdteske	_PATH_ZONETAB="$CHROOTENV$_PATH_ZONETAB"
157238438Sdteske	_PATH_ISO3166="$CHROOTENV$_PATH_ISO3166"
158238438Sdteske	_PATH_ZONEINFO="$CHROOTENV$_PATH_ZONEINFO"
159238438Sdteske	_PATH_LOCALTIME="$CHROOTENV$_PATH_LOCALTIME"
160238438Sdteske	_PATH_DB="$CHROOTENV$_PATH_DB"
161238438Sdteske	_PATH_WALL_CMOS_CLOCK="$CHROOTENV$_PATH_WALL_CMOS_CLOCK"
162238438Sdteskefi
163238438Sdteske
164238438Sdteske#
165238438Sdteske# Process `-r' command-line option
166238438Sdteske#
167238438Sdteskeif [ "$REINSTALL" ]; then
168238438Sdteske	[ -f "$_PATH_DB" -a -r "$_PATH_DB" ] ||
169238438Sdteske		f_die 1 "$msg_cannot_open_for_reading" "$_PATH_DB"
170259054Sdteske	f_eval_catch -dk zoneinfo "$0" cat 'cat "%s"' "$_PATH_DB" ||
171238438Sdteske		f_die 1 "$msg_error_reading" "$_PATH_DB"
172238438Sdteske	[ "$zoneinfo" ] ||
173238438Sdteske		f_die 1 "$msg_unable_to_determine_name_from_db" "$_PATH_DB"
174238438Sdteske	f_install_zoneinfo "$zoneinfo"
175238438Sdteske	exit $?
176238438Sdteskefi
177238438Sdteske
178238438Sdteske#
179238438Sdteske# If the arguments on the command-line do not specify a file,
180238438Sdteske# then interpret it as a zoneinfo name
181238438Sdteske#
182238438Sdteskeif [ $# -ge 1 ]; then
183238438Sdteske	zoneinfo="$1"
184238438Sdteske
185238438Sdteske	if [ ! -f "$zoneinfo" ]; then
186238438Sdteske		USEDIALOG=
187238438Sdteske		f_install_zoneinfo "$zoneinfo"
188238438Sdteske		exit $?
189238438Sdteske	fi
190238438Sdteske
191238438Sdteske	# FALLTHROUGH
192238438Sdteskefi
193238438Sdteske
194238438Sdteske#
195238438Sdteske# Process the UTC option
196238438Sdteske#
197238438Sdteskeif [ "$_PATH_WALL_CMOS_CLOCK" -a ! "$SKIPUTC" ]; then
198238438Sdteske	f_dialog_title "$msg_select_local_or_utc"
199238438Sdteske	title="$DIALOG_TITLE"
200238438Sdteske	btitle="$DIALOG_BACKTITLE"
201238438Sdteske	f_dialog_title_restore
202238438Sdteske	msg="$msg_is_machine_clock_utc"
203238438Sdteske
204238438Sdteske	if [ "$USE_XDIALOG" ]; then
205238438Sdteske		defaultno="default-no"
206238438Sdteske		height=10 width=77
207238438Sdteske	else
208238438Sdteske		defaultno="defaultno"
209238438Sdteske		height=7 width=73
210238438Sdteske	fi
211238438Sdteske
212238438Sdteske	if [ "$USE_XDIALOG" ]; then
213238438Sdteske		$DIALOG \
214238438Sdteske			--title "$title"         \
215238438Sdteske			--backtitle "$btitle"    \
216238438Sdteske			--$defaultno             \
217238438Sdteske			--ok-label "$msg_yes"    \
218238438Sdteske			--cancel-label "$msg_no" \
219238438Sdteske			--yesno "$msg" $height $width
220238438Sdteske		result=$?
221238438Sdteske	else
222238438Sdteske		$DIALOG \
223238438Sdteske			--title "$title"       \
224238438Sdteske			--backtitle "$btitle"  \
225238438Sdteske			--$defaultno           \
226238438Sdteske			--yes-label "$msg_yes" \
227238438Sdteske			--no-label "$msg_no"   \
228238438Sdteske			--yesno "$msg" $height $width
229238438Sdteske		result=$?
230238438Sdteske	fi
231238438Sdteske
232256181Sdteske	if [ $result -eq $DIALOG_OK ]; then
233238438Sdteske		# User chose YES
234238438Sdteske		[ "$REALLYDOIT" ] &&
235238438Sdteske			f_quietly rm -f "$_PATH_WALL_CMOS_CLOCK"
236238438Sdteske	else
237238438Sdteske		# User chose NO, pressed ESC (or Ctrl-C), or closed box
238238438Sdteske		[ "$REALLYDOIT" ] &&
239238438Sdteske			( umask 222 && :> "$_PATH_WALL_CMOS_CLOCK" )
240238438Sdteske	fi
241238438Sdteskefi
242238438Sdteske
243238438Sdteske#
244238438Sdteske# Process optional default zone argument
245238438Sdteske#
246238438Sdteskeif [ $# -ge 1 ]; then
247238438Sdteske	default="$1"
248238438Sdteske
249238438Sdteske	f_dialog_title "$msg_default_zone_provided"
250259054Sdteske	f_sprintf msg "\n$msg_use_default_zone" "$default"
251251979Sdteske	hline=
252251979Sdteske	f_dialog_yesno "$msg" "$hline"
253251979Sdteske	result=$?
254238438Sdteske	f_dialog_title_restore
255238438Sdteske
256256181Sdteske	if [ $result -eq $DIALOG_OK ]; then
257238438Sdteske		# User chose YES
258238438Sdteske		f_install_zoneinfo_file "$default"
259238438Sdteske		result=$?
260238438Sdteske		[ ! "$USE_XDIALOG" ] && f_dialog_clear
261238438Sdteske		exit $result
262238438Sdteske	fi
263238438Sdteske
264238438Sdteske	[ ! "$USE_XDIALOG" ] && f_dialog_clear
265238438Sdteskefi
266238438Sdteske
267238438Sdteske#
268238438Sdteske# Override the user-supplied umask
269238438Sdteske#
270238438Sdteskeumask 022
271238438Sdteske
272238438Sdteske#
273238438Sdteske# Read databases and perform initialization
274238438Sdteske#
275238438Sdteskef_read_iso3166_table # creates $COUNTRIES and $country_*_name
276238438Sdteskef_read_zones         # creates $country_*_{descr,cont,filename}
277238438Sdteskef_sort_countries     # sorts the countries listed for each continent
278238438Sdteskef_make_menus         # creates $continent_menu_list and $continent_*_menu_list
279238438Sdteske
280238438Sdteske#
281238438Sdteske# Launch application main menu
282238438Sdteske#
283278489Sdteskedefaultctry=
284278489Sdteskedefaultzone=
285238438SdteskeNEED_CONTINENT=1
286238438SdteskeNEED_COUNTRY=1
287238438Sdteskewhile :; do
288238438Sdteske	if [ "$NEED_CONTINENT" ]; then
289238438Sdteske		dialog_menu_main # prompt the user to select a continent/ocean
290238438Sdteske		retval=$?
291251236Sdteske		f_dialog_menutag_fetch mtag
292238438Sdteske
293256181Sdteske		if [ $retval -ne $DIALOG_OK ]; then
294238438Sdteske			[ "$TZ_OR_FAIL" ] && f_die
295238438Sdteske			exit $SUCCESS
296238438Sdteske		fi
297238438Sdteske
298238438Sdteske		NEED_CONTINENT=
299238438Sdteske
300238438Sdteske		continent=$( eval f_dialog_menutag2item \"\$mtag\" \
301238438Sdteske		                  	$continent_menu_list )
302278489Sdteske		f_find_continent "$continent" cont
303278489Sdteske		f_continent $cont title cont_title
304278489Sdteske		f_continent $cont nitems nitems
305278489Sdteske		f_OCEANP $cont isocean
306238438Sdteske	fi
307238438Sdteske
308238438Sdteske	if [ "$NEED_COUNTRY" ]; then
309238438Sdteske		if [ "$cont_title" = "$continent_utc_title" ]; then
310238438Sdteske			if f_set_zone_utc; then
311238438Sdteske				break
312238438Sdteske			else
313238438Sdteske				NEED_CONTINENT=1
314238438Sdteske				continue
315238438Sdteske			fi
316238438Sdteske		fi
317238438Sdteske
318238438Sdteske		#
319238438Sdteske		# Short cut -- if there's only one country, don't post a menu.
320238438Sdteske		#
321238438Sdteske		if [ $nitems -eq 1 ]; then
322238438Sdteske			tag=1
323238438Sdteske		else
324238438Sdteske			#
325238438Sdteske			# It's amazing how much good grammar really matters...
326238438Sdteske			#
327238438Sdteske			if [ ! "$isocean" ]; then
328259054Sdteske				f_sprintf title "$msg_country_title" \
329259054Sdteske				                "$cont_title"
330238438Sdteske				f_dialog_title "$title"
331238438Sdteske				title="$DIALOG_TITLE"
332238438Sdteske				btitle="$DIALOG_BACKTITLE"
333238438Sdteske				f_dialog_title_restore
334238438Sdteske				prompt="$msg_select_country"
335238438Sdteske			else
336259054Sdteske				f_sprintf title "$msg_island_and_group_title" \
337259054Sdteske				                "$cont_title"
338238438Sdteske				f_dialog_title "$title"
339238438Sdteske				title="$DIALOG_TITLE"
340238438Sdteske				btitle="$DIALOG_BACKTITLE"
341238438Sdteske				f_dialog_title_restore
342238438Sdteske				prompt="$msg_select_island_or_group"
343238438Sdteske			fi
344238438Sdteske
345238438Sdteske			#
346238438Sdteske			# Calculate size of menu
347238438Sdteske			#
348278489Sdteske			f_continent $cont menu_list menu_list
349251190Sdteske			eval f_dialog_menu_size height width rows \
350251190Sdteske			                        \"\$title\"  \
351251190Sdteske			                        \"\$btitle\" \
352251190Sdteske			                        \"\$prompt\" \
353251190Sdteske			                        \"\"         \
354251190Sdteske			                        $menu_list
355238438Sdteske
356238438Sdteske			#
357238438Sdteske			# Launch the country selection menu
358238438Sdteske			#
359251236Sdteske			tag=$( eval $DIALOG \
360249751Sdteske				--title \"\$title\"              \
361249751Sdteske				--backtitle \"\$btitle\"         \
362249751Sdteske				--ok-label \"\$msg_ok\"          \
363249751Sdteske				--cancel-label \"\$msg_cancel\"  \
364249751Sdteske				--default-item \"\$defaultctry\" \
365251190Sdteske				--menu \"\$prompt\"              \
366251190Sdteske				$height $width $rows             \
367249751Sdteske				$menu_list                       \
368240768Sdteske				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
369240768Sdteske			)
370238438Sdteske			retval=$?
371251236Sdteske			f_dialog_data_sanitize tag
372249751Sdteske			defaultctry="$tag"
373238438Sdteske
374256181Sdteske			if [ $retval -ne $DIALOG_OK ]; then
375238438Sdteske				NEED_CONTINENT=1
376238438Sdteske				continue # back to main menu
377238438Sdteske			fi
378238438Sdteske		fi
379238438Sdteske
380238438Sdteske		# Get the country code from the user's selection 
381278489Sdteske		f_continent $cont tlc_$tag tlc
382238438Sdteske
383238438Sdteske		NEED_COUNTRY=
384238438Sdteske	fi
385238438Sdteske
386238438Sdteske	#
387238438Sdteske	# If the selection has only one zone (nzones == -1),
388238438Sdteske	# just set it.
389238438Sdteske	#
390278489Sdteske	f_country $tlc nzones nzones
391238438Sdteske	if [ $nzones -lt 0 ]; then
392278489Sdteske		f_country $tlc cont real_cont
393278489Sdteske		f_continent $real_cont name real_continent
394278489Sdteske		f_country $tlc name name
395278489Sdteske		f_country $tlc filename filename
396238438Sdteske
397238438Sdteske		if ! f_confirm_zone "$real_continent/$filename"; then
398238438Sdteske			[ $nitems -eq 1 ] && NEED_CONTINENT=1
399238438Sdteske			NEED_COUNTRY=1
400238438Sdteske			continue
401238438Sdteske		fi
402238438Sdteske	else
403278489Sdteske		f_country $tlc name name
404278489Sdteske		f_sprintf title "$msg_country_time_zones" "$name"
405238438Sdteske		f_dialog_title "$title"
406259054Sdteske		title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
407238438Sdteske		f_dialog_title_restore
408238438Sdteske		prompt="$msg_select_zone"
409278489Sdteske		f_country $tlc menu_list menu_list
410251190Sdteske		eval f_dialog_menu_size height width rows \
411251190Sdteske			\"\$title\"  \"\$btitle\" \"\$prompt\" \"\" $menu_list
412238438Sdteske
413238438Sdteske		#
414238438Sdteske		# Launch the zone selection menu
415238438Sdteske		# NOTE: This is as deep as we go
416238438Sdteske		#
417251236Sdteske		n=$( eval $DIALOG \
418249751Sdteske			--title \"\$title\"              \
419249751Sdteske			--backtitle \"\$btitle\"         \
420249751Sdteske			--ok-label \"\$msg_ok\"          \
421249751Sdteske			--cancel-label \"\$msg_cancel\"  \
422249751Sdteske			--default-item \"\$defaultzone\" \
423251190Sdteske			--menu \"\$prompt\"              \
424251190Sdteske			$height $width $rows             \
425249751Sdteske			$menu_list                       \
426240768Sdteske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
427240768Sdteske		)
428238438Sdteske		retval=$?
429251236Sdteske		f_dialog_data_sanitize n
430249751Sdteske		defaultzone="$n"
431238438Sdteske
432256181Sdteske		if [ $retval -ne $DIALOG_OK ]; then
433238438Sdteske			[ $nitems -eq 1 ] && NEED_CONTINENT=1
434238438Sdteske			NEED_COUNTRY=1
435238438Sdteske			continue
436238438Sdteske		fi
437238438Sdteske
438278489Sdteske		f_country $tlc cont_$n real_cont
439278489Sdteske		f_continent $real_cont name real_continent
440278489Sdteske		f_country $tlc name name
441278489Sdteske		f_country $tlc filename_$n filename
442238438Sdteske
443238438Sdteske		f_confirm_zone "$real_continent/$filename" || continue
444238438Sdteske	fi
445238438Sdteske
446256181Sdteske	[ $retval -eq $DIALOG_OK ] || continue # back to main menu
447238438Sdteske
448238438Sdteske	if ! f_install_zoneinfo "$real_continent/$filename"; then
449238438Sdteske		[ $nzones -lt 0 ] && NEED_COUNTRY=1
450238438Sdteske	else
451238438Sdteske		break
452238438Sdteske	fi
453238438Sdteskedone
454238438Sdteske
455238438Sdteske################################################################################
456238438Sdteske# END
457238438Sdteske################################################################################
458