misc/143142: [PATCH] Fix non-POSIX compliant multiline conditional in portsnap(1)

Garrett Cooper gcooper at FreeBSD.org
Sun Jan 24 06:10:02 UTC 2010


>Number:         143142
>Category:       misc
>Synopsis:       [PATCH] Fix non-POSIX compliant multiline conditional in portsnap(1)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jan 24 06:10:00 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Garrett Cooper
>Release:        9-CURRENT
>Organization:
Ironport
>Environment:
[gcooper at optimus /usr/ports]$ uname -a
FreeBSD optimus.zenmetsuhitotuyaneshita.net 9.0-CURRENT FreeBSD 9.0-CURRENT #0: Thu Jan  7 17:03:57 PST 2010     root at optimus.zenmetsuhitotuyaneshita.net:/usr/obj/usr/src/sys/OPTIMUS  amd64
>Description:
Over a year ago, I submitted an email to determine why bash didn't function with portsnap because I tried updating my ports via my Mac, because at the time I didn't have a network connection in my apartment. bash is the system shell on Mac, and thus it failed to execute, like so:

[gcooper at optimus /usr/ports]$ bash `which portsnap`
/usr/sbin/portsnap: line 882: syntax error near unexpected token `newline'
/usr/sbin/portsnap: line 882: ` if !'

According to the bash folks (<http://www.mail-archive.com/bug-bash@gnu.org/msg04116.html>), multiline // inline conditionals aren't POSIX compliant. Thus, there are two issues with how portsnap is coded today. The attached patch takes care of those issues, and also swaps out `basename $0` for ${0##*/} (equivalent logic in Bourne shell).

This has been tested on sh in -CURRENT and bash 4.x, and there isn't a regression with the affected logic paths when doing:

portsnap fetch extract

Additional blocks may or may not need to be tested.
>How-To-Repeat:
bash `which portsnap`
>Fix:
See attached patch.

Patch attached with submission follows:

Index: portsnap.sh
===================================================================
--- portsnap.sh	(revision 202909)
+++ portsnap.sh	(working copy)
@@ -34,7 +34,7 @@
 # --no-stats	-- don't show progress statistics while fetching files
 usage() {
 	cat <<EOF
-usage: `basename $0` [options] command ... [path]
+usage: ${0##*/} [options] command ... [path]
 
 Options:
   -d workdir   -- Store working files in workdir
@@ -240,23 +240,23 @@
 	_WORKDIR_bad="Directory does not exist or is not writable: "
 
 	if [ -z "${SERVERNAME}" ]; then
-		echo -n "`basename $0`: "
+		echo -n "${0##*/}: "
 		echo "${_SERVERNAME_z}"
 		exit 1
 	fi
 	if [ -z "${KEYPRINT}" ]; then
-		echo -n "`basename $0`: "
+		echo -n "${0##*/}: "
 		echo "${_KEYPRINT_z}"
 		exit 1
 	fi
 	if ! echo "${KEYPRINT}" | grep -qE "^[0-9a-f]{64}$"; then
-		echo -n "`basename $0`: "
+		echo -n "${0##*/}: "
 		echo -n "${_KEYPRINT_bad}"
 		echo ${KEYPRINT}
 		exit 1
 	fi
 	if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then
-		echo -n "`basename $0`: "
+		echo -n "${0##*/}: "
 		echo -n "${_WORKDIR_bad}"
 		echo ${WORKDIR}
 		exit 1
@@ -277,13 +277,13 @@
 	_PORTSDIR_bad="Directory is not writable: "
 
 	if ! [ -d "${WORKDIR}" ]; then
-		echo -n "`basename $0`: "
+		echo -n "${0##*/}: "
 		echo -n "${_WORKDIR_bad}"
 		echo ${WORKDIR}
 		exit 1
 	fi
 	if [ -d "${PORTSDIR}" ] && ! [ -w "${PORTSDIR}" ]; then
-		echo -n "`basename $0`: "
+		echo -n "${0##*/}: "
 		echo -n "${_PORTSDIR_bad}"
 		echo ${PORTSDIR}
 		exit 1
@@ -292,7 +292,7 @@
 	if ! [ -d "${WORKDIR}/files" -a -r "${WORKDIR}/tag"	\
 	    -a -r "${WORKDIR}/INDEX" -a -r "${WORKDIR}/tINDEX" ]; then
 		echo "No snapshot available.  Try running"
-		echo "# `basename $0` fetch"
+		echo "# ${0##*/} fetch"
 		exit 1
 	fi
 
@@ -306,8 +306,8 @@
 
 	if ! [ -r ${PORTSDIR}/.portsnap.INDEX ]; then
 		echo "${PORTSDIR} was not created by portsnap."
-		echo -n "You must run '`basename $0` extract' before "
-		echo "running '`basename $0` update'."
+		echo -n "You must run '${0##*/} extract' before "
+		echo "running '${0##*/} update'."
 		exit 1
 	fi
 
@@ -584,7 +584,7 @@
 fetch_progress() {
 	LNC=0
 	while read x; do
-		LNC=$(($LNC + 1))
+		: $(( LNC += 1 ))
 		if [ $(($LNC % 10)) = 0 ]; then
 			echo -n $LNC
 		elif [ $(($LNC % 2)) = 0 ]; then
@@ -879,35 +879,30 @@
 extract_run() {
 	mkdir -p ${PORTSDIR} || return 1
 
-	if !
-		if ! [ -z "${EXTRACTPATH}" ]; then
-			grep "^${EXTRACTPATH}" ${WORKDIR}/INDEX
-		elif ! [ -z "${REFUSE}" ]; then
-			grep -vE "${REFUSE}" ${WORKDIR}/INDEX
-		else
-			cat ${WORKDIR}/INDEX
-		fi | tr '|' ' ' | while read FILE HASH; do
-		echo ${PORTSDIR}/${FILE}
-		if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then
-			echo "files/${HASH}.gz not found -- snapshot corrupt."
-			return 1
-		fi
-		case ${FILE} in
-		*/)
-			rm -rf ${PORTSDIR}/${FILE%/}
-			mkdir -p ${PORTSDIR}/${FILE}
-			tar -xzf ${WORKDIR}/files/${HASH}.gz	\
-			    -C ${PORTSDIR}/${FILE}
-			;;
-		*)
-			rm -f ${PORTSDIR}/${FILE}
-			tar -xzf ${WORKDIR}/files/${HASH}.gz	\
-			    -C ${PORTSDIR} ${FILE}
-			;;
-		esac
-	done; then
+	(if ! [ -z "${EXTRACTPATH}" ]; then
+		grep "^${EXTRACTPATH}" ${WORKDIR}/INDEX
+	elif ! [ -z "${REFUSE}" ]; then
+		grep -vE "${REFUSE}" ${WORKDIR}/INDEX
+	else
+		cat ${WORKDIR}/INDEX
+	fi) | tr '|' ' ' | while read FILE HASH; do
+	echo ${PORTSDIR}/${FILE}
+	if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then
+		echo "files/${HASH}.gz not found -- snapshot corrupt."
 		return 1
 	fi
+	case ${FILE} in
+	*/)
+		rm -rf ${PORTSDIR}/${FILE%/}
+		mkdir -p ${PORTSDIR}/${FILE}
+		tar -xzf ${WORKDIR}/files/${HASH}.gz -C ${PORTSDIR}/${FILE}
+		;;
+	*)
+		rm -f ${PORTSDIR}/${FILE}
+		tar -xzf ${WORKDIR}/files/${HASH}.gz -C ${PORTSDIR} ${FILE}
+		;;
+	esac; done
+	[ $? -ne 0 ] && return 1
 	if [ ! -z "${EXTRACTPATH}" ]; then
 		return 0;
 	fi
@@ -948,14 +943,11 @@
 
 # Install new files
 	echo "Extracting new files:"
-	if !
-		if ! [ -z "${REFUSE}" ]; then
-			grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort
-		else
-			sort ${WORKDIR}/INDEX
-		fi |
-	    comm -13 ${PORTSDIR}/.portsnap.INDEX - |
-	    while read LINE; do
+	(if ! [ -z "${REFUSE}" ]; then
+		grep -vE "${REFUSE}" ${WORKDIR}/INDEX | sort
+	else
+		sort ${WORKDIR}/INDEX
+	fi) | comm -13 ${PORTSDIR}/.portsnap.INDEX - | while read LINE; do
 		FILE=`echo ${LINE} | cut -f 1 -d '|'`
 		HASH=`echo ${LINE} | cut -f 2 -d '|'`
 		echo ${PORTSDIR}/${FILE}
@@ -974,9 +966,8 @@
 			    -C ${PORTSDIR} ${FILE}
 			;;
 		esac
-	done; then
-		return 1
-	fi
+	done
+	[ $? -ne 0 ] && return 1
 
 	extract_metadata
 	extract_indices
@@ -999,9 +990,9 @@
 # interactively, then run fetch_check_params and fetch_run
 cmd_fetch() {
 	if [ ! -t 0 ]; then
-		echo -n "`basename $0` fetch should not "
+		echo -n "${0##*/} fetch should not "
 		echo "be run non-interactively."
-		echo "Run `basename $0` cron instead."
+		echo "Run ${0##*/} cron instead."
 		exit 1
 	fi
 	fetch_check_params


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list