Give etcupdate the ability to use etc.tgz and xetc.tgz.

* Expand the "-s" flag to -s {srcdir|tgzfile|tempdir}.
* Deprecate the "-b" flag.  It is replaced by "-s tempdir".
* Change "-s srcdir" to refer to the top of the source tree (e.g.
  /usr/src) instead of the etc subdirectory.

In etcupdate's interactive phase, enhance the "s" command to be able
to invoke alternative diff commands.

Also some style changes.

Approved by christos
This commit is contained in:
apb 2006-02-18 19:29:48 +00:00
parent 717f2d5d7e
commit 7e321ef839
2 changed files with 245 additions and 102 deletions

View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# $NetBSD: etcupdate,v 1.22 2005/04/17 23:12:40 lukem Exp $
# $NetBSD: etcupdate,v 1.23 2006/02/18 19:29:48 apb Exp $
#
# Copyright (c) 2001 The NetBSD Foundation, Inc.
# All rights reserved.
@ -53,39 +53,51 @@ PATH="/sbin:/usr/sbin:/bin:/usr/bin:${PATH}"
# Default settings
TEMPROOT="${TEMPROOT:=/tmp/temproot}"
SRCDIR="${SRCDIR:=/usr/src/etc}"
PAGER="${PAGER:=/usr/bin/more}"
SWIDTH=`stty -a | awk '/columns/{w=$6}END{if(w==0){w=80}print w}'`
WIDTH="${WIDTH:=${SWIDTH}}"
VERBOSE=
CONTINUE=
BINARY=
AUTOMATIC=
LOCALSKIP=
DIFF_COMMAND="diff -u"
VERBOSE=false
CONTINUE=false
SOURCEMODE=false # true for "-s source_dir"
SRCDIR= # directory for SOURCEMODE
BINARYMODE=false # true for both BINARYDIRMODE and BINARYTGZMODE
BINARYDIRMODE=false # true for "-s extracted_dir"
BINARYDIR= # directory name for BINARYDIRMODE
BINARYTGZMODE=false # true for "-s etc.tgz"
TGZLIST= # colon-separated list for BINARYTGZMODE
AUTOMATIC=false
LOCALSKIP=false
MACHINE="${MACHINE:=`uname -m`}"
export MACHINE
MACHINE_ARCH="${MACHINE_ARCH:=`uname -p`}"
export MACHINE_ARCH
# Settings for post-installation procedures
NEED_MTREE=
NEED_MAKEDEV=
NEED_NEWALIASES=
NEED_PWD_MKDB=
NEED_MTREE=false
NEED_MAKEDEV=false
NEED_NEWALIASES=false
NEED_PWD_MKDB=false
myname="${0##*/}"
usage() {
cat << EOF
Usage: `basename $0` [options]
Usage: ${myname} [options]
Options:
-b srcdir Location of the extracted sets
-p pager Which pager to use (default: /usr/bin/more)
-s srcdir Location of the source files (default: /usr/src/etc)
-s {srcdir|tgzfile|tempdir} (default: /usr/src)
Location of the source files used to populate the
target directory. This may be any of the following:
* A directory that contains a NetBSD source tree;
* A distribution set file such as "etc.tgz" or "xetc.tgz";
* A temporary directory in which one or both of "etc.tgz"
and "xetc.tgz" have been extracted.
-t temproot Where to store temporary files (default: /tmp/temproot)
-w width Screen width (default: 80)
-a Automatically update unmodified files
-l Automatically skip files with strictly local changes
(this option has no effect on files lacking RCS Ids)
@ -99,7 +111,7 @@ EOF
verbose() {
# $* = message to display if in verbose mode
[ ! -z "${VERBOSE}" ] && echo ${*}
${VERBOSE} && echo "${*}"
}
yesno() {
@ -123,7 +135,7 @@ install_dir() {
if yesno "Create ${1}"; then
verbose "Creating ${1}"
mkdir -p "${1}" || exit 1
NEED_MTREE=YES
NEED_MTREE=true
fi
}
@ -137,16 +149,16 @@ install_file() {
# Check if this was a special file
case "${1}" in
/dev/MAKEDEV)
NEED_MAKEDEV=YES
NEED_MAKEDEV=true
;;
/dev/MAKEDEV.local)
NEED_MAKEDEV=YES
NEED_MAKEDEV=true
;;
/etc/mail/aliases)
NEED_NEWALIASES=YES
NEED_NEWALIASES=true
;;
/etc/master.passwd)
NEED_PWD_MKDB=YES
NEED_PWD_MKDB=true
;;
esac
}
@ -154,7 +166,7 @@ install_file() {
install_checksum() {
# $1 = target file
[ "${AUTOMATIC}" != "YES" ] && return
${AUTOMATIC} || return
D=`dirname "${1}"`
mkdir -p "/var/etcupdate/${D}"
@ -171,22 +183,22 @@ diff_and_merge_file() {
return
fi
if [ "${AUTOMATIC}" = "YES" -a -f "/var/etcupdate/${1}" ] ; then
if ${AUTOMATIC} && [ -f "/var/etcupdate/${1}" ]; then
SUM1=`md5 "${1}"`
SUM2=`cat "/var/etcupdate/${1}"`
if [ "${SUM1}" = "${SUM2}" ] ; then
if [ "${SUM1}" = "${SUM2}" ]; then
install_file "${1}"
install_checksum "${1}"
return
fi
fi
if [ "${LOCALSKIP}" = "YES" ] ; then
if ${LOCALSKIP}; then
ID1=`ident -q "${TEMPROOT}${1}" | sed -n 2p`
ID1="${ID1:-0}"
ID2=`ident -q "${1}" | sed -n 2p`
ID2="${ID2:-1}"
if [ "${ID1}" = "${ID2}" ] ; then
if [ "${ID1}" = "${ID2}" ]; then
verbose "===> ${1} (ok:RCS)"
rm -f "${TEMPROOT}${1}"
return
@ -196,16 +208,16 @@ diff_and_merge_file() {
clear
if [ ! -f "${1}" ]; then
verbose "===> ${1} (missing)"
DOES_EXIST=
DOES_EXIST=false
else
verbose "===> ${1} (modified)"
verbose ""
DOES_EXIST=YES
DOES_EXIST=true
diff -u "${1}" "${TEMPROOT}${1}" | ${PAGER}
fi
STAY_HERE=YES
ALREADY_MERGED=
STAY_HERE=true
ALREADY_MERGED=false
# Determine name for the backup file (/foo/._etcupdate.bar)
D=`dirname "${TEMPROOT}${1}"`
@ -213,7 +225,7 @@ diff_and_merge_file() {
B="${D}/.etcupdate.${F}"
F="${D}/${F}"
while [ "x${STAY_HERE}" = "xYES" ]; do
while ${STAY_HERE}; do
# Ask the user if (s)he wants to install the new
# version or perform a more complicated manual work.
@ -228,29 +240,35 @@ diff_and_merge_file() {
echo ""
echo "Please select one of the following operations:"
echo ""
if [ -z "${DOES_EXIST}" ]; then
if ! ${DOES_EXIST}; then
cat << EOF
d Don't install the missing file
i Install the missing file
v Show the missing file
EOF
elif [ -z "${ALREADY_MERGED}" ]; then
elif ! ${ALREADY_MERGED}; then
cat << EOF
d Don't install the new file
i Install the new file (overwrites your modifications!)
d Don't install the new file (keep your old file)
i Install the new file (overwrites your local modifications!)
m Merge the currently installed and new files
s Show the differences between the currently installed and new files
sd Show the differences ... using "diff -u"
sw Show the differences ... using "wdiff -n -l"
scommand Show the differences ... using the specified diff-like command
v Show the new file
EOF
else
cat << EOF
d Don't install the new file
i Install the new file (overwrites your modifications!)
m Merge again the currently installed and new files
s Show the differences between the currently installed and new files
u Undo merge and restore the temporary file from backup
d Don't install the merged file (keep your old file)
i Install the merged file
m Merge again (your old file against the result from the previous merge)
s Show the differences between the currently installed and new merged files
sd Show the differences ... using "diff -u"
sw Show the differences ... using "wdiff -n -l"
scommand Show the differences ... using the specified diff-like command
u Undo merge and restore the original version of the new file
v Show the merged file
EOF
@ -262,17 +280,17 @@ EOF
[dD])
verbose "Removing ${TEMPROOT}${1}"
rm -f "${TEMPROOT}${1}"
STAY_HERE=NO
STAY_HERE=false
;;
[iI])
install_file "${1}"
if [ -z "${ALREADY_MERGED}" ]; then
if ! ${ALREADY_MERGED}; then
install_checksum "${1}"
fi
STAY_HERE=NO
STAY_HERE=false
;;
[mM])
[ -z "${DOES_EXIST}" ] && continue
${DOES_EXIST} || continue
[ ! -f "${B}" ] && cp "${F}" "${B}"
cp "${TEMPROOT}${1}" "${TEMPROOT}${1}.merged"
sdiff -o "${TEMPROOT}${1}.merged" \
@ -280,24 +298,30 @@ EOF
--suppress-common-lines --text \
"${1}" "${TEMPROOT}${1}"
mv -f "${TEMPROOT}${1}.merged" "${TEMPROOT}${1}"
ALREADY_MERGED=YES
ALREADY_MERGED=true
;;
[sS])
[ -z "${DOES_EXIST}" ] && continue
diff -u "${1}" "${TEMPROOT}${1}" | ${PAGER}
[sS]*)
${DOES_EXIST} || continue
case "${ANSWER}" in
[sS]) : no change ;;
[sS]d) DIFF_COMMAND="diff -u" ;;
[sS]w) DIFF_COMMAND="wdiff -n -l" ;;
*) DIFF_COMMAND="${ANSWER#?}" ;;
esac
${DIFF_COMMAND} "${1}" "${TEMPROOT}${1}" | ${PAGER}
;;
[uU])
if [ -f "${B}" ]; then
echo "*** Restoring ${F}"
mv -f "${B}" "${F}"
fi
ALREADY_MERGED=
ALREADY_MERGED=false
;;
[vV])
${PAGER} "${TEMPROOT}${1}"
;;
"")
STAY_HERE=NO
STAY_HERE=false
;;
*)
echo "*** Invalid selection!"
@ -326,19 +350,18 @@ set -- ${ARGV}
for i; do
case "${i}" in
-a)
AUTOMATIC=YES
AUTOMATIC=true
shift
;;
-b)
BINARY=YES
SRCDIR="${2}"
shift 2
echo "The '-b tempdir' option has been replaced by '-s tempdir'"
exit 1
;;
-h)
usage
;;
-l)
LOCALSKIP=YES
LOCALSKIP=true
shift
;;
-p)
@ -346,15 +369,45 @@ for i; do
shift 2
;;
-s)
SRCDIR="${2}"
# Three cases:
# -s tgzfile
# -s srcdir
# -s extracted_dir
arg="${2}"
shift 2
if [ -f "${arg}" ]; then
# arg refers to a *.tgz file.
# This may happen twice, for both etc.tgz and
# xetc.tgz, so we build up a colon-separated
# list in TGZLIST.
BINARYMODE=true
BINARYTGZMODE=true
TGZLIST="${TGZLIST}${TGZLIST:+:}${arg}"
elif [ -d "${arg}" ] && [ -f "${ARG}/etc/Makefile" ]; then
# arg refers to a source directory
SOURCEMODE=true
SRCDIR="${arg}"
elif [ -d "${arg}" ] && [ -f "${ARG}/../etc/Makefile" ]; then
# backward compatibility: allow arg to refer to
# etc subdirectory within source dir.
SOURCEMODE=true
SRCDIR="${arg}/.."
elif [ -d "${arg}" ] && [ -d "${ARG}/etc" ]; then
# arg refers to a directory where the
# sets have already been extracted
BINARYMODE=true
BINARYDIRMODE=true
BINARYDIR="${arg}"
else
usage
fi
;;
-t)
TEMPROOT="${2}"
shift 2
;;
-v)
VERBOSE=YES
VERBOSE=true
shift
;;
-w)
@ -373,8 +426,21 @@ if [ `id -u` -ne 0 ]; then
echo "*** ERROR: You MUST be root"
exit 1
fi
if [ ! -z "${BINARY}" ]; then
TEMPROOT="${SRCDIR}"
if ${SOURCEMODE} && ${BINARYMODE}; then
usage
fi
if ${BINARYDIRMODE} && ${BINARYTGZMODE}; then
usage
fi
if ${BINARYDIRMODE}; then
SRCDIR="${BINARYDIR}"
TEMPROOT="${BINARYDIR}"
fi
if ${BINARYTGZMODE}; then
SRCDIR="${TEMPROOT}"
fi
if ${SOURCEMODE} && [ -x "${SRCDIR}" ]; then
SRCDIR=/usr/src
fi
if [ -z "${SRCDIR}" -o -z "${TEMPROOT}" ]; then
echo "*** ERROR: One of the following variables is undefined"
@ -384,21 +450,21 @@ if [ -z "${SRCDIR}" -o -z "${TEMPROOT}" ]; then
echo ""
exit 1
fi
if [ -z "${BINARY}" -a -r "${TEMPROOT}" ]; then
if ! ${BINARYDIRMODE} && [ -r "${TEMPROOT}" ]; then
echo ""
echo "*** WARNING: ${TEMPROOT} already exists"
echo ""
if yesno "Continue previously aborted update"; then
CONTINUE=YES
CONTINUE=true
elif yesno "Remove the old ${TEMPROOT}"; then
echo "*** Removing ${TEMPROOT}"
rm -rf "${TEMPROOT}"
fi
fi
if [ -z "${CONTINUE}" ]; then
if ! ${CONTINUE}; then
# Are we using the sources or binaries?
if [ -z "${BINARY}" ]; then
if ! ${BINARYDIRMODE}; then
# Create the temporary root directory
echo "*** Creating ${TEMPROOT}"
mkdir -p "${TEMPROOT}"
@ -406,10 +472,25 @@ if [ -z "${CONTINUE}" ]; then
echo "*** ERROR: Unable to create ${TEMPROOT}"
exit 1
fi
fi
if ${BINARYTGZMODE}; then
# Populate ${TEMPROOT} from ${TGZLIST}
oldIFS="${IFS}"
IFS=:
for tgz in ${TGZLIST}; do
if [ ! -f "${tgz}" ]; then
echo "*** ERROR: Unable to find ${tgz}"
exit 1
fi
echo "*** Populating ${TEMPROOT} from ${tgz}"
tar -zxpf "${tgz}" -C "${TEMPROOT}"
[ $? -ne 0 ] && exit 1
done
IFS="${oldIFS}"
elif ! ${BINARYMODE}; then
# Populate ${TEMPROOT} from ${SRCDIR}
if [ ! -f "${SRCDIR}/Makefile" ]; then
echo "*** ERROR: Unable to find ${SRCDIR}/Makefile"
if [ ! -f "${SRCDIR}/etc/Makefile" ]; then
echo "*** ERROR: Unable to find ${SRCDIR}/etc/Makefile"
exit 1
fi
# Set the environment for make
@ -421,14 +502,15 @@ if [ -z "${CONTINUE}" ]; then
INSTALL_DONE=1 \
USETOOLS=never"
echo "*** Populating ${TEMPROOT} from ${SRCDIR}"
cd ${SRCDIR}
if [ -z "${VERBOSE}" ]; then
cd ${SRCDIR}/etc
if ! ${VERBOSE}; then
eval ${MAKE_ENV} make distribution > /dev/null
else
eval ${MAKE_ENV} make distribution
fi
[ $? -ne 0 ] && exit 1
elif [ ! -f "${TEMPROOT}/dev/MAKEDEV" ]; then
fi
if [ ! -f "${TEMPROOT}/dev/MAKEDEV" ]; then
echo ""
echo "*** WARNING: ${TEMPROOT}/dev/MAKEDEV not found"
echo "Make sure you update /dev/MAKEDEV later and run"
@ -485,14 +567,14 @@ else
fi
# Do some post-installation tasks
if [ ! -z "${NEED_MTREE}" ]; then
if ${NEED_MTREE}; then
if yesno "You have created new directories. Run mtree to set" \
"permissions"
then
(cd / && mtree -Udef /etc/mtree/NetBSD.dist)
fi
fi
if [ ! -z "${NEED_MAKEDEV}" ]; then
if ${NEED_MAKEDEV}; then
if yesno "Do you want to rebuild the device nodes in /dev"; then
verbose "Running MAKEDEV in /dev"
(cd "/dev" && ./MAKEDEV all)
@ -504,7 +586,7 @@ if [ ! -z "${NEED_MAKEDEV}" ]; then
echo ""
fi
fi
if [ ! -z "${NEED_NEWALIASES}" ]; then
if ${NEED_NEWALIASES}; then
if yesno "Do you want to rebuild the mail alias database"; then
verbose "Running newaliases"
newaliases
@ -516,7 +598,7 @@ if [ ! -z "${NEED_NEWALIASES}" ]; then
echo ""
fi
fi
if [ ! -z "${NEED_PWD_MKDB}" ]; then
if ${NEED_PWD_MKDB}; then
if yesno "Do you want to rebuild the password databases from the" \
"new master.passwd"
then
@ -531,9 +613,9 @@ if [ ! -z "${NEED_PWD_MKDB}" ]; then
echo ""
fi
fi
if [ -x /usr/sbin/postinstall -a -z "${BINARY}" ]; then
S=`echo ${SRCDIR} | sed 's+/etc++'`
if [ -x /usr/sbin/postinstall ] && ! ${BINARYMODE}; then
# XXX we should also run postinstall in binary mode
echo "*** Running /usr/sbin/postinstall"
/usr/sbin/postinstall -s "${S}" check
/usr/sbin/postinstall -s "${SRCDIR}" check
fi
echo "*** All done"

View File

@ -1,4 +1,4 @@
.\" $NetBSD: etcupdate.8,v 1.10 2003/04/02 19:30:57 wiz Exp $
.\" $NetBSD: etcupdate.8,v 1.11 2006/02/18 19:29:48 apb Exp $
.\"
.\" Copyright (c) 2001 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -34,7 +34,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd April 2, 2003
.Dd February 18, 2006
.Dt ETCUPDATE 8
.Os
.Sh NAME
@ -44,9 +44,8 @@
.Sh SYNOPSIS
.Nm
.Op Fl ahlv
.Op Fl b Ar srcdir
.Op Fl p Ar pager
.Op Fl s Ar srcdir
.Op Fl s Brq Ar srcdir | Ar tgzfile | Ar tempdir
.Op Fl t Ar temproot
.Op Fl w Ar width
.Sh DESCRIPTION
@ -106,7 +105,11 @@ options later in this manual page.)
Instead of using sources, the user can also extract one or more binary
distribution sets in a special location and use those as the reference
files (see usage of the
.Fl b Ar srcdir
.Fl s Ar tempdir
option later in this manual page),
or specify one or more binary distribution sets directly
(see usage of the
.Fl s Ar tgzfile
option later in this manual page).
.Pp
The following options are available:
@ -122,19 +125,6 @@ to store MD5 checksums in
.Pa /var/etcupdate
and use these checksums to determine if there have been any
local modifications.
.It Fl b Ar srcdir
Location of reference files extracted from a binary distribution of
.Nx .
Note that reference files in
.Pa srcdir
will be altered and removed by
.Nm
when using the
.Fl b Ar srcdir
option (as the
.Pa srcdir
directory is treated like
.Pa temproot ) .
.It Fl h
Prints a help text.
.It Fl l
@ -155,28 +145,79 @@ but it can be changed either with this option
or by defining the
.Ev PAGER
variable.
.It Fl s Brq Ar srcdir | Ar tgzfile | Ar tempdir
The location of the reference files, or the
.Nx
source files used to create the reference files.
This may be specified in one of three ways:
.Bl -tag -width XXsXtempdirXX
.It Fl s Ar srcdir
The location of the
.Nx
sources files used to create the reference files.
source files used to create the reference files.
By default this is
.Pa /usr/src/etc
.Pa /usr/src
but it can be changed either with this option
or the
.Ev SRCDIR
variable.
Note that
.Ar srcdir
should refer to the top of the source directory tree;
earlier versions of
.Nm
expected
.Ar srcdir
to refer to the
.Pa etc
subdirectory within the source tree.
.It Fl s Ar tgzfile
The location of a set file from a binary distribution of
.Nx .
The set file is a compressed archive containing reference files.
This option may be specified twice, to specify the locations of
both the
.Pa etc.tgz
and
.Pa xetc.tgz
sets.
The files from the specified sets will be extracted to the
.Pa temproot
directory.
.It Fl s Ar tempdir
Location of reference files extracted from a binary distribution of
.Nx .
Note that reference files in
.Pa tempdir
will be altered and removed by
.Nm
when using the
.Fl s Ar tempdir
option (as the
.Pa tempdir
directory is treated like
.Pa temproot ) .
.El
.It Fl t Ar temproot
Specifies the location of the
.Pa temproot
directory.
The temporary reference files created from
.Pa /usr/src/etc
the source directory specified by
.Fl s Ar srcdir ,
or the temporary reference files extracted from
the binary tgz sets specified by
.Fl s Ar tgzfile ,
will be stored there.
By default this is
.Pa /tmp/temproot
but can be changed either with this option or the
.Ev TEMPROOT
environment variable.
It is an error to specify
.Fl t Ar temproot
in conjunction with
.Fl s Ar tempdir .
.It Fl v
Makes
.Nm
@ -238,7 +279,7 @@ settings.
.Sh EXAMPLES
You have just upgraded your
.Nx
host from 1.6 to 1.6.1 and now it's time
host from 3.0 to 4.0 and now it's time
to update the configuration files as well.
To update the configuration files from the sources (if you have the
.Pa /usr/src/etc
@ -247,20 +288,25 @@ directory):
.Dl etcupdate
.Pp
The default location of the source files is
.Pa /usr/src/etc
.Pa /usr/src
but this may be overridden with the
.Fl s Ar srcdir
command line argument:
.Pp
.Dl etcupdate -s /some/where/src/etc
.Dl etcupdate -s /some/where/src
.Pp
To update the configuration files from binary distribution sets
do something like this:
.Pp
.Dl etcupdate -s /some/where/etc.tgz -s /some/where/xetc.tgz
.Pp
or like this:
.Pp
.Dl mkdir /tmp/temproot
.Dl cd /tmp/temproot
.Dl tar xpzf /some/where/etc.tgz
.Dl etcupdate -b /tmp/temproot
.Dl tar -xpzf /some/where/etc.tgz
.Dl tar -xpzf /some/where/xetc.tgz
.Dl etcupdate -s /tmp/temproot
.Pp
You have modified only few files in the
.Pa /etc
@ -286,6 +332,21 @@ The
.Nm
command appeared in
.Nx 1.6 .
.Pp
In
.Nx 4.0 ,
the
.Fl s Ar tgzfile
option was added, the
.Fl b Ar tempdir
option was converted to
.Fl s Ar tempdir ,
and the
.Fl s Ar srcdir
option was changed to refer to the top of the
source directory tree rather than to the
.Pa etc
subdirectory.
.Sh AUTHORS
The script was written by
.An Martti Kuparinen