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 ;; @@ -516,9 +523,9 @@ # 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} + echo -n "File does not exist " >&2 + echo -n "or is not readable: " >&2 + echo ${CONFFILE} >&2 exit 1 fi @@ -544,8 +551,8 @@ L=$(($L + 1)) LINEX=`echo "${LINE}" | cut -f 1 -d '#'` if ! configline ${LINEX}; then - echo "Error processing configuration file, line $L:" - echo "==> ${LINE}" + echo "Error processing configuration file, line $L:" >&2 + echo "==> ${LINE}" >&2 exit 1 fi done < ${CONFFILE} @@ -582,22 +589,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 +644,31 @@ _WORKDIR_bad2="Directory is not on a persistent filesystem: " if [ -z "${SERVERNAME}" ]; then - echo -n "`basename $0`: " - echo "${_SERVERNAME_z}" + echo -n "`basename $0`: " >&2 + echo "${_SERVERNAME_z}" >&2 exit 1 fi if [ -z "${KEYPRINT}" ]; then - echo -n "`basename $0`: " - echo "${_KEYPRINT_z}" + echo -n "`basename $0`: " >&2 + echo "${_KEYPRINT_z}" >&2 exit 1 fi if ! echo "${KEYPRINT}" | grep -qE "^[0-9a-f]{64}$"; then - echo -n "`basename $0`: " - echo -n "${_KEYPRINT_bad}" - echo ${KEYPRINT} + echo -n "`basename $0`: " >&2 + echo -n "${_KEYPRINT_bad}" >&2 + echo ${KEYPRINT} >&2 exit 1 fi if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then - echo -n "`basename $0`: " - echo -n "${_WORKDIR_bad}" - echo ${WORKDIR} + echo -n "`basename $0`: " >&2 + echo -n "${_WORKDIR_bad}" >&2 + echo ${WORKDIR} >&2 exit 1 fi case `df -T ${WORKDIR}` in */dev/md[0-9]* | *tmpfs*) - echo -n "`basename $0`: " - echo -n "${_WORKDIR_bad2}" - echo ${WORKDIR} + echo -n "`basename $0`: " >&2 + echo -n "${_WORKDIR_bad2}" >&2 + echo ${WORKDIR} >&2 exit 1 ;; esac @@ -683,7 +702,7 @@ BOOTFILE=`sysctl -n kern.bootfile` KERNELDIR=${BOOTFILE%/kernel} if ! [ -d ${KERNELDIR} ]; then - echo "Cannot identify running kernel" + echo "Cannot identify running kernel" >&2 exit 1 fi @@ -722,17 +741,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?)" + echo -n "`basename $0`: " >&2 + echo -n "-r option is meaningless with 'fetch' command. " >&2 + echo "(Did you mean 'upgrade' instead?)" >&2 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." + echo "You have a partially completed upgrade pending" >&2 + echo "Run '$0 install' first." >&2 + echo "Run '$0 fetch -F' to proceed anyway." >&2 exit 1 fi } @@ -747,15 +766,15 @@ # 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}" + echo -n "`basename $0`: " >&2 + echo "${_TARGETRELEASE_z}" >&2 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" + echo -n "`basename $0`: " >&2 + echo "Cannot upgrade from ${RELNUM} to itself" >&2 exit 1 fi @@ -782,23 +801,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." + echo "You must be root to run this." >&2 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." + echo "Updates cannot be installed when the system securelevel" >&2 + echo "is greater than zero." >&2 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} + echo -n "`basename $0`: " >&2 + echo -n "${_WORKDIR_bad}" >&2 + echo ${WORKDIR} >&2 exit 1 fi cd ${WORKDIR} || exit 1 @@ -816,8 +835,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'." + echo "Update manifest is corrupt -- this should never happen." >&2 + echo "Re-run '$0 fetch'." >&2 exit 1 fi @@ -825,7 +844,7 @@ BOOTFILE=`sysctl -n kern.bootfile` KERNELDIR=${BOOTFILE%/kernel} if ! [ -d ${KERNELDIR} ]; then - echo "Cannot identify running kernel" + echo "Cannot identify running kernel" >&2 exit 1 fi } @@ -835,16 +854,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." + echo "You must be root to run this." >&2 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} + echo -n "`basename $0`: " >&2 + echo -n "${_WORKDIR_bad}" >&2 + echo ${WORKDIR} >&2 exit 1 fi cd ${WORKDIR} || exit 1 @@ -854,12 +873,12 @@ # Check that we have updates ready to rollback if ! [ -L ${BDHASH}-rollback ]; then - echo "No rollback directory found." + echo "No rollback directory found." >&2 exit 1 fi if ! [ -f ${BDHASH}-rollback/INDEX-OLD ] || ! [ -f ${BDHASH}-rollback/INDEX-NEW ]; then - echo "Update manifest is corrupt -- this should never happen." + echo "Update manifest is corrupt -- this should never happen." >&2 exit 1 fi } @@ -881,25 +900,25 @@ _WORKDIR_bad="Directory does not exist or is not writable: " if [ -z "${SERVERNAME}" ]; then - echo -n "`basename $0`: " - echo "${_SERVERNAME_z}" + echo -n "`basename $0`: " >&2 + echo "${_SERVERNAME_z}" >&2 exit 1 fi if [ -z "${KEYPRINT}" ]; then - echo -n "`basename $0`: " - echo "${_KEYPRINT_z}" + echo -n "`basename $0`: " >&2 + echo "${_KEYPRINT_z}" >&2 exit 1 fi if ! echo "${KEYPRINT}" | grep -qE "^[0-9a-f]{64}$"; then - echo -n "`basename $0`: " - echo -n "${_KEYPRINT_bad}" - echo ${KEYPRINT} + echo -n "`basename $0`: " >&2 + echo -n "${_KEYPRINT_bad}" >&2 + echo ${KEYPRINT} >&2 exit 1 fi if ! [ -d "${WORKDIR}" -a -w "${WORKDIR}" ]; then - echo -n "`basename $0`: " - echo -n "${_WORKDIR_bad}" - echo ${WORKDIR} + echo -n "`basename $0`: " >&2 + echo -n "${_WORKDIR_bad}" >&2 + echo ${WORKDIR} >&2 exit 1 fi cd ${WORKDIR} || exit 1 @@ -919,7 +938,7 @@ BOOTFILE=`sysctl -n kern.bootfile` KERNELDIR=${BOOTFILE%/kernel} if ! [ -d ${KERNELDIR} ]; then - echo "Cannot identify running kernel" + echo "Cannot identify running kernel" >&2 exit 1 fi @@ -988,7 +1007,10 @@ # 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." + if [ ${INFOREDIR} != "/dev/stdout" ]; then + echo "Looking up ${SERVERNAME} mirrors..." >&2 + fi + echo "none found." >&2 return 1 fi @@ -1015,7 +1037,7 @@ # Have we run out of mirrors? if [ `wc -l < serverlist` -eq 0 ]; then - echo "No mirrors remaining, giving up." + echo "No mirrors remaining, giving up." >&2 return 1 fi @@ -1123,13 +1145,19 @@ 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." + if [ ${INFOREDIR} != "/dev/stdout" ] + echo -n "Fetching public key from ${SERVERNAME}... " >&2 + fi + echo "failed." >&2 return 1 fi if ! [ `${SHA256} -q pub.ssl` = ${KEYPRINT} ]; then - echo "key has incorrect hash." + if [ ${INFOREDIR} != "/dev/stdout" ] + echo -n "Fetching public key from ${SERVERNAME}... " >&2 + fi + echo "key has incorrect hash." >&2 rm -f pub.ssl return 1 fi @@ -1161,7 +1189,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` @@ -1392,13 +1419,19 @@ while read Y; do if ! [ -f ${Y}.gz ]; then - echo "failed." + if [ ${INFOREDIR} != "/dev/stdout" ] + echo -n "Fetching metadata files ..." >&2 + fi + echo "failed." >&2 return 1 fi if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then mv ${Y}.gz files/${Y}.gz else + if [ ${INFOREDIR} != "/dev/stdout" ] + echo -n "Fetching metadata files ..." >&2 + fi echo "metadata is corrupt." return 1 fi @@ -1781,6 +1814,9 @@ # Make sure we got them all, and move them into /files/ while read Y; do if ! [ -f ${Y}.gz ]; then + if [ ${INFOREDIR} != "/dev/stdout" ]; then + echo -n "Fetching files from ${OLDRELNUM} for merging... " >&2 + fi echo "failed." return 1 fi @@ -1788,7 +1824,10 @@ ${SHA256} -q` = ${Y} ]; then mv ${Y}.gz files/${Y}.gz else - echo "${Y} has incorrect hash." + if [ ${INFOREDIR} != "/dev/stdout" ]; then + echo -n "Fetching files from ${OLDRELNUM} for merging... " >&2 + fi + echo "${Y} has incorrect hash." >&2 return 1 fi done < filelist @@ -1843,7 +1882,7 @@ cp "${BASEDIR}/${F}" tmpfile if [ `sha256 -q tmpfile` != ${HASH} ]; then echo - echo "File changed while FreeBSD Update running: ${F}" + echo "File changed while FreeBSD Update running: ${F}" >&2 return 1 fi @@ -1913,14 +1952,20 @@ while read Y; do if ! [ -f ${Y}.gz ]; then - echo "failed." + if [ ${INFOREDIR} != "/dev/stdout" ]; then + echo -n "Fetching files... " >&2 + fi + echo "failed." >&2 return 1 fi if [ `gunzip -c < ${Y}.gz | ${SHA256} -q` = ${Y} ]; then mv ${Y}.gz files/${Y}.gz else - echo "${Y} has incorrect hash." + if [ ${INFOREDIR} != "/dev/stdout" ]; then + echo -n "Fetching files... " >&2 + fi + echo "${Y} has incorrect hash." >&2 return 1 fi done < filelist @@ -1943,10 +1988,10 @@ # Report to the user if any updates were avoided due to local changes if [ -s modifiedfiles ]; then echo - echo -n "The following files are affected by updates, " - echo "but no changes have" - echo -n "been downloaded because the files have been " - echo "modified locally:" + echo -n "The following files are affected by updates, " >&2 + echo "but no changes have" >&2 + echo -n "been downloaded because the files have been " >&2 + echo "modified locally:" >&2 cat modifiedfiles fi | $PAGER rm modifiedfiles @@ -1956,8 +2001,8 @@ ! [ -s INDEX-NEW ]; then rm INDEX-PRESENT INDEX-NEW echo - echo -n "No updates needed to update system to " - echo "${RELNUM}-p${RELPATCHNUM}." + echo -n "No updates needed to update system to " >&2 + echo "${RELNUM}-p${RELPATCHNUM}." >&2 return fi @@ -1975,8 +2020,8 @@ # Report removed files, if any if [ -s files.removed ]; then echo - echo -n "The following files will be removed " - echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" + echo -n "The following files will be removed " >&2 + echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" >&2 cat files.removed fi | $PAGER rm files.removed @@ -1984,8 +2029,8 @@ # Report added files, if any if [ -s files.added ]; then echo - echo -n "The following files will be added " - echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" + echo -n "The following files will be added " >&2 + echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" >&2 cat files.added fi | $PAGER rm files.added @@ -1993,8 +2038,8 @@ # Report updated files, if any if [ -s files.updated ]; then echo - echo -n "The following files will be updated " - echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" + echo -n "The following files will be updated " >&2 + echo "as part of updating to ${RELNUM}-p${RELPATCHNUM}:" >&2 cat files.updated fi | $PAGER @@ -2026,7 +2071,7 @@ # If the EoL time is past, warn. if [ ${EOLTIME} -lt ${NOWTIME} ]; then echo - cat <<-EOF + cat <<-EOF >&2 WARNING: `uname -sr` HAS PASSED ITS END-OF-LIFE DATE. Any security issues discovered after `date -r ${EOLTIME}` will not have been corrected. @@ -2070,7 +2115,7 @@ # Print the warning echo - cat <<-EOF + cat <<-EOF >&2 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 +2758,7 @@ # the end and try again. CNT=$((CNT + 1)) if [ $CNT -gt 9 ]; then - echo "Could not find valid backup dir ($BASEDIR/$BACKUPKERNELDIR)" + echo "Could not find valid backup dir ($BASEDIR/$BACKUPKERNELDIR)" >&2 exit 1 fi BACKUPKERNELDIR="`echo $BACKUPKERNELDIR | sed -Ee 's/[0-9]\$//'`" @@ -2752,7 +2797,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" + echo "Could not create kernel backup directory" >&2 exit 1 fi @@ -3136,7 +3181,7 @@ while read FPATH TYPE OWNER GROUP PERM HASH LINK P_TYPE P_OWNER P_GROUP P_PERM P_HASH P_LINK; do # Warn about different object types. if ! [ "${TYPE}" = "${P_TYPE}" ]; then - echo -n "${FPATH} is a " + echo -n "${FPATH} is a " >&2 case "${P_TYPE}" in f) echo -n "regular file, " ;; @@ -3198,7 +3243,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 >&2 < INDEX-NOTMATCHING # Clean up rm $1 $1.noflags $1.sorted $2 INDEX-NOTMATCHING @@ -3215,7 +3260,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 @@ -3245,7 +3290,6 @@ # Compare INDEX-ALL and INDEX-PRESENT and print warnings about any # differences. IDS_compare INDEX-ALL INDEX-PRESENT -} #### Main functions -- call parameter-handling and core functions @@ -3262,13 +3306,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." + echo -n "`basename $0` fetch should not " >&2 + echo "be run non-interactively." >&2 + echo "Run `basename $0` cron instead." >&2 exit 1 fi fetch_check_params - fetch_run || exit 1 + fetch_run > ${INFOREDIR} || exit 1 ISFETCHED=1 } @@ -3281,7 +3325,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 +3357,7 @@ # Compare system against a "known good" index. cmd_IDS () { IDS_check_params - IDS_run || exit 1 + IDS_run > ${INFOREDIR} || exit 1 } #### Entry point