[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[patches] Patch: Eliminate ksh-dependency in tzselect



This patch (which I think is right, but I haven't retested it since I first set it up) removes the dependency on ksh from tzselect.

Looking at the code associated with ldd and xtrace, it looks like there is already some support in the elf/Makefile code for building ldd for plain-old-sh, by stripping the leading $. This used to have an additional problem ("set -o pipefail" caused ash to exit rather than merely failing), but that seems to be fixed.

We have some interest in seeing this fixed, since we like to ship tiny filesystems without bash or ksh. (Requiring ash rather than msh is fine by me.)

Copyright issues: The substantive thing here is func_select, which is actually mine personally (it's from my shell book) rather than WRS's. I don't think anyone cares about the ownership of the change from "select" to "while func_select", but you're welcome to it. I have given the func_select code away before and I believe I've placed it in the public domain.

This needs more testing than I have time for right now, but the basic trick of reimplementing select as a function is well-tested.

--- glibc-2.8.orig/timezone/tzselect.ksh 2009-06-22 11:23:11.000000000 -0700
+++ glibc-2.8/timezone/tzselect.sh	2009-06-22 11:52:26.000000000 -0700
@@ -1,27 +1,16 @@
-#! @KSH@
+#! @SH@

-# '@(#)tzselect.ksh	8.1'
+# '@(#)tzselect.sh	8.1'

# Ask the user about the time zone, and output the resulting TZ value to stdout.
 # Interact with the user via stderr and stdin.

 # Contributed by Paul Eggert.

-# Porting notes:
-#
-# This script requires several features of the Korn shell.
-# If your host lacks the Korn shell,
-# you can use either of the following free programs instead:
-#
-#	<a href=ftp://ftp.gnu.org/pub/gnu/>
-#	Bourne-Again shell (bash)
-#	</a>
-#
-#	<a href=ftp://ftp.cs.mun.ca/pub/pdksh/pdksh.tar.gz>
-#	Public domain ksh
-#	</a>
-#
-# This script also uses several features of modern awk programs.
+# func_select allows this script to run on shells (such as busybox ash)
+# which lack the ksh "select" builtin.
+
+# This script uses several features of modern awk programs.
# If your host lacks awk, or has an old awk that does not conform to Posix.2,
 # you can use either of the following free programs instead:
 #
@@ -33,6 +22,70 @@
 #	mawk
 #	</a>

+# Implement ksh-style select in POSIX shell
+
+# We need a mostly-portable echo-n.
+case `echo -n "foo\c"` in
+*n*c*)  func_echo_n() { echo "$*"; } ;;
+*n*)    func_echo_n() { echo "$*\c"; } ;;
+*)      func_echo_n() { echo -n "$*"; } ;;
+esac
+
+# Synopsis: Replace "select foo in list" with "while func_select foo in list"
+# and this works just like ksh, so far as I know.
+func_select () {
+	func_select_args=0
+	if expr "$1" : "^[_a-zA-Z][_a-zA-Z0-9]*$" > /dev/null; then
+		func_select_var=$1
+	else
+		echo >&2 "func_select: '$1' is not a valid variable name."
+		return 1
+	fi
+	shift 1
+	case $1 in
+		in) shift 1;;
+ *) echo >&2 "func_select: usage: func_select var in ... (you must provide
+arguments)"; return 1;;
+	esac
+	case $# in
+		0) echo >&2 "func_select: usage: func_select var in ..."; return 1;;
+	esac
+	for func_select_arg
+	do
+		func_select_args=`expr $func_select_args + 1`
+		eval func_select_a_$func_select_args=\$func_select_arg
+	done
+	REPLY=""
+	while :
+	do
+		if test -z "$REPLY"; then
+			func_select_i=1
+			while test $func_select_i -le $func_select_args
+			do
+				eval echo "\"\$func_select_i) \$func_select_a_$func_select_i\""
+				func_select_i=`expr $func_select_i + 1`
+			done
+		fi
+		func_echo_n "${PS3-#? }" >&2
+		if read REPLY; then
+			if test -n "${REPLY}"; then
+				if expr "$REPLY" : '^[1-9][0-9]*$' > /dev/null; then
+ if test "$REPLY" -ge 1 && test "$REPLY" -le $func_select_args; then
+						eval $func_select_var=\$func_select_a_$REPLY
+					else
+						eval $func_select_var=
+					fi
+				else
+					eval $func_select_var=
+				fi
+				return 0
+			fi
+		else
+			eval $func_select_var=
+			return 1
+		fi
+	done
+}

 # Specify default values for environment variables if they are unset.
 : ${AWK=awk}
@@ -62,7 +115,7 @@


# 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
+case $(echo 1 | (while func_select x in x; do break; done) 2>/dev/ null) in
 ?*) PS3=
 esac

@@ -82,7 +135,7 @@

 	echo >&2 'Please select a continent or ocean.'

-	select continent in \
+	while func_select continent in \
 	    Africa \
 	    Americas \
 	    Antarctica \
@@ -162,7 +215,7 @@
 		case $countries in
 		*"$newline"*)
 			echo >&2 'Please select a country.'
-			select country in $countries
+			while func_select country in $countries
 			do
 			    case $country in
 			    '') echo >&2 'Please enter a number in range.';;
@@ -201,7 +254,7 @@
 		*"$newline"*)
 			echo >&2 'Please select one of the following' \
 				'time zone regions.'
-			select region in $regions
+			while func_select region in $regions
 			do
 				case $region in
 				'') echo >&2 'Please enter a number in range.';;
@@ -278,7 +331,7 @@
 	echo >&2 "Is the above information OK?"

 	ok=
-	select ok in Yes No
+	while func_select ok in Yes No
 	do
 	    case $ok in
 	    '') echo >&2 'Please enter 1 for Yes, or 2 for No.';;

--
Peter Seebach <peter.seebach@xxxxxxxxxxxxx>
Listen, get this.  Nobody with a good compiler needs to be justified.