mergemaster.sh revision 111905
1#!/bin/sh
2
3# mergemaster
4
5# Compare files created by /usr/src/etc/Makefile (or the directory
6# the user specifies) with the currently installed copies.
7
8# Copyright 1998-2003 Douglas Barton
9# DougB@FreeBSD.org
10
11# $FreeBSD: head/usr.sbin/mergemaster/mergemaster.sh 111905 2003-03-05 12:42:08Z dougb $
12
13PATH=/bin:/usr/bin:/usr/sbin
14
15display_usage () {
16  VERSION_NUMBER=`grep "[$]FreeBSD:" $0 | cut -d ' ' -f 4`
17  echo "mergemaster version ${VERSION_NUMBER}"
18  echo 'Usage: mergemaster [-scrvahipC] [-m /path]'
19  echo '         [-t /path] [-d] [-u N] [-w N] [-D /path]'
20  echo "Options:"
21  echo "  -s  Strict comparison (diff every pair of files)"
22  echo "  -c  Use context diff instead of unified diff"
23  echo "  -r  Re-run on a previously cleaned directory (skip temproot creation)"
24  echo "  -v  Be more verbose about the process, include additional checks"
25  echo "  -a  Leave all files that differ to merge by hand"
26  echo "  -h  Display more complete help"
27  echo '  -i  Automatically install files that do not exist in destination directory'
28  echo '  -p  Pre-buildworld mode, only compares crucial files'
29  echo '  -C  Compare local rc.conf variables to the defaults'
30  echo "  -m /path/directory  Specify location of source to do the make in"
31  echo "  -t /path/directory  Specify temp root directory"
32  echo "  -d  Add date and time to directory name (e.g., /var/tmp/temproot.`date +%m%d.%H.%M`)"
33  echo "  -u N  Specify a numeric umask"
34  echo "  -w N  Specify a screen width in columns to sdiff"
35  echo '  -D /path/directory  Specify the destination directory to install files to'
36  echo ''
37}
38
39display_help () {
40  echo "* To specify a directory other than /var/tmp/temproot for the"
41  echo "  temporary root environment, use -t /path/to/temp/root"
42  echo "* The -w option takes a number as an argument for the column width"
43  echo "  of the screen.  The default is 80."
44  echo '* The -a option causes mergemaster to run without prompting.'
45}
46
47# Loop allowing the user to use sdiff to merge files and display the merged
48# file.
49merge_loop () {
50  case "${VERBOSE}" in
51  '') ;;
52  *)
53      echo "   *** Type h at the sdiff prompt (%) to get usage help"
54      ;;
55  esac
56  echo ''
57  MERGE_AGAIN=yes
58  while [ "${MERGE_AGAIN}" = "yes" ]; do
59    # Prime file.merged so we don't blat the owner/group id's
60    cp -p "${COMPFILE}" "${COMPFILE}.merged"
61    sdiff -o "${COMPFILE}.merged" --text --suppress-common-lines \
62      --width=${SCREEN_WIDTH:-80} "${DESTDIR}${COMPFILE#.}" "${COMPFILE}"
63    INSTALL_MERGED=V
64    while [ "${INSTALL_MERGED}" = "v" -o "${INSTALL_MERGED}" = "V" ]; do
65      echo ''
66      echo "  Use 'i' to install merged file"
67      echo "  Use 'r' to re-do the merge"
68      echo "  Use 'v' to view the merged file"
69      echo "  Default is to leave the temporary file to deal with by hand"
70      echo ''
71      echo -n "    *** How should I deal with the merged file? [Leave it for later] "
72      read INSTALL_MERGED
73
74      case "${INSTALL_MERGED}" in
75      [iI])
76        mv "${COMPFILE}.merged" "${COMPFILE}"
77        echo ''
78        if mm_install "${COMPFILE}"; then
79          echo "     *** Merged version of ${COMPFILE} installed successfully"
80        else
81          echo "     *** Problem installing ${COMPFILE}, it will remain to merge by hand later"
82        fi
83        unset MERGE_AGAIN
84        ;;
85      [rR])
86        rm "${COMPFILE}.merged"
87        ;;
88      [vV])
89        ${PAGER} "${COMPFILE}.merged"
90        ;;
91      '')
92        echo "   *** ${COMPFILE} will remain for your consideration"
93        unset MERGE_AGAIN
94        ;;
95      *)
96        echo "invalid choice: ${INSTALL_MERGED}"
97        INSTALL_MERGED=V
98        ;;
99      esac
100    done
101  done
102}
103
104# Loop showing user differences between files, allow merge, skip or install
105# options
106diff_loop () {
107
108  HANDLE_COMPFILE=v
109
110  while [ "${HANDLE_COMPFILE}" = "v" -o "${HANDLE_COMPFILE}" = "V" -o \
111    "${HANDLE_COMPFILE}" = "NOT V" ]; do
112    if [ -f "${DESTDIR}${COMPFILE#.}" -a -f "${COMPFILE}" ]; then
113      if [ "${HANDLE_COMPFILE}" = "v" -o "${HANDLE_COMPFILE}" = "V" ]; then
114	echo ''
115	echo '   ======================================================================   '
116	echo ''
117        (
118          echo "  *** Displaying differences between ${COMPFILE} and installed version:"
119          echo ''
120          diff ${DIFF_FLAG} ${DIFF_OPTIONS} "${DESTDIR}${COMPFILE#.}" "${COMPFILE}"
121        ) | ${PAGER}
122        echo ''
123      fi
124    else
125      echo ''
126      echo "  *** There is no installed version of ${COMPFILE}"
127      echo ''
128      case "${AUTO_INSTALL}" in
129      [Yy][Ee][Ss])
130        echo ''
131        if mm_install "${COMPFILE}"; then
132          echo "   *** ${COMPFILE} installed successfully"
133          echo ''
134          # Make the list print one file per line
135          AUTO_INSTALLED_FILES="${AUTO_INSTALLED_FILES}      ${DESTDIR}${COMPFILE#.}
136"
137        else
138          echo "   *** Problem installing ${COMPFILE}, it will remain to merge by hand"
139        fi
140        return
141        ;;
142      *)
143        NO_INSTALLED=yes
144        ;;
145      esac
146    fi
147
148    echo "  Use 'd' to delete the temporary ${COMPFILE}"
149    echo "  Use 'i' to install the temporary ${COMPFILE}"
150    case "${NO_INSTALLED}" in
151    '')
152      echo "  Use 'm' to merge the temporary and installed versions"
153      echo "  Use 'v' to view the diff results again"
154      ;;
155    esac
156    echo ''
157    echo "  Default is to leave the temporary file to deal with by hand"
158    echo ''
159    echo -n "How should I deal with this? [Leave it for later] "
160    read HANDLE_COMPFILE
161
162    case "${HANDLE_COMPFILE}" in
163    [dD])
164      rm "${COMPFILE}"
165      echo ''
166      echo "   *** Deleting ${COMPFILE}"
167      ;;
168    [iI])
169      echo ''
170      if mm_install "${COMPFILE}"; then
171        echo "   *** ${COMPFILE} installed successfully"
172      else
173        echo "   *** Problem installing ${COMPFILE}, it will remain to merge by hand"
174      fi
175      ;;
176    [mM])
177      case "${NO_INSTALLED}" in
178      '')
179        # interact with user to merge files
180        merge_loop
181        ;;
182      *)
183        echo ''
184        echo "   *** There is no installed version of ${COMPFILE}"
185        echo ''
186        HANDLE_COMPFILE="NOT V"
187        ;;
188      esac # End of "No installed version of file but user selected merge" test
189      ;;
190    [vV])
191      continue
192      ;;
193    '')
194      echo ''
195      echo "   *** ${COMPFILE} will remain for your consideration"
196      ;;
197    *)
198      # invalid choice, show menu again.
199      echo "invalid choice: ${HANDLE_COMPFILE}"
200      echo ''
201      HANDLE_COMPFILE="NOT V"
202      continue
203      ;;
204    esac  # End of "How to handle files that are different"
205  done
206  unset NO_INSTALLED
207  echo ''
208  case "${VERBOSE}" in
209  '') ;;
210  *)
211    sleep 3
212    ;;
213  esac
214}
215
216press_to_continue () {
217  local DISCARD
218  echo -n ' *** Press the [Enter] or [Return] key to continue '
219  read DISCARD
220}
221
222# Set the default path for the temporary root environment
223#
224TEMPROOT='/var/tmp/temproot'
225
226# Read /etc/mergemaster.rc first so the one in $HOME can override
227#
228if [ -r /etc/mergemaster.rc ]; then
229  . /etc/mergemaster.rc
230fi
231
232# Read .mergemasterrc before command line so CLI can override
233#
234if [ -r "$HOME/.mergemasterrc" ]; then
235  . "$HOME/.mergemasterrc"
236fi
237
238# Check the command line options
239#
240while getopts ":ascrvhipCm:t:du:w:D:" COMMAND_LINE_ARGUMENT ; do
241  case "${COMMAND_LINE_ARGUMENT}" in
242  s)
243    STRICT=yes
244    unset DIFF_OPTIONS
245    ;;
246  c)
247    DIFF_FLAG='-c'
248    ;;
249  r)
250    RERUN=yes
251    ;;
252  v)
253    case "${AUTO_RUN}" in
254    '') VERBOSE=yes ;;
255    esac
256    ;;
257  a)
258    AUTO_RUN=yes
259    unset VERBOSE
260    ;;
261  h)
262    display_usage
263    display_help
264    exit 0
265    ;;
266  i)
267    AUTO_INSTALL=yes
268    ;;
269  C)
270    COMP_CONFS=yes
271    ;;
272  p)
273    PRE_WORLD=yes
274    unset COMP_CONFS
275    unset AUTO_RUN
276    ;;
277  m)
278    SOURCEDIR=${OPTARG}
279    ;;
280  t)
281    TEMPROOT=${OPTARG}
282    ;;
283  d)
284    TEMPROOT=${TEMPROOT}.`date +%m%d.%H.%M`
285    ;;
286  u)
287    NEW_UMASK=${OPTARG}
288    ;;
289  w)
290    SCREEN_WIDTH=${OPTARG}
291    ;;
292  D)
293    DESTDIR=${OPTARG}
294    ;;
295  *)
296    display_usage
297    exit 1
298    ;;
299  esac
300done
301
302echo ''
303
304# If the user has a pager defined, make sure we can run it
305#
306case "${DONT_CHECK_PAGER}" in
307'')
308  while ! type "${PAGER%% *}" >/dev/null && [ -n "${PAGER}" ]; do
309    echo " *** Your PAGER environment variable specifies '${PAGER}', but"
310    echo "     due to the limited PATH that I use for security reasons,"
311    echo "     I cannot execute it.  So, what would you like to do?"
312    echo ''
313    echo "  Use 'e' to exit mergemaster and fix your PAGER variable"
314    if [ -x /usr/bin/less -o -x /usr/local/bin/less ]; then
315    echo "  Use 'l' to set PAGER to 'less' for this run"
316    fi
317    echo "  Use 'm' to use plain old 'more' as your PAGER for this run"
318    echo ''
319    echo "  Default is to use plain old 'more' "
320    echo ''
321    echo -n "What should I do? [Use 'more'] "
322    read FIXPAGER
323
324    case "${FIXPAGER}" in
325    [eE])
326       exit 0
327       ;;
328    [lL])
329       if [ -x /usr/bin/less ]; then
330         PAGER=/usr/bin/less
331       elif [ -x /usr/local/bin/less ]; then
332         PAGER=/usr/local/bin/less
333       else
334         echo ''
335         echo " *** Fatal Error:"
336         echo "     You asked to use 'less' as your pager, but I can't"
337         echo "     find it in /usr/bin or /usr/local/bin"
338         exit 1
339       fi
340       ;;
341    [mM]|'')
342       PAGER=more
343       ;;
344    *)
345       echo ''
346       echo "invalid choice: ${FIXPAGER}"
347    esac
348    echo ''
349  done
350  ;;
351esac
352
353# If user has a pager defined, or got assigned one above, use it.
354# If not, use more.
355#
356PAGER=${PAGER:-more}
357
358if [ -n "${VERBOSE}" -a ! "${PAGER}" = "more" ]; then
359  echo " *** You have ${PAGER} defined as your pager so we will use that"
360  echo ''
361  sleep 3
362fi
363
364# Assign the diff flag once so we will not have to keep testing it
365#
366DIFF_FLAG=${DIFF_FLAG:--u}
367
368# Assign the source directory
369#
370SOURCEDIR=${SOURCEDIR:-/usr/src/etc}
371
372# Check the width of the user's terminal
373#
374if [ -t 0 ]; then
375  w=`tput columns`
376  case "${w}" in
377  0|'') ;; # No-op, since the input is not valid
378  *)
379    case "${SCREEN_WIDTH}" in
380    '') SCREEN_WIDTH="${w}" ;;
381    "${w}") ;; # No-op, since they are the same
382    *)
383      echo -n "*** You entered ${SCREEN_WIDTH} as your screen width, but stty "
384      echo "thinks it is ${w}."
385      echo ''
386      echo -n "What would you like to use? [${w}] "
387      read SCREEN_WIDTH
388      case "${SCREEN_WIDTH}" in
389      '') SCREEN_WIDTH="${w}" ;;
390      esac
391      ;;
392    esac
393  esac
394fi
395
396# Define what CVS $Id tag to look for to aid portability.
397#
398CVS_ID_TAG=FreeBSD
399
400delete_temproot () {
401  rm -rf "${TEMPROOT}" 2>/dev/null
402  chflags -R 0 "${TEMPROOT}" 2>/dev/null
403  rm -rf "${TEMPROOT}" || exit 1
404}
405
406case "${RERUN}" in
407'')
408  # Set up the loop to test for the existence of the
409  # temp root directory.
410  #
411  TEST_TEMP_ROOT=yes
412  while [ "${TEST_TEMP_ROOT}" = "yes" ]; do
413    if [ -d "${TEMPROOT}" ]; then
414      echo "*** The directory specified for the temporary root environment,"
415      echo "    ${TEMPROOT}, exists.  This can be a security risk if untrusted"
416      echo "    users have access to the system."
417      echo ''
418      case "${AUTO_RUN}" in
419      '')
420        echo "  Use 'd' to delete the old ${TEMPROOT} and continue"
421        echo "  Use 't' to select a new temporary root directory"
422        echo "  Use 'e' to exit mergemaster"
423        echo ''
424        echo "  Default is to use ${TEMPROOT} as is"
425        echo ''
426        echo -n "How should I deal with this? [Use the existing ${TEMPROOT}] "
427        read DELORNOT
428
429        case "${DELORNOT}" in
430        [dD])
431          echo ''
432          echo "   *** Deleting the old ${TEMPROOT}"
433          echo ''
434          delete_temproot || exit 1
435          unset TEST_TEMP_ROOT
436          ;;
437        [tT])
438          echo "   *** Enter new directory name for temporary root environment"
439          read TEMPROOT
440          ;;
441        [eE])
442          exit 0
443          ;;
444        '')
445          echo ''
446          echo "   *** Leaving ${TEMPROOT} intact"
447          echo ''
448          unset TEST_TEMP_ROOT
449          ;;
450        *)
451          echo ''
452          echo "invalid choice: ${DELORNOT}"
453          echo ''
454          ;;
455        esac
456        ;;
457      *)
458        # If this is an auto-run, try a hopefully safe alternative then
459        # re-test anyway.
460        TEMPROOT=/var/tmp/temproot.`date +%m%d.%H.%M.%S`
461        ;;
462      esac
463    else
464      unset TEST_TEMP_ROOT
465    fi
466  done
467
468  echo "*** Creating the temporary root environment in ${TEMPROOT}"
469
470  if mkdir -p "${TEMPROOT}"; then
471    echo " *** ${TEMPROOT} ready for use"
472  fi
473
474  if [ ! -d "${TEMPROOT}" ]; then
475    echo ''
476    echo "  *** FATAL ERROR: Cannot create ${TEMPROOT}"
477    echo ''
478    exit 1
479  fi
480
481  echo " *** Creating and populating directory structure in ${TEMPROOT}"
482  echo ''
483
484  case "${VERBOSE}" in
485  '') ;;
486  *)
487    press_to_continue
488    ;;
489  esac
490
491  case "${PRE_WORLD}" in
492  '')
493    { cd ${SOURCEDIR} &&
494      case "${DESTDIR}" in
495      '') ;;
496      *)
497      make DESTDIR=${DESTDIR} distrib-dirs
498        ;;
499      esac
500      make DESTDIR=${TEMPROOT} distrib-dirs &&
501      make MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj obj &&
502      make MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj DESTDIR=${TEMPROOT} \
503          distribution;} ||
504    { echo '';
505     echo "  *** FATAL ERROR: Cannot 'cd' to ${SOURCEDIR} and install files to";
506      echo "      the temproot environment";
507      echo '';
508      exit 1;}
509    ;;
510  *)
511    # Only set up files that are crucial to {build|install}world
512    { mkdir -p ${TEMPROOT}/etc &&
513      cp -p ${SOURCEDIR}/master.passwd ${TEMPROOT}/etc &&
514      cp -p ${SOURCEDIR}/group ${TEMPROOT}/etc;} ||
515    { echo '';
516      echo '  *** FATAL ERROR: Cannot copy files to the temproot environment';
517      echo '';
518      exit 1;}
519    ;;
520  esac
521
522  # Doing the inventory and removing files that we don't want to compare only
523  # makes sense if we are not doing a rerun, since we have no way of knowing
524  # what happened to the files during previous incarnations.
525  case "${VERBOSE}" in
526  '') ;;
527  *)
528    echo ''
529    echo ' *** The following files exist only in the installed version of'
530    echo "     ${DESTDIR}/etc.  In the vast majority of cases these files"
531    echo '     are necessary parts of the system and should not be deleted.'
532    echo '     However because these files are not updated by this process you'
533    echo '     might want to verify their status before rebooting your system.'
534    echo ''
535    press_to_continue
536    diff -qr ${DESTDIR}/etc ${TEMPROOT}/etc | grep "^Only in ${DESTDIR}/etc" | ${PAGER}
537    echo ''
538    press_to_continue
539    ;;
540  esac
541
542  # Avoid comparing the motd if the user specifies it in .mergemasterrc
543  case "${IGNORE_MOTD}" in
544  '') ;;
545  *) rm -f ${TEMPROOT}/etc/motd
546     ;;
547  esac
548
549  # Avoid trying to update MAKEDEV if /dev is on a devfs
550  if /sbin/sysctl vfs.devfs.generation > /dev/null 2>&1 ; then
551    rm -f ${TEMPROOT}/dev/MAKEDEV ${TEMPROOT}/dev/MAKEDEV.local
552  fi
553
554  ;; # End of the "RERUN" test
555esac
556
557# We really don't want to have to deal with files like login.conf.db, pwd.db,
558# or spwd.db.  Instead, we want to compare the text versions, and run *_mkdb.
559# Prompt the user to do so below, as needed.
560#
561rm -f ${TEMPROOT}/etc/*.db ${TEMPROOT}/etc/passwd
562
563# We only need to compare things like freebsd.cf once
564find ${TEMPROOT}/usr/obj -type f -delete 2>/dev/null
565
566# Get ready to start comparing files
567
568# Check umask if not specified on the command line,
569# and we are not doing an autorun
570#
571if [ -z "${NEW_UMASK}" -a -z "${AUTO_RUN}" ]; then
572  USER_UMASK=`umask`
573  case "${USER_UMASK}" in
574  0022|022) ;;
575  *)
576    echo ''
577    echo " *** Your umask is currently set to ${USER_UMASK}.  By default, this script"
578    echo "     installs all files with the same user, group and modes that"
579    echo "     they are created with by ${SOURCEDIR}/Makefile, compared to"
580    echo "     a umask of 022.  This umask allows world read permission when"
581    echo "     the file's default permissions have it."
582    echo ''
583    echo "     No world permissions can sometimes cause problems.  A umask of"
584    echo "     022 will restore the default behavior, but is not mandatory."
585    echo "     /etc/master.passwd is a special case.  Its file permissions"
586    echo "     will be 600 (rw-------) if installed."
587    echo ''
588    echo -n "What umask should I use? [${USER_UMASK}] "
589    read NEW_UMASK
590
591    NEW_UMASK="${NEW_UMASK:-$USER_UMASK}"
592    ;;
593  esac
594  echo ''
595fi
596
597CONFIRMED_UMASK=${NEW_UMASK:-0022}
598
599# Warn users who still have ${DESTDIR}/etc/sysconfig
600#
601if [ -e "${DESTDIR}/etc/sysconfig" ]; then
602  echo ''
603  echo " *** There is a sysconfig file on this system in ${DESTDIR}/etc/."
604  echo ''
605  echo '     Starting with FreeBSD version 2.2.2 those settings moved from'
606  echo '     /etc/sysconfig to /etc/rc.conf.  If you are upgrading an older'
607  echo '     system make sure that you transfer your settings by hand from'
608  echo '     sysconfig to rc.conf and install the rc.conf file.  If you'
609  echo '     have already made this transition, you should consider'
610  echo '     renaming or deleting the sysconfig file.'
611  echo ''
612  case "${AUTO_RUN}" in
613  '')
614    echo -n "Continue with the merge process? [yes] "
615    read CONT_OR_NOT
616
617    case "${CONT_OR_NOT}" in
618    [nN]*)
619      exit 0
620      ;;
621    *)
622      echo "   *** Continuing"
623      echo ''
624      ;;
625    esac
626    ;;
627  *) ;;
628  esac
629fi
630
631# Use the umask/mode information to install the files
632# Create directories as needed
633#
634do_install_and_rm () {
635  install -m "${1}" "${2}" "${3}" &&
636  rm -f "${2}"
637}
638
639# 4095 = "obase=10;ibase=8;07777" | bc
640find_mode () {
641  local OCTAL
642  OCTAL=$(( ~$(echo "obase=10; ibase=8; ${CONFIRMED_UMASK}" | bc) & 4095 &
643    $(echo "obase=10; ibase=8; $(stat -f "%OMp%OLp" ${1})" | bc) )) 
644  printf "%04o\n" ${OCTAL}
645}
646
647mm_install () {
648  local INSTALL_DIR
649  INSTALL_DIR=${1#.}
650  INSTALL_DIR=${INSTALL_DIR%/*}
651
652  case "${INSTALL_DIR}" in
653  '')
654    INSTALL_DIR=/
655    ;;
656  esac
657
658  if [ -n "${DESTDIR}${INSTALL_DIR}" -a ! -d "${DESTDIR}${INSTALL_DIR}" ]; then
659    DIR_MODE=`find_mode "${TEMPROOT}/${INSTALL_DIR}"`
660    install -d -o root -g wheel -m "${DIR_MODE}" "${DESTDIR}${INSTALL_DIR}"
661  fi
662
663  FILE_MODE=`find_mode "${1}"`
664
665  if [ ! -x "${1}" ]; then
666    case "${1#.}" in
667    /etc/mail/aliases)
668      NEED_NEWALIASES=yes
669      ;;
670    /etc/login.conf)
671      NEED_CAP_MKDB=yes
672      ;;
673    /etc/master.passwd)
674      do_install_and_rm 600 "${1}" "${DESTDIR}${INSTALL_DIR}"
675      NEED_PWD_MKDB=yes
676      DONT_INSTALL=yes
677      ;;
678    /.cshrc | /.profile)
679    case "${AUTO_INSTALL}" in
680    '')
681      case "${LINK_EXPLAINED}" in
682      '')
683        echo "   *** Historically BSD derived systems have had a"
684        echo "       hard link from /.cshrc and /.profile to"
685        echo "       their namesakes in /root.  Please indicate"
686        echo "       your preference below for bringing your"
687        echo "       installed files up to date."
688        echo ''
689        LINK_EXPLAINED=yes
690        ;;
691      esac
692
693      echo "   Use 'd' to delete the temporary ${COMPFILE}"
694      echo "   Use 'l' to delete the existing ${DESTDIR}${COMPFILE#.} and create the link"
695      echo ''
696      echo "   Default is to leave the temporary file to deal with by hand"
697      echo ''
698      echo -n "  How should I handle ${COMPFILE}? [Leave it to install later] "
699      read HANDLE_LINK
700      ;;
701    *)  # Part of AUTO_INSTALL
702      HANDLE_LINK=l
703      ;;
704    esac
705
706      case "${HANDLE_LINK}" in
707      [dD]*)
708        rm "${COMPFILE}"
709        echo ''
710        echo "   *** Deleting ${COMPFILE}"
711        ;;
712      [lL]*)
713        echo ''
714        rm -f "${DESTDIR}${COMPFILE#.}"
715        if ln "${DESTDIR}/root/${COMPFILE##*/}" "${DESTDIR}${COMPFILE#.}"; then
716          echo "   *** Link from ${DESTDIR}${COMPFILE#.} to ${DESTDIR}/root/${COMPFILE##*/} installed successfully"
717          rm "${COMPFILE}"
718        else
719          echo "   *** Error linking ${DESTDIR}${COMPFILE#.} to ${DESTDIR}/root/${COMPFILE##*/}, ${COMPFILE} will remain to install by hand"
720        fi
721        ;;
722      *)
723        echo "   *** ${COMPFILE} will remain for your consideration"
724        ;;
725      esac
726      DONT_INSTALL=yes
727      ;;
728    esac
729
730    case "${DONT_INSTALL}" in
731    '')
732      do_install_and_rm "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}"
733      ;;
734    *)
735      unset DONT_INSTALL
736      ;;
737    esac
738  else	# File matched -x
739    case "${1#.}" in
740    /dev/MAKEDEV)
741      NEED_MAKEDEV=yes
742      ;;
743    esac
744    do_install_and_rm "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}"
745  fi
746  return $?
747}
748
749echo ''
750echo "*** Beginning comparison"
751echo ''
752
753cd "${TEMPROOT}"
754
755if [ -r "${MM_PRE_COMPARE_SCRIPT}" ]; then
756  . "${MM_PRE_COMPARE_SCRIPT}"
757fi
758
759# Using -size +0 avoids uselessly checking the empty log files created
760# by ${SOURCEDIR}/Makefile and the device entries in ./dev, but does
761# check the scripts in ./dev, as we'd like (assuming no devfs of course).
762#
763for COMPFILE in `find . -type f -size +0`; do
764
765  # First, check to see if the file exists in DESTDIR.  If not, the
766  # diff_loop function knows how to handle it.
767  #
768  if [ ! -e "${DESTDIR}${COMPFILE#.}" ]; then
769    case "${AUTO_RUN}" in
770      '')
771        diff_loop
772        ;;
773      *)
774        case "${AUTO_INSTALL}" in
775        '')
776          # If this is an auto run, make it official
777          echo "   *** ${COMPFILE} will remain for your consideration"
778          ;;
779        *)
780          diff_loop
781          ;;
782        esac
783        ;;
784    esac # Auto run test
785    continue
786  fi
787
788  case "${STRICT}" in
789  '' | [Nn][Oo])
790    # Compare CVS $Id's first so if the file hasn't been modified
791    # local changes will be ignored.
792    # If the files have the same $Id, delete the one in temproot so the
793    # user will have less to wade through if files are left to merge by hand.
794    #
795    CVSID1=`grep "[$]${CVS_ID_TAG}:" ${DESTDIR}${COMPFILE#.} 2>/dev/null`
796    CVSID2=`grep "[$]${CVS_ID_TAG}:" ${COMPFILE} 2>/dev/null` || CVSID2=none
797
798    case "${CVSID2}" in
799    "${CVSID1}")
800      echo " *** Temp ${COMPFILE} and installed have the same CVS Id, deleting"
801      rm "${COMPFILE}"
802      ;;
803    esac
804    ;;
805  esac
806
807  # If the file is still here either because the $Ids are different, the
808  # file doesn't have an $Id, or we're using STRICT mode; look at the diff.
809  #
810  if [ -f "${COMPFILE}" ]; then
811
812    # Do an absolute diff first to see if the files are actually different.
813    # If they're not different, delete the one in temproot.
814    #
815    if diff -q ${DIFF_OPTIONS} "${DESTDIR}${COMPFILE#.}" "${COMPFILE}" > \
816      /dev/null 2>&1; then
817      echo " *** Temp ${COMPFILE} and installed are the same, deleting"
818      rm "${COMPFILE}"
819    else
820      # Ok, the files are different, so show the user where they differ.
821      # Use user's choice of diff methods; and user's pager if they have one.
822      # Use more if not.
823      # Use unified diffs by default.  Context diffs give me a headache. :)
824      #
825      case "${AUTO_RUN}" in
826      '')
827        # prompt user to install/delete/merge changes
828        diff_loop
829        ;;
830      *)
831        # If this is an auto run, make it official
832        echo "   *** ${COMPFILE} will remain for your consideration"
833        ;;
834      esac # Auto run test
835    fi # Yes, the files are different
836  fi # Yes, the file still remains to be checked
837done # This is for the do way up there at the beginning of the comparison
838
839echo ''
840echo "*** Comparison complete"
841echo ''
842
843TEST_FOR_FILES=`find ${TEMPROOT} -type f -size +0 2>/dev/null`
844if [ -n "${TEST_FOR_FILES}" ]; then
845  echo "*** Files that remain for you to merge by hand:"
846  find "${TEMPROOT}" -type f -size +0
847  echo ''
848fi
849
850case "${AUTO_RUN}" in
851'')
852  echo -n "Do you wish to delete what is left of ${TEMPROOT}? [no] "
853  read DEL_TEMPROOT
854
855  case "${DEL_TEMPROOT}" in
856  [yY]*)
857    if delete_temproot; then
858      echo " *** ${TEMPROOT} has been deleted"
859    else
860      echo " *** Unable to delete ${TEMPROOT}"
861    fi
862    ;;
863  *)
864    echo " *** ${TEMPROOT} will remain"
865    ;;
866  esac
867  ;;
868*) ;;
869esac
870
871case "${AUTO_INSTALLED_FILES}" in
872'') ;;
873*)
874  case "${AUTO_RUN}" in
875  '')
876    (
877      echo ''
878      echo '*** You chose the automatic install option for files that did not'
879      echo '    exist on your system.  The following were installed for you:'
880      echo "${AUTO_INSTALLED_FILES}"
881    ) | ${PAGER}
882    ;;
883  *)
884    echo ''
885    echo '*** You chose the automatic install option for files that did not'
886    echo '    exist on your system.  The following were installed for you:'
887    echo "${AUTO_INSTALLED_FILES}"
888    ;;
889  esac
890  ;;
891esac
892
893run_it_now () {
894  case "${AUTO_RUN}" in
895  '')
896    unset YES_OR_NO
897    echo ''
898    echo -n '    Would you like to run it now? y or n [n] '
899    read YES_OR_NO
900
901    case "${YES_OR_NO}" in
902    y)
903      echo "    Running ${1}"
904      echo ''
905      eval "${1}"
906      ;;
907    ''|n)
908      echo ''
909      echo "       *** Cancelled"
910      echo ''
911      echo "    Make sure to run ${1} yourself"
912      ;;
913    *)
914      echo ''
915      echo "       *** Sorry, I do not understand your answer (${YES_OR_NO})"
916      echo ''
917      echo "    Make sure to run ${1} yourself"
918    esac
919    ;;
920  *) ;;
921  esac
922}
923
924case "${NEED_MAKEDEV}" in
925'') ;;
926*)
927  echo ''
928  echo "*** You installed a new ${DESTDIR}/dev/MAKEDEV script, so make sure that you run"
929  echo "    'cd ${DESTDIR}/dev && /bin/sh MAKEDEV all' to rebuild your devices"
930  run_it_now "cd ${DESTDIR}/dev && /bin/sh MAKEDEV all"
931  ;;
932esac
933
934case "${NEED_NEWALIASES}" in
935'') ;;
936*)
937  echo ''
938  if [ -n "${DESTDIR}" ]; then
939    echo "*** You installed a new aliases file into ${DESTDIR}/etc/mail, but"
940    echo "    the newaliases command is limited to the directories configured"
941    echo "    in sendmail.cf.  Make sure to create your aliases database by"
942    echo "    hand when your sendmail configuration is done."
943  else
944    echo "*** You installed a new aliases file, so make sure that you run"
945    echo "    '/usr/bin/newaliases' to rebuild your aliases database"
946    run_it_now '/usr/bin/newaliases'
947  fi
948  ;;
949esac
950
951case "${NEED_CAP_MKDB}" in
952'') ;;
953*)
954  echo ''
955  echo "*** You installed a login.conf file, so make sure that you run"
956  echo "    '/usr/bin/cap_mkdb ${DESTDIR}/etc/login.conf'"
957  echo "     to rebuild your login.conf database"
958  run_it_now "/usr/bin/cap_mkdb ${DESTDIR}/etc/login.conf"
959  ;;
960esac
961
962case "${NEED_PWD_MKDB}" in
963'') ;;
964*)
965  echo ''
966  echo "*** You installed a new master.passwd file, so make sure that you run"
967  if [ -n "${DESTDIR}" ]; then
968    echo "    '/usr/sbin/pwd_mkdb -d ${DESTDIR}/etc -p ${DESTDIR}/etc/master.passwd'"
969    echo "    to rebuild your password files"
970    run_it_now "/usr/sbin/pwd_mkdb -d ${DESTDIR}/etc -p ${DESTDIR}/etc/master.passwd"
971  else
972    echo "    '/usr/sbin/pwd_mkdb -p /etc/master.passwd'"
973    echo "     to rebuild your password files"
974    run_it_now '/usr/sbin/pwd_mkdb -p /etc/master.passwd'
975  fi
976  ;;
977esac
978
979echo ''
980
981if [ -r "${MM_EXIT_SCRIPT}" ]; then
982  . "${MM_EXIT_SCRIPT}"
983fi
984
985case "${COMP_CONFS}" in
986'') ;;
987*)
988  . ${DESTDIR}/etc/defaults/rc.conf
989
990  (echo ''
991  echo "*** Comparing conf files: ${rc_conf_files}"
992
993  for CONF_FILE in ${rc_conf_files}; do
994    if [ -r "${DESTDIR}${CONF_FILE}" ]; then
995      echo ''
996      echo "*** From ${DESTDIR}${CONF_FILE}"
997      echo "*** From ${DESTDIR}/etc/defaults/rc.conf"
998
999      for RC_CONF_VAR in `grep -i ^[a-z] ${DESTDIR}${CONF_FILE} |
1000        cut -d '=' -f 1`; do
1001        echo ''
1002        grep -w ^${RC_CONF_VAR} ${DESTDIR}${CONF_FILE}
1003        grep -w ^${RC_CONF_VAR} ${DESTDIR}/etc/defaults/rc.conf ||
1004          echo ' * No default variable with this name'
1005      done
1006    fi
1007  done) | ${PAGER}
1008  echo ''
1009  ;;
1010esac
1011
1012case "${PRE_WORLD}" in
1013'') ;;
1014*)
1015  MAKE_CONF="${SOURCEDIR%etc}share/examples/etc/make.conf"
1016
1017  (echo ''
1018  echo '*** Comparing make variables'
1019  echo ''
1020  echo "*** From ${DESTDIR}/etc/make.conf"
1021  echo "*** From ${MAKE_CONF}"
1022
1023  for MAKE_VAR in `grep -i ^[a-z] ${DESTDIR}/etc/make.conf | cut -d '=' -f 1`; do
1024    echo ''
1025    grep -w ^${MAKE_VAR} ${DESTDIR}/etc/make.conf
1026    grep -w ^#${MAKE_VAR} ${MAKE_CONF} ||
1027      echo ' * No example variable with this name'
1028  done) | ${PAGER}
1029  ;;
1030esac
1031
1032exit 0
1033
1034