Index: usr.sbin/freebsd-update/freebsd-update.8 =================================================================== --- usr.sbin/freebsd-update/freebsd-update.8 +++ usr.sbin/freebsd-update/freebsd-update.8 @@ -41,6 +41,7 @@ .Op Fl r Ar newrelease .Op Fl s Ar server .Op Fl t Ar address +.Op Fl q .Op Fl -not-running-from-cron .Cm command ... .Sh DESCRIPTION @@ -104,6 +105,8 @@ command, if any, to .Ar address . (default: root, or as given in the configuration file.) +.It Fl q +Hide any status related messages .It Fl -not-running-from-cron Force .Nm Cm fetch Index: usr.sbin/freebsd-update/freebsd-update.sh =================================================================== --- usr.sbin/freebsd-update/freebsd-update.sh +++ usr.sbin/freebsd-update/freebsd-update.sh @@ -52,6 +52,7 @@ (default: update.FreeBSD.org) -t address -- Mail output of cron command, if any, to address (default: root) + -q -- Hide any status related messages --not-running-from-cron -- Run without a tty, for use by automated tools --currently-running release @@ -322,6 +323,9 @@ [Nn][Oo][Ss][Tt][Aa][Tt][Ss]) VERBOSELEVEL=nostats ;; + [Nn][Oo][Nn][Ee]) + VERBOSELEVEL=none + ;; [Ss][Tt][Aa][Tt][Ss]) VERBOSELEVEL=stats ;; @@ -484,7 +488,10 @@ config_VerboseLevel $1 || usage ;; - # Aliases for "-v debug" and "-v nostats" + # Aliases for "-v none", "-v debug" and "-v nostats" + -q) + config_VerboseLevel none || usage + ;; --debug) config_VerboseLevel debug || usage ;; @@ -511,14 +518,24 @@ fi } +print_error () { + if [ $# -eq 0 ]; then + while read LINE; do + echo "${LINE}" >&2 + done + else + echo $@ >&2 + fi +} + # Parse the configuration file parse_conffile () { # If a configuration file was specified on the command line, check # that it exists and is readable. if [ ! -z "${CONFFILE}" ] && [ ! -r "${CONFFILE}" ]; then - echo -n "File does not exist " - echo -n "or is not readable: " - echo ${CONFFILE} + print_error -n "File does not exist " + print_error -n "or is not readable: " + print_error ${CONFFILE} exit 1 fi @@ -544,8 +561,8 @@ L=$(($L + 1)) LINEX=`echo "${LINE}" | cut -f 1 -d '#'` if ! configline ${LINEX}; then - echo "Error processing configuration file, line $L:" - echo "==> ${LINE}" + print_error "Error processing configuration file, line $L:" + print_error "==> ${LINE}" exit 1 fi done < ${CONFFILE} @@ -582,22 +599,34 @@ fetch_setup_verboselevel () { case ${VERBOSELEVEL} in debug) + INFOREDIR="/dev/stdout" QUIETREDIR="/dev/stderr" - QUIETFLAG=" " + QUIETFLAG="" STATSREDIR="/dev/stderr" DDSTATS=".." XARGST="-t" NDEBUG=" " ;; nostats) - QUIETREDIR="" + INFOREDIR="/dev/stdout" + QUIETREDIR="/dev/stdout" QUIETFLAG="" STATSREDIR="/dev/null" DDSTATS=".." XARGST="" NDEBUG="" ;; + none) + INFOREDIR="/dev/null" + QUIETREDIR="/dev/null" + QUIETFLAG="-q" + STATSREDIR="/dev/null" + DDSTATS=".." + XARGST="" + NDEBUG="" + ;; stats) + INFOREDIR="/dev/stdout" QUIETREDIR="/dev/null" QUIETFLAG="-q" STATSREDIR="/dev/stdout" @@ -625,31 +654,31 @@ _WORKDIR_bad2="Directory is not on a persistent filesystem: " if [ -z "${SERVERNAME}" ]; then - echo -n "`basename $0`: " - echo "${_SERVERNAME_z}" + print_error -n "`basename $0`: " + print_error "${_SERVERNAME_z}" exit 1 fi if [ -z "${KEYPRINT}" ]; then - echo -n "`basename $0`: " - echo "${_KEYPRINT_z}" + print_error -n "`basename $0`: " + print_error "${_KEYPRINT_z}" exit 1 fi if ! echo "${KEYPRINT}" | grep -qE "^[0-9a-f]{64}$"; then - echo -n "`basename $0`: " - echo -n "${_KEYPRINT_bad}" - echo ${KEYPRINT} + print_error -n "`basename $0`: " + print_error -n "${_KEYPRINT_bad}" + print_error ${KEYPRINT} exit 1 fi if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then - echo -n "`basename $0`: " - echo -n "${_WORKDIR_bad}" - echo ${WORKDIR} + print_error -n "`basename $0`: " + print_error -n "${_WORKDIR_bad}" + print_error ${WORKDIR} exit 1 fi case `df -T ${WORKDIR}` in */dev/md[0-9]* | *tmpfs*) - echo -n "`basename $0`: " - echo -n "${_WORKDIR_bad2}" - echo ${WORKDIR} + print_error -n "`basename $0`: " + print_error -n "${_WORKDIR_bad2}" + print_error ${WORKDIR} exit 1 ;; esac @@ -683,7 +712,7 @@ BOOTFILE=`sysctl -n kern.bootfile` KERNELDIR=${BOOTFILE%/kernel} if ! [ -d ${KERNELDIR} ]; then - echo "Cannot identify running kernel" + print_error "Cannot identify running kernel" exit 1 fi @@ -722,17 +751,17 @@ fetchupgrade_check_params if ! [ -z "${TARGETRELEASE}" ]; then - echo -n "`basename $0`: " - echo -n "-r option is meaningless with 'fetch' command. " - echo "(Did you mean 'upgrade' instead?)" + print_error -n "`basename $0`: " + print_error -n "-r option is meaningless with 'fetch' command. " + print_error "(Did you mean 'upgrade' instead?)" exit 1 fi # Check that we have updates ready to install if [ -f ${BDHASH}-install/kerneldone -a $FORCEFETCH -eq 0 ]; then - echo "You have a partially completed upgrade pending" - echo "Run '$0 install' first." - echo "Run '$0 fetch -F' to proceed anyway." + print_error "You have a partially completed upgrade pending" + print_error "Run '$0 install' first." + print_error "Run '$0 fetch -F' to proceed anyway." exit 1 fi } @@ -747,30 +776,30 @@ # We need TARGETRELEASE set _TARGETRELEASE_z="Release target must be specified via -r option." if [ -z "${TARGETRELEASE}" ]; then - echo -n "`basename $0`: " - echo "${_TARGETRELEASE_z}" + print_error -n "`basename $0`: " + print_error "${_TARGETRELEASE_z}" exit 1 fi # The target release should be != the current release. if [ "${TARGETRELEASE}" = "${RELNUM}" ]; then - echo -n "`basename $0`: " - echo "Cannot upgrade from ${RELNUM} to itself" + print_error -n "`basename $0`: " + print_error "Cannot upgrade from ${RELNUM} to itself" exit 1 fi # Turning off AllowAdd or AllowDelete is a bad idea for upgrades. if [ "${ALLOWADD}" = "no" ]; then - echo -n "`basename $0`: " - echo -n "WARNING: \"AllowAdd no\" is a bad idea " - echo "when upgrading between releases." - echo + print_error -n "`basename $0`: " + print_error -n "WARNING: \"AllowAdd no\" is a bad idea " + print_error "when upgrading between releases." + print_error fi if [ "${ALLOWDELETE}" = "no" ]; then - echo -n "`basename $0`: " - echo -n "WARNING: \"AllowDelete no\" is a bad idea " - echo "when upgrading between releases." - echo + print_error -n "`basename $0`: " + print_error -n "WARNING: \"AllowDelete no\" is a bad idea " + print_error "when upgrading between releases." + print_error fi # Set EDITOR to /usr/bin/vi if it isn't already set @@ -782,23 +811,23 @@ install_check_params () { # Check that we are root. All sorts of things won't work otherwise. if [ `id -u` != 0 ]; then - echo "You must be root to run this." + print_error "You must be root to run this." exit 1 fi # Check that securelevel <= 0. Otherwise we can't update schg files. if [ `sysctl -n kern.securelevel` -gt 0 ]; then - echo "Updates cannot be installed when the system securelevel" - echo "is greater than zero." + print_error "Updates cannot be installed when the system securelevel" + print_error "is greater than zero." exit 1 fi # Check that we have a working directory _WORKDIR_bad="Directory does not exist or is not writable: " if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then - echo -n "`basename $0`: " - echo -n "${_WORKDIR_bad}" - echo ${WORKDIR} + print_error -n "`basename $0`: " + print_error -n "${_WORKDIR_bad}" + print_error ${WORKDIR} exit 1 fi cd ${WORKDIR} || exit 1 @@ -816,8 +845,8 @@ fi if ! [ -f ${BDHASH}-install/INDEX-OLD ] || ! [ -f ${BDHASH}-install/INDEX-NEW ]; then - echo "Update manifest is corrupt -- this should never happen." - echo "Re-run '$0 fetch'." + print_error "Update manifest is corrupt -- this should never happen." + print_error "Re-run '$0 fetch'." exit 1 fi @@ -825,7 +854,7 @@ BOOTFILE=`sysctl -n kern.bootfile` KERNELDIR=${BOOTFILE%/kernel} if ! [ -d ${KERNELDIR} ]; then - echo "Cannot identify running kernel" + print_error "Cannot identify running kernel" exit 1 fi } @@ -835,16 +864,16 @@ rollback_check_params () { # Check that we are root. All sorts of things won't work otherwise. if [ `id -u` != 0 ]; then - echo "You must be root to run this." + print_error "You must be root to run this." exit 1 fi # Check that we have a working directory _WORKDIR_bad="Directory does not exist or is not writable: " if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then - echo -n "`basename $0`: " - echo -n "${_WORKDIR_bad}" - echo ${WORKDIR} + print_error -n "`basename $0`: " + print_error -n "${_WORKDIR_bad}" + print_error ${WORKDIR} exit 1 fi cd ${WORKDIR} || exit 1 @@ -854,12 +883,12 @@ # Check that we have updates ready to rollback if ! [ -L ${BDHASH}-rollback ]; then - echo "No rollback directory found." + print_error "No rollback directory found." exit 1 fi if ! [ -f ${BDHASH}-rollback/INDEX-OLD ] || ! [ -f ${BDHASH}-rollback/INDEX-NEW ]; then - echo "Update manifest is corrupt -- this should never happen." + print_error "Update manifest is corrupt -- this should never happen." exit 1 fi } @@ -881,25 +910,25 @@ _WORKDIR_bad="Directory does not exist or is not writable: " if [ -z "${SERVERNAME}" ]; then - echo -n "`basename $0`: " - echo "${_SERVERNAME_z}" + print_error -n "`basename $0`: " + print_error "${_SERVERNAME_z}" exit 1 fi if [ -z "${KEYPRINT}" ]; then - echo -n "`basename $0`: " - echo "${_KEYPRINT_z}" + print_error -n "`basename $0`: " + print_error "${_KEYPRINT_z}" exit 1 fi if ! echo "${KEYPRINT}" | grep -qE "^[0-9a-f]{64}$"; then - echo -n "`basename $0`: " - echo -n "${_KEYPRINT_bad}" - echo ${KEYPRINT} + print_error -n "`basename $0`: " + print_error -n "${_KEYPRINT_bad}" + print_error ${KEYPRINT} exit 1 fi if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then - echo -n "`basename $0`: " - echo -n "${_WORKDIR_bad}" - echo ${WORKDIR} + print_error -n "`basename $0`: " + print_error -n "${_WORKDIR_bad}" + print_error ${WORKDIR} exit 1 fi cd ${WORKDIR} || exit 1 @@ -919,7 +948,7 @@ BOOTFILE=`sysctl -n kern.bootfile` KERNELDIR=${BOOTFILE%/kernel} if ! [ -d ${KERNELDIR} ]; then - echo "Cannot identify running kernel" + print_error "Cannot identify running kernel" exit 1 fi @@ -988,7 +1017,7 @@ # If no records, give up -- we'll just use the server name we were given. if [ `wc -l < serverlist_full` -eq 0 ]; then - echo "none found." + print_error "found no ${SERVERNAME} mirrors." return 1 fi @@ -1015,7 +1044,7 @@ # Have we run out of mirrors? if [ `wc -l < serverlist` -eq 0 ]; then - echo "No mirrors remaining, giving up." + print_error "No mirrors remaining, giving up." return 1 fi @@ -1123,13 +1152,13 @@ echo -n "Fetching public key from ${SERVERNAME}... " rm -f pub.ssl fetch ${QUIETFLAG} http://${SERVERNAME}/${FETCHDIR}/pub.ssl \ - 2>${QUIETREDIR} || true + 2>${QUIETREDIR} >${INFOREDIR} || true if ! [ -r pub.ssl ]; then - echo "failed." + print_error "failed to fetch public key from ${SERVERNAME}." return 1 fi if ! [ `${SHA256} -q pub.ssl` = ${KEYPRINT} ]; then - echo "key has incorrect hash." + print_error "public key from ${SERVERNAME} has incorrect hash." rm -f pub.ssl return 1 fi @@ -1161,7 +1190,6 @@ fi echo "done." - RELPATCHNUM=`cut -f 4 -d '|' < tag.new` TINDEXHASH=`cut -f 5 -d '|' < tag.new` EOLTIME=`cut -f 6 -d '|' < tag.new` @@ -1178,11 +1206,11 @@ RELPX=0 fi if [ "${RELPATCHNUM}" -lt "${RELPX}" ]; then - echo - echo -n "Files on mirror (${RELNUM}-p${RELPATCHNUM})" - echo " appear older than what" - echo "we are currently running (`uname -r`)!" - echo "Cowardly refusing to proceed any further." + print_error + print_error -n "Files on mirror (${RELNUM}-p${RELPATCHNUM})" + print_error " appear older than what" + print_error "we are currently running (`uname -r`)!" + print_error "Cowardly refusing to proceed any further." return 1 fi @@ -1196,12 +1224,12 @@ LASTRELPATCHNUM=`cut -f 4 -d '|' < tag` if [ "${RELPATCHNUM}" -lt "${LASTRELPATCHNUM}" ]; then - echo - echo -n "Files on mirror (${RELNUM}-p${RELPATCHNUM})" - echo " are older than the" - echo -n "most recently seen updates" - echo " (${RELNUM}-p${LASTRELPATCHNUM})." - echo "Cowardly refusing to proceed any further." + print_error + print_error -n "Files on mirror (${RELNUM}-p${RELPATCHNUM})" + print_error " are older than the" + print_error -n "most recently seen updates" + print_error " (${RELNUM}-p${LASTRELPATCHNUM})." + print_error "Cowardly refusing to proceed any further." return 1 fi fi @@ -1226,10 +1254,10 @@ # Print an error message about signed metadata being bogus. fetch_metadata_bogus () { - echo - echo "The update metadata$1 is correctly signed, but" - echo "failed an integrity check." - echo "Cowardly refusing to proceed any further." + print_error + print_error "The update metadata$1 is correctly signed, but" + print_error "failed an integrity check." + print_error "Cowardly refusing to proceed any further." return 1 } @@ -1392,14 +1420,14 @@ while read Y; do if ! [ -f ${Y}.gz ]; then - echo "failed." + print_error "failed to fetch metadata files." return 1 fi if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then mv ${Y}.gz files/${Y}.gz else - echo "metadata is corrupt." + print_error "metadata is corrupt." return 1 fi done < filelist @@ -1781,14 +1809,14 @@ # Make sure we got them all, and move them into /files/ while read Y; do if ! [ -f ${Y}.gz ]; then - echo "failed." + print_error "failed to fetch files from ${OLDRELNUM}." return 1 fi if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then mv ${Y}.gz files/${Y}.gz else - echo "${Y} has incorrect hash." + print_error "${Y} from ${OLDRELNUM} has incorrect hash." return 1 fi done < filelist @@ -1842,8 +1870,8 @@ # Make sure the file hasn't changed. cp "${BASEDIR}/${F}" tmpfile if [ `sha256 -q tmpfile` != ${HASH} ]; then - echo - echo "File changed while FreeBSD Update running: ${F}" + print_error + print_error "File changed while FreeBSD Update running: ${F}" return 1 fi @@ -1913,14 +1941,14 @@ while read Y; do if ! [ -f ${Y}.gz ]; then - echo "failed." + print_error "failed to fetch files." return 1 fi if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then mv ${Y}.gz files/${Y}.gz else - echo "${Y} has incorrect hash." + print_error "${Y} has incorrect hash." return 1 fi done < filelist @@ -1995,7 +2023,6 @@ echo echo -n "The following files will be updated " echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" - cat files.updated fi | $PAGER rm files.updated @@ -2025,8 +2052,8 @@ # If the EoL time is past, warn. if [ ${EOLTIME} -lt ${NOWTIME} ]; then - echo - cat <<-EOF + cat <<-EOF | print_error + WARNING: `uname -sr` HAS PASSED ITS END-OF-LIFE DATE. Any security issues discovered after `date -r ${EOLTIME}` will not have been corrected. @@ -2069,8 +2096,8 @@ fi # Print the warning - echo - cat <<-EOF + cat <<-EOF | print_error + WARNING: `uname -sr` is approaching its End-of-Life date. It is strongly recommended that you upgrade to a newer release within the next ${NUM} ${UNIT}. @@ -2713,7 +2740,7 @@ # the end and try again. CNT=$((CNT + 1)) if [ $CNT -gt 9 ]; then - echo "Could not find valid backup dir ($BASEDIR/$BACKUPKERNELDIR)" + print_error "Could not find valid backup dir ($BASEDIR/$BACKUPKERNELDIR)" exit 1 fi BACKUPKERNELDIR="`echo $BACKUPKERNELDIR | sed -Ee 's/[0-9]\$//'`" @@ -2752,7 +2779,7 @@ # Mark the directory as having been created by freebsd-update. touch $BASEDIR/$BACKUPKERNELDIR/.freebsd-update if [ $? -ne 0 ]; then - echo "Could not create kernel backup directory" + print_error "Could not create kernel backup directory" exit 1 fi @@ -3198,8 +3225,7 @@ # We don't warn about different hard links, since some # some archivers break hard links, and as long as the # underlying data is correct they really don't matter. - done < INDEX-NOTMATCHING - + done < INDEX-NOTMATCHING | print_error # Clean up rm $1 $1.noflags $1.sorted $2 INDEX-NOTMATCHING } @@ -3215,7 +3241,7 @@ while ! fetch_key; do fetch_pick_server || return 1 done - + # Try to fetch the metadata index signature ("tag") until we run # out of available servers; and sanity check the downloaded tag. while ! fetch_tag; do @@ -3262,13 +3288,13 @@ # interactively, then run fetch_check_params and fetch_run cmd_fetch () { if [ ! -t 0 -a $NOTTYOK -eq 0 ]; then - echo -n "`basename $0` fetch should not " - echo "be run non-interactively." - echo "Run `basename $0` cron instead." + print_error -n "`basename $0` fetch should not " + print_error "be run non-interactively." + print_error "Run `basename $0` cron instead." exit 1 fi fetch_check_params - fetch_run || exit 1 + fetch_run > ${INFOREDIR} || exit 1 ISFETCHED=1 } @@ -3281,7 +3307,9 @@ sleep `jot -r 1 0 3600` TMPFILE=`mktemp /tmp/freebsd-update.XXXXXX` || exit 1 - if ! fetch_run >> ${TMPFILE} || + mkfifo _fetch_results + cat _fetch_results > ${INFOREDIR} | cat - >> ${TMPFILE} & + if ! fetch_run > _fetch_results || ! grep -q "No updates needed" ${TMPFILE} || [ ${VERBOSELEVEL} = "debug" ]; then mail -s "`hostname` security updates" ${MAILTO} < ${TMPFILE} @@ -3311,7 +3339,7 @@ # Compare system against a "known good" index. cmd_IDS () { IDS_check_params - IDS_run || exit 1 + IDS_run > ${INFOREDIR} || exit 1 } #### Entry point