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