intl/icu/source/tools/tzcode/tzselect.ksh

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 #! /bin/ksh
michael@0 2
michael@0 3 # '@(#)tzselect.ksh 8.1'
michael@0 4
michael@0 5 # Ask the user about the time zone, and output the resulting TZ value to stdout.
michael@0 6 # Interact with the user via stderr and stdin.
michael@0 7
michael@0 8 # Contributed by Paul Eggert.
michael@0 9
michael@0 10 # Porting notes:
michael@0 11 #
michael@0 12 # This script requires several features of the Korn shell.
michael@0 13 # If your host lacks the Korn shell,
michael@0 14 # you can use either of the following free programs instead:
michael@0 15 #
michael@0 16 # <a href=ftp://ftp.gnu.org/pub/gnu/>
michael@0 17 # Bourne-Again shell (bash)
michael@0 18 # </a>
michael@0 19 #
michael@0 20 # <a href=ftp://ftp.cs.mun.ca/pub/pdksh/pdksh.tar.gz>
michael@0 21 # Public domain ksh
michael@0 22 # </a>
michael@0 23 #
michael@0 24 # This script also uses several features of modern awk programs.
michael@0 25 # If your host lacks awk, or has an old awk that does not conform to Posix.2,
michael@0 26 # you can use either of the following free programs instead:
michael@0 27 #
michael@0 28 # <a href=ftp://ftp.gnu.org/pub/gnu/>
michael@0 29 # GNU awk (gawk)
michael@0 30 # </a>
michael@0 31 #
michael@0 32 # <a href=ftp://ftp.whidbey.net/pub/brennan/>
michael@0 33 # mawk
michael@0 34 # </a>
michael@0 35
michael@0 36
michael@0 37 # Specify default values for environment variables if they are unset.
michael@0 38 : ${AWK=awk}
michael@0 39 : ${TZDIR=$(pwd)}
michael@0 40
michael@0 41 # Check for awk Posix compliance.
michael@0 42 ($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
michael@0 43 [ $? = 123 ] || {
michael@0 44 echo >&2 "$0: Sorry, your \`$AWK' program is not Posix compatible."
michael@0 45 exit 1
michael@0 46 }
michael@0 47
michael@0 48 # Make sure the tables are readable.
michael@0 49 TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
michael@0 50 TZ_ZONE_TABLE=$TZDIR/zone.tab
michael@0 51 for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE
michael@0 52 do
michael@0 53 <$f || {
michael@0 54 echo >&2 "$0: time zone files are not set up correctly"
michael@0 55 exit 1
michael@0 56 }
michael@0 57 done
michael@0 58
michael@0 59 newline='
michael@0 60 '
michael@0 61 IFS=$newline
michael@0 62
michael@0 63
michael@0 64 # Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout.
michael@0 65 case $(echo 1 | (select x in x; do break; done) 2>/dev/null) in
michael@0 66 ?*) PS3=
michael@0 67 esac
michael@0 68
michael@0 69
michael@0 70 # Begin the main loop. We come back here if the user wants to retry.
michael@0 71 while
michael@0 72
michael@0 73 echo >&2 'Please identify a location' \
michael@0 74 'so that time zone rules can be set correctly.'
michael@0 75
michael@0 76 continent=
michael@0 77 country=
michael@0 78 region=
michael@0 79
michael@0 80
michael@0 81 # Ask the user for continent or ocean.
michael@0 82
michael@0 83 echo >&2 'Please select a continent or ocean.'
michael@0 84
michael@0 85 select continent in \
michael@0 86 Africa \
michael@0 87 Americas \
michael@0 88 Antarctica \
michael@0 89 'Arctic Ocean' \
michael@0 90 Asia \
michael@0 91 'Atlantic Ocean' \
michael@0 92 Australia \
michael@0 93 Europe \
michael@0 94 'Indian Ocean' \
michael@0 95 'Pacific Ocean' \
michael@0 96 'none - I want to specify the time zone using the Posix TZ format.'
michael@0 97 do
michael@0 98 case $continent in
michael@0 99 '')
michael@0 100 echo >&2 'Please enter a number in range.';;
michael@0 101 ?*)
michael@0 102 case $continent in
michael@0 103 Americas) continent=America;;
michael@0 104 *' '*) continent=$(expr "$continent" : '\([^ ]*\)')
michael@0 105 esac
michael@0 106 break
michael@0 107 esac
michael@0 108 done
michael@0 109 case $continent in
michael@0 110 '')
michael@0 111 exit 1;;
michael@0 112 none)
michael@0 113 # Ask the user for a Posix TZ string. Check that it conforms.
michael@0 114 while
michael@0 115 echo >&2 'Please enter the desired value' \
michael@0 116 'of the TZ environment variable.'
michael@0 117 echo >&2 'For example, GST-10 is a zone named GST' \
michael@0 118 'that is 10 hours ahead (east) of UTC.'
michael@0 119 read TZ
michael@0 120 $AWK -v TZ="$TZ" 'BEGIN {
michael@0 121 tzname = "[^-+,0-9][^-+,0-9][^-+,0-9]+"
michael@0 122 time = "[0-2]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?"
michael@0 123 offset = "[-+]?" time
michael@0 124 date = "(J?[0-9]+|M[0-9]+\.[0-9]+\.[0-9]+)"
michael@0 125 datetime = "," date "(/" time ")?"
michael@0 126 tzpattern = "^(:.*|" tzname offset "(" tzname \
michael@0 127 "(" offset ")?(" datetime datetime ")?)?)$"
michael@0 128 if (TZ ~ tzpattern) exit 1
michael@0 129 exit 0
michael@0 130 }'
michael@0 131 do
michael@0 132 echo >&2 "\`$TZ' is not a conforming" \
michael@0 133 'Posix time zone string.'
michael@0 134 done
michael@0 135 TZ_for_date=$TZ;;
michael@0 136 *)
michael@0 137 # Get list of names of countries in the continent or ocean.
michael@0 138 countries=$($AWK -F'\t' \
michael@0 139 -v continent="$continent" \
michael@0 140 -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
michael@0 141 '
michael@0 142 /^#/ { next }
michael@0 143 $3 ~ ("^" continent "/") {
michael@0 144 if (!cc_seen[$1]++) cc_list[++ccs] = $1
michael@0 145 }
michael@0 146 END {
michael@0 147 while (getline <TZ_COUNTRY_TABLE) {
michael@0 148 if ($0 !~ /^#/) cc_name[$1] = $2
michael@0 149 }
michael@0 150 for (i = 1; i <= ccs; i++) {
michael@0 151 country = cc_list[i]
michael@0 152 if (cc_name[country]) {
michael@0 153 country = cc_name[country]
michael@0 154 }
michael@0 155 print country
michael@0 156 }
michael@0 157 }
michael@0 158 ' <$TZ_ZONE_TABLE | sort -f)
michael@0 159
michael@0 160
michael@0 161 # If there's more than one country, ask the user which one.
michael@0 162 case $countries in
michael@0 163 *"$newline"*)
michael@0 164 echo >&2 'Please select a country.'
michael@0 165 select country in $countries
michael@0 166 do
michael@0 167 case $country in
michael@0 168 '') echo >&2 'Please enter a number in range.';;
michael@0 169 ?*) break
michael@0 170 esac
michael@0 171 done
michael@0 172
michael@0 173 case $country in
michael@0 174 '') exit 1
michael@0 175 esac;;
michael@0 176 *)
michael@0 177 country=$countries
michael@0 178 esac
michael@0 179
michael@0 180
michael@0 181 # Get list of names of time zone rule regions in the country.
michael@0 182 regions=$($AWK -F'\t' \
michael@0 183 -v country="$country" \
michael@0 184 -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
michael@0 185 '
michael@0 186 BEGIN {
michael@0 187 cc = country
michael@0 188 while (getline <TZ_COUNTRY_TABLE) {
michael@0 189 if ($0 !~ /^#/ && country == $2) {
michael@0 190 cc = $1
michael@0 191 break
michael@0 192 }
michael@0 193 }
michael@0 194 }
michael@0 195 $1 == cc { print $4 }
michael@0 196 ' <$TZ_ZONE_TABLE)
michael@0 197
michael@0 198
michael@0 199 # If there's more than one region, ask the user which one.
michael@0 200 case $regions in
michael@0 201 *"$newline"*)
michael@0 202 echo >&2 'Please select one of the following' \
michael@0 203 'time zone regions.'
michael@0 204 select region in $regions
michael@0 205 do
michael@0 206 case $region in
michael@0 207 '') echo >&2 'Please enter a number in range.';;
michael@0 208 ?*) break
michael@0 209 esac
michael@0 210 done
michael@0 211 case $region in
michael@0 212 '') exit 1
michael@0 213 esac;;
michael@0 214 *)
michael@0 215 region=$regions
michael@0 216 esac
michael@0 217
michael@0 218 # Determine TZ from country and region.
michael@0 219 TZ=$($AWK -F'\t' \
michael@0 220 -v country="$country" \
michael@0 221 -v region="$region" \
michael@0 222 -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
michael@0 223 '
michael@0 224 BEGIN {
michael@0 225 cc = country
michael@0 226 while (getline <TZ_COUNTRY_TABLE) {
michael@0 227 if ($0 !~ /^#/ && country == $2) {
michael@0 228 cc = $1
michael@0 229 break
michael@0 230 }
michael@0 231 }
michael@0 232 }
michael@0 233 $1 == cc && $4 == region { print $3 }
michael@0 234 ' <$TZ_ZONE_TABLE)
michael@0 235
michael@0 236 # Make sure the corresponding zoneinfo file exists.
michael@0 237 TZ_for_date=$TZDIR/$TZ
michael@0 238 <$TZ_for_date || {
michael@0 239 echo >&2 "$0: time zone files are not set up correctly"
michael@0 240 exit 1
michael@0 241 }
michael@0 242 esac
michael@0 243
michael@0 244
michael@0 245 # Use the proposed TZ to output the current date relative to UTC.
michael@0 246 # Loop until they agree in seconds.
michael@0 247 # Give up after 8 unsuccessful tries.
michael@0 248
michael@0 249 extra_info=
michael@0 250 for i in 1 2 3 4 5 6 7 8
michael@0 251 do
michael@0 252 TZdate=$(LANG=C TZ="$TZ_for_date" date)
michael@0 253 UTdate=$(LANG=C TZ=UTC0 date)
michael@0 254 TZsec=$(expr "$TZdate" : '.*:\([0-5][0-9]\)')
michael@0 255 UTsec=$(expr "$UTdate" : '.*:\([0-5][0-9]\)')
michael@0 256 case $TZsec in
michael@0 257 $UTsec)
michael@0 258 extra_info="
michael@0 259 Local time is now: $TZdate.
michael@0 260 Universal Time is now: $UTdate."
michael@0 261 break
michael@0 262 esac
michael@0 263 done
michael@0 264
michael@0 265
michael@0 266 # Output TZ info and ask the user to confirm.
michael@0 267
michael@0 268 echo >&2 ""
michael@0 269 echo >&2 "The following information has been given:"
michael@0 270 echo >&2 ""
michael@0 271 case $country+$region in
michael@0 272 ?*+?*) echo >&2 " $country$newline $region";;
michael@0 273 ?*+) echo >&2 " $country";;
michael@0 274 +) echo >&2 " TZ='$TZ'"
michael@0 275 esac
michael@0 276 echo >&2 ""
michael@0 277 echo >&2 "Therefore TZ='$TZ' will be used.$extra_info"
michael@0 278 echo >&2 "Is the above information OK?"
michael@0 279
michael@0 280 ok=
michael@0 281 select ok in Yes No
michael@0 282 do
michael@0 283 case $ok in
michael@0 284 '') echo >&2 'Please enter 1 for Yes, or 2 for No.';;
michael@0 285 ?*) break
michael@0 286 esac
michael@0 287 done
michael@0 288 case $ok in
michael@0 289 '') exit 1;;
michael@0 290 Yes) break
michael@0 291 esac
michael@0 292 do :
michael@0 293 done
michael@0 294
michael@0 295 case $SHELL in
michael@0 296 *csh) file=.login line="setenv TZ '$TZ'";;
michael@0 297 *) file=.profile line="TZ='$TZ'; export TZ"
michael@0 298 esac
michael@0 299
michael@0 300 echo >&2 "
michael@0 301 You can make this change permanent for yourself by appending the line
michael@0 302 $line
michael@0 303 to the file '$file' in your home directory; then log out and log in again.
michael@0 304
michael@0 305 Here is that TZ value again, this time on standard output so that you
michael@0 306 can use the $0 command in shell scripts:"
michael@0 307
michael@0 308 echo "$TZ"

mercurial