After the error the other day with dash and glibc-2.3.6, I decided to install dash[1] and give it a whirl as /bin/sh. Things went mostly pretty well with respect to rogue bashisms throughout the system. I've attached some patches to fix up the bootscripts while consulting the POSIX spec on shells[2].
First patch is to eliminated "echo -[en]" since it's not always supported by POSIX shells. I chose to use printf since it was a builtin in dash. I didn't notice until later that it's not mentioned in POSIX. And the executable printf is in /usr/bin. We can maintain the same "echo -[en]" syntax by switching in /bin/echo everywhere, too. Second patch is just a tweak for boot_mesg. There's an excessive pipeline using sed and grep to count the characters in the input string. Fortunately, POSIX mandates that shells respect ${#var} to return the length of the string. I chose to add 1 for an extra space (the old way ended up with 2 spaces for some reason). $((...)) can be used for arithmetic expansion according to POSIX. Third patch is a combo because I couldn't keep the diffs separated in the console script. First fix has to do with &> syntax. This is equivalent to ">file 2>&1" according to bash(1), and that syntax is supported by POSIX shells. The second part has to do with trapping on ERR. Although `set -e' is supported in POSIX, trapping is only mandated for signals. So, I just sprinkled a bunch of conditionals through the console script to try to achieve the same effect as the error trapping. Let me know what you guys think. -- Dan [1] http://gondor.apana.org.au/~herbert/dash/ [2] http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
I don't know if printf is the right way to go since POSIX doesn't say it needs to be a builtin from what I can see. If it's not builting, then it's in /usr/bin, which isn't available at boot. All the shells I've looked at have printf builtin, though. Otherwise, we should use /bin/echo, which has the same semantics as bash's echo. Index: bootscripts/lfs/init.d/functions =================================================================== --- bootscripts/lfs/init.d/functions (revision 7926) +++ bootscripts/lfs/init.d/functions (working copy) @@ -40,12 +40,12 @@ COL=$((${COLUMNS} - 8)) WCOL=$((${COL} - 2)) -## Set Cursor Position Commands, used via echo -e +## Set Cursor Position Commands, used via printf SET_COL="\\033[${COL}G" # at the $COL char SET_WCOL="\\033[${WCOL}G" # at the $WCOL char CURS_UP="\\033[1A\\033[0G" # Up one line, at the 0'th char -## Set color commands, used via echo -e +## Set color commands, used via printf # Please consult `man console_codes for more information # under the "ECMA-48 Set Graphics Rendition" section # @@ -79,13 +79,13 @@ #******************************************************************************* boot_mesg() { - local ECHOPARM="" + local ENDCHAR='\n' while true do case "${1}" in -n) - ECHOPARM=" -n " + ENDCHAR= shift 1 ;; -*) @@ -104,7 +104,7 @@ -e 's,.,.,g' -e 'l 1' | grep -c \$`" # Print the message to the screen - echo ${ECHOPARM} -e "${2}${1}" + printf "${2}${1}${ENDCHAR}" } @@ -117,28 +117,25 @@ boot_log() { # Left in for backwards compatibility - echo -n "" + : } echo_ok() { - echo -n -e "${CURS_UP}${SET_COL}${BRACKET}[${SUCCESS} OK ${BRACKET}]" - echo -e "${NORMAL}" - boot_mesg_flush + printf "${CURS_UP}${SET_COL}${BRACKET}[${SUCCESS} OK ${BRACKET}]${NORMAL}\n" + boot_mesg_flush } echo_failure() { - echo -n -e "${CURS_UP}${SET_COL}${BRACKET}[${FAILURE} FAIL ${BRACKET}]" - echo -e "${NORMAL}" - boot_mesg_flush + printf "${CURS_UP}${SET_COL}${BRACKET}[${FAILURE} FAIL ${BRACKET}]${NORMAL}\n" + boot_mesg_flush } echo_warning() { - echo -n -e "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} WARN ${BRACKET}]" - echo -e "${NORMAL}" - boot_mesg_flush + printf "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} WARN ${BRACKET}]${NORMAL}\n" + boot_mesg_flush } print_error_msg() @@ -209,20 +206,20 @@ # may call it this way. case "${2}" in running) - echo -e -n "${CURS_UP}" - echo -e -n "\\033[${STRING_LENGTH}G " + printf "${CURS_UP}" + printf "\\033[${STRING_LENGTH}G " boot_mesg "Already running." ${WARNING} echo_warning ;; not_running) - echo -e -n "${CURS_UP}" - echo -e -n "\\033[${STRING_LENGTH}G " + printf "${CURS_UP}" + printf "\\033[${STRING_LENGTH}G " boot_mesg "Not running." ${WARNING} echo_warning ;; not_available) - echo -e -n "${CURS_UP}" - echo -e -n "\\033[${STRING_LENGTH}G " + printf "${CURS_UP}" + printf "\\033[${STRING_LENGTH}G " boot_mesg "Not available." ${WARNING} echo_warning ;; @@ -278,18 +275,18 @@ getpids "${1}" if [ -n "${pidlist}" ]; then - echo -e "${INFO}${base} is running with Process"\ - "ID(s) ${pidlist}.${NORMAL}" + printf "${INFO}${base} is running with Process"\ + "ID(s) ${pidlist}.${NORMAL}\n" else if [ -n "${base}" -a -e "/var/run/${base}.pid" ]; then - echo -e "${WARNING}${1} is not running but"\ - "/var/run/${base}.pid exists.${NORMAL}" + printf "${WARNING}${1} is not running but"\ + "/var/run/${base}.pid exists.${NORMAL}\n" else if [ -n "${PIDFILE}" -a -e "${PIDFILE}" ]; then - echo -e "${WARNING}${1} is not running"\ - "but ${PIDFILE} exists.${NORMAL}" + printf "${WARNING}${1} is not running" \ + "but ${PIDFILE} exists.${NORMAL}\n" else - echo -e "${INFO}${1} is not running.${NORMAL}" + printf "${INFO}${1} is not running.${NORMAL}\n" fi fi fi @@ -627,15 +624,15 @@ # # Outputs: Text output to screen # -# Dependencies: echo +# Dependencies: printf # # Todo: logging # #******************************************************************************* log_success_msg() { - echo -n -e "[EMAIL PROTECTED]" - echo -e "${SET_COL}""${BRACKET}""[""${SUCCESS}"" OK ""${BRACKET}""]""${NORMAL}" + printf "[EMAIL PROTECTED]" + printf "${SET_COL}""${BRACKET}""[""${SUCCESS}"" OK ""${BRACKET}""]""${NORMAL}\n" return 0 } @@ -648,14 +645,14 @@ # # Outputs: Text output to screen # -# Dependencies: echo +# Dependencies: printf # # Todo: logging # #******************************************************************************* log_failure_msg() { - echo -n -e "[EMAIL PROTECTED]" - echo -e "${SET_COL}""${BRACKET}""[""${FAILURE}"" FAIL ""${BRACKET}""]""${NORMAL}" + printf "[EMAIL PROTECTED]" + printf "${SET_COL}""${BRACKET}""[""${FAILURE}"" FAIL ""${BRACKET}""]""${NORMAL}\n" return 0 } @@ -674,8 +671,8 @@ # #******************************************************************************* log_warning_msg() { - echo -n -e "[EMAIL PROTECTED]" - echo -e "${SET_COL}""${BRACKET}""[""${WARNING}"" WARN ""${BRACKET}""]""${NORMAL}" + printf "[EMAIL PROTECTED]" + printf "${SET_COL}""${BRACKET}""[""${WARNING}"" WARN ""${BRACKET}""]""${NORMAL}\n" return 0 } Index: bootscripts/lfs/init.d/console =================================================================== --- bootscripts/lfs/init.d/console (revision 7926) +++ bootscripts/lfs/init.d/console (working copy) @@ -42,8 +42,8 @@ # Figure out the command to set the console into the # desired mode is_true "${UNICODE}" && - MODE_COMMAND="echo -en '\033%G' && kbd_mode -u" || - MODE_COMMAND="echo -en '[EMAIL PROTECTED](K' && kbd_mode -a" + MODE_COMMAND="printf '\033%G' && kbd_mode -u" || + MODE_COMMAND="printf '[EMAIL PROTECTED](K' && kbd_mode -a" # On framebuffer consoles, font has to be set for each vt in # UTF-8 mode. This doesn't hurt in non-UTF-8 mode also.
Just a tweak to use arithmetic expansion and string length, which are both mandated by POSIX, rather than spawning two processes every time boot_mesg() is called. Index: bootscripts/lfs/init.d/functions =================================================================== --- bootscripts/lfs/init.d/functions (revision 7926) +++ bootscripts/lfs/init.d/functions (working copy) @@ -99,9 +99,8 @@ done ## Figure out the length of what is to be printed to be used - ## for warning messges. - STRING_LENGTH="`echo "${1}" | sed \ - -e 's,.,.,g' -e 'l 1' | grep -c \$`" + ## for warning messges. + STRING_LENGTH=$((${#1} + 1)) # Print the message to the screen echo ${ECHOPARM} -e "${2}${1}"
Two fixes here since their diffs blend together. 1. POSIX says that shells only need to trap on signals. Trapping on ERR isn't always supported. I've sprinkled in conditionals to set the failed variable in spots that seemed appropriate for checking errors. 2. &> redirection is not supported in POSIX. Fortunately, it's equivalent to >word 2>&1 according to bash(1). Index: bootscripts/lfs/init.d/console =================================================================== --- bootscripts/lfs/init.d/console (revision 7926) +++ bootscripts/lfs/init.d/console (working copy) @@ -29,7 +29,6 @@ } failed=0 -trap failed=1 ERR case "${1}" in start) @@ -63,14 +62,19 @@ grep -o '\btty[[:digit:]]*\b'` do openvt -f -w -c ${TTY#tty} -- \ - /bin/sh -c "${MODE_COMMAND}" + /bin/sh -c "${MODE_COMMAND}" || failed=1 done # Set the font (if not already set above) and the keymap - is_true "${USE_FB}" || [ -z "${FONT}" ] || setfont $FONT - [ -z "${KEYMAP}" ] || loadkeys ${KEYMAP} &>/dev/null + is_true "${USE_FB}" || [ -z "${FONT}" ] || + setfont $FONT || + failed=1 + [ -z "${KEYMAP}" ] || + loadkeys ${KEYMAP} >/dev/null 2>&1 || + failed=1 [ -z "${KEYMAP_CORRECTIONS}" ] || - loadkeys ${KEYMAP_CORRECTIONS} &>/dev/null + loadkeys ${KEYMAP_CORRECTIONS} >/dev/null 2>&1 || + failed=1 # Linux kernel generates wrong bytes when composing # in Unicode mode. That's why we disable dead keys in Unicode @@ -82,11 +86,14 @@ [ -n "$BROKEN_COMPOSE" ] || BROKEN_COMPOSE="$UNICODE" ! is_true "$BROKEN_COMPOSE" || - echo "" | loadkeys -c &>/dev/null + echo "" | loadkeys -c >/dev/null 2>&1 || + failed=1 # Convert the keymap from $LEGACY_CHARSET to UTF-8 [ -z "$LEGACY_CHARSET" ] || - dumpkeys -c "$LEGACY_CHARSET" | loadkeys -u &>/dev/null + dumpkeys -c "$LEGACY_CHARSET" | + loadkeys -u >/dev/null 2>&1 || + failed=1 # If any of the commands above failed, the trap at the # top would set $failed to 1 Index: bootscripts/lfs/init.d/mountkernfs =================================================================== --- bootscripts/lfs/init.d/mountkernfs (revision 7926) +++ bootscripts/lfs/init.d/mountkernfs (working copy) @@ -19,12 +19,12 @@ start) boot_mesg -n "Mounting kernel-based file systems:" ${INFO} - if ! mountpoint /proc &> /dev/null; then + if ! mountpoint /proc >/dev/null 2>&1; then boot_mesg -n " /proc" ${NORMAL} mount -n /proc || failed=1 fi - if ! mountpoint /sys &> /dev/null; then + if ! mountpoint /sys >/dev/null 2>&1; then boot_mesg -n " /sys" ${NORMAL} mount -n /sys || failed=1 fi
-- http://linuxfromscratch.org/mailman/listinfo/lfs-dev FAQ: http://www.linuxfromscratch.org/faq/ Unsubscribe: See the above information page