Blame timezone/tzselect.ksh

Packit 6c4009
#!/bin/bash
Packit 6c4009
Packit 6c4009
PKGVERSION='(tzcode) '
Packit 6c4009
TZVERSION=see_Makefile
Packit 6c4009
REPORT_BUGS_TO=tz@iana.org
Packit 6c4009
Packit 6c4009
# Ask the user about the time zone, and output the resulting TZ value to stdout.
Packit 6c4009
# Interact with the user via stderr and stdin.
Packit 6c4009
Packit 6c4009
# Contributed by Paul Eggert.  This file is in the public domain.
Packit 6c4009
Packit 6c4009
# Porting notes:
Packit 6c4009
#
Packit 6c4009
# This script requires a Posix-like shell and prefers the extension of a
Packit 6c4009
# 'select' statement.  The 'select' statement was introduced in the
Packit 6c4009
# Korn shell and is available in Bash and other shell implementations.
Packit 6c4009
# If your host lacks both Bash and the Korn shell, you can get their
Packit 6c4009
# source from one of these locations:
Packit 6c4009
#
Packit 6c4009
#	Bash <http://www.gnu.org/software/bash/bash.html>
Packit 6c4009
#	Korn Shell <http://www.kornshell.com/>
Packit 6c4009
#	Public Domain Korn Shell <http://www.cs.mun.ca/~michael/pdksh/>
Packit 6c4009
#
Packit 6c4009
# For portability to Solaris 9 /bin/sh this script avoids some POSIX
Packit 6c4009
# features and common extensions, such as $(...) (which works sometimes
Packit 6c4009
# but not others), $((...)), and $10.
Packit 6c4009
#
Packit 6c4009
# This script also uses several features of modern awk programs.
Packit 6c4009
# If your host lacks awk, or has an old awk that does not conform to Posix,
Packit 6c4009
# you can use either of the following free programs instead:
Packit 6c4009
#
Packit 6c4009
#	Gawk (GNU awk) <http://www.gnu.org/software/gawk/>
Packit 6c4009
#	mawk <http://invisible-island.net/mawk/>
Packit 6c4009
Packit 6c4009
Packit 6c4009
# Specify default values for environment variables if they are unset.
Packit 6c4009
: ${AWK=awk}
Packit 6c4009
: ${TZDIR=`pwd`}
Packit 6c4009
Packit 6c4009
# Output one argument as-is to standard output.
Packit 6c4009
# Safer than 'echo', which can mishandle '\' or leading '-'.
Packit 6c4009
say() {
Packit 6c4009
    printf '%s\n' "$1"
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
# Check for awk Posix compliance.
Packit 6c4009
($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
Packit 6c4009
[ $? = 123 ] || {
Packit 6c4009
	say >&2 "$0: Sorry, your '$AWK' program is not Posix compatible."
Packit 6c4009
	exit 1
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
coord=
Packit 6c4009
location_limit=10
Packit 6c4009
zonetabtype=zone1970
Packit 6c4009
Packit 6c4009
usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT]
Packit 6c4009
Select a time zone interactively.
Packit 6c4009
Packit 6c4009
Options:
Packit 6c4009
Packit 6c4009
  -c COORD
Packit 6c4009
    Instead of asking for continent and then country and then city,
Packit 6c4009
    ask for selection from time zones whose largest cities
Packit 6c4009
    are closest to the location with geographical coordinates COORD.
Packit 6c4009
    COORD should use ISO 6709 notation, for example, '-c +4852+00220'
Packit 6c4009
    for Paris (in degrees and minutes, North and East), or
Packit 6c4009
    '-c -35-058' for Buenos Aires (in degrees, South and West).
Packit 6c4009
Packit 6c4009
  -n LIMIT
Packit 6c4009
    Display at most LIMIT locations when -c is used (default $location_limit).
Packit 6c4009
Packit 6c4009
  --version
Packit 6c4009
    Output version information.
Packit 6c4009
Packit 6c4009
  --help
Packit 6c4009
    Output this help.
Packit 6c4009
Packit 6c4009
Report bugs to $REPORT_BUGS_TO."
Packit 6c4009
Packit 6c4009
# Ask the user to select from the function's arguments,
Packit 6c4009
# and assign the selected argument to the variable 'select_result'.
Packit 6c4009
# Exit on EOF or I/O error.  Use the shell's 'select' builtin if available,
Packit 6c4009
# falling back on a less-nice but portable substitute otherwise.
Packit 6c4009
if
Packit 6c4009
  case $BASH_VERSION in
Packit 6c4009
  ?*) : ;;
Packit 6c4009
  '')
Packit 6c4009
    # '; exit' should be redundant, but Dash doesn't properly fail without it.
Packit 6c4009
    (eval 'set --; select x; do break; done; exit') </dev/null 2>/dev/null
Packit 6c4009
  esac
Packit 6c4009
then
Packit 6c4009
  # Do this inside 'eval', as otherwise the shell might exit when parsing it
Packit 6c4009
  # even though it is never executed.
Packit 6c4009
  eval '
Packit 6c4009
    doselect() {
Packit 6c4009
      select select_result
Packit 6c4009
      do
Packit 6c4009
	case $select_result in
Packit 6c4009
	"") echo >&2 "Please enter a number in range." ;;
Packit 6c4009
	?*) break
Packit 6c4009
	esac
Packit 6c4009
      done || exit
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
    # Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout.
Packit 6c4009
    case $BASH_VERSION in
Packit 6c4009
    [01].*)
Packit 6c4009
      case `echo 1 | (select x in x; do break; done) 2>/dev/null` in
Packit 6c4009
      ?*) PS3=
Packit 6c4009
      esac
Packit 6c4009
    esac
Packit 6c4009
  '
Packit 6c4009
else
Packit 6c4009
  doselect() {
Packit 6c4009
    # Field width of the prompt numbers.
Packit 6c4009
    select_width=`expr $# : '.*'`
Packit 6c4009
Packit 6c4009
    select_i=
Packit 6c4009
Packit 6c4009
    while :
Packit 6c4009
    do
Packit 6c4009
      case $select_i in
Packit 6c4009
      '')
Packit 6c4009
	select_i=0
Packit 6c4009
	for select_word
Packit 6c4009
	do
Packit 6c4009
	  select_i=`expr $select_i + 1`
Packit 6c4009
	  printf >&2 "%${select_width}d) %s\\n" $select_i "$select_word"
Packit 6c4009
	done ;;
Packit 6c4009
      *[!0-9]*)
Packit 6c4009
	echo >&2 'Please enter a number in range.' ;;
Packit 6c4009
      *)
Packit 6c4009
	if test 1 -le $select_i && test $select_i -le $#; then
Packit 6c4009
	  shift `expr $select_i - 1`
Packit 6c4009
	  select_result=$1
Packit 6c4009
	  break
Packit 6c4009
	fi
Packit 6c4009
	echo >&2 'Please enter a number in range.'
Packit 6c4009
      esac
Packit 6c4009
Packit 6c4009
      # Prompt and read input.
Packit 6c4009
      printf >&2 %s "${PS3-#? }"
Packit 6c4009
      read select_i || exit
Packit 6c4009
    done
Packit 6c4009
  }
Packit 6c4009
fi
Packit 6c4009
Packit 6c4009
while getopts c:n:t:-: opt
Packit 6c4009
do
Packit 6c4009
    case $opt$OPTARG in
Packit 6c4009
    c*)
Packit 6c4009
	coord=$OPTARG ;;
Packit 6c4009
    n*)
Packit 6c4009
	location_limit=$OPTARG ;;
Packit 6c4009
    t*) # Undocumented option, used for developer testing.
Packit 6c4009
	zonetabtype=$OPTARG ;;
Packit 6c4009
    -help)
Packit 6c4009
	exec echo "$usage" ;;
Packit 6c4009
    -version)
Packit 6c4009
	exec echo "tzselect $PKGVERSION$TZVERSION" ;;
Packit 6c4009
    -*)
Packit 6c4009
	say >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;;
Packit 6c4009
    *)
Packit 6c4009
	say >&2 "$0: try '$0 --help'"; exit 1 ;;
Packit 6c4009
    esac
Packit 6c4009
done
Packit 6c4009
Packit 6c4009
shift `expr $OPTIND - 1`
Packit 6c4009
case $# in
Packit 6c4009
0) ;;
Packit 6c4009
*) say >&2 "$0: $1: unknown argument"; exit 1 ;;
Packit 6c4009
esac
Packit 6c4009
Packit 6c4009
# Make sure the tables are readable.
Packit 6c4009
TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
Packit 6c4009
TZ_ZONE_TABLE=$TZDIR/$zonetabtype.tab
Packit 6c4009
for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE
Packit 6c4009
do
Packit 6c4009
	<"$f" || {
Packit 6c4009
		say >&2 "$0: time zone files are not set up correctly"
Packit 6c4009
		exit 1
Packit 6c4009
	}
Packit 6c4009
done
Packit 6c4009
Packit 6c4009
# If the current locale does not support UTF-8, convert data to current
Packit 6c4009
# locale's format if possible, as the shell aligns columns better that way.
Packit 6c4009
# Check the UTF-8 of U+12345 CUNEIFORM SIGN URU TIMES KI.
Packit 6c4009
! $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) != 1 }' &&
Packit 6c4009
    { tmp=`(mktemp -d) 2>/dev/null` || {
Packit 6c4009
	tmp=${TMPDIR-/tmp}/tzselect.$$ &&
Packit 6c4009
	(umask 77 && mkdir -- "$tmp")
Packit 6c4009
    };} &&
Packit 6c4009
    trap 'status=$?; rm -fr -- "$tmp"; exit $status' 0 HUP INT PIPE TERM &&
Packit 6c4009
    (iconv -f UTF-8 -t //TRANSLIT <"$TZ_COUNTRY_TABLE" >$tmp/iso3166.tab) \
Packit 6c4009
        2>/dev/null &&
Packit 6c4009
    TZ_COUNTRY_TABLE=$tmp/iso3166.tab &&
Packit 6c4009
    iconv -f UTF-8 -t //TRANSLIT <"$TZ_ZONE_TABLE" >$tmp/$zonetabtype.tab &&
Packit 6c4009
    TZ_ZONE_TABLE=$tmp/$zonetabtype.tab
Packit 6c4009
Packit 6c4009
newline='
Packit 6c4009
'
Packit 6c4009
IFS=$newline
Packit 6c4009
Packit 6c4009
Packit 6c4009
# Awk script to read a time zone table and output the same table,
Packit 6c4009
# with each column preceded by its distance from 'here'.
Packit 6c4009
output_distances='
Packit 6c4009
  BEGIN {
Packit 6c4009
    FS = "\t"
Packit 6c4009
    while (getline 
Packit 6c4009
      if ($0 ~ /^[^#]/)
Packit 6c4009
        country[$1] = $2
Packit 6c4009
    country["US"] = "US" # Otherwise the strings get too long.
Packit 6c4009
  }
Packit 6c4009
  function abs(x) {
Packit 6c4009
    return x < 0 ? -x : x;
Packit 6c4009
  }
Packit 6c4009
  function min(x, y) {
Packit 6c4009
    return x < y ? x : y;
Packit 6c4009
  }
Packit 6c4009
  function convert_coord(coord, deg, minute, ilen, sign, sec) {
Packit 6c4009
    if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9][0-9][0-9]([^0-9]|$)/) {
Packit 6c4009
      degminsec = coord
Packit 6c4009
      intdeg = degminsec < 0 ? -int(-degminsec / 10000) : int(degminsec / 10000)
Packit 6c4009
      minsec = degminsec - intdeg * 10000
Packit 6c4009
      intmin = minsec < 0 ? -int(-minsec / 100) : int(minsec / 100)
Packit 6c4009
      sec = minsec - intmin * 100
Packit 6c4009
      deg = (intdeg * 3600 + intmin * 60 + sec) / 3600
Packit 6c4009
    } else if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9]([^0-9]|$)/) {
Packit 6c4009
      degmin = coord
Packit 6c4009
      intdeg = degmin < 0 ? -int(-degmin / 100) : int(degmin / 100)
Packit 6c4009
      minute = degmin - intdeg * 100
Packit 6c4009
      deg = (intdeg * 60 + minute) / 60
Packit 6c4009
    } else
Packit 6c4009
      deg = coord
Packit 6c4009
    return deg * 0.017453292519943296
Packit 6c4009
  }
Packit 6c4009
  function convert_latitude(coord) {
Packit 6c4009
    match(coord, /..*[-+]/)
Packit 6c4009
    return convert_coord(substr(coord, 1, RLENGTH - 1))
Packit 6c4009
  }
Packit 6c4009
  function convert_longitude(coord) {
Packit 6c4009
    match(coord, /..*[-+]/)
Packit 6c4009
    return convert_coord(substr(coord, RLENGTH))
Packit 6c4009
  }
Packit 6c4009
  # Great-circle distance between points with given latitude and longitude.
Packit 6c4009
  # Inputs and output are in radians.  This uses the great-circle special
Packit 6c4009
  # case of the Vicenty formula for distances on ellipsoids.
Packit 6c4009
  function gcdist(lat1, long1, lat2, long2, dlong, x, y, num, denom) {
Packit 6c4009
    dlong = long2 - long1
Packit 6c4009
    x = cos(lat2) * sin(dlong)
Packit 6c4009
    y = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlong)
Packit 6c4009
    num = sqrt(x * x + y * y)
Packit 6c4009
    denom = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(dlong)
Packit 6c4009
    return atan2(num, denom)
Packit 6c4009
  }
Packit 6c4009
  # Parallel distance between points with given latitude and longitude.
Packit 6c4009
  # This is the product of the longitude difference and the cosine
Packit 6c4009
  # of the latitude of the point that is further from the equator.
Packit 6c4009
  # I.e., it considers longitudes to be further apart if they are
Packit 6c4009
  # nearer the equator.
Packit 6c4009
  function pardist(lat1, long1, lat2, long2) {
Packit 6c4009
    return abs(long1 - long2) * min(cos(lat1), cos(lat2))
Packit 6c4009
  }
Packit 6c4009
  # The distance function is the sum of the great-circle distance and
Packit 6c4009
  # the parallel distance.  It could be weighted.
Packit 6c4009
  function dist(lat1, long1, lat2, long2) {
Packit 6c4009
    return gcdist(lat1, long1, lat2, long2) + pardist(lat1, long1, lat2, long2)
Packit 6c4009
  }
Packit 6c4009
  BEGIN {
Packit 6c4009
    coord_lat = convert_latitude(coord)
Packit 6c4009
    coord_long = convert_longitude(coord)
Packit 6c4009
  }
Packit 6c4009
  /^[^#]/ {
Packit 6c4009
    here_lat = convert_latitude($2)
Packit 6c4009
    here_long = convert_longitude($2)
Packit 6c4009
    line = $1 "\t" $2 "\t" $3
Packit 6c4009
    sep = "\t"
Packit 6c4009
    ncc = split($1, cc, /,/)
Packit 6c4009
    for (i = 1; i <= ncc; i++) {
Packit 6c4009
      line = line sep country[cc[i]]
Packit 6c4009
      sep = ", "
Packit 6c4009
    }
Packit 6c4009
    if (NF == 4)
Packit 6c4009
      line = line " - " $4
Packit 6c4009
    printf "%g\t%s\n", dist(coord_lat, coord_long, here_lat, here_long), line
Packit 6c4009
  }
Packit 6c4009
'
Packit 6c4009
Packit 6c4009
# Begin the main loop.  We come back here if the user wants to retry.
Packit 6c4009
while
Packit 6c4009
Packit 6c4009
	echo >&2 'Please identify a location' \
Packit 6c4009
		'so that time zone rules can be set correctly.'
Packit 6c4009
Packit 6c4009
	continent=
Packit 6c4009
	country=
Packit 6c4009
	region=
Packit 6c4009
Packit 6c4009
	case $coord in
Packit 6c4009
	?*)
Packit 6c4009
		continent=coord;;
Packit 6c4009
	'')
Packit 6c4009
Packit 6c4009
	# Ask the user for continent or ocean.
Packit 6c4009
Packit 6c4009
	echo >&2 'Please select a continent, ocean, "coord", or "TZ".'
Packit 6c4009
Packit 6c4009
        quoted_continents=`
Packit 6c4009
	  $AWK '
Packit 6c4009
	    BEGIN { FS = "\t" }
Packit 6c4009
	    /^[^#]/ {
Packit 6c4009
              entry = substr($3, 1, index($3, "/") - 1)
Packit 6c4009
              if (entry == "America")
Packit 6c4009
		entry = entry "s"
Packit 6c4009
              if (entry ~ /^(Arctic|Atlantic|Indian|Pacific)$/)
Packit 6c4009
		entry = entry " Ocean"
Packit 6c4009
              printf "'\''%s'\''\n", entry
Packit 6c4009
            }
Packit 6c4009
          ' <"$TZ_ZONE_TABLE" |
Packit 6c4009
	  sort -u |
Packit 6c4009
	  tr '\n' ' '
Packit 6c4009
	  echo ''
Packit 6c4009
	`
Packit 6c4009
Packit 6c4009
	eval '
Packit 6c4009
	    doselect '"$quoted_continents"' \
Packit 6c4009
		"coord - I want to use geographical coordinates." \
Packit 6c4009
		"TZ - I want to specify the time zone using the Posix TZ format."
Packit 6c4009
	    continent=$select_result
Packit 6c4009
	    case $continent in
Packit 6c4009
	    Americas) continent=America;;
Packit 6c4009
	    *" "*) continent=`expr "$continent" : '\''\([^ ]*\)'\''`
Packit 6c4009
	    esac
Packit 6c4009
	'
Packit 6c4009
	esac
Packit 6c4009
Packit 6c4009
	case $continent in
Packit 6c4009
	TZ)
Packit 6c4009
		# Ask the user for a Posix TZ string.  Check that it conforms.
Packit 6c4009
		while
Packit 6c4009
			echo >&2 'Please enter the desired value' \
Packit 6c4009
				'of the TZ environment variable.'
Packit 6c4009
			echo >&2 'For example, GST-10 is a zone named GST' \
Packit 6c4009
				'that is 10 hours ahead (east) of UTC.'
Packit 6c4009
			read TZ
Packit 6c4009
			$AWK -v TZ="$TZ" 'BEGIN {
Packit 6c4009
				tzname = "(<[[:alnum:]+-]{3,}>|[[:alpha:]]{3,})"
Packit 6c4009
				time = "(2[0-4]|[0-1]?[0-9])" \
Packit 6c4009
				  "(:[0-5][0-9](:[0-5][0-9])?)?"
Packit 6c4009
				offset = "[-+]?" time
Packit 6c4009
				mdate = "M([1-9]|1[0-2])\\.[1-5]\\.[0-6]"
Packit 6c4009
				jdate = "((J[1-9]|[0-9]|J?[1-9][0-9]" \
Packit 6c4009
				  "|J?[1-2][0-9][0-9])|J?3[0-5][0-9]|J?36[0-5])"
Packit 6c4009
				datetime = ",(" mdate "|" jdate ")(/" time ")?"
Packit 6c4009
				tzpattern = "^(:.*|" tzname offset "(" tzname \
Packit 6c4009
				  "(" offset ")?(" datetime datetime ")?)?)$"
Packit 6c4009
				if (TZ ~ tzpattern) exit 1
Packit 6c4009
				exit 0
Packit 6c4009
			}'
Packit 6c4009
		do
Packit 6c4009
		    say >&2 "'$TZ' is not a conforming Posix time zone string."
Packit 6c4009
		done
Packit 6c4009
		TZ_for_date=$TZ;;
Packit 6c4009
	*)
Packit 6c4009
		case $continent in
Packit 6c4009
		coord)
Packit 6c4009
		    case $coord in
Packit 6c4009
		    '')
Packit 6c4009
			echo >&2 'Please enter coordinates' \
Packit 6c4009
				'in ISO 6709 notation.'
Packit 6c4009
			echo >&2 'For example, +4042-07403 stands for'
Packit 6c4009
			echo >&2 '40 degrees 42 minutes north,' \
Packit 6c4009
				'74 degrees 3 minutes west.'
Packit 6c4009
			read coord;;
Packit 6c4009
		    esac
Packit 6c4009
		    distance_table=`$AWK \
Packit 6c4009
			    -v coord="$coord" \
Packit 6c4009
			    -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
Packit 6c4009
			    "$output_distances" <"$TZ_ZONE_TABLE" |
Packit 6c4009
		      sort -n |
Packit 6c4009
		      sed "${location_limit}q"
Packit 6c4009
		    `
Packit 6c4009
		    regions=`say "$distance_table" | $AWK '
Packit 6c4009
		      BEGIN { FS = "\t" }
Packit 6c4009
		      { print $NF }
Packit 6c4009
		    '`
Packit 6c4009
		    echo >&2 'Please select one of the following' \
Packit 6c4009
			    'time zone regions,'
Packit 6c4009
		    echo >&2 'listed roughly in increasing order' \
Packit 6c4009
			    "of distance from $coord".
Packit 6c4009
		    doselect $regions
Packit 6c4009
		    region=$select_result
Packit 6c4009
		    TZ=`say "$distance_table" | $AWK -v region="$region" '
Packit 6c4009
		      BEGIN { FS="\t" }
Packit 6c4009
		      $NF == region { print $4 }
Packit 6c4009
		    '`
Packit 6c4009
		    ;;
Packit 6c4009
		*)
Packit 6c4009
		# Get list of names of countries in the continent or ocean.
Packit 6c4009
		countries=`$AWK \
Packit 6c4009
			-v continent="$continent" \
Packit 6c4009
			-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
Packit 6c4009
		'
Packit 6c4009
			BEGIN { FS = "\t" }
Packit 6c4009
			/^#/ { next }
Packit 6c4009
			$3 ~ ("^" continent "/") {
Packit 6c4009
			    ncc = split($1, cc, /,/)
Packit 6c4009
			    for (i = 1; i <= ncc; i++)
Packit 6c4009
				if (!cc_seen[cc[i]]++) cc_list[++ccs] = cc[i]
Packit 6c4009
			}
Packit 6c4009
			END {
Packit 6c4009
				while (getline 
Packit 6c4009
					if ($0 !~ /^#/) cc_name[$1] = $2
Packit 6c4009
				}
Packit 6c4009
				for (i = 1; i <= ccs; i++) {
Packit 6c4009
					country = cc_list[i]
Packit 6c4009
					if (cc_name[country]) {
Packit 6c4009
					  country = cc_name[country]
Packit 6c4009
					}
Packit 6c4009
					print country
Packit 6c4009
				}
Packit 6c4009
			}
Packit 6c4009
		' <"$TZ_ZONE_TABLE" | sort -f`
Packit 6c4009
Packit 6c4009
Packit 6c4009
		# If there's more than one country, ask the user which one.
Packit 6c4009
		case $countries in
Packit 6c4009
		*"$newline"*)
Packit 6c4009
			echo >&2 'Please select a country' \
Packit 6c4009
				'whose clocks agree with yours.'
Packit 6c4009
			doselect $countries
Packit 6c4009
			country=$select_result;;
Packit 6c4009
		*)
Packit 6c4009
			country=$countries
Packit 6c4009
		esac
Packit 6c4009
Packit 6c4009
Packit 6c4009
		# Get list of names of time zone rule regions in the country.
Packit 6c4009
		regions=`$AWK \
Packit 6c4009
			-v country="$country" \
Packit 6c4009
			-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
Packit 6c4009
		'
Packit 6c4009
			BEGIN {
Packit 6c4009
				FS = "\t"
Packit 6c4009
				cc = country
Packit 6c4009
				while (getline 
Packit 6c4009
					if ($0 !~ /^#/  &&  country == $2) {
Packit 6c4009
						cc = $1
Packit 6c4009
						break
Packit 6c4009
					}
Packit 6c4009
				}
Packit 6c4009
			}
Packit 6c4009
			/^#/ { next }
Packit 6c4009
			$1 ~ cc { print $4 }
Packit 6c4009
		' <"$TZ_ZONE_TABLE"`
Packit 6c4009
Packit 6c4009
Packit 6c4009
		# If there's more than one region, ask the user which one.
Packit 6c4009
		case $regions in
Packit 6c4009
		*"$newline"*)
Packit 6c4009
			echo >&2 'Please select one of the following' \
Packit 6c4009
				'time zone regions.'
Packit 6c4009
			doselect $regions
Packit 6c4009
			region=$select_result;;
Packit 6c4009
		*)
Packit 6c4009
			region=$regions
Packit 6c4009
		esac
Packit 6c4009
Packit 6c4009
		# Determine TZ from country and region.
Packit 6c4009
		TZ=`$AWK \
Packit 6c4009
			-v country="$country" \
Packit 6c4009
			-v region="$region" \
Packit 6c4009
			-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
Packit 6c4009
		'
Packit 6c4009
			BEGIN {
Packit 6c4009
				FS = "\t"
Packit 6c4009
				cc = country
Packit 6c4009
				while (getline 
Packit 6c4009
					if ($0 !~ /^#/  &&  country == $2) {
Packit 6c4009
						cc = $1
Packit 6c4009
						break
Packit 6c4009
					}
Packit 6c4009
				}
Packit 6c4009
			}
Packit 6c4009
			/^#/ { next }
Packit 6c4009
			$1 ~ cc && $4 == region { print $3 }
Packit 6c4009
		' <"$TZ_ZONE_TABLE"`
Packit 6c4009
		esac
Packit 6c4009
Packit 6c4009
		# Make sure the corresponding zoneinfo file exists.
Packit 6c4009
		TZ_for_date=$TZDIR/$TZ
Packit 6c4009
		<"$TZ_for_date" || {
Packit 6c4009
			say >&2 "$0: time zone files are not set up correctly"
Packit 6c4009
			exit 1
Packit 6c4009
		}
Packit 6c4009
	esac
Packit 6c4009
Packit 6c4009
Packit 6c4009
	# Use the proposed TZ to output the current date relative to UTC.
Packit 6c4009
	# Loop until they agree in seconds.
Packit 6c4009
	# Give up after 8 unsuccessful tries.
Packit 6c4009
Packit 6c4009
	extra_info=
Packit 6c4009
	for i in 1 2 3 4 5 6 7 8
Packit 6c4009
	do
Packit 6c4009
		TZdate=`LANG=C TZ="$TZ_for_date" date`
Packit 6c4009
		UTdate=`LANG=C TZ=UTC0 date`
Packit 6c4009
		TZsec=`expr "$TZdate" : '.*:\([0-5][0-9]\)'`
Packit 6c4009
		UTsec=`expr "$UTdate" : '.*:\([0-5][0-9]\)'`
Packit 6c4009
		case $TZsec in
Packit 6c4009
		$UTsec)
Packit 6c4009
			extra_info="
Packit 6c4009
Selected time is now:	$TZdate.
Packit 6c4009
Universal Time is now:	$UTdate."
Packit 6c4009
			break
Packit 6c4009
		esac
Packit 6c4009
	done
Packit 6c4009
Packit 6c4009
Packit 6c4009
	# Output TZ info and ask the user to confirm.
Packit 6c4009
Packit 6c4009
	echo >&2 ""
Packit 6c4009
	echo >&2 "The following information has been given:"
Packit 6c4009
	echo >&2 ""
Packit 6c4009
	case $country%$region%$coord in
Packit 6c4009
	?*%?*%)	say >&2 "	$country$newline	$region";;
Packit 6c4009
	?*%%)	say >&2 "	$country";;
Packit 6c4009
	%?*%?*) say >&2 "	coord $coord$newline	$region";;
Packit 6c4009
	%%?*)	say >&2 "	coord $coord";;
Packit 6c4009
	*)	say >&2 "	TZ='$TZ'"
Packit 6c4009
	esac
Packit 6c4009
	say >&2 ""
Packit 6c4009
	say >&2 "Therefore TZ='$TZ' will be used.$extra_info"
Packit 6c4009
	say >&2 "Is the above information OK?"
Packit 6c4009
Packit 6c4009
	doselect Yes No
Packit 6c4009
	ok=$select_result
Packit 6c4009
	case $ok in
Packit 6c4009
	Yes) break
Packit 6c4009
	esac
Packit 6c4009
do coord=
Packit 6c4009
done
Packit 6c4009
Packit 6c4009
case $SHELL in
Packit 6c4009
*csh) file=.login line="setenv TZ '$TZ'";;
Packit 6c4009
*) file=.profile line="TZ='$TZ'; export TZ"
Packit 6c4009
esac
Packit 6c4009
Packit 6c4009
test -t 1 && say >&2 "
Packit 6c4009
You can make this change permanent for yourself by appending the line
Packit 6c4009
	$line
Packit 6c4009
to the file '$file' in your home directory; then log out and log in again.
Packit 6c4009
Packit 6c4009
Here is that TZ value again, this time on standard output so that you
Packit 6c4009
can use the $0 command in shell scripts:"
Packit 6c4009
Packit 6c4009
say "$TZ"