timezone revision 251979
1238438Sdteske#!/bin/sh
2238438Sdteske#-
3249746Sdteske# Copyright (c) 2011-2013 Devin Teske
4238438Sdteske# 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
16238438Sdteske# 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
20238438Sdteske# DAMAGES (INLUDING, 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: head/usr.sbin/bsdconfig/timezone/timezone 251979 2013-06-19 00:09:21Z dteske $
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
46243112Sdteskeipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
47238438Sdteske[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
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
65238438SdteskeSKIPUTC=
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
122238438Sdteske# Incorporate rc-file if it exists
123238438Sdteske[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
124238438Sdteske
125238438Sdteske#
126238438Sdteske# Process command-line arguments
127238438Sdteske#
128250633Sdteskewhile getopts C:ehnrsv$GETOPTS_STDARGS flag; do
129238438Sdteske	case "$flag" in
130238438Sdteske	C) CHROOTENV="$OPTARG";;
131238438Sdteske	e) TZ_OR_FAIL=1;;
132238438Sdteske	n) REALLYDOIT=;;
133238438Sdteske	r) REINSTALL=1
134238438Sdteske	   USEDIALOG=;;
135238438Sdteske	s) SKIPUTC=1;;
136238438Sdteske	v) VERBOSE=1;;
137238438Sdteske	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
138238438Sdteske	esac
139238438Sdteskedone
140238438Sdteskeshift $(( $OPTIND - 1 ))
141238438Sdteske
142238438Sdteske#
143238438Sdteske# Initialize
144238438Sdteske#
145238438Sdteskef_dialog_title "$msg_time_zone"
146238438Sdteskef_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
147238438Sdteskef_mustberoot_init
148238438Sdteske
149238438Sdteske#
150238438Sdteske# Process `-C chroot_directory' command-line argument
151238438Sdteske#
152238438Sdteskeif [ "$CHROOTENV" ]; then
153238438Sdteske	_PATH_ZONETAB="$CHROOTENV$_PATH_ZONETAB"
154238438Sdteske	_PATH_ISO3166="$CHROOTENV$_PATH_ISO3166"
155238438Sdteske	_PATH_ZONEINFO="$CHROOTENV$_PATH_ZONEINFO"
156238438Sdteske	_PATH_LOCALTIME="$CHROOTENV$_PATH_LOCALTIME"
157238438Sdteske	_PATH_DB="$CHROOTENV$_PATH_DB"
158238438Sdteske	_PATH_WALL_CMOS_CLOCK="$CHROOTENV$_PATH_WALL_CMOS_CLOCK"
159238438Sdteskefi
160238438Sdteske
161238438Sdteske#
162238438Sdteske# Process `-r' command-line option
163238438Sdteske#
164238438Sdteskeif [ "$REINSTALL" ]; then
165238438Sdteske	[ -f "$_PATH_DB" -a -r "$_PATH_DB" ] ||
166238438Sdteske		f_die 1 "$msg_cannot_open_for_reading" "$_PATH_DB"
167238438Sdteske	zoneinfo=$( cat "$_PATH_DB" ) ||
168238438Sdteske		f_die 1 "$msg_error_reading" "$_PATH_DB"
169238438Sdteske	[ "$zoneinfo" ] ||
170238438Sdteske		f_die 1 "$msg_unable_to_determine_name_from_db" "$_PATH_DB"
171238438Sdteske	f_install_zoneinfo "$zoneinfo"
172238438Sdteske	exit $?
173238438Sdteskefi
174238438Sdteske
175238438Sdteske#
176238438Sdteske# If the arguments on the command-line do not specify a file,
177238438Sdteske# then interpret it as a zoneinfo name
178238438Sdteske#
179238438Sdteskeif [ $# -ge 1 ]; then
180238438Sdteske	zoneinfo="$1"
181238438Sdteske
182238438Sdteske	if [ ! -f "$zoneinfo" ]; then
183238438Sdteske		USEDIALOG=
184238438Sdteske		f_install_zoneinfo "$zoneinfo"
185238438Sdteske		exit $?
186238438Sdteske	fi
187238438Sdteske
188238438Sdteske	# FALLTHROUGH
189238438Sdteskefi
190238438Sdteske
191238438Sdteske#
192238438Sdteske# Process the UTC option
193238438Sdteske#
194238438Sdteskeif [ "$_PATH_WALL_CMOS_CLOCK" -a ! "$SKIPUTC" ]; then
195238438Sdteske	f_dialog_title "$msg_select_local_or_utc"
196238438Sdteske	title="$DIALOG_TITLE"
197238438Sdteske	btitle="$DIALOG_BACKTITLE"
198238438Sdteske	f_dialog_title_restore
199238438Sdteske	msg="$msg_is_machine_clock_utc"
200238438Sdteske
201238438Sdteske	if [ "$USE_XDIALOG" ]; then
202238438Sdteske		defaultno="default-no"
203238438Sdteske		height=10 width=77
204238438Sdteske	else
205238438Sdteske		defaultno="defaultno"
206238438Sdteske		height=7 width=73
207238438Sdteske	fi
208238438Sdteske
209238438Sdteske	if [ "$USE_XDIALOG" ]; then
210238438Sdteske		$DIALOG \
211238438Sdteske			--title "$title"         \
212238438Sdteske			--backtitle "$btitle"    \
213238438Sdteske			--$defaultno             \
214238438Sdteske			--ok-label "$msg_yes"    \
215238438Sdteske			--cancel-label "$msg_no" \
216238438Sdteske			--yesno "$msg" $height $width
217238438Sdteske		result=$?
218238438Sdteske	else
219238438Sdteske		$DIALOG \
220238438Sdteske			--title "$title"       \
221238438Sdteske			--backtitle "$btitle"  \
222238438Sdteske			--$defaultno           \
223238438Sdteske			--yes-label "$msg_yes" \
224238438Sdteske			--no-label "$msg_no"   \
225238438Sdteske			--yesno "$msg" $height $width
226238438Sdteske		result=$?
227238438Sdteske	fi
228238438Sdteske
229238438Sdteske	if [ $result -eq 0 ]; then
230238438Sdteske		# User chose YES
231238438Sdteske		[ "$REALLYDOIT" ] &&
232238438Sdteske			f_quietly rm -f "$_PATH_WALL_CMOS_CLOCK"
233238438Sdteske	else
234238438Sdteske		# User chose NO, pressed ESC (or Ctrl-C), or closed box
235238438Sdteske		[ "$REALLYDOIT" ] &&
236238438Sdteske			( umask 222 && :> "$_PATH_WALL_CMOS_CLOCK" )
237238438Sdteske	fi
238238438Sdteskefi
239238438Sdteske
240238438Sdteske#
241238438Sdteske# Process optional default zone argument
242238438Sdteske#
243238438Sdteskeif [ $# -ge 1 ]; then
244238438Sdteske	default="$1"
245238438Sdteske
246238438Sdteske	f_dialog_title "$msg_default_zone_provided"
247251979Sdteske	msg=$( printf "\n$msg_use_default_zone" "$default" )
248251979Sdteske	hline=
249251979Sdteske	f_dialog_yesno "$msg" "$hline"
250251979Sdteske	result=$?
251238438Sdteske	f_dialog_title_restore
252238438Sdteske
253238438Sdteske	if [ $result -eq 0 ]; then
254238438Sdteske		# User chose YES
255238438Sdteske		f_install_zoneinfo_file "$default"
256238438Sdteske		result=$?
257238438Sdteske		[ ! "$USE_XDIALOG" ] && f_dialog_clear
258238438Sdteske		exit $result
259238438Sdteske	fi
260238438Sdteske
261238438Sdteske	[ ! "$USE_XDIALOG" ] && f_dialog_clear
262238438Sdteskefi
263238438Sdteske
264238438Sdteske#
265238438Sdteske# Override the user-supplied umask
266238438Sdteske#
267238438Sdteskeumask 022
268238438Sdteske
269238438Sdteske#
270238438Sdteske# Read databases and perform initialization
271238438Sdteske#
272238438Sdteskef_read_iso3166_table # creates $COUNTRIES and $country_*_name
273238438Sdteskef_read_zones         # creates $country_*_{descr,cont,filename}
274238438Sdteskef_sort_countries     # sorts the countries listed for each continent
275238438Sdteskef_make_menus         # creates $continent_menu_list and $continent_*_menu_list
276238438Sdteske
277238438Sdteske#
278238438Sdteske# Launch application main menu
279238438Sdteske#
280249751Sdteskedefaultctry=""
281249751Sdteskedefaultzone=""
282238438SdteskeNEED_CONTINENT=1
283238438SdteskeNEED_COUNTRY=1
284238438Sdteskewhile :; do
285238438Sdteske	if [ "$NEED_CONTINENT" ]; then
286238438Sdteske		dialog_menu_main # prompt the user to select a continent/ocean
287238438Sdteske		retval=$?
288251236Sdteske		f_dialog_menutag_fetch mtag
289238438Sdteske
290238438Sdteske		if [ $retval -ne 0 ]; then
291238438Sdteske			[ "$TZ_OR_FAIL" ] && f_die
292238438Sdteske			exit $SUCCESS
293238438Sdteske		fi
294238438Sdteske
295238438Sdteske		NEED_CONTINENT=
296238438Sdteske
297238438Sdteske		continent=$( eval f_dialog_menutag2item \"\$mtag\" \
298238438Sdteske		                  	$continent_menu_list )
299238438Sdteske		cont=$( f_find_continent "$continent" )
300238438Sdteske		cont_title=$( f_continent $cont title )
301238438Sdteske		nitems=$( f_continent $cont nitems )
302238438Sdteske		isocean=$( f_OCEANP $cont )
303238438Sdteske	fi
304238438Sdteske
305238438Sdteske	if [ "$NEED_COUNTRY" ]; then
306238438Sdteske		if [ "$cont_title" = "$continent_utc_title" ]; then
307238438Sdteske			if f_set_zone_utc; then
308238438Sdteske				break
309238438Sdteske			else
310238438Sdteske				NEED_CONTINENT=1
311238438Sdteske				continue
312238438Sdteske			fi
313238438Sdteske		fi
314238438Sdteske
315238438Sdteske		#
316238438Sdteske		# Short cut -- if there's only one country, don't post a menu.
317238438Sdteske		#
318238438Sdteske		if [ $nitems -eq 1 ]; then
319238438Sdteske			tag=1
320238438Sdteske		else
321238438Sdteske			#
322238438Sdteske			# It's amazing how much good grammar really matters...
323238438Sdteske			#
324238438Sdteske			if [ ! "$isocean" ]; then
325238438Sdteske				title=$( printf "$msg_country_title" \
326238438Sdteske				                "$cont_title" )
327238438Sdteske				f_dialog_title "$title"
328238438Sdteske				title="$DIALOG_TITLE"
329238438Sdteske				btitle="$DIALOG_BACKTITLE"
330238438Sdteske				f_dialog_title_restore
331238438Sdteske				prompt="$msg_select_country"
332238438Sdteske			else
333238438Sdteske				title=$( printf "$msg_island_and_group_title" \
334238438Sdteske				                "$cont_title" )
335238438Sdteske				f_dialog_title "$title"
336238438Sdteske				title="$DIALOG_TITLE"
337238438Sdteske				btitle="$DIALOG_BACKTITLE"
338238438Sdteske				f_dialog_title_restore
339238438Sdteske				prompt="$msg_select_island_or_group"
340238438Sdteske			fi
341238438Sdteske
342238438Sdteske			#
343238438Sdteske			# Calculate size of menu
344238438Sdteske			#
345238438Sdteske			menu_list=$( f_continent $cont menu_list )
346251190Sdteske			eval f_dialog_menu_size height width rows \
347251190Sdteske			                        \"\$title\"  \
348251190Sdteske			                        \"\$btitle\" \
349251190Sdteske			                        \"\$prompt\" \
350251190Sdteske			                        \"\"         \
351251190Sdteske			                        $menu_list
352238438Sdteske
353238438Sdteske			#
354238438Sdteske			# Launch the country selection menu
355238438Sdteske			#
356251236Sdteske			tag=$( eval $DIALOG \
357249751Sdteske				--title \"\$title\"              \
358249751Sdteske				--backtitle \"\$btitle\"         \
359249751Sdteske				--ok-label \"\$msg_ok\"          \
360249751Sdteske				--cancel-label \"\$msg_cancel\"  \
361249751Sdteske				--default-item \"\$defaultctry\" \
362251190Sdteske				--menu \"\$prompt\"              \
363251190Sdteske				$height $width $rows             \
364249751Sdteske				$menu_list                       \
365240768Sdteske				2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
366240768Sdteske			)
367238438Sdteske			retval=$?
368251236Sdteske			f_dialog_data_sanitize tag
369249751Sdteske			defaultctry="$tag"
370238438Sdteske
371238438Sdteske			if [ $retval -ne 0 ]; then
372238438Sdteske				NEED_CONTINENT=1
373238438Sdteske				continue # back to main menu
374238438Sdteske			fi
375238438Sdteske		fi
376238438Sdteske
377238438Sdteske		# Get the country code from the user's selection 
378238438Sdteske		tlc=$( f_continent $cont tlc_$tag )
379238438Sdteske
380238438Sdteske		NEED_COUNTRY=
381238438Sdteske	fi
382238438Sdteske
383238438Sdteske	#
384238438Sdteske	# If the selection has only one zone (nzones == -1),
385238438Sdteske	# just set it.
386238438Sdteske	#
387238438Sdteske	nzones=$( f_country $tlc nzones )
388238438Sdteske	if [ $nzones -lt 0 ]; then
389238438Sdteske		real_cont=$( f_country $tlc cont )
390238438Sdteske		real_continent=$( f_continent $real_cont name )
391238438Sdteske		name=$( f_country $tlc name )
392238438Sdteske		filename=$( f_country $tlc filename )
393238438Sdteske
394238438Sdteske		if ! f_confirm_zone "$real_continent/$filename"; then
395238438Sdteske			[ $nitems -eq 1 ] && NEED_CONTINENT=1
396238438Sdteske			NEED_COUNTRY=1
397238438Sdteske			continue
398238438Sdteske		fi
399238438Sdteske	else
400238438Sdteske		title=$( printf "$msg_country_time_zones" \
401238438Sdteske		                "$( f_country $tlc name )" )
402238438Sdteske		f_dialog_title "$title"
403238438Sdteske		title="$DIALOG_TITLE"
404238438Sdteske		btitle="$DIALOG_BACKTITLE"
405238438Sdteske		f_dialog_title_restore
406238438Sdteske		prompt="$msg_select_zone"
407238438Sdteske		menu_list=$( f_country $tlc menu_list )
408251190Sdteske		eval f_dialog_menu_size height width rows \
409251190Sdteske			\"\$title\"  \"\$btitle\" \"\$prompt\" \"\" $menu_list
410238438Sdteske
411238438Sdteske		#
412238438Sdteske		# Launch the zone selection menu
413238438Sdteske		# NOTE: This is as deep as we go
414238438Sdteske		#
415251236Sdteske		n=$( eval $DIALOG \
416249751Sdteske			--title \"\$title\"              \
417249751Sdteske			--backtitle \"\$btitle\"         \
418249751Sdteske			--ok-label \"\$msg_ok\"          \
419249751Sdteske			--cancel-label \"\$msg_cancel\"  \
420249751Sdteske			--default-item \"\$defaultzone\" \
421251190Sdteske			--menu \"\$prompt\"              \
422251190Sdteske			$height $width $rows             \
423249751Sdteske			$menu_list                       \
424240768Sdteske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
425240768Sdteske		)
426238438Sdteske		retval=$?
427251236Sdteske		f_dialog_data_sanitize n
428249751Sdteske		defaultzone="$n"
429238438Sdteske
430238438Sdteske		if [ $retval -ne 0 ]; then
431238438Sdteske			[ $nitems -eq 1 ] && NEED_CONTINENT=1
432238438Sdteske			NEED_COUNTRY=1
433238438Sdteske			continue
434238438Sdteske		fi
435238438Sdteske
436238438Sdteske		real_cont=$( f_country $tlc cont_$n )
437238438Sdteske		real_continent=$( f_continent $real_cont name )
438238438Sdteske		name=$( f_country $tlc name )
439238438Sdteske		filename=$( f_country $tlc filename_$n )
440238438Sdteske
441238438Sdteske		f_confirm_zone "$real_continent/$filename" || continue
442238438Sdteske	fi
443238438Sdteske
444238438Sdteske	[ $retval -eq 0 ] || continue # back to main menu
445238438Sdteske
446238438Sdteske	if ! f_install_zoneinfo "$real_continent/$filename"; then
447238438Sdteske		[ $nzones -lt 0 ] && NEED_COUNTRY=1
448238438Sdteske	else
449238438Sdteske		break
450238438Sdteske	fi
451238438Sdteskedone
452238438Sdteske
453238438Sdteske################################################################################
454238438Sdteske# END
455238438Sdteske################################################################################
456