Patchwork Replace "echo -e" with "printf" to have the same behavior in dash or bash

login
register
mail settings
Submitter Andrei Gherzan
Date Sept. 20, 2012, 8:44 a.m.
Message ID <1348130679-31552-1-git-send-email-andrei@gherzan.ro>
Download mbox | patch
Permalink /patch/36951/
State New
Headers show

Comments

Andrei Gherzan - Sept. 20, 2012, 8:44 a.m.
oe-core removed the prerequisite to have sh as bash. POSIX doesn't define
any options and furthermore allows echo -e to be the default behavior.
This means that in dash "echo -e" will actually print "-e" and interpret
backslashes by default. We use instead "printf" builtin command with or
without "\n" to simulate echo -e or echo -n.

[YOCTO #3138]

Signed-off-by: Andrei Gherzan <andrei@gherzan.ro>
---
 meta/classes/buildhistory.bbclass                 |    6 +++---
 meta/classes/cml1.bbclass                         |    2 +-
 meta/classes/license.bbclass                      |    6 +++---
 meta/classes/package_deb.bbclass                  |    2 +-
 meta/classes/package_ipk.bbclass                  |    2 +-
 meta/classes/package_rpm.bbclass                  |    6 +++---
 meta/classes/populate_sdk_base.bbclass            |    8 ++++----
 meta/recipes-core/base-files/base-files_3.0.14.bb |    8 ++++----
 meta/recipes-extended/libzypp/libzypp_git.bb      |    4 ++--
 meta/recipes-extended/lsb/lsb_4.1.bb              |    6 +++---
 scripts/contrib/ddimage                           |    2 +-
 11 files changed, 26 insertions(+), 26 deletions(-)
Paul Eggleton - Sept. 20, 2012, 9:13 a.m.
On Thursday 20 September 2012 11:44:39 Andrei Gherzan wrote:
> oe-core removed the prerequisite to have sh as bash. POSIX doesn't define
> any options and furthermore allows echo -e to be the default behavior.
> This means that in dash "echo -e" will actually print "-e" and interpret
> backslashes by default. We use instead "printf" builtin command with or
> without "\n" to simulate echo -e or echo -n.

I haven't looked over the whole patch, but I did notice a couple of issues - 
printf does not behave exactly like echo in a couple of situations: 

 (a) if you supply no arguments printf will return an error whereas echo does 
not, this will probably break situations where you have changed the script to 
do 'printf > /some/file'. Since these statements are usually intended to create 
or truncate the specified file, I wonder if we should just change these to do '> 
/some/file' instead which works for dash and bash (and doesn't otherwise appear 
to be a bashism).

 (b) 'printf "\n"' will print just one newline, whereas echo -e "\n" prints 
two. Not sure if this is significant but I think we would rather keep the 
behaviour the same.

Cheers,
Paul
Andrei Gherzan - Sept. 20, 2012, 9:17 a.m.
On Thu, Sep 20, 2012 at 12:13 PM, Paul Eggleton <
paul.eggleton@linux.intel.com> wrote:

> On Thursday 20 September 2012 11:44:39 Andrei Gherzan wrote:
> > oe-core removed the prerequisite to have sh as bash. POSIX doesn't define
> > any options and furthermore allows echo -e to be the default behavior.
> > This means that in dash "echo -e" will actually print "-e" and interpret
> > backslashes by default. We use instead "printf" builtin command with or
> > without "\n" to simulate echo -e or echo -n.
>
> I haven't looked over the whole patch, but I did notice a couple of issues
> -
> printf does not behave exactly like echo in a couple of situations:
>
>  (a) if you supply no arguments printf will return an error whereas echo
> does
> not, this will probably break situations where you have changed the script
> to
> do 'printf > /some/file'. Since these statements are usually intended to
> create
> or truncate the specified file, I wonder if we should just change these to
> do '>
> /some/file' instead which works for dash and bash (and doesn't otherwise
> appear
> to be a bashism).
>
>
Already fixed. Patch was on the way.


>  (b) 'printf "\n"' will print just one newline, whereas echo -e "\n" prints
> two. Not sure if this is significant but I think we would rather keep the
> behaviour the same.
>
>
I didn't notice this but you are right. Just tested... I will add this as
well. Thank you.

ag

Patch

diff --git a/meta/classes/buildhistory.bbclass b/meta/classes/buildhistory.bbclass
index e121088..8519c74 100644
--- a/meta/classes/buildhistory.bbclass
+++ b/meta/classes/buildhistory.bbclass
@@ -293,13 +293,13 @@  buildhistory_get_image_installed() {
 	# Change delimiter from pipe to -> and set style for recommend lines
 	sed -i -e 's:|: -> :' -e 's:\[REC\]:[style=dotted]:' -e 's:$:;:' ${BUILDHISTORY_DIR_IMAGE}/depends.tmp
 	# Add header, sorted and de-duped contents and footer and then delete the temp file
-	echo -e "digraph depends {\n    node [shape=plaintext]" > ${BUILDHISTORY_DIR_IMAGE}/depends.dot
+	printf "digraph depends {\n    node [shape=plaintext]" > ${BUILDHISTORY_DIR_IMAGE}/depends.dot
 	cat ${BUILDHISTORY_DIR_IMAGE}/depends.tmp | sort | uniq >> ${BUILDHISTORY_DIR_IMAGE}/depends.dot
 	echo "}" >>  ${BUILDHISTORY_DIR_IMAGE}/depends.dot
 	rm ${BUILDHISTORY_DIR_IMAGE}/depends.tmp
 
 	# Produce installed package sizes list
-	echo -n > ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp
+	printf > ${BUILDHISTORY_DIR_IMAGE}/installed-package-sizes.tmp
 	cat $pkgcache | while read pkg pkgfile
 	do
 		if [ -f $pkgfile ] ; then
@@ -330,7 +330,7 @@  buildhistory_get_imageinfo() {
 	( cd ${IMAGE_ROOTFS} && find . -ls | awk '{ if ( $7 ~ /[0-9]/ ) printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, $7, $11, $12, $13 ; else printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, 0, $10, $11, $12 }' | sort -k5 > ${BUILDHISTORY_DIR_IMAGE}/files-in-image.txt )
 
 	# Record some machine-readable meta-information about the image
-	echo -n > ${BUILDHISTORY_DIR_IMAGE}/image-info.txt
+	printf > ${BUILDHISTORY_DIR_IMAGE}/image-info.txt
 	cat >> ${BUILDHISTORY_DIR_IMAGE}/image-info.txt <<END
 ${@buildhistory_get_imagevars(d)}
 END
diff --git a/meta/classes/cml1.bbclass b/meta/classes/cml1.bbclass
index 67f17ad..37ed792 100644
--- a/meta/classes/cml1.bbclass
+++ b/meta/classes/cml1.bbclass
@@ -20,7 +20,7 @@  python do_menuconfig() {
         except OSError:
             mtime = 0
 
-        oe_terminal("${SHELL} -c \"make menuconfig; if [ $? -ne 0 ]; then echo 'Command failed.'; echo -n 'Press any key to continue... '; read r; fi\"", '${PN} Configuration', d)
+        oe_terminal("${SHELL} -c \"make menuconfig; if [ $? -ne 0 ]; then echo 'Command failed.'; printf 'Press any key to continue... '; read r; fi\"", '${PN} Configuration', d)
 
         # FIXME this check can be removed when the minimum bitbake version has been bumped
         if hasattr(bb.build, 'write_taint'):
diff --git a/meta/classes/license.bbclass b/meta/classes/license.bbclass
index 29fe938..024e579 100644
--- a/meta/classes/license.bbclass
+++ b/meta/classes/license.bbclass
@@ -112,16 +112,16 @@  license_create_manifest() {
 		echo "PACKAGE NAME:" ${pkg} >> ${LICENSE_MANIFEST}
 		echo "PACKAGE VERSION:" ${pkged_pv} >> ${LICENSE_MANIFEST}
 		echo "RECIPE NAME:" ${pkged_pn} >> ${LICENSE_MANIFEST}
-		echo -n "LICENSE:" >> ${LICENSE_MANIFEST}
+		printf "LICENSE:" >> ${LICENSE_MANIFEST}
 		for lic in ${pkged_lic}; do
 			# to reference a license file trim trailing + symbol
 			if [ -e "${LICENSE_DIRECTORY}/${pkged_pn}/generic_${lic%+}" ]; then
-				echo -n " ${lic}" >> ${LICENSE_MANIFEST}
+				printf " ${lic}" >> ${LICENSE_MANIFEST}
 			else
 				echo "WARNING: The license listed ${lic} was not in the licenses collected for ${pkged_pn}"
 			fi
 		done
-		echo -e "\n" >> ${LICENSE_MANIFEST}
+		printf "\n" >> ${LICENSE_MANIFEST}
 	done
 
 	# Two options here:
diff --git a/meta/classes/package_deb.bbclass b/meta/classes/package_deb.bbclass
index 48511df..a6d4e02 100644
--- a/meta/classes/package_deb.bbclass
+++ b/meta/classes/package_deb.bbclass
@@ -192,7 +192,7 @@  deb_log_check() {
 		if (echo "$lf_txt" | grep -v log_check | grep "$keyword_die") >/dev/null 2>&1
 		then
 			echo "log_check: There were error messages in the logfile"
-			echo -e "log_check: Matched keyword: [$keyword_die]\n"
+			printf "log_check: Matched keyword: [$keyword_die]\n"
 			echo "$lf_txt" | grep -v log_check | grep -C 5 -i "$keyword_die"
 			echo ""
 			do_exit=1
diff --git a/meta/classes/package_ipk.bbclass b/meta/classes/package_ipk.bbclass
index e94586e..dbf0feb 100644
--- a/meta/classes/package_ipk.bbclass
+++ b/meta/classes/package_ipk.bbclass
@@ -181,7 +181,7 @@  ipk_log_check() {
 		if (echo "$lf_txt" | grep -v log_check | grep "$keyword_die") >/dev/null 2>&1
 		then
 			echo "log_check: There were error messages in the logfile"
-			echo -e "log_check: Matched keyword: [$keyword_die]\n"
+			printf "log_check: Matched keyword: [$keyword_die]\n"
 			echo "$lf_txt" | grep -v log_check | grep -C 5 -i "$keyword_die"
 			echo ""
 			do_exit=1
diff --git a/meta/classes/package_rpm.bbclass b/meta/classes/package_rpm.bbclass
index 61f0117..0972af5 100644
--- a/meta/classes/package_rpm.bbclass
+++ b/meta/classes/package_rpm.bbclass
@@ -110,7 +110,7 @@  rpm_log_check() {
 		if (echo "$lf_txt" | grep -v log_check | grep "$keyword_die") >/dev/null 2>&1
 		then
 			echo "log_check: There were error messages in the logfile"
-			echo -e "log_check: Matched keyword: [$keyword_die]\n"
+			printf "log_check: Matched keyword: [$keyword_die]\n"
 			echo "$lf_txt" | grep -v log_check | grep -C 5 -i "$keyword_die"
 			echo ""
 			do_exit=1
@@ -211,8 +211,8 @@  process_pkg_list_rpm() {
 	pkgs="$@"
 	local confbase=${INSTALL_CONFBASE_RPM}
 
-	echo -n > ${target_rootfs}/install/base_archs.pkglist
-	echo -n > ${target_rootfs}/install/ml_archs.pkglist
+	printf > ${target_rootfs}/install/base_archs.pkglist
+	printf > ${target_rootfs}/install/ml_archs.pkglist
 
 	for pkg in $pkgs; do
 		echo "Processing $pkg..."
diff --git a/meta/classes/populate_sdk_base.bbclass b/meta/classes/populate_sdk_base.bbclass
index 1c151d7..2bff41f 100644
--- a/meta/classes/populate_sdk_base.bbclass
+++ b/meta/classes/populate_sdk_base.bbclass
@@ -118,7 +118,7 @@  fakeroot create_shar() {
 
 DEFAULT_INSTALL_DIR="${SDKPATH}"
 
-echo -n "Enter target directory for Poky SDK (default: $DEFAULT_INSTALL_DIR): "
+printf "Enter target directory for Poky SDK (default: $DEFAULT_INSTALL_DIR): "
 read target_sdk_dir
 
 if [ "$target_sdk_dir" = "" ]; then
@@ -128,7 +128,7 @@  fi
 eval target_sdk_dir=$target_sdk_dir
 target_sdk_dir=$(readlink -m $target_sdk_dir)
 
-echo -n "You are about to install Poky SDK to \"$target_sdk_dir\". Proceed[Y/n]?"
+printf "You are about to install Poky SDK to \"$target_sdk_dir\". Proceed[Y/n]?"
 read answer
 
 if [ "$answer" = "" ]; then
@@ -148,11 +148,11 @@  fi
 
 payload_offset=$(($(grep -na -m1 "^MARKER:$" $(basename $0)|cut -d':' -f1) + 1))
 
-echo -n "Extracting SDK..."
+printf "Extracting SDK..."
 tail -n +$payload_offset $(basename $0) | tar xj --strip-components=4 -C $target_sdk_dir
 echo "done"
 
-echo -n "Setting it up..."
+printf "Setting it up..."
 # fix environment paths
 env_setup_script=$(find $target_sdk_dir -name "environment-setup-${REAL_MULTIMACH_TARGET_SYS}")
 sed -e "s:$DEFAULT_INSTALL_DIR:$target_sdk_dir:g" -i $env_setup_script
diff --git a/meta/recipes-core/base-files/base-files_3.0.14.bb b/meta/recipes-core/base-files/base-files_3.0.14.bb
index e80cff1..ba355ee 100644
--- a/meta/recipes-core/base-files/base-files_3.0.14.bb
+++ b/meta/recipes-core/base-files/base-files_3.0.14.bb
@@ -117,11 +117,11 @@  do_install_basefilesissue () {
 
 	install -m 644 ${WORKDIR}/issue*  ${D}${sysconfdir}  
         if [ -n "${DISTRO_NAME}" ]; then
-		echo -n "${DISTRO_NAME} " >> ${D}${sysconfdir}/issue
-		echo -n "${DISTRO_NAME} " >> ${D}${sysconfdir}/issue.net
+		printf "${DISTRO_NAME} " >> ${D}${sysconfdir}/issue
+		printf "${DISTRO_NAME} " >> ${D}${sysconfdir}/issue.net
 		if [ -n "${DISTRO_VERSION}" ]; then
-			echo -n "${DISTRO_VERSION} " >> ${D}${sysconfdir}/issue
-			echo -n "${DISTRO_VERSION} " >> ${D}${sysconfdir}/issue.net
+			printf "${DISTRO_VERSION} " >> ${D}${sysconfdir}/issue
+			printf "${DISTRO_VERSION} " >> ${D}${sysconfdir}/issue.net
 		fi
 		echo "\n \l" >> ${D}${sysconfdir}/issue
 		echo >> ${D}${sysconfdir}/issue
diff --git a/meta/recipes-extended/libzypp/libzypp_git.bb b/meta/recipes-extended/libzypp/libzypp_git.bb
index 3a323e7..1729c78 100644
--- a/meta/recipes-extended/libzypp/libzypp_git.bb
+++ b/meta/recipes-extended/libzypp/libzypp_git.bb
@@ -106,10 +106,10 @@  do_archgen () {
 				continue;;
 		esac
 		if [ "${AVOID_CONSTRUCTOR}" != "true" ]; then
-		  echo -n "  const Arch Arch_${each_arch} " | tr - _		>> zypp/oe-arch.h
+		  printf "  const Arch Arch_${each_arch} " | tr - _		>> zypp/oe-arch.h
 		  echo "(_${each_arch});" | tr - _				>> zypp/oe-arch.h
 		else
-		  echo -n "  const Arch Arch_${each_arch} " | tr - _		>> zypp/oe-arch.h
+		  printf "  const Arch Arch_${each_arch} " | tr - _		>> zypp/oe-arch.h
 		  echo "( IdString ( \"${each_arch}\" ) );" | tr - _		>> zypp/oe-arch.h
 		fi
 	done
diff --git a/meta/recipes-extended/lsb/lsb_4.1.bb b/meta/recipes-extended/lsb/lsb_4.1.bb
index a3242db..55ea241 100644
--- a/meta/recipes-extended/lsb/lsb_4.1.bb
+++ b/meta/recipes-extended/lsb/lsb_4.1.bb
@@ -31,12 +31,12 @@  do_install(){
 	mkdir -p ${D}${base_bindir}
 	mkdir -p ${D}/${baselib}
 	mkdir -p ${D}${sysconfdir}/lsb-release.d
-	echo -n "LSB_VERSION=\"core-4.1-noarch:" > ${D}${sysconfdir}/lsb-release
+	printf "LSB_VERSION=\"core-4.1-noarch:" > ${D}${sysconfdir}/lsb-release
 
 	if [ "${TARGET_ARCH}" = "i586" ];then
-		echo -n "core-4.1-ia32" >>  ${D}${sysconfdir}/lsb-release
+		printf "core-4.1-ia32" >>  ${D}${sysconfdir}/lsb-release
 	else
-		echo -n "core-4.1-${TARGET_ARCH}" >>  ${D}${sysconfdir}/lsb-release
+		printf "core-4.1-${TARGET_ARCH}" >>  ${D}${sysconfdir}/lsb-release
 	fi
 	echo "\"" >> ${D}${sysconfdir}/lsb-release
 	echo "DISTRIB_ID=${DISTRO}" >> ${D}${sysconfdir}/lsb-release
diff --git a/scripts/contrib/ddimage b/scripts/contrib/ddimage
index 2cba9b2..956699c 100755
--- a/scripts/contrib/ddimage
+++ b/scripts/contrib/ddimage
@@ -75,7 +75,7 @@  fi
 image_details $IMAGE
 device_details $(basename $DEVICE)
 
-echo -n "Write $IMAGE to $DEVICE [y/N]? "
+printf "Write $IMAGE to $DEVICE [y/N]? "
 read RESPONSE
 if [ "$RESPONSE" != "y" ]; then
 	echo "Write aborted"