#!/bin/sh # FreeBSD system port upgrade script # # Licence: BSDLike - http://rickvanderzwet.nl/LICENSE # Rick van der Zwet . /etc/rc.subr # Pointers to avoid confusion co-respond with logical boolean style values. # WARNING do not compare with exit codes! FALSE=0 TRUE=1 ask_question() { # Will return 1 if yes, return 0 if no QUESTION=$1 DEFAULT=$2 echo -n "$QUESTION? [$DEFAULT]: "; read INPUT INPUT=${INPUT:-"${DEFAULT}"} checkyesno INPUT || return 1 && return 0 } echo_list() { PREFIX=$1 shift for ENTRY in $*; do echo "$PREFIX $ENTRY" done } # # SuperCow power only if [ `id -u` -ne 0 ]; then echo "Sorry root only" 1>&2 exit 128 fi # Make sure we always using the latest version CHANGES=`svn up --non-interactive $(dirname $0) | wc -l` if [ $CHANGES -gt 1 ]; then sh $0 exit 0 fi # # Check which ports-mgnt tool to use to upgrade outdated ports # FORCE_PORTUPGRADE=${FORCE_PORTUPGRADE:-$FALSE} FORCE_PORTMASTER=${FORCE_PORTMASTER:-$FALSE} PORTUPGRADE_INSTALLED=$FALSE PORTMASTER_INSTALLED=$FALSE USE_PORTMGNT="none" if [ -n "`whereis -qb portupgrade`" ]; then PORTUPGRADE_INSTALLED=$TRUE fi if [ -n "`whereis -qb portmaster`" ]; then PORTMASTER_INSTALLED=$TRUE fi if [ $FORCE_PORTMASTER -eq $TRUE ]; then if [ $PORTMASTER_INSTALLED -eq $FALSE ]; then echo "# ERROR: FORCE_PORTMASTER set but binary not found" exit 1 fi USE_PORTMGNT="portmaster" elif [ $FORCE_PORTUPGRADE -eq $TRUE ]; then if [ $PORTUPGRADE_INSTALLED -eq $FALSE ]; then echo "# ERROR: FORCE_PORTUPGRADE set but binary not found" exit 1 fi USE_PORTMGNT="portupgrade" else if [ $PORTUPGRADE_INSTALLED -eq $TRUE ]; then if [ $PORTMASTER_INSTALLED -eq $TRUE ]; then echo "# ERROR: both portmaster and portupgrade are installed" echo "# Pick your favorite by setting either FORCE_PORTMASTER=1 or FORCE_PORTUPGRADE=1" exit 1 fi USE_PORTMGNT="portupgrade" else if [ $PORTMASTER_INSTALLED -eq $FALSE ]; then echo "# WARNING: ports-mgnt/portupgrade not found!" echo "# WARNING: ports-mgnt/portmaster not found!" echo "# ERROR : Not port upgrade tool installed" exit 1 fi USE_PORTMGNT="portmaster" fi fi DIRNAME=`dirname $0` BATCH=${BATCH-""} # Get list of rc.d marked for updates RC_FILES=`$DIRNAME/port-list.sh` RUNNING_DAEMONS="" for RC_FILE in $RC_FILES; do $RC_FILE onestatus | grep -q 'is running as' && { RUNNING_DAEMONS="$RUNNING_DAEMONS $RC_FILE" } done # Update port tree echo "# Updating portstree ..." portsnap update > /dev/null # Update ports listing echo "# Checking ports which needs updating ..." NEWPORTS=`pkg_version -qol '<'` # Check for potentional trouble. # XXX: Weird -q does not strip at '!' check BROKENPORTS=`pkg_version -qol '!' | awk '{print $1}'` if [ -n "$BROKENPORTS" ]; then echo "# WARNING comparion failed, fix by hand"; echo_list "# - " $BROKENPORTS fi if [ -z "$NEWPORTS" ]; then echo "# No ports to update" echo "# All done, goodbye" exit 0 fi # Check for broken pkgdb, else we have trouble during upgrades if [ $USE_PORTMGNT = "portupgrade" ]; then pkgdb -a || exit 1 fi # # Update ports if [ -z "$BATCH" ]; then # Make sure we have read the (new) UPDATING announcements # Use ls to display the last motification time of the directories in # /var/db/pkg and assume that is the last time the user read the # UPDATING file LAST_UPDATED=`ls -rtlD '%Y%m%d' /var/db/pkg/ | awk 'END{print $6}'` # Find new entries TMPFILE=`mktemp -t $(basename $0).XXX` awk -F: -v last=$LAST_UPDATED '{if (match($0,"^[0-9]+:$") && $1 < last) {exit}; print $0}' /usr/ports/UPDATING > $TMPFILE echo "# Show new /usr/ports/UPDATING entries (starting from $LAST_UPDATED) ..." if [`cat $TMPFILE | wc -l` -eq 7 ]; then echo "## No new entries found" else cat $TMPFILE fi rm $TMPFILE # agree to the terms of the game echo "# Ports pending update:" echo_list "# - " $NEWPORTS ask_question "# Do you like to upgrade the affected ports" "no" || exit 1 # # Stop daemons DAEMONS_STOPPED=$FALSE if [ -n "$RC_FILES" ]; then echo "# Affected daemons:"; echo_list "# - " $RC_FILES if [ -n "$RUNNING_DAEMONS" ]; then echo "# Running daemons:"; echo_list "# - " $RUNNING_DAEMONS ask_question "# Do you like to stop running daemons" "yes" && { for RC_FILE in $RUNNING_DAEMONS; do $RC_FILE stop done; DAEMONS_STOPPED=$TRUE } fi fi fi echo "# Using update tool '$USE_PORTMGNT" case $USE_PORTMGNT in portupgrade) portupgrade -r -mBATCH=yes -a $NEWPORTS ;; portmaster) portmaster -d --no-confirm --no-term-title --no-index-fetch -mBATCH=yes -a $NEWPORTS ;; *) echo "# ERROR: Failed to find a port management tool" exit 1 ;; esac echo "# Ports updated:" echo_list "# - " $NEWPORTS # # (Re)start daemons. Assume we only like to start the just stopped ones. if [ -n "$RC_FILES" ]; then echo "# Affected daemons:"; echo_list "# - " $RC_FILES if [ -n "$RUNNING_DAEMONS" ]; then if [ $DAEMONS_STOPPED -eq $TRUE ]; then echo "# Enabled daemons: "; echo_list "# - " $RUNNING_DAEMONS ask_question "# Do you like to start your daemons" "yes" && { for RC_FILE in $RUNNING_DAEMONS; do $RC_FILE start done } else echo "# Running daemons: "; echo_list "# - " $RUNNING_DAEMONS ask_question "# Do you like to restart your daemons" "yes" && { for RC_FILE in $RUNNING_DAEMONS; do $RC_FILE restart done } fi fi fi echo "# All done, goodbye"