mirror of
https://frontier.innolan.net/rainlance/amiga-tz.git
synced 2026-09-19 07:04:43 +00:00
tzselect: port to /bin/sh
Problem reported by Patrick 'P. J.' McDermott in <http://mm.icann.org/pipermail/tz/2013-October/020441.html>. This code is quite a bit different from what he proposed. * tzselect.ksh: Rewrite so that it should work with /bin/sh on common platforms. For portability to Solaris 9 /bin/sh, use `...`, not $(...), and avoid $((...)). (doselect): New function. Use this instead of plain 'select'. Callers no longer need to worry whether it sets the var to empty. * Makefile, NEWS: Document this.
This commit is contained in:
@@ -246,8 +246,12 @@ ZFLAGS=
|
|||||||
# The name of a Posix-compliant `awk' on your system.
|
# The name of a Posix-compliant `awk' on your system.
|
||||||
AWK= awk
|
AWK= awk
|
||||||
|
|
||||||
# The full path name of a Posix-compliant shell that supports the Korn shell's
|
# The full path name of a Posix-compliant shell, preferably one that supports
|
||||||
# 'select' statement, as an extension. These days, Bash is the most popular.
|
# the Korn shell's 'select' statement as an extension.
|
||||||
|
# These days, Bash is the most popular.
|
||||||
|
# It should be OK to set this to /bin/sh, on platforms where /bin/sh
|
||||||
|
# lacks 'select' or doesn't completely conform to Posix, but /bin/bash
|
||||||
|
# is typically nicer if it works.
|
||||||
KSHELL= /bin/bash
|
KSHELL= /bin/bash
|
||||||
|
|
||||||
# The path where SGML DTDs are kept.
|
# The path where SGML DTDs are kept.
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ Unreleased, experimental changes
|
|||||||
This avoids some year-2038 glitches introduced in 2013g.
|
This avoids some year-2038 glitches introduced in 2013g.
|
||||||
(Thanks to Yoshito Umaoka for reporting the problem.)
|
(Thanks to Yoshito Umaoka for reporting the problem.)
|
||||||
|
|
||||||
|
Changes affecting API
|
||||||
|
|
||||||
|
The 'tzselect' command no longer requires the 'select' command,
|
||||||
|
and should now work with /bin/sh on more platforms. (Thanks to
|
||||||
|
Patrick 'P. J.' McDermott for reporting the problem.)
|
||||||
|
|
||||||
Changes affecting the build procedure
|
Changes affecting the build procedure
|
||||||
|
|
||||||
The builder can specify which programs to use, if any, instead of
|
The builder can specify which programs to use, if any, instead of
|
||||||
|
|||||||
+107
-78
@@ -11,7 +11,7 @@ REPORT_BUGS_TO=tz@iana.org
|
|||||||
|
|
||||||
# Porting notes:
|
# Porting notes:
|
||||||
#
|
#
|
||||||
# This script requires a Posix-like shell with the extension of a
|
# This script requires a Posix-like shell and prefers the extension of a
|
||||||
# 'select' statement. The 'select' statement was introduced in the
|
# 'select' statement. The 'select' statement was introduced in the
|
||||||
# Korn shell and is available in Bash and other shell implementations.
|
# Korn shell and is available in Bash and other shell implementations.
|
||||||
# If your host lacks both Bash and the Korn shell, you can get their
|
# If your host lacks both Bash and the Korn shell, you can get their
|
||||||
@@ -21,6 +21,10 @@ REPORT_BUGS_TO=tz@iana.org
|
|||||||
# Korn Shell <http://www.kornshell.com/>
|
# Korn Shell <http://www.kornshell.com/>
|
||||||
# Public Domain Korn Shell <http://www.cs.mun.ca/~michael/pdksh/>
|
# Public Domain Korn Shell <http://www.cs.mun.ca/~michael/pdksh/>
|
||||||
#
|
#
|
||||||
|
# For portability to Solaris 9 /bin/sh this script avoids some POSIX
|
||||||
|
# features and common extensions, such as $(...) (which works sometimes
|
||||||
|
# but not others), $((...)), and $10.
|
||||||
|
#
|
||||||
# This script also uses several features of modern awk programs.
|
# This script also uses several features of modern awk programs.
|
||||||
# If your host lacks awk, or has an old awk that does not conform to Posix,
|
# If your host lacks awk, or has an old awk that does not conform to Posix,
|
||||||
# you can use either of the following free programs instead:
|
# you can use either of the following free programs instead:
|
||||||
@@ -31,7 +35,7 @@ REPORT_BUGS_TO=tz@iana.org
|
|||||||
|
|
||||||
# Specify default values for environment variables if they are unset.
|
# Specify default values for environment variables if they are unset.
|
||||||
: ${AWK=awk}
|
: ${AWK=awk}
|
||||||
: ${TZDIR=$(pwd)}
|
: ${TZDIR=`pwd`}
|
||||||
|
|
||||||
# Check for awk Posix compliance.
|
# Check for awk Posix compliance.
|
||||||
($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
|
($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
|
||||||
@@ -67,6 +71,74 @@ Options:
|
|||||||
|
|
||||||
Report bugs to $REPORT_BUGS_TO."
|
Report bugs to $REPORT_BUGS_TO."
|
||||||
|
|
||||||
|
# Ask the user to select from the function's arguments,
|
||||||
|
# and assign the selected argument to the variable 'select_result'.
|
||||||
|
# Exit on EOF or I/O error. Use the shell's 'select' builtin if available,
|
||||||
|
# falling back on a less-nice but portable substitute otherwise.
|
||||||
|
if
|
||||||
|
case $BASH_VERSION in
|
||||||
|
?*) : ;;
|
||||||
|
'')
|
||||||
|
# '; exit' should be redundant, but Dash doesn't properly fail without it.
|
||||||
|
(eval 'set --; select x; do break; done; exit') 2>/dev/null
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
# Do this inside 'eval', as otherwise the shell might exit when parsing it
|
||||||
|
# even though it is never executed.
|
||||||
|
eval '
|
||||||
|
doselect() {
|
||||||
|
select select_result
|
||||||
|
do
|
||||||
|
case $select_result in
|
||||||
|
"") echo >&2 "Please enter a number in range." ;;
|
||||||
|
?*) break
|
||||||
|
esac
|
||||||
|
done || exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout.
|
||||||
|
case $BASH_VERSION in
|
||||||
|
[01].*)
|
||||||
|
case `echo 1 | (select x in x; do break; done) 2>/dev/null` in
|
||||||
|
?*) PS3=
|
||||||
|
esac
|
||||||
|
esac
|
||||||
|
'
|
||||||
|
else
|
||||||
|
doselect() {
|
||||||
|
# Field width of the prompt numbers.
|
||||||
|
select_width=`expr $# : '.*'`
|
||||||
|
|
||||||
|
select_i=
|
||||||
|
|
||||||
|
while :
|
||||||
|
do
|
||||||
|
case $select_i in
|
||||||
|
'')
|
||||||
|
select_i=0
|
||||||
|
for select_word
|
||||||
|
do
|
||||||
|
select_i=`expr $select_i + 1`
|
||||||
|
printf "%${select_width}d) %s\\n" $select_i "$select_word"
|
||||||
|
done ;;
|
||||||
|
*[!0-9]*)
|
||||||
|
echo >&2 'Please enter a number in range.' ;;
|
||||||
|
*)
|
||||||
|
if test 1 -le $select_i && test $select_i -le $#; then
|
||||||
|
shift `expr $select_i - 1`
|
||||||
|
select_result=$1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo >&2 'Please enter a number in range.'
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Prompt and read input.
|
||||||
|
printf %s >&2 "${PS3-#? }"
|
||||||
|
read select_i || exit
|
||||||
|
done
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
while getopts c:n:-: opt
|
while getopts c:n:-: opt
|
||||||
do
|
do
|
||||||
case $opt$OPTARG in
|
case $opt$OPTARG in
|
||||||
@@ -85,7 +157,7 @@ do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
shift $((OPTIND-1))
|
shift `expr $OPTIND - 1`
|
||||||
case $# in
|
case $# in
|
||||||
0) ;;
|
0) ;;
|
||||||
*) echo >&2 "$0: $1: unknown argument"; exit 1 ;;
|
*) echo >&2 "$0: $1: unknown argument"; exit 1 ;;
|
||||||
@@ -107,11 +179,6 @@ newline='
|
|||||||
IFS=$newline
|
IFS=$newline
|
||||||
|
|
||||||
|
|
||||||
# Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout.
|
|
||||||
case $(echo 1 | (select x in x; do break; done) 2>/dev/null) in
|
|
||||||
?*) PS3=
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Awk script to read a time zone table and output the same table,
|
# Awk script to read a time zone table and output the same table,
|
||||||
# with each column preceded by its distance from 'here'.
|
# with each column preceded by its distance from 'here'.
|
||||||
output_distances='
|
output_distances='
|
||||||
@@ -191,7 +258,7 @@ while
|
|||||||
|
|
||||||
echo >&2 'Please select a continent, ocean, "coord", or "TZ".'
|
echo >&2 'Please select a continent, ocean, "coord", or "TZ".'
|
||||||
|
|
||||||
quoted_continents=$(
|
quoted_continents=`
|
||||||
$AWK -F'\t' '
|
$AWK -F'\t' '
|
||||||
/^[^#]/ {
|
/^[^#]/ {
|
||||||
entry = substr($3, 1, index($3, "/") - 1)
|
entry = substr($3, 1, index($3, "/") - 1)
|
||||||
@@ -205,30 +272,21 @@ while
|
|||||||
sort -u |
|
sort -u |
|
||||||
tr '\n' ' '
|
tr '\n' ' '
|
||||||
echo ''
|
echo ''
|
||||||
)
|
`
|
||||||
|
|
||||||
eval '
|
eval '
|
||||||
select continent in '"$quoted_continents"' \
|
doselect '"$quoted_continents"' \
|
||||||
"coord - I want to use geographical coordinates." \
|
"coord - I want to use geographical coordinates." \
|
||||||
"TZ - I want to specify the time zone using the Posix TZ format."
|
"TZ - I want to specify the time zone using the Posix TZ format."
|
||||||
do
|
continent=$select_result
|
||||||
case $continent in
|
case $continent in
|
||||||
"")
|
Americas) continent=America;;
|
||||||
echo >&2 "Please enter a number in range.";;
|
*" "*) continent=`expr "$continent" : '\''\([^ ]*\)'\''`
|
||||||
?*)
|
esac
|
||||||
case $continent in
|
|
||||||
Americas) continent=America;;
|
|
||||||
*" "*) continent=$(expr "$continent" : '\''\([^ ]*\)'\'')
|
|
||||||
esac
|
|
||||||
break
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
'
|
'
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case $continent in
|
case $continent in
|
||||||
'')
|
|
||||||
exit 1;;
|
|
||||||
TZ)
|
TZ)
|
||||||
# Ask the user for a Posix TZ string. Check that it conforms.
|
# Ask the user for a Posix TZ string. Check that it conforms.
|
||||||
while
|
while
|
||||||
@@ -265,36 +323,31 @@ while
|
|||||||
'74 degrees 3 minutes west.'
|
'74 degrees 3 minutes west.'
|
||||||
read coord;;
|
read coord;;
|
||||||
esac
|
esac
|
||||||
distance_table=$($AWK \
|
distance_table=`$AWK \
|
||||||
-v coord="$coord" \
|
-v coord="$coord" \
|
||||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||||
"$output_distances" <$TZ_ZONE_TABLE |
|
"$output_distances" <$TZ_ZONE_TABLE |
|
||||||
sort -n |
|
sort -n |
|
||||||
sed "${location_limit}q"
|
sed "${location_limit}q"
|
||||||
)
|
`
|
||||||
regions=$(echo "$distance_table" | $AWK '
|
regions=`echo "$distance_table" | $AWK '
|
||||||
BEGIN { FS = "\t" }
|
BEGIN { FS = "\t" }
|
||||||
{ print $NF }
|
{ print $NF }
|
||||||
')
|
'`
|
||||||
echo >&2 'Please select one of the following' \
|
echo >&2 'Please select one of the following' \
|
||||||
'time zone regions,'
|
'time zone regions,'
|
||||||
echo >&2 'listed roughly in increasing order' \
|
echo >&2 'listed roughly in increasing order' \
|
||||||
"of distance from $coord".
|
"of distance from $coord".
|
||||||
select region in $regions
|
doselect $regions
|
||||||
do
|
region=$select_result
|
||||||
case $region in
|
TZ=`echo "$distance_table" | $AWK -v region="$region" '
|
||||||
'') echo >&2 'Please enter a number in range.';;
|
|
||||||
?*) break;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
TZ=$(echo "$distance_table" | $AWK -v region="$region" '
|
|
||||||
BEGIN { FS="\t" }
|
BEGIN { FS="\t" }
|
||||||
$NF == region { print $4 }
|
$NF == region { print $4 }
|
||||||
')
|
'`
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
# Get list of names of countries in the continent or ocean.
|
# Get list of names of countries in the continent or ocean.
|
||||||
countries=$($AWK -F'\t' \
|
countries=`$AWK -F'\t' \
|
||||||
-v continent="$continent" \
|
-v continent="$continent" \
|
||||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||||
'
|
'
|
||||||
@@ -314,7 +367,7 @@ while
|
|||||||
print country
|
print country
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
' <$TZ_ZONE_TABLE | sort -f)
|
' <$TZ_ZONE_TABLE | sort -f`
|
||||||
|
|
||||||
|
|
||||||
# If there's more than one country, ask the user which one.
|
# If there's more than one country, ask the user which one.
|
||||||
@@ -322,24 +375,15 @@ while
|
|||||||
*"$newline"*)
|
*"$newline"*)
|
||||||
echo >&2 'Please select a country' \
|
echo >&2 'Please select a country' \
|
||||||
'whose clocks agree with yours.'
|
'whose clocks agree with yours.'
|
||||||
select country in $countries
|
doselect $countries
|
||||||
do
|
country=$select_result;;
|
||||||
case $country in
|
|
||||||
'') echo >&2 'Please enter a number in range.';;
|
|
||||||
?*) break
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
case $country in
|
|
||||||
'') exit 1
|
|
||||||
esac;;
|
|
||||||
*)
|
*)
|
||||||
country=$countries
|
country=$countries
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
||||||
# Get list of names of time zone rule regions in the country.
|
# Get list of names of time zone rule regions in the country.
|
||||||
regions=$($AWK -F'\t' \
|
regions=`$AWK -F'\t' \
|
||||||
-v country="$country" \
|
-v country="$country" \
|
||||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||||
'
|
'
|
||||||
@@ -353,7 +397,7 @@ while
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$1 == cc { print $4 }
|
$1 == cc { print $4 }
|
||||||
' <$TZ_ZONE_TABLE)
|
' <$TZ_ZONE_TABLE`
|
||||||
|
|
||||||
|
|
||||||
# If there's more than one region, ask the user which one.
|
# If there's more than one region, ask the user which one.
|
||||||
@@ -361,22 +405,14 @@ while
|
|||||||
*"$newline"*)
|
*"$newline"*)
|
||||||
echo >&2 'Please select one of the following' \
|
echo >&2 'Please select one of the following' \
|
||||||
'time zone regions.'
|
'time zone regions.'
|
||||||
select region in $regions
|
doselect $regions
|
||||||
do
|
region=$select_result;;
|
||||||
case $region in
|
|
||||||
'') echo >&2 'Please enter a number in range.';;
|
|
||||||
?*) break
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
case $region in
|
|
||||||
'') exit 1
|
|
||||||
esac;;
|
|
||||||
*)
|
*)
|
||||||
region=$regions
|
region=$regions
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Determine TZ from country and region.
|
# Determine TZ from country and region.
|
||||||
TZ=$($AWK -F'\t' \
|
TZ=`$AWK -F'\t' \
|
||||||
-v country="$country" \
|
-v country="$country" \
|
||||||
-v region="$region" \
|
-v region="$region" \
|
||||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||||
@@ -391,7 +427,7 @@ while
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$1 == cc && $4 == region { print $3 }
|
$1 == cc && $4 == region { print $3 }
|
||||||
' <$TZ_ZONE_TABLE)
|
' <$TZ_ZONE_TABLE`
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Make sure the corresponding zoneinfo file exists.
|
# Make sure the corresponding zoneinfo file exists.
|
||||||
@@ -410,10 +446,10 @@ while
|
|||||||
extra_info=
|
extra_info=
|
||||||
for i in 1 2 3 4 5 6 7 8
|
for i in 1 2 3 4 5 6 7 8
|
||||||
do
|
do
|
||||||
TZdate=$(LANG=C TZ="$TZ_for_date" date)
|
TZdate=`LANG=C TZ="$TZ_for_date" date`
|
||||||
UTdate=$(LANG=C TZ=UTC0 date)
|
UTdate=`LANG=C TZ=UTC0 date`
|
||||||
TZsec=$(expr "$TZdate" : '.*:\([0-5][0-9]\)')
|
TZsec=`expr "$TZdate" : '.*:\([0-5][0-9]\)'`
|
||||||
UTsec=$(expr "$UTdate" : '.*:\([0-5][0-9]\)')
|
UTsec=`expr "$UTdate" : '.*:\([0-5][0-9]\)'`
|
||||||
case $TZsec in
|
case $TZsec in
|
||||||
$UTsec)
|
$UTsec)
|
||||||
extra_info="
|
extra_info="
|
||||||
@@ -440,16 +476,9 @@ Universal Time is now: $UTdate."
|
|||||||
echo >&2 "Therefore TZ='$TZ' will be used.$extra_info"
|
echo >&2 "Therefore TZ='$TZ' will be used.$extra_info"
|
||||||
echo >&2 "Is the above information OK?"
|
echo >&2 "Is the above information OK?"
|
||||||
|
|
||||||
ok=
|
doselect Yes No
|
||||||
select ok in Yes No
|
ok=$select_result
|
||||||
do
|
|
||||||
case $ok in
|
|
||||||
'') echo >&2 'Please enter 1 for Yes, or 2 for No.';;
|
|
||||||
?*) break
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
case $ok in
|
case $ok in
|
||||||
'') exit 1;;
|
|
||||||
Yes) break
|
Yes) break
|
||||||
esac
|
esac
|
||||||
do coord=
|
do coord=
|
||||||
|
|||||||
Reference in New Issue
Block a user