1 #!/bin/sh 2 # 3 # $NetBSD: etcupdate,v 1.65 2022/01/17 08:47:03 lukem Exp $ 4 # 5 # Copyright (c) 2001-2022 The NetBSD Foundation, Inc. 6 # All rights reserved. 7 # 8 # This code is derived from software contributed to The NetBSD Foundation 9 # by Martti Kuparinen. 10 # 11 # Redistribution and use in source and binary forms, with or without 12 # modification, are permitted provided that the following conditions 13 # are met: 14 # 1. Redistributions of source code must retain the above copyright 15 # notice, this list of conditions and the following disclaimer. 16 # 2. Redistributions in binary form must reproduce the above copyright 17 # notice, this list of conditions and the following disclaimer in the 18 # documentation and/or other materials provided with the distribution. 19 # 20 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 # POSSIBILITY OF SUCH DAMAGE. 31 # 32 # 33 # This script helps you to update the configuration files in /etc 34 # after an operating system upgrade. Instead of running "make distribution" 35 # in /usr/src/etc (and losing your current configuration) you can easily 36 # see the modifications and either install the new version or merge the 37 # changes in to your current configuration files. 38 # 39 # This script was written by Martti Kuparinen <martti (at] NetBSD.org> and 40 # improved by several other NetBSD users. 41 # 42 # The idea for this script (including code fragments, variable names etc.) 43 # came from the FreeBSD mergemaster (by Douglas Barton). 44 # 45 PATH="/sbin:/usr/sbin:/bin:/usr/bin:${PATH}" 46 47 # Default settings 48 PROG="${0##*/}" 49 DESTDIR="" # must not have a trailing slash 50 DESTDIR_BRE="" # basic regex to match ${DESTDIR} 51 TEMPROOT="${TEMPROOT:=/tmp/temproot}" 52 PAGER="${PAGER:=/usr/bin/more}" 53 SWIDTH="$(stty size | awk '{w=$2}END{if(w==0){w=80}print w}')" 54 WIDTH="${WIDTH:="${SWIDTH}"}" 55 DIFF_COMMAND="diff -u" 56 VERBOSE=false 57 CONTINUE=false 58 SOURCEMODE=false # true for "-s source_dir" 59 SRCDIR= # directory for SOURCEMODE 60 BINARYMODE=false # true for both BINARYDIRMODE and BINARYTGZMODE 61 BINARYDIRMODE=false # true for "-s extracted_dir" 62 BINARYDIR= # directory name for BINARYDIRMODE 63 BINARYTGZMODE=false # true for "-s etc.tgz" 64 TGZLIST= # quoted list list of files for BINARYTGZMODE 65 SRC_ARGLIST= # quoted list of "-s" args 66 N_SRC_ARGS=0 # number of "-s" args 67 AUTOMATIC=false 68 LOCALSKIP=false 69 MACHINE="${MACHINE:="$(uname -m)"}" 70 export MACHINE 71 MACHINE_ARCH="${MACHINE_ARCH:="$(uname -p)"}" 72 export MACHINE_ARCH 73 74 # Settings for post-installation procedures 75 NEED_ANYTHING=false 76 NEED_MAKEDEV=false 77 NEED_MTREE=false 78 NEED_NEWALIASES=false 79 NEED_PWD_MKDB=false 80 NEED_SERVICES_MKDB=false 81 82 83 help() 84 { 85 cat << EOF 86 87 Usage: ${PROG} [-alv] [-d DESTDIR] [-p PAGER] [-s SRC_ARG] [-t TEMPROOT] [-w WIDTH] 88 ${PROG} ( -h | -? ) 89 90 Options: 91 92 -a Automatically update unmodified files. 93 -d DESTDIR Destination directory to check. [/] 94 -h Display this help, and exit. 95 -l Automatically skip files with strictly local changes 96 (this option has no effect on files lacking RCS Ids). 97 -p PAGER Which pager to use [/usr/bin/more] 98 -s SRC_ARG Location of the source files. [/usr/src] 99 This may be any of the following: 100 -s SRC_DIR A directory that contains a NetBSD 101 source tree. 102 -s TGZ_DIR A directory in which one or both of 103 "etc.tgz" and "xetc.tgz" have been extracted. 104 -s TGZ_FILE A distribution set file such as "etc.tgz" or 105 "xetc.tgz". May be specified multiple times. 106 -t TEMPROOT Where to store temporary files. [/tmp/temproot] 107 -w WIDTH Screen width. [80] 108 -v Be more verbose. 109 -? Display this help, and exit. 110 111 EOF 112 } 113 114 usage() 115 { 116 help 1>&2 117 exit 1 118 } 119 120 verbose() 121 { 122 # $* = message to display if in verbose mode 123 124 ${VERBOSE} && echo "${@}" 125 } 126 127 yesno() 128 { 129 # $* = message to display 130 131 echo -n "${@}? (y/[n]) " 132 read ANSWER 133 case "${ANSWER}" in 134 y|Y) 135 return 0 136 ;; 137 *) 138 return 1 139 ;; 140 esac 141 } 142 143 # Quote args to make them safe in the shell. 144 # Usage: quotedlist="$(shell_quote args...)" 145 # 146 # After building up a quoted list, use it by evaling it inside 147 # double quotes, like this: 148 # eval "set -- $quotedlist" 149 # or like this: 150 # eval "\$command $quotedlist \$filename" 151 # 152 shell_quote() 153 {( 154 local result='' 155 local arg qarg 156 LC_COLLATE=C ; export LC_COLLATE # so [a-zA-Z0-9] works in ASCII 157 for arg in "$@" ; do 158 case "${arg}" in 159 '') 160 qarg="''" 161 ;; 162 *[!-./a-zA-Z0-9]*) 163 # Convert each embedded ' to '\'', 164 # then insert ' at the beginning of the first line, 165 # and append ' at the end of the last line. 166 # Finally, elide unnecessary '' pairs at the 167 # beginning and end of the result and as part of 168 # '\'''\'' sequences that result from multiple 169 # adjacent quotes in he input. 170 qarg="$(printf "%s\n" "$arg" | \ 171 ${SED:-sed} -e "s/'/'\\\\''/g" \ 172 -e "1s/^/'/" -e "\$s/\$/'/" \ 173 -e "1s/^''//" -e "\$s/''\$//" \ 174 -e "s/'''/'/g" 175 )" 176 ;; 177 *) 178 # Arg is not the empty string, and does not contain 179 # any unsafe characters. Leave it unchanged for 180 # readability. 181 qarg="${arg}" 182 ;; 183 esac 184 result="${result}${result:+ }${qarg}" 185 done 186 printf "%s\n" "$result" 187 )} 188 189 # Convert arg $1 to a basic regular expression (as in sed) 190 # that will match the arg. This works by inserting backslashes 191 # before characters that are special in basic regular expressions. 192 # It also inserts backslashes before the extra characters specified 193 # in $2 (which defaults to "/,"). 194 # XXX: Does not handle embedded newlines. 195 # Usage: regex="$(bre_quote "${string}")" 196 bre_quote() 197 { 198 local arg="$1" 199 local extra="${2-/,}" 200 printf "%s\n" "${arg}" | sed -e 's/[][^$.*\\'"${extra}"']/\\&/g' 201 } 202 203 install_dir() 204 { 205 # $1 = target directory (relative to ${DESTDIR}) 206 207 NEED_ANYTHING=true 208 if yesno "Create ${DESTDIR}${1}"; then 209 verbose "Creating ${DESTDIR}${1}" 210 mkdir -p "${DESTDIR}${1}" || exit 1 211 NEED_MTREE=true 212 fi 213 } 214 215 install_file() 216 { 217 # $1 = target file (relative to ${DESTDIR}) 218 219 NEED_ANYTHING=true 220 # Install the new file 221 verbose "Installing ${DESTDIR}${1}" 222 cp -p "${TEMPROOT}${1}" "${DESTDIR}${1}" && rm -f "${TEMPROOT}${1}" 223 224 # Check if this was a special file 225 case "${1}" in 226 /dev/MAKEDEV) 227 NEED_MAKEDEV=true 228 ;; 229 /dev/MAKEDEV.local) 230 NEED_MAKEDEV=true 231 ;; 232 /etc/mail/aliases) 233 NEED_NEWALIASES=true 234 ;; 235 /etc/master.passwd) 236 NEED_PWD_MKDB=true 237 ;; 238 /etc/services) 239 NEED_SERVICES_MKDB=true 240 ;; 241 esac 242 } 243 244 install_checksum() 245 { 246 # $1 = target file (relative to ${DESTDIR}) 247 248 ${AUTOMATIC} || return 249 250 NEED_ANYTHING=true 251 D="$(dirname "${1}")" 252 mkdir -p "${DESTDIR}/var/etcupdate/${D}" 253 verbose "Saving MD5 checksum for ${DESTDIR}${1} to" \ 254 "${DESTDIR}/var/etcupdate/${1}" 255 # The sed part of the following pipeline changes things like 256 # "MD5 (/path/to/dest/dir/etc/filename) = abc123" to 257 # "MD5 (/etc/filename) = abc123". 258 md5 "${DESTDIR}${1}" | sed -e "s,(${DESTDIR_BRE},(," \ 259 > "${DESTDIR}/var/etcupdate/${1}" 260 } 261 262 # Initialise the DIFF_EXTRA_OPTIONS variable. 263 init_diff_extra_options() 264 { 265 # 266 # Start with a few options that are always available. 267 # 268 DIFF_EXTRA_OPTIONS=\ 269 " su Show differences in unified format (\"diff -u\") 270 sc Show differences in context format (\"diff -c\") 271 ss Show differences side by side (\"sdiff -w${WIDTH}\")" 272 # 273 # wdiff is not part of the base system, but the 274 # user might have installed it from pkgsrc. It is 275 # useful to show differences on a word by word basis 276 # instead of line by line. If it is executable 277 # then offer to use it in the menu. 278 # 279 if (wdiff /dev/null /dev/null) >/dev/null 2>&1 ; then 280 DIFF_EXTRA_OPTIONS="${DIFF_EXTRA_OPTIONS} 281 sw Show differences word by word (\"wdiff -n -l\")" 282 fi 283 # 284 # End with an option to use a user-specified diff-like command. 285 # 286 DIFF_EXTRA_OPTIONS="${DIFF_EXTRA_OPTIONS} 287 scommand Show differences using the specified diff-like command" 288 } 289 290 diff_and_merge_file() 291 { 292 # $1 = target file (relative to ${DESTDIR}) 293 294 if cmp -s "${TEMPROOT}${1}" "${DESTDIR}${1}"; then 295 verbose "===> ${1} (ok)" 296 rm -f "${TEMPROOT}${1}" 297 install_checksum "${1}" 298 return 299 fi 300 301 if ${AUTOMATIC} && [ -f "${DESTDIR}/var/etcupdate/${1}" ]; then 302 SUM1="$(md5 "${1}")" 303 SUM2="$(cat "${DESTDIR}/var/etcupdate/${1}")" 304 if [ "${SUM1}" = "${SUM2}" ]; then 305 install_file "${1}" 306 install_checksum "${1}" 307 return 308 fi 309 fi 310 311 if ${LOCALSKIP}; then 312 ID1="$(ident -q "${TEMPROOT}${1}" | sed -n 2p)" 313 ID1="${ID1:-0}" 314 ID2="$(ident -q "${DESTDIR}${1}" | sed -n 2p)" 315 ID2="${ID2:-1}" 316 if [ "${ID1}" = "${ID2}" ]; then 317 verbose "===> ${1} (ok:RCS)" 318 rm -f "${TEMPROOT}${1}" 319 return 320 fi 321 fi 322 323 clear 324 if [ ! -f "${DESTDIR}${1}" ]; then 325 verbose "===> ${DESTDIR}${1} (missing)" 326 DOES_EXIST=false 327 else 328 verbose "===> ${DESTDIR}${1} (modified)" 329 verbose "" 330 DOES_EXIST=true 331 diff -u "${DESTDIR}${1}" "${TEMPROOT}${1}" | ${PAGER} 332 fi 333 334 STAY_HERE=true 335 ALREADY_MERGED=false 336 337 # Determine name for the backup file (/foo/._etcupdate.bar) 338 D="$(dirname "${TEMPROOT}${1}")" 339 F="$(basename "${TEMPROOT}${1}")" 340 B="${D}/.etcupdate.${F}" 341 F="${D}/${F}" 342 343 while ${STAY_HERE}; do 344 345 # Ask the user if (s)he wants to install the new 346 # version or perform a more complicated manual work. 347 echo "" 348 echo -n "File: ${DESTDIR}${1}" 349 if [ ! -f "${DESTDIR}${1}" ]; then 350 echo -n " (missing)" 351 else 352 echo -n " (modified)" 353 fi 354 echo "" 355 echo "" 356 echo "Please select one of the following operations:" 357 echo "" 358 if ! ${DOES_EXIST}; then 359 cat << EOF 360 d Don't install the missing file 361 i Install the missing file 362 v Show the missing file 363 364 EOF 365 elif ! ${ALREADY_MERGED}; then 366 cat << EOF 367 d Don't install the new file (keep your old file) 368 i Install the new file (overwrites your local modifications!) 369 m Merge the currently installed and new files 370 s Show the differences between the currently installed and new files 371 ${DIFF_EXTRA_OPTIONS} 372 v Show the new file 373 374 EOF 375 else 376 cat << EOF 377 d Don't install the merged file (keep your old file) 378 i Install the merged file (overwrites your old file) 379 m Merge again (your old file against the result from the previous merge) 380 s Show the differences between the currently installed and new merged files 381 ${DIFF_EXTRA_OPTIONS} 382 u Undo merge (start again with the original version of the new file) 383 v Show the merged file 384 385 EOF 386 fi 387 echo -n "What do you want to do? [Leave it for later] " 388 read ANSWER 389 case "${ANSWER}" in 390 391 [dD]) 392 verbose "Removing ${TEMPROOT}${1}" 393 rm -f "${TEMPROOT}${1}" 394 STAY_HERE=false 395 ;; 396 [iI]) 397 install_file "${1}" 398 if ! ${ALREADY_MERGED}; then 399 install_checksum "${1}" 400 fi 401 STAY_HERE=false 402 ;; 403 [mM]) 404 ${DOES_EXIST} || continue 405 [ ! -f "${B}" ] && cp "${F}" "${B}" 406 cp "${TEMPROOT}${1}" "${TEMPROOT}${1}.merged" 407 sdiff -o "${TEMPROOT}${1}.merged" \ 408 --width=${WIDTH} \ 409 --suppress-common-lines --text \ 410 "${DESTDIR}${1}" "${TEMPROOT}${1}" 411 mv -f "${TEMPROOT}${1}.merged" "${TEMPROOT}${1}" 412 ALREADY_MERGED=true 413 ;; 414 [sS]*) 415 ${DOES_EXIST} || continue 416 case "${ANSWER}" in 417 [sS]) : no change ;; 418 [sS]u) DIFF_COMMAND="diff -u" ;; 419 [sS]c) DIFF_COMMAND="diff -c" ;; 420 [sS]s) DIFF_COMMAND="sdiff -w${WIDTH}" ;; 421 [sS]w) DIFF_COMMAND="wdiff -n -l" ;; 422 [sS]*) DIFF_COMMAND="${ANSWER#?}" ;; 423 esac 424 ${DIFF_COMMAND} "${DESTDIR}${1}" "${TEMPROOT}${1}" \ 425 | ${PAGER} 426 ;; 427 [uU]) 428 if [ -f "${B}" ]; then 429 echo "*** Restoring ${F}" 430 mv -f "${B}" "${F}" 431 fi 432 ALREADY_MERGED=false 433 ;; 434 [vV]) 435 ${PAGER} "${TEMPROOT}${1}" 436 ;; 437 "") 438 STAY_HERE=false 439 ;; 440 *) 441 echo "*** Invalid selection!" 442 ;; 443 esac 444 done 445 rm -f "$B" 446 } 447 448 # Set the environment for make. 449 set_makeenv() 450 { 451 # 452 # INSTALL_DONE=1 prevents installation of unwanted 453 # files (things that are not part of the etc set). 454 # BUILD=1 allows building of files that are wanted. 455 # 456 MAKE_ENV=" \ 457 NETBSDSRCDIR=$(shell_quote "${SRCDIR}") \ 458 DESTDIR=$(shell_quote "${TEMPROOT}") \ 459 MAKE=make \ 460 MTREE=mtree \ 461 TOOL_MTREE=mtree \ 462 INSTALL_DONE=1 \ 463 BUILD=1 \ 464 USETOOLS=never" 465 } 466 467 # 468 # main() 469 # 470 471 # Read global configuration 472 GLOBALRC="/etc/${PROG}.conf" 473 [ -r ${GLOBALRC} ] && . ${GLOBALRC} 474 475 # Read user configuration 476 USERRC="${HOME}/.{PROG}rc" 477 [ -r ${USERRC} ] && . ${USERRC} 478 479 # Read command line arguments 480 while getopts :ad:hlp:s:t:vw: i 481 do 482 case "${i}" in 483 a) 484 AUTOMATIC=true 485 ;; 486 d) 487 DESTDIR="${OPTARG}" 488 ;; 489 h) 490 help 491 exit 0 492 ;; 493 l) 494 LOCALSKIP=true 495 ;; 496 p) 497 PAGER="${OPTARG}" 498 ;; 499 s) 500 # Three cases: 501 # -s tgzfile (may be repeated) 502 # -s srcdir (may not be repeated) 503 # -s extracted_dir (may not be repeated) 504 arg="${OPTARG}" 505 qarg="$(shell_quote "${OPTARG}")" 506 N_SRC_ARGS=$(( N_SRC_ARGS + 1 )) 507 SRC_ARGLIST="${SRC_ARGLIST}${SRC_ARGLIST:+ }-s ${qarg}" 508 if [ -f "${arg}" ]; then 509 # arg refers to a *.tgz file. 510 # This may happen twice, for both etc.tgz and 511 # xetc.tgz, so we build up a list in TGZLIST. 512 BINARYMODE=true 513 BINARYTGZMODE=true 514 TGZLIST="${TGZLIST}${TGZLIST:+ }${qarg}" 515 elif [ -d "${arg}" ] && [ -f "${arg}/etc/Makefile" ]; then 516 # arg refers to a source directory 517 SOURCEMODE=true 518 SRCDIR="${arg}" 519 elif [ -d "${arg}" ] && [ -d "${arg}/etc" ] \ 520 && ! [ -f "${arg}/etc/Makefile" ] 521 then 522 # arg refers to a directory where the 523 # sets have already been extracted 524 BINARYMODE=true 525 BINARYDIRMODE=true 526 BINARYDIR="${arg}" 527 else 528 echo "*** Nonexistent or invalid file or directory" \ 529 "for -s ${arg}" 530 usage 531 fi 532 ;; 533 t) 534 TEMPROOT="${OPTARG}" 535 ;; 536 v) 537 VERBOSE=true 538 ;; 539 w) 540 WIDTH="${OPTARG}" 541 ;; 542 "?") 543 if [ "${OPTARG}" = "?" ]; then 544 help 545 exit 0 546 fi 547 echo 1>&2 "${PROG}: Unknown option -${OPTARG}" 548 usage 549 ;; 550 551 :) 552 echo 1>&2 "${PROG}: Missing argument for option -${OPTARG}" 553 usage 554 ;; 555 556 *) 557 echo 1>&2 "${PROG}: Unimplemented option -${i}" 558 exit 3 559 ;; 560 esac 561 done 562 shift $((${OPTIND} - 1)) 563 if [ $# -ne 0 ] ; then 564 echo 1>&2 "${PROG}: Unknown extra arguments" 565 usage 566 fi 567 568 # Last minute sanity checks 569 if [ "$(id -u)" -ne 0 ]; then 570 echo "*** ERROR: You MUST be root" 571 exit 1 572 fi 573 DESTDIR="${DESTDIR%/}" # remove trailing slash, if any. result might be "". 574 DESTDIR_BRE="$(bre_quote "${DESTDIR}")" 575 if [ "${N_SRC_ARGS}" -gt 1 ] && ( ${SOURCEMODE} || ${BINARYDIRMODE} ); then 576 echo 1>&2 "${PROG}: Multiple -s args are allowed only with tgz files" 577 usage 578 fi 579 case "${TEMPROOT}" in 580 /*) : OK ;; 581 *) new="${PWD:-$(pwd)}/${TEMPROOT}" 582 echo "*** NOTE: Using TEMPROOT \"${new}\" instead of \"${TEMPROOT}\"" 583 TEMPROOT="${new}" 584 ;; 585 esac 586 if ${BINARYDIRMODE}; then 587 SRCDIR="${TEMPROOT}" 588 fi 589 if ${BINARYTGZMODE}; then 590 SRCDIR="${TEMPROOT}" 591 fi 592 if [ "${N_SRC_ARGS}" -eq 0 ]; then 593 # default if no "-s" option was specified 594 SOURCEMODE=true 595 SRCDIR="/usr/src" 596 SRC_ARGLIST="-s $(shell_quote "${SRCDIR}")" 597 fi 598 if [ -z "${SRCDIR}" -o -z "${TEMPROOT}" ]; then 599 echo "*** ERROR: One of the following variables is undefined" 600 echo "" 601 echo "SRCDIR=\"${SRCDIR}\"" 602 echo "TEMPROOT=\"${TEMPROOT}\"" 603 echo "" 604 exit 1 605 fi 606 if [ -r "${TEMPROOT}" ]; then 607 echo "" 608 echo "*** WARNING: ${TEMPROOT} already exists" 609 echo "" 610 if yesno "Continue previously aborted update"; then 611 CONTINUE=true 612 elif yesno "Remove the old ${TEMPROOT}"; then 613 echo "*** Removing ${TEMPROOT}" 614 rm -rf "${TEMPROOT}" 615 fi 616 fi 617 618 if ! ${CONTINUE}; then 619 # Create the temporary root directory 620 echo "*** Creating ${TEMPROOT}" 621 mkdir -p "${TEMPROOT}" 622 if [ ! -d "${TEMPROOT}" ]; then 623 echo "*** ERROR: Unable to create ${TEMPROOT}" 624 exit 1 625 fi 626 # Are we using the sources or binaries? 627 if ${BINARYTGZMODE}; then 628 # Populate ${TEMPROOT} from ${TGZLIST} 629 eval "set -- ${TGZLIST}" 630 for tgz in "$@"; do 631 if [ ! -f "${tgz}" ]; then 632 echo "*** ERROR: Unable to find ${tgz}" 633 exit 1 634 fi 635 echo "*** Populating ${TEMPROOT} from ${tgz}" 636 tar -zxpf "${tgz}" -C "${TEMPROOT}" 637 [ $? -ne 0 ] && exit 1 638 done 639 elif ${BINARYDIRMODE}; then 640 # Populate ${TEMPROOT} from ${SRCDIR} by copying. 641 # Copy only the files that belong to the etc and xetc sets. 642 echo "*** Populating ${TEMPROOT} from ${BINARYDIR} (copying)" 643 for setname in etc xetc; do 644 mtreefile="${BINARYDIR}/etc/mtree/set.${setname}" 645 if ${VERBOSE}; then vflag="-v"; else vflag=""; fi 646 if [ -f "${mtreefile}" ]; then 647 echo "*** Copying files belonging to" \ 648 "${setname} set" 649 (cd "${BINARYDIR}" \ 650 && pax -rwdM ${vflag} "${TEMPROOT%/}/." 651 ) <"${mtreefile}" 652 [ $? -ne 0 ] && exit 1 653 else 654 echo "*** Not copying files belonging to" \ 655 "${setname} set: ${mtreefile} not found" 656 fi 657 done 658 elif ${SOURCEMODE}; then 659 # Populate ${TEMPROOT} from ${SRCDIR} by running make 660 if [ ! -f "${SRCDIR}/etc/Makefile" ]; then 661 echo "*** ERROR: Unable to find ${SRCDIR}/etc/Makefile" 662 exit 1 663 fi 664 set_makeenv 665 echo "*** Populating ${TEMPROOT} from ${SRCDIR} (make distribution)" 666 cd ${SRCDIR}/etc 667 if ! ${VERBOSE}; then 668 eval "${MAKE_ENV} make distribution > /dev/null" 669 else 670 eval "${MAKE_ENV} make distribution" 671 fi 672 [ $? -ne 0 ] && exit 1 673 fi 674 if ! [ -f "${TEMPROOT}/etc/mtree/set.etc" ]; then 675 echo "*** ERROR: Files from the etc.tgz set are missing" 676 exit 1 677 fi 678 if [ ! -f "${TEMPROOT}/dev/MAKEDEV" ]; then 679 echo "" 680 echo "*** WARNING: ${TEMPROOT}/dev/MAKEDEV not found" 681 echo "Make sure you update /dev/MAKEDEV later and run" 682 echo "(cd /dev && ./MAKEDEV all) to rebuild the device nodes" 683 echo "" 684 fi 685 686 # Ignore the following files during comparison 687 rm -f "${TEMPROOT}"/etc/passwd 688 rm -f "${TEMPROOT}"/etc/pwd.db 689 rm -f "${TEMPROOT}"/etc/spwd.db 690 find "${TEMPROOT}" -type f -size 0 -exec rm {} \; 691 692 # Ignore files we're told to ignore 693 if [ ! -z "${IGNOREFILES}" ]; then 694 echo "*** Ignoring files: ${IGNOREFILES}" 695 for file in ${IGNOREFILES}; do 696 rm -f "${TEMPROOT}"${file} 697 done 698 fi 699 700 # Are there any new directories? 701 echo "*** Checking for new directories" 702 exec 3<&0 703 find "${TEMPROOT}" -type d | \ 704 while read i; do 705 D="${i#"${TEMPROOT}"}" 706 [ "x${i}" = "x${TEMPROOT}" ] && continue 707 [ ! -d "${D}" ] && install_dir "${D}" <&3 708 done 709 fi 710 711 # Start the comparison 712 echo "*** Checking for added/modified files" 713 init_diff_extra_options 714 exec 3<&0 715 find "${TEMPROOT}" -type f -a ! -name \*.etcupdate.\* | \ 716 while read i; do 717 D="${i#"${TEMPROOT}"}" 718 diff_and_merge_file "${D}" <&3 719 done 720 721 # Do we have files which were not processed? 722 REMAINING="$(find "${TEMPROOT}" -type f -a ! -name \*.etcupdate.\*)" 723 if [ ! -z "${REMAINING}" ]; then 724 echo "" 725 echo "*** The following files need your attention:" 726 echo "" 727 echo "${REMAINING}" | sed -e 's/^/ /' 728 echo "" 729 elif ! ${NEED_ANYTHING}; then 730 echo "" 731 echo "*** No changes were needed" 732 echo "" 733 fi 734 if yesno "Remove ${TEMPROOT}"; then 735 echo "*** Removing ${TEMPROOT}" 736 rm -rf "${TEMPROOT}" 737 else 738 echo "*** Keeping ${TEMPROOT}" 739 fi 740 741 # Clean up after "make distribution" 742 if ${SOURCEMODE}; then 743 echo "*** Cleaning up in ${SRCDIR}/etc" 744 set_makeenv 745 cd ${SRCDIR}/etc 746 if ! ${VERBOSE}; then 747 eval "${MAKE_ENV} make clean > /dev/null" 748 else 749 eval "${MAKE_ENV} make clean" 750 fi 751 fi 752 753 # Do some post-installation tasks 754 if ${NEED_PWD_MKDB}; then 755 pwd_mkdb_cmd="$(shell_quote \ 756 pwd_mkdb ${DESTDIR:+-d "${DESTDIR}"} \ 757 -p "${DESTDIR}/etc/master.passwd")" 758 if yesno "Do you want to rebuild the password databases from the" \ 759 "new ${DESTDIR}/etc/master.passwd" 760 then 761 verbose "Running pwd_mkdb" 762 eval "${pwd_mkdb_cmd}" 763 else 764 echo "" 765 echo "*** You MUST rebuild the password databases to make" \ 766 "the changes visible" 767 echo "*** This is done by running \"${pwd_mkdb_cmd}\" as root" 768 echo "" 769 fi 770 fi 771 772 if ! ${NEED_SERVICES_MKDB}; then 773 if test -e "${DESTDIR}/var/db/services.db" \ 774 -a ! -e "${DESTDIR}/var/db/services.cdb" 775 then 776 NEED_SERVICES_MKDB=true 777 fi 778 fi 779 780 if ${NEED_SERVICES_MKDB}; then 781 services_mkdb_cmd="$(shell_quote services_mkdb -V cdb \ 782 -o "${DESTDIR}/var/db/services.cdb" \ 783 "${DESTDIR}/etc/services")" 784 if yesno "Do you want to rebuild the services databases from the" \ 785 "new ${DESTDIR}/etc/services" 786 then 787 verbose "Running services_mkdb" 788 eval "${services_mkdb_cmd}" 789 else 790 echo "" 791 echo "*** You SHOULD rebuild the services databases to make" \ 792 "the changes visible" 793 echo "*** This is done by running \"${services_mkdb_cmd}\"" \ 794 "as root" 795 echo "" 796 fi 797 fi 798 if ${NEED_MTREE}; then 799 if yesno "You have created new directories. Run mtree to set" \ 800 "permissions" 801 then 802 (cd "${DESTDIR:-/}" && \ 803 mtree -Udef "${DESTDIR}/etc/mtree/NetBSD.dist") 804 fi 805 fi 806 if ${NEED_MAKEDEV}; then 807 makedev_cmd="($(shell_quote cd "${DESTDIR}/dev") && ./MAKEDEV all)" 808 if yesno "Do you want to rebuild the device nodes in ${DESTDIR}/dev" 809 then 810 verbose "Running MAKEDEV in /dev" 811 eval "${makedev_cmd}" 812 else 813 echo "" 814 echo "*** You SHOULD rebuild the device nodes in" \ 815 "${DESTDIR}/dev" 816 echo "*** This is done by running \"${makedev_cmd}\" as root." 817 echo "" 818 fi 819 fi 820 if ${NEED_NEWALIASES}; then 821 newaliases_cmd="newaliases" 822 # XXX newaliases doesn't work with DESTDIR. 823 # We could check whether the system configuration is 824 # sufficiently standard, and then run postalias(1) with the 825 # right args to make it work, but changes to /etc/mail/aliases 826 # are so rare that it doesn't seem worth the effort of checking 827 # that the system's mail configuration is standard. 828 if [ -z "${DESTDIR}" ] && \ 829 yesno "Do you want to rebuild the mail alias database" 830 then 831 verbose "Running newaliases" 832 eval "${newaliases_cmd}" 833 else 834 echo "" 835 echo "*** You MUST rebuild the mail alias database to make" \ 836 "the changes visible" 837 echo "*** This is done by running \"${newaliases_cmd}\" as root" 838 if [ -n "${DESTDIR}" ]; then 839 postalias_cmd="$(shell_quote \ 840 postalias "hash:${DESTDIR}/etc/mail/aliases")" 841 echo "*** but it won't work with DESTDIR=${DESTDIR}." 842 echo "*** If you use postfix(1) with the default" \ 843 "configuration, then you can try" 844 echo "*** running \"${postalias_cmd}\" as root." 845 fi 846 echo "" 847 fi 848 fi 849 if [ -x "${DESTDIR}/usr/sbin/postinstall" ]; then 850 postinstall_cmd="$(shell_quote "${DESTDIR}/usr/sbin/postinstall" \ 851 ${DESTDIR:+-d "${DESTDIR}"}) ${SRC_ARGLIST} check" 852 echo "*** Running ${DESTDIR}/usr/sbin/postinstall" 853 eval "${postinstall_cmd}" 854 fi 855 echo "*** All done" 856