about summary refs log tree commit diff
path: root/timezone/tzselect.ksh
diff options
context:
space:
mode:
Diffstat (limited to 'timezone/tzselect.ksh')
-rwxr-xr-xtimezone/tzselect.ksh125
1 files changed, 55 insertions, 70 deletions
diff --git a/timezone/tzselect.ksh b/timezone/tzselect.ksh
index 38941bbc55..ca3d82c6aa 100755
--- a/timezone/tzselect.ksh
+++ b/timezone/tzselect.ksh
@@ -20,12 +20,6 @@ REPORT_BUGS_TO=tz@iana.org
 #	Korn Shell <http://www.kornshell.com/>
 #	MirBSD Korn Shell <http://www.mirbsd.org/mksh.htm>
 #
-# For portability to Solaris 10 /bin/sh (supported by Oracle through
-# January 2027) this script avoids some POSIX features and common
-# extensions, such as $(...), $((...)), ! CMD, unquoted ^, ${#ID},
-# ${ID##PAT}, ${ID%%PAT}, and $10.  Although some of these constructs
-# work sometimes, it's simpler to avoid them entirely.
-#
 # This script also uses several features of POSIX awk.
 # If your host lacks awk, or has an old awk that does not conform to POSIX,
 # you can use any of the following free programs instead:
@@ -45,7 +39,6 @@ set -f
 
 # Specify default values for environment variables if they are unset.
 : ${AWK=awk}
-: ${PWD=`pwd`}
 : ${TZDIR=$PWD}
 
 # Output one argument as-is to standard output, with trailing newline.
@@ -54,13 +47,6 @@ say() {
   printf '%s\n' "$1"
 }
 
-# Check for awk POSIX compliance.
-($AWK -v x=y 'BEGIN { exit 123 }') <>/dev/null >&0 2>&0
-[ $? = 123 ] || {
-  say >&2 "$0: Sorry, your '$AWK' program is not POSIX compatible."
-  exit 1
-}
-
 coord=
 location_limit=10
 zonetabtype=zone1970
@@ -117,8 +103,7 @@ then
 else
   doselect() {
     # Field width of the prompt numbers.
-    print_nargs_length="BEGIN {print length(\"$#\");}"
-    select_width=`$AWK "$print_nargs_length"`
+    select_width=${##}
 
     select_i=
 
@@ -129,14 +114,14 @@ else
 	select_i=0
 	for select_word
 	do
-	  select_i=`$AWK "BEGIN { print $select_i + 1 }"`
+	  select_i=$(($select_i + 1))
 	  printf >&2 "%${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 `$AWK "BEGIN { print $select_i - 1 }"`
+	  shift $(($select_i - 1))
 	  select_result=$1
 	  break
 	fi
@@ -170,7 +155,7 @@ do
   esac
 done
 
-shift `$AWK "BEGIN { print $OPTIND - 1 }"`
+shift $(($OPTIND - 1))
 case $# in
 0) ;;
 *) say >&2 "$0: $1: unknown argument"; exit 1
@@ -178,11 +163,13 @@ esac
 
 # translit=true to try transliteration.
 # This is false if U+12345 CUNEIFORM SIGN URU TIMES KI has length 1
-# which means awk (and presumably the shell) do not need transliteration.
-if $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) == 1 }'; then
-  translit=true
-else
-  translit=false
+# which means the shell and (presumably) awk do not need transliteration.
+# It is true if the byte string has some other length in characters, or
+# if this is a POSIX.1-2017 or earlier shell that does not support $'...'.
+CUNEIFORM_SIGN_URU_TIMES_KI=$'\360\222\215\205'
+if test ${#CUNEIFORM_SIGN_URU_TIMES_KI} = 1
+then translit=false
+else translit=true
 fi
 
 # Read into shell variable $1 the contents of file $2.
@@ -192,10 +179,10 @@ fi
 # if that does not work, fall back on 'cat'.
 read_file() {
   { $translit && {
-    eval "$1=\`(iconv -f UTF-8 -t //TRANSLIT) 2>/dev/null <\"\$2\"\`" ||
-    eval "$1=\`(iconv -f UTF-8) 2>/dev/null <\"\$2\"\`"
+    eval "$1=\$( (iconv -f UTF-8 -t //TRANSLIT) 2>/dev/null <\"\$2\")" ||
+    eval "$1=\$( (iconv -f UTF-8) 2>/dev/null <\"\$2\")"
   }; } ||
-  eval "$1=\`cat <\"\$2\"\`" || {
+  eval "$1=\$(cat <\"\$2\")" || {
     say >&2 "$0: time zone files are not set up correctly"
     exit 1
   }
@@ -403,7 +390,7 @@ while
     echo >&2 \
       'Please select a continent, ocean, "coord", "TZ", "time", or "now".'
 
-    quoted_continents=`
+    quoted_continents=$(
       $AWK '
 	function handle_entry(entry) {
 	  entry = substr(entry, 1, index(entry, "/") - 1)
@@ -433,12 +420,12 @@ while
       sort -u |
       tr '\n' ' '
       echo ''
-    `
+    )
 
     eval '
       doselect '"$quoted_continents"' \
 	"coord - I want to use geographical coordinates." \
-	"TZ - I want to specify the timezone using a POSIX.1-2017 TZ string." \
+	"TZ - I want to specify the timezone using a proleptic TZ string." \
 	"time - I know local time already." \
 	"now - Like \"time\", but configure only for timestamps from now on."
       continent=$select_result
@@ -462,16 +449,17 @@ while
 
   case $continent in
   TZ)
-    # Ask the user for a POSIX.1-2017 TZ string.  Check that it conforms.
+    # Ask the user for a proleptic TZ string.  Check that it conforms.
     check_POSIX_TZ_string='
       BEGIN {
 	tz = substr(ARGV[1], 2)
 	ARGV[1] = ""
 	tzname = ("(<[[:alnum:]+-][[:alnum:]+-][[:alnum:]+-]+>" \
 		  "|[[:alpha:]][[:alpha:]][[:alpha:]]+)")
-	time = ("(2[0-4]|[0-1]?[0-9])" \
-		"(:[0-5][0-9](:[0-5][0-9])?)?")
-	offset = "[-+]?" time
+	sign = "[-+]?"
+	hhmm = "(:[0-5][0-9](:[0-5][0-9])?)?"
+	offset = sign "(2[0-4]|[0-1]?[0-9])" hhmm
+	time = sign "(16[0-7]|(1[0-5]|[0-9]?)[0-9])" hhmm
 	mdate = "M([1-9]|1[0-2])\\.[1-5]\\.[0-6]"
 	jdate = ("((J[1-9]|[0-9]|J?[1-9][0-9]" \
 		 "|J?[1-2][0-9][0-9])|J?3[0-5][0-9]|J?36[0-5])")
@@ -492,7 +480,7 @@ while
       read tz
       $AWK "$check_POSIX_TZ_string" ="$tz"
     do
-      say >&2 "'$tz' is not a conforming POSIX.1-2017 timezone string."
+      say >&2 "'$tz' is not a conforming POSIX proleptic TZ string."
     done
     TZ_for_date=$tz;;
   *)
@@ -507,14 +495,14 @@ while
 	  '74 degrees 3 minutes west.'
 	read coord
       esac
-      distance_table=`
+      distance_table=$(
 	$AWK \
 	  "$output_distances_or_times" \
 	  ="$coord" ="$TZ_COUNTRY_TABLE" ="$TZ_ZONE_TABLE" |
 	sort -n |
 	$AWK "{print} NR == $location_limit { exit }"
-      `
-      regions=`
+      )
+      regions=$(
 	$AWK '
 	  BEGIN {
 	    distance_table = substr(ARGV[1], 2)
@@ -526,13 +514,13 @@ while
 	    }
 	  }
 	' ="$distance_table"
-      `
+      )
       echo >&2 'Please select one of the following timezones,'
       echo >&2 'listed roughly in increasing order' \
 	"of distance from $coord".
       doselect $regions
       region=$select_result
-      tz=`
+      tz=$(
 	$AWK '
 	  BEGIN {
 	    distance_table = substr(ARGV[1], 2)
@@ -546,22 +534,22 @@ while
 	    }
 	  }
 	' ="$distance_table" ="$region"
-      `;;
+      );;
     *)
       case $continent in
       now|time)
 	minute_format='%a %b %d %H:%M'
-	old_minute=`TZ=UTC0 date +"$minute_format"`
+	old_minute=$(TZ=UTC0 date +"$minute_format")
 	for i in 1 2 3
 	do
-	  time_table_command=`
+	  time_table_command=$(
 	    $AWK \
 	      -v output_times=1 \
 	      "$output_distances_or_times" \
 	      = = ="$TZ_ZONE_TABLE"
-	  `
-	  time_table=`eval "$time_table_command"`
-	  new_minute=`TZ=UTC0 date +"$minute_format"`
+	  )
+	  time_table=$(eval "$time_table_command")
+	  new_minute=$(TZ=UTC0 date +"$minute_format")
 	  case $old_minute in
 	  "$new_minute") break
 	  esac
@@ -569,11 +557,11 @@ while
 	done
 	echo >&2 "The system says Universal Time is $new_minute."
 	echo >&2 "Assuming that's correct, what is the local time?"
-	sorted_table=`say "$time_table" | sort -k2n -k2,5 -k1n` || {
+	sorted_table=$(say "$time_table" | sort -k2n -k2,5 -k1n) || {
 	  say >&2 "$0: cannot sort time table"
 	  exit 1
 	}
-	eval doselect `
+	eval doselect $(
 	  $AWK '
 	    BEGIN {
 	      sorted_table = substr(ARGV[1], 2)
@@ -590,10 +578,10 @@ while
 	      }
 	    }
 	  ' ="$sorted_table"
-	`
+	)
 	time=$select_result
 	continent_re='^'
-	zone_table=`
+	zone_table=$(
 	  $AWK '
 	    BEGIN {
 	      time = substr(ARGV[1], 2)
@@ -609,13 +597,13 @@ while
 	      }
 	    }
 	  ' ="$time" ="$time_table"
-	`
-	countries=`
+	)
+	countries=$(
 	  $AWK \
 	    "$output_country_list" \
 	    ="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" |
 	  sort -f
-	`
+	)
 	;;
       *)
 	continent_re="^$continent/"
@@ -623,16 +611,16 @@ while
       esac
 
       # Get list of names of countries in the continent or ocean.
-      countries=`
+      countries=$(
 	$AWK \
 	  "$output_country_list" \
 	  ="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" |
 	sort -f
-      `
+      )
       # If all zone table entries have comments, and there are
       # at most 22 entries, asked based on those comments.
       # This fits the prompt onto old-fashioned 24-line screens.
-      regions=`
+      regions=$(
 	$AWK '
 	  BEGIN {
 	    TZ_ZONE_TABLE = substr(ARGV[1], 2)
@@ -653,7 +641,7 @@ while
 		print comment[i]
 	  }
 	' ="$zone_table"
-      `
+      )
 
       # If there's more than one country, ask the user which one.
       case $countries in
@@ -669,7 +657,7 @@ while
 
 
       # Get list of timezones in the country.
-      regions=`
+      regions=$(
 	$AWK '
 	  BEGIN {
 	    country = substr(ARGV[1], 2)
@@ -696,7 +684,7 @@ while
 	    }
 	  }
 	' ="$country" ="$TZ_COUNTRY_TABLE" ="$zone_table"
-      `
+      )
 
       # If there's more than one region, ask the user which one.
       case $regions in
@@ -707,7 +695,7 @@ while
       esac
 
       # Determine tz from country and region.
-      tz=`
+      tz=$(
 	$AWK '
 	  BEGIN {
 	    country = substr(ARGV[1], 2)
@@ -735,7 +723,7 @@ while
 	    }
 	  }
 	' ="$country" ="$region" ="$TZ_COUNTRY_TABLE" ="$zone_table"
-      `
+      )
     esac
 
     # Make sure the corresponding zoneinfo file exists.
@@ -754,14 +742,11 @@ while
   extra_info=
   for i in 1 2 3 4 5 6 7 8
   do
-    TZdate=`LANG=C TZ="$TZ_for_date" date`
-    UTdate=`LANG=C TZ=UTC0 date`
-    if $AWK '
-	  function getsecs(d) {
-	    return match(d, /.*:[0-5][0-9]/) ? substr(d, RLENGTH - 1, 2) : ""
-	  }
-	  BEGIN { exit getsecs(ARGV[1]) != getsecs(ARGV[2]) }
-       ' ="$TZdate" ="$UTdate"
+    TZdate=$(LANG=C TZ="$TZ_for_date" date)
+    UTdate=$(LANG=C TZ=UTC0 date)
+    TZsecsetc=${TZdate##*[0-5][0-9]:}
+    UTsecsetc=${UTdate##*[0-5][0-9]:}
+    if test "${TZsecsetc%%[!0-9]*}" = "${UTsecsetc%%[!0-9]*}"
     then
       extra_info="
 Selected time is now:	$TZdate.
@@ -801,7 +786,7 @@ done
 
 case $SHELL in
 *csh) file=.login line="setenv TZ '$tz'";;
-*)    file=.profile line="TZ='$tz'; export TZ"
+*)    file=.profile line="export TZ='$tz'"
 esac
 
 test -t 1 && say >&2 "