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