mergemaster.sh revision 101362
1251881Speter#!/bin/sh
2251881Speter
3251881Speter# mergemaster
4251881Speter
5251881Speter# Compare files created by /usr/src/etc/Makefile (or the directory
6251881Speter# the user specifies) with the currently installed copies.
7251881Speter
8251881Speter# Copyright 1998-2002 Douglas Barton
9251881Speter# DougB@FreeBSD.org
10251881Speter
11251881Speter# $FreeBSD: head/usr.sbin/mergemaster/mergemaster.sh 101362 2002-08-05 08:47:52Z dougb $
12251881Speter
13251881SpeterPATH=/bin:/usr/bin:/usr/sbin
14251881Speter
15251881Speterdisplay_usage () {
16251881Speter  VERSION_NUMBER=`grep "[$]FreeBSD:" $0 | cut -d ' ' -f 4`
17251881Speter  echo "mergemaster version ${VERSION_NUMBER}"
18251881Speter  echo 'Usage: mergemaster [-scrvahipC] [-m /path]'
19251881Speter  echo '         [-t /path] [-d] [-u N] [-w N] [-D /path]'
20251881Speter  echo "Options:"
21251881Speter  echo "  -s  Strict comparison (diff every pair of files)"
22251881Speter  echo "  -c  Use context diff instead of unified diff"
23251881Speter  echo "  -r  Re-run on a previously cleaned directory (skip temproot creation)"
24251881Speter  echo "  -v  Be more verbose about the process, include additional checks"
25251881Speter  echo "  -a  Leave all files that differ to merge by hand"
26251881Speter  echo "  -h  Display more complete help"
27251881Speter  echo '  -i  Automatically install files that do not exist in destination directory'
28251881Speter  echo '  -p  Pre-buildworld mode, only compares crucial files'
29289180Speter  echo '  -C  Compare local rc.conf variables to the defaults'
30251881Speter  echo "  -m /path/directory  Specify location of source to do the make in"
31251881Speter  echo "  -t /path/directory  Specify temp root directory"
32251881Speter  echo "  -d  Add date and time to directory name (e.g., /var/tmp/temproot.`date +%m%d.%H.%M`)"
33251881Speter  echo "  -u N  Specify a numeric umask"
34251881Speter  echo "  -w N  Specify a screen width in columns to sdiff"
35251881Speter  echo '  -D /path/directory  Specify the destination directory to install files to'
36251881Speter  echo ''
37251881Speter}
38251881Speter
39251881Speterdisplay_help () {
40251881Speter  echo "* To specify a directory other than /var/tmp/temproot for the"
41251881Speter  echo "  temporary root environment, use -t /path/to/temp/root"
42251881Speter  echo "* The -w option takes a number as an argument for the column width"
43251881Speter  echo "  of the screen.  The default is 80."
44251881Speter  echo '* The -a option causes mergemaster to run without prompting.'
45251881Speter}
46251881Speter
47251881Speter# Loop allowing the user to use sdiff to merge files and display the merged
48251881Speter# file.
49251881Spetermerge_loop () {
50251881Speter  case "${VERBOSE}" in
51251881Speter  '') ;;
52251881Speter  *)
53251881Speter      echo "   *** Type h at the sdiff prompt (%) to get usage help"
54251881Speter      ;;
55251881Speter  esac
56251881Speter  echo ''
57289180Speter  MERGE_AGAIN=yes
58251881Speter  while [ "${MERGE_AGAIN}" = "yes" ]; do
59289180Speter    # Prime file.merged so we don't blat the owner/group id's
60251881Speter    cp -p "${COMPFILE}" "${COMPFILE}.merged"
61251881Speter    sdiff -o "${COMPFILE}.merged" --text --suppress-common-lines \
62251881Speter      --width=${SCREEN_WIDTH:-80} "${DESTDIR}${COMPFILE#.}" "${COMPFILE}"
63251881Speter    INSTALL_MERGED=V
64251881Speter    while [ "${INSTALL_MERGED}" = "v" -o "${INSTALL_MERGED}" = "V" ]; do
65251881Speter      echo ''
66251881Speter      echo "  Use 'i' to install merged file"
67251881Speter      echo "  Use 'r' to re-do the merge"
68251881Speter      echo "  Use 'v' to view the merged file"
69251881Speter      echo "  Default is to leave the temporary file to deal with by hand"
70251881Speter      echo ''
71251881Speter      echo -n "    *** How should I deal with the merged file? [Leave it for later] "
72251881Speter      read INSTALL_MERGED
73251881Speter
74251881Speter      case "${INSTALL_MERGED}" in
75251881Speter      [iI])
76251881Speter        mv "${COMPFILE}.merged" "${COMPFILE}"
77251881Speter        echo ''
78251881Speter        if mm_install "${COMPFILE}"; then
79251881Speter          echo "     *** Merged version of ${COMPFILE} installed successfully"
80251881Speter        else
81251881Speter          echo "     *** Problem installing ${COMPFILE}, it will remain to merge by hand later"
82251881Speter        fi
83251881Speter        unset MERGE_AGAIN
84251881Speter        ;;
85251881Speter      [rR])
86251881Speter        rm "${COMPFILE}.merged"
87251881Speter        ;;
88251881Speter      [vV])
89251881Speter        ${PAGER} "${COMPFILE}.merged"
90251881Speter        ;;
91251881Speter      '')
92251881Speter        echo "   *** ${COMPFILE} will remain for your consideration"
93251881Speter        unset MERGE_AGAIN
94251881Speter        ;;
95251881Speter      *)
96251881Speter        echo "invalid choice: ${INSTALL_MERGED}"
97251881Speter        INSTALL_MERGED=V
98251881Speter        ;;
99251881Speter      esac
100251881Speter    done
101251881Speter  done
102251881Speter}
103251881Speter
104251881Speter# Loop showing user differences between files, allow merge, skip or install
105251881Speter# options
106251881Speterdiff_loop () {
107251881Speter
108251881Speter  HANDLE_COMPFILE=v
109251881Speter
110251881Speter  while [ "${HANDLE_COMPFILE}" = "v" -o "${HANDLE_COMPFILE}" = "V" -o \
111251881Speter    "${HANDLE_COMPFILE}" = "NOT V" ]; do
112251881Speter    if [ -f "${DESTDIR}${COMPFILE#.}" -a -f "${COMPFILE}" ]; then
113251881Speter      if [ "${HANDLE_COMPFILE}" = "v" -o "${HANDLE_COMPFILE}" = "V" ]; then
114251881Speter	echo ''
115251881Speter	echo '   ======================================================================   '
116251881Speter	echo ''
117251881Speter        (
118251881Speter          echo ''
119251881Speter          echo "  *** Displaying differences between ${COMPFILE} and installed version:"
120251881Speter          echo ''
121289180Speter          diff "${DIFF_FLAG}" "${DESTDIR}${COMPFILE#.}" "${COMPFILE}"
122289180Speter        ) | ${PAGER}
123289180Speter        echo ''
124289180Speter      fi
125251881Speter    else
126251881Speter      echo ''
127251881Speter      echo "  *** There is no installed version of ${COMPFILE}"
128251881Speter      echo ''
129251881Speter      case "${AUTO_INSTALL}" in
130251881Speter      [Yy][Ee][Ss])
131251881Speter        echo ''
132251881Speter        if mm_install "${COMPFILE}"; then
133251881Speter          echo "   *** ${COMPFILE} installed successfully"
134251881Speter          echo ''
135251881Speter          # Make the list print one file per line
136251881Speter          AUTO_INSTALLED_FILES="${AUTO_INSTALLED_FILES}      ${DESTDIR}${COMPFILE#.}
137251881Speter"
138251881Speter        else
139251881Speter          echo "   *** Problem installing ${COMPFILE}, it will remain to merge by hand"
140251881Speter        fi
141251881Speter        return
142251881Speter        ;;
143251881Speter      *)
144251881Speter        NO_INSTALLED=yes
145251881Speter        ;;
146251881Speter      esac
147251881Speter    fi
148251881Speter
149251881Speter    echo "  Use 'd' to delete the temporary ${COMPFILE}"
150251881Speter    echo "  Use 'i' to install the temporary ${COMPFILE}"
151251881Speter    case "${NO_INSTALLED}" in
152251881Speter    '')
153251881Speter      echo "  Use 'm' to merge the temporary and installed versions"
154289180Speter      echo "  Use 'v' to view the diff results again"
155251881Speter      ;;
156251881Speter    esac
157251881Speter    echo ''
158251881Speter    echo "  Default is to leave the temporary file to deal with by hand"
159251881Speter    echo ''
160251881Speter    echo -n "How should I deal with this? [Leave it for later] "
161251881Speter    read HANDLE_COMPFILE
162251881Speter
163251881Speter    case "${HANDLE_COMPFILE}" in
164251881Speter    [dD])
165251881Speter      rm "${COMPFILE}"
166251881Speter      echo ''
167251881Speter      echo "   *** Deleting ${COMPFILE}"
168251881Speter      ;;
169251881Speter    [iI])
170251881Speter      echo ''
171251881Speter      if mm_install "${COMPFILE}"; then
172251881Speter        echo "   *** ${COMPFILE} installed successfully"
173251881Speter      else
174251881Speter        echo "   *** Problem installing ${COMPFILE}, it will remain to merge by hand"
175251881Speter      fi
176251881Speter      ;;
177251881Speter    [mM])
178251881Speter      case "${NO_INSTALLED}" in
179251881Speter      '')
180251881Speter        # interact with user to merge files
181251881Speter        merge_loop
182251881Speter        ;;
183251881Speter      *)
184251881Speter        echo ''
185251881Speter        echo "   *** There is no installed version of ${COMPFILE}"
186251881Speter        echo ''
187251881Speter        HANDLE_COMPFILE="NOT V"
188251881Speter        ;;
189251881Speter      esac # End of "No installed version of file but user selected merge" test
190251881Speter      ;;
191251881Speter    [vV])
192251881Speter      continue
193251881Speter      ;;
194251881Speter    '')
195251881Speter      echo ''
196251881Speter      echo "   *** ${COMPFILE} will remain for your consideration"
197251881Speter      ;;
198251881Speter    *)
199251881Speter      # invalid choice, show menu again.
200251881Speter      echo "invalid choice: ${HANDLE_COMPFILE}"
201251881Speter      echo ''
202251881Speter      HANDLE_COMPFILE="NOT V"
203251881Speter      continue
204251881Speter      ;;
205251881Speter    esac  # End of "How to handle files that are different"
206251881Speter  done
207251881Speter  unset NO_INSTALLED
208251881Speter  echo ''
209251881Speter  case "${VERBOSE}" in
210251881Speter  '') ;;
211251881Speter  *)
212251881Speter    sleep 3
213251881Speter    ;;
214251881Speter  esac
215251881Speter}
216251881Speter
217251881Speterpress_to_continue () {
218251881Speter  local DISCARD
219251881Speter  echo -n ' *** Press the [Enter] or [Return] key to continue '
220251881Speter  read DISCARD
221251881Speter}
222251881Speter
223251881Speter# Set the default path for the temporary root environment
224251881Speter#
225251881SpeterTEMPROOT='/var/tmp/temproot'
226251881Speter
227251881Speter# Read /etc/mergemaster.rc first so the one in $HOME can override
228251881Speter#
229251881Speterif [ -r /etc/mergemaster.rc ]; then
230251881Speter  . /etc/mergemaster.rc
231251881Speterfi
232251881Speter
233251881Speter# Read .mergemasterrc before command line so CLI can override
234251881Speter#
235251881Speterif [ -r "$HOME/.mergemasterrc" ]; then
236251881Speter  . "$HOME/.mergemasterrc"
237251881Speterfi
238251881Speter
239251881Speter# Check the command line options
240251881Speter#
241251881Speterwhile getopts ":ascrvhipCm:t:du:w:D:" COMMAND_LINE_ARGUMENT ; do
242251881Speter  case "${COMMAND_LINE_ARGUMENT}" in
243289180Speter  s)
244289180Speter    STRICT=yes
245289180Speter    ;;
246251881Speter  c)
247251881Speter    DIFF_FLAG='-c'
248251881Speter    ;;
249251881Speter  r)
250251881Speter    RERUN=yes
251251881Speter    ;;
252251881Speter  v)
253251881Speter    case "${AUTO_RUN}" in
254251881Speter    '') VERBOSE=yes ;;
255251881Speter    esac
256251881Speter    ;;
257251881Speter  a)
258251881Speter    AUTO_RUN=yes
259251881Speter    unset VERBOSE
260251881Speter    ;;
261251881Speter  h)
262251881Speter    display_usage
263251881Speter    display_help
264251881Speter    exit 0
265251881Speter    ;;
266251881Speter  i)
267251881Speter    AUTO_INSTALL=yes
268251881Speter    ;;
269251881Speter  C)
270251881Speter    COMP_CONFS=yes
271251881Speter    ;;
272251881Speter  p)
273251881Speter    PRE_WORLD=yes
274251881Speter    unset COMP_CONFS
275251881Speter    unset AUTO_RUN
276251881Speter    ;;
277251881Speter  m)
278251881Speter    SOURCEDIR=${OPTARG}
279251881Speter    ;;
280251881Speter  t)
281251881Speter    TEMPROOT=${OPTARG}
282251881Speter    ;;
283251881Speter  d)
284251881Speter    TEMPROOT=${TEMPROOT}.`date +%m%d.%H.%M`
285251881Speter    ;;
286251881Speter  u)
287251881Speter    NEW_UMASK=${OPTARG}
288251881Speter    ;;
289251881Speter  w)
290251881Speter    SCREEN_WIDTH=${OPTARG}
291251881Speter    ;;
292251881Speter  D)
293251881Speter    DESTDIR=${OPTARG}
294251881Speter    ;;
295251881Speter  *)
296251881Speter    display_usage
297251881Speter    exit 1
298251881Speter    ;;
299251881Speter  esac
300251881Speterdone
301251881Speter
302251881Speterecho ''
303251881Speter
304289180Speter# If the user has a pager defined, make sure we can run it
305289180Speter#
306289180Spetercase "${DONT_CHECK_PAGER}" in
307251881Speter'')
308251881Speter  while ! type "${PAGER%% *}" >/dev/null && [ -n "${PAGER}" ]; do
309251881Speter    echo " *** Your PAGER environment variable specifies '${PAGER}', but"
310251881Speter    echo "     due to the limited PATH that I use for security reasons,"
311251881Speter    echo "     I cannot execute it.  So, what would you like to do?"
312251881Speter    echo ''
313251881Speter    echo "  Use 'e' to exit mergemaster and fix your PAGER variable"
314251881Speter    if [ -x /usr/bin/less -o -x /usr/local/bin/less ]; then
315251881Speter    echo "  Use 'l' to set PAGER to 'less' for this run"
316251881Speter    fi
317251881Speter    echo "  Use 'm' to use plain old 'more' as your PAGER for this run"
318251881Speter    echo ''
319251881Speter    echo "  Default is to use plain old 'more' "
320251881Speter    echo ''
321251881Speter    echo -n "What should I do? [Use 'more'] "
322251881Speter    read FIXPAGER
323251881Speter
324251881Speter    case "${FIXPAGER}" in
325251881Speter    [eE])
326251881Speter       exit 0
327251881Speter       ;;
328251881Speter    [lL])
329251881Speter       if [ -x /usr/bin/less ]; then
330251881Speter         PAGER=/usr/bin/less
331251881Speter       elif [ -x /usr/local/bin/less ]; then
332251881Speter         PAGER=/usr/local/bin/less
333251881Speter       else
334251881Speter         echo ''
335251881Speter         echo " *** Fatal Error:"
336251881Speter         echo "     You asked to use 'less' as your pager, but I can't"
337251881Speter         echo "     find it in /usr/bin or /usr/local/bin"
338251881Speter         exit 1
339251881Speter       fi
340251881Speter       ;;
341251881Speter    [mM]|'')
342251881Speter       PAGER=more
343251881Speter       ;;
344251881Speter    *)
345251881Speter       echo ''
346251881Speter       echo "invalid choice: ${FIXPAGER}"
347251881Speter    esac
348251881Speter    echo ''
349251881Speter  done
350251881Speter  ;;
351251881Speteresac
352251881Speter
353251881Speter# If user has a pager defined, or got assigned one above, use it.
354251881Speter# If not, use more.
355251881Speter#
356251881SpeterPAGER=${PAGER:-more}
357251881Speter
358251881Speterif [ -n "${VERBOSE}" -a ! "${PAGER}" = "more" ]; then
359251881Speter  echo " *** You have ${PAGER} defined as your pager so we will use that"
360251881Speter  echo ''
361251881Speter  sleep 3
362251881Speterfi
363251881Speter
364251881Speter# Assign the diff flag once so we will not have to keep testing it
365251881Speter#
366251881SpeterDIFF_FLAG=${DIFF_FLAG:--u}
367251881Speter
368251881Speter# Assign the source directory
369251881Speter#
370251881SpeterSOURCEDIR=${SOURCEDIR:-/usr/src/etc}
371251881Speter
372251881Speter# Check the width of the user's terminal
373251881Speter#
374251881Speterif [ -t 0 ]; then
375251881Speter  w=$(stty -a | sed -ne 's/.* \([0-9][0-9]*\) columns.*/\1/p')
376251881Speter  case "${w}" in
377251881Speter  0|'') ;; # No-op, since the input is not valid
378251881Speter  *)
379251881Speter    case "${SCREEN_WIDTH}" in
380251881Speter    '') SCREEN_WIDTH="${w}" ;;
381251881Speter    "${w}") ;; # No-op, since they are the same
382251881Speter    *)
383251881Speter      echo -n "*** You entered ${SCREEN_WIDTH} as your screen width, but stty "
384251881Speter      echo "thinks it is ${w}."
385251881Speter      echo ''
386251881Speter      echo -n "What would you like to use? [${w}] "
387251881Speter      read SCREEN_WIDTH
388251881Speter      case "${SCREEN_WIDTH}" in
389251881Speter      '') SCREEN_WIDTH="${w}" ;;
390251881Speter      esac
391251881Speter      ;;
392251881Speter    esac
393251881Speter  esac
394251881Speterfi
395251881Speter
396251881Speter# Define what CVS $Id tag to look for to aid portability.
397251881Speter#
398251881SpeterCVS_ID_TAG=FreeBSD
399251881Speter
400289180Speterdelete_temproot () {
401289180Speter  rm -rf "${TEMPROOT}" 2>/dev/null
402289180Speter  chflags -R 0 "${TEMPROOT}" 2>/dev/null
403289180Speter  rm -rf "${TEMPROOT}" || exit 1
404251881Speter}
405251881Speter
406251881Spetercase "${RERUN}" in
407251881Speter'')
408251881Speter  # Set up the loop to test for the existence of the
409251881Speter  # temp root directory.
410251881Speter  #
411251881Speter  TEST_TEMP_ROOT=yes
412251881Speter  while [ "${TEST_TEMP_ROOT}" = "yes" ]; do
413251881Speter    if [ -d "${TEMPROOT}" ]; then
414251881Speter      echo "*** The directory specified for the temporary root environment,"
415251881Speter      echo "    ${TEMPROOT}, exists.  This can be a security risk if untrusted"
416251881Speter      echo "    users have access to the system."
417251881Speter      echo ''
418251881Speter      case "${AUTO_RUN}" in
419251881Speter      '')
420251881Speter        echo "  Use 'd' to delete the old ${TEMPROOT} and continue"
421251881Speter        echo "  Use 't' to select a new temporary root directory"
422251881Speter        echo "  Use 'e' to exit mergemaster"
423251881Speter        echo ''
424251881Speter        echo "  Default is to use ${TEMPROOT} as is"
425251881Speter        echo ''
426251881Speter        echo -n "How should I deal with this? [Use the existing ${TEMPROOT}] "
427289180Speter        read DELORNOT
428289180Speter
429289180Speter        case "${DELORNOT}" in
430289180Speter        [dD])
431289180Speter          echo ''
432289180Speter          echo "   *** Deleting the old ${TEMPROOT}"
433289180Speter          echo ''
434289180Speter          delete_temproot || exit 1
435251881Speter          unset TEST_TEMP_ROOT
436289180Speter          ;;
437289180Speter        [tT])
438289180Speter          echo "   *** Enter new directory name for temporary root environment"
439251881Speter          read TEMPROOT
440251881Speter          ;;
441251881Speter        [eE])
442251881Speter          exit 0
443251881Speter          ;;
444251881Speter        '')
445251881Speter          echo ''
446251881Speter          echo "   *** Leaving ${TEMPROOT} intact"
447251881Speter          echo ''
448251881Speter          unset TEST_TEMP_ROOT
449251881Speter          ;;
450251881Speter        *)
451251881Speter          echo ''
452251881Speter          echo "invalid choice: ${DELORNOT}"
453251881Speter          echo ''
454251881Speter          ;;
455251881Speter        esac
456251881Speter        ;;
457251881Speter      *)
458251881Speter        # If this is an auto-run, try a hopefully safe alternative then
459251881Speter        # re-test anyway.
460251881Speter        TEMPROOT=/var/tmp/temproot.`date +%m%d.%H.%M.%S`
461251881Speter        ;;
462251881Speter      esac
463251881Speter    else
464251881Speter      unset TEST_TEMP_ROOT
465251881Speter    fi
466251881Speter  done
467251881Speter
468251881Speter  echo "*** Creating the temporary root environment in ${TEMPROOT}"
469251881Speter
470251881Speter  if mkdir -p "${TEMPROOT}"; then
471251881Speter    echo " *** ${TEMPROOT} ready for use"
472251881Speter  fi
473251881Speter
474251881Speter  if [ ! -d "${TEMPROOT}" ]; then
475251881Speter    echo ''
476251881Speter    echo "  *** FATAL ERROR: Cannot create ${TEMPROOT}"
477251881Speter    echo ''
478251881Speter    exit 1
479251881Speter  fi
480251881Speter
481251881Speter  echo " *** Creating and populating directory structure in ${TEMPROOT}"
482362181Sdim  echo ''
483251881Speter
484251881Speter  case "${VERBOSE}" in
485251881Speter  '') ;;
486251881Speter  *)
487251881Speter    press_to_continue
488251881Speter    ;;
489251881Speter  esac
490362181Sdim
491251881Speter  case "${PRE_WORLD}" in
492251881Speter  '')
493251881Speter    { cd ${SOURCEDIR} &&
494251881Speter      case "${DESTDIR}" in
495251881Speter      '') ;;
496251881Speter      *)
497251881Speter      make DESTDIR=${DESTDIR} distrib-dirs
498251881Speter        ;;
499251881Speter      esac
500251881Speter      make DESTDIR=${TEMPROOT} distrib-dirs &&
501251881Speter      make MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj obj &&
502251881Speter      make MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj DESTDIR=${TEMPROOT} \
503251881Speter          -DNO_MAKEDEV_RUN distribution;} ||
504251881Speter    { echo '';
505251881Speter     echo "  *** FATAL ERROR: Cannot 'cd' to ${SOURCEDIR} and install files to";
506362181Sdim      echo "      the temproot environment";
507362181Sdim      echo '';
508362181Sdim      exit 1;}
509362181Sdim    ;;
510362181Sdim  *)
511251881Speter    # Only set up files that are crucial to {build|install}world
512362181Sdim    { mkdir -p ${TEMPROOT}/etc &&
513362181Sdim      cp -p ${SOURCEDIR}/master.passwd ${TEMPROOT}/etc &&
514362181Sdim      cp -p ${SOURCEDIR}/group ${TEMPROOT}/etc;} ||
515362181Sdim    { echo '';
516362181Sdim      echo '  *** FATAL ERROR: Cannot copy files to the temproot environment';
517362181Sdim      echo '';
518362181Sdim      exit 1;}
519362181Sdim    ;;
520362181Sdim  esac
521362181Sdim
522362181Sdim  # Doing the inventory and removing files that we don't want to compare only
523362181Sdim  # makes sense if we are not doing a rerun, since we have no way of knowing
524362181Sdim  # what happened to the files during previous incarnations.
525362181Sdim  case "${VERBOSE}" in
526362181Sdim  '') ;;
527362181Sdim  *)
528251881Speter    echo ''
529251881Speter    echo ' *** The following files exist only in the installed version of'
530251881Speter    echo "     ${DESTDIR}/etc.  In the vast majority of cases these files"
531251881Speter    echo '     are necessary parts of the system and should not be deleted.'
532251881Speter    echo '     However because these files are not updated by this process you'
533251881Speter    echo '     might want to verify their status before rebooting your system.'
534251881Speter    echo ''
535251881Speter    press_to_continue
536251881Speter    diff -qr ${DESTDIR}/etc ${TEMPROOT}/etc | grep "^Only in ${DESTDIR}/etc" | ${PAGER}
537251881Speter    echo ''
538251881Speter    press_to_continue
539251881Speter    ;;
540251881Speter  esac
541251881Speter
542251881Speter  # Avoid comparing the motd if the user specifies it in .mergemasterrc
543251881Speter  case "${IGNORE_MOTD}" in
544251881Speter  '') ;;
545251881Speter  *) rm -f ${TEMPROOT}/etc/motd
546251881Speter     ;;
547251881Speter  esac
548251881Speter
549251881Speter  # Avoid trying to update MAKEDEV if /dev is on a devfs
550251881Speter  if /sbin/sysctl vfs.devfs.generation > /dev/null 2>&1 ; then
551251881Speter    rm -f ${TEMPROOT}/dev/MAKEDEV ${TEMPROOT}/dev/MAKEDEV.local
552251881Speter  fi
553251881Speter
554251881Speter  ;; # End of the "RERUN" test
555251881Speteresac
556251881Speter
557251881Speter# We really don't want to have to deal with these files, since
558251881Speter# master.passwd is the real file that should be compared, then
559251881Speter# the user should run pwd_mkdb if necessary.
560251881Speter#
561251881Speterrm -f ${TEMPROOT}/etc/spwd.db ${TEMPROOT}/etc/passwd ${TEMPROOT}/etc/pwd.db
562251881Speter
563251881Speter# We only need to compare things like freebsd.cf once
564251881Speterfind ${TEMPROOT}/usr/obj -type f -delete 2>/dev/null
565251881Speter
566251881Speter# Get ready to start comparing files
567251881Speter
568251881Speter# Check umask if not specified on the command line,
569251881Speter# and we are not doing an autorun
570251881Speter#
571251881Speterif [ -z "${NEW_UMASK}" -a -z "${AUTO_RUN}" ]; then
572251881Speter  USER_UMASK=`umask`
573251881Speter  case "${USER_UMASK}" in
574251881Speter  0022|022) ;;
575251881Speter  *)
576251881Speter    echo ''
577251881Speter    echo " *** Your umask is currently set to ${USER_UMASK}.  By default, this script"
578251881Speter    echo "     installs all files with the same user, group and modes that"
579251881Speter    echo "     they are created with by ${SOURCEDIR}/Makefile, compared to"
580251881Speter    echo "     a umask of 022.  This umask allows world read permission when"
581251881Speter    echo "     the file's default permissions have it."
582251881Speter    echo ''
583251881Speter    echo "     No world permissions can sometimes cause problems.  A umask of"
584251881Speter    echo "     022 will restore the default behavior, but is not mandatory."
585251881Speter    echo "     /etc/master.passwd is a special case.  Its file permissions"
586251881Speter    echo "     will be 600 (rw-------) if installed."
587251881Speter    echo ''
588251881Speter    echo -n "What umask should I use? [${USER_UMASK}] "
589251881Speter    read NEW_UMASK
590251881Speter
591251881Speter    NEW_UMASK="${NEW_UMASK:-$USER_UMASK}"
592251881Speter    ;;
593251881Speter  esac
594251881Speter  echo ''
595251881Speterfi
596251881Speter
597251881SpeterCONFIRMED_UMASK=${NEW_UMASK:-0022}
598251881Speter
599251881Speter# Warn users who still have ${DESTDIR}/etc/sysconfig
600251881Speter#
601251881Speterif [ -e "${DESTDIR}/etc/sysconfig" ]; then
602251881Speter  echo ''
603251881Speter  echo " *** There is a sysconfig file on this system in ${DESTDIR}/etc/."
604251881Speter  echo ''
605251881Speter  echo '     Starting with FreeBSD version 2.2.2 those settings moved from'
606251881Speter  echo '     /etc/sysconfig to /etc/rc.conf.  If you are upgrading an older'
607251881Speter  echo '     system make sure that you transfer your settings by hand from'
608251881Speter  echo '     sysconfig to rc.conf and install the rc.conf file.  If you'
609251881Speter  echo '     have already made this transition, you should consider'
610251881Speter  echo '     renaming or deleting the sysconfig file.'
611251881Speter  echo ''
612251881Speter  case "${AUTO_RUN}" in
613251881Speter  '')
614251881Speter    echo -n "Continue with the merge process? [yes] "
615251881Speter    read CONT_OR_NOT
616251881Speter
617251881Speter    case "${CONT_OR_NOT}" in
618289180Speter    [nN]*)
619289180Speter      exit 0
620289180Speter      ;;
621289180Speter    *)
622251881Speter      echo "   *** Continuing"
623251881Speter      echo ''
624251881Speter      ;;
625251881Speter    esac
626251881Speter    ;;
627251881Speter  *) ;;
628251881Speter  esac
629251881Speterfi
630251881Speter
631251881Speter# Use the umask/mode information to install the files
632251881Speter# Create directories as needed
633251881Speter#
634251881Speterdo_install_and_rm () {
635251881Speter  install -m "${1}" "${2}" "${3}" &&
636251881Speter  rm -f "${2}"
637251881Speter}
638289180Speter
639289180Speter# 4095 = "obase=10;ibase=8;07777" | bc
640289180Speterfind_mode () {
641289180Speter  local OCTAL
642289180Speter  OCTAL=$(( ~$(echo "obase=10; ibase=8; ${CONFIRMED_UMASK}" | bc) & 4095 &
643289180Speter    $(echo "obase=10; ibase=8; $(stat -f "%OMp%OLp" ${1})" | bc) )) 
644289180Speter  printf "%04o\n" ${OCTAL}
645251881Speter}
646289180Speter
647289180Spetermm_install () {
648289180Speter  local INSTALL_DIR
649289180Speter  INSTALL_DIR=${1#.}
650289180Speter  INSTALL_DIR=${INSTALL_DIR%/*}
651289180Speter
652289180Speter  case "${INSTALL_DIR}" in
653289180Speter  '')
654251881Speter    INSTALL_DIR=/
655251881Speter    ;;
656251881Speter  esac
657251881Speter
658251881Speter  if [ -n "${DESTDIR}${INSTALL_DIR}" -a ! -d "${DESTDIR}${INSTALL_DIR}" ]; then
659251881Speter    DIR_MODE=`find_mode "${TEMPROOT}/${INSTALL_DIR}"`
660251881Speter    install -d -o root -g wheel -m "${DIR_MODE}" "${DESTDIR}${INSTALL_DIR}"
661251881Speter  fi
662251881Speter
663251881Speter  FILE_MODE=`find_mode "${1}"`
664251881Speter
665251881Speter  if [ ! -x "${1}" ]; then
666251881Speter    case "${1#.}" in
667251881Speter    /etc/mail/aliases)
668251881Speter      NEED_NEWALIASES=yes
669251881Speter      ;;
670251881Speter    /etc/login.conf)
671251881Speter      NEED_CAP_MKDB=yes
672251881Speter      ;;
673251881Speter    /etc/master.passwd)
674289180Speter      do_install_and_rm 600 "${1}" "${DESTDIR}${INSTALL_DIR}"
675289180Speter      NEED_PWD_MKDB=yes
676289180Speter      DONT_INSTALL=yes
677289180Speter      ;;
678289180Speter    /.cshrc | /.profile)
679251881Speter    case "${AUTO_INSTALL}" in
680289180Speter    '')
681251881Speter      case "${LINK_EXPLAINED}" in
682289180Speter      '')
683289180Speter        echo "   *** Historically BSD derived systems have had a"
684251881Speter        echo "       hard link from /.cshrc and /.profile to"
685289180Speter        echo "       their namesakes in /root.  Please indicate"
686289180Speter        echo "       your preference below for bringing your"
687289180Speter        echo "       installed files up to date."
688289180Speter        echo ''
689289180Speter        LINK_EXPLAINED=yes
690251881Speter        ;;
691251881Speter      esac
692251881Speter
693251881Speter      echo "   Use 'd' to delete the temporary ${COMPFILE}"
694251881Speter      echo "   Use 'l' to delete the existing ${DESTDIR}${COMPFILE#.} and create the link"
695251881Speter      echo ''
696251881Speter      echo "   Default is to leave the temporary file to deal with by hand"
697251881Speter      echo ''
698251881Speter      echo -n "  How should I handle ${COMPFILE}? [Leave it to install later] "
699298845Sdim      read HANDLE_LINK
700251881Speter      ;;
701251881Speter    *)  # Part of AUTO_INSTALL
702251881Speter      HANDLE_LINK=l
703251881Speter      ;;
704251881Speter    esac
705251881Speter
706251881Speter      case "${HANDLE_LINK}" in
707251881Speter      [dD]*)
708251881Speter        rm "${COMPFILE}"
709251881Speter        echo ''
710251881Speter        echo "   *** Deleting ${COMPFILE}"
711251881Speter        ;;
712251881Speter      [lL]*)
713289180Speter        echo ''
714289180Speter        rm -f "${DESTDIR}${COMPFILE#.}"
715289180Speter        if ln "${DESTDIR}/root/${COMPFILE##*/}" "${DESTDIR}${COMPFILE#.}"; then
716251881Speter          echo "   *** Link from ${DESTDIR}${COMPFILE#.} to ${DESTDIR}/root/${COMPFILE##*/} installed successfully"
717289180Speter          rm "${COMPFILE}"
718289180Speter        else
719251881Speter          echo "   *** Error linking ${DESTDIR}${COMPFILE#.} to ${DESTDIR}/root/${COMPFILE##*/}, ${COMPFILE} will remain to install by hand"
720251881Speter        fi
721289180Speter        ;;
722289180Speter      *)
723289180Speter        echo "   *** ${COMPFILE} will remain for your consideration"
724251881Speter        ;;
725289180Speter      esac
726289180Speter      DONT_INSTALL=yes
727298845Sdim      ;;
728289180Speter    esac
729251881Speter
730289180Speter    case "${DONT_INSTALL}" in
731289180Speter    '')
732289180Speter      do_install_and_rm "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}"
733289180Speter      ;;
734251881Speter    *)
735289180Speter      unset DONT_INSTALL
736289180Speter      ;;
737289180Speter    esac
738289180Speter  else	# File matched -x
739289180Speter    case "${1#.}" in
740289180Speter    /dev/MAKEDEV)
741289180Speter      NEED_MAKEDEV=yes
742251881Speter      ;;
743251881Speter    esac
744251881Speter    do_install_and_rm "${FILE_MODE}" "${1}" "${DESTDIR}${INSTALL_DIR}"
745362181Sdim  fi
746362181Sdim  return $?
747362181Sdim}
748362181Sdim
749362181Sdimecho ''
750362181Sdimecho "*** Beginning comparison"
751362181Sdimecho ''
752362181Sdim
753362181Sdimcd "${TEMPROOT}"
754362181Sdim
755362181Sdimif [ -r "${MM_PRE_COMPARE_SCRIPT}" ]; then
756362181Sdim  . "${MM_PRE_COMPARE_SCRIPT}"
757362181Sdimfi
758362181Sdim
759362181Sdim# Using -size +0 avoids uselessly checking the empty log files created
760362181Sdim# by ${SOURCEDIR}/Makefile and the device entries in ./dev, but does
761362181Sdim# check the scripts in ./dev, as we'd like (assuming no devfs of course).
762362181Sdim#
763362181Sdimfor COMPFILE in `find . -type f -size +0`; do
764362181Sdim
765362181Sdim  # First, check to see if the file exists in DESTDIR.  If not, the
766362181Sdim  # diff_loop function knows how to handle it.
767362181Sdim  #
768362181Sdim  if [ ! -e "${DESTDIR}${COMPFILE#.}" ]; then
769362181Sdim    case "${AUTO_RUN}" in
770362181Sdim      '')
771362181Sdim        diff_loop
772362181Sdim        ;;
773362181Sdim      *)
774362181Sdim        case "${AUTO_INSTALL}" in
775362181Sdim        '')
776362181Sdim          # If this is an auto run, make it official
777362181Sdim          echo "   *** ${COMPFILE} will remain for your consideration"
778362181Sdim          ;;
779362181Sdim        *)
780362181Sdim          diff_loop
781362181Sdim          ;;
782362181Sdim        esac
783362181Sdim        ;;
784362181Sdim    esac # Auto run test
785362181Sdim    continue
786362181Sdim  fi
787362181Sdim
788362181Sdim  case "${STRICT}" in
789362181Sdim  '' | [Nn][Oo])
790362181Sdim    # Compare CVS $Id's first so if the file hasn't been modified
791362181Sdim    # local changes will be ignored.
792362181Sdim    # If the files have the same $Id, delete the one in temproot so the
793362181Sdim    # user will have less to wade through if files are left to merge by hand.
794362181Sdim    #
795362181Sdim    CVSID1=`grep "[$]${CVS_ID_TAG}:" ${DESTDIR}${COMPFILE#.} 2>/dev/null`
796362181Sdim    CVSID2=`grep "[$]${CVS_ID_TAG}:" ${COMPFILE} 2>/dev/null` || CVSID2=none
797362181Sdim
798362181Sdim    case "${CVSID2}" in
799362181Sdim    "${CVSID1}")
800362181Sdim      echo " *** Temp ${COMPFILE} and installed have the same CVS Id, deleting"
801362181Sdim      rm "${COMPFILE}"
802362181Sdim      ;;
803362181Sdim    esac
804362181Sdim    ;;
805362181Sdim  esac
806362181Sdim
807362181Sdim  # If the file is still here either because the $Ids are different, the
808362181Sdim  # file doesn't have an $Id, or we're using STRICT mode; look at the diff.
809362181Sdim  #
810251881Speter  if [ -f "${COMPFILE}" ]; then
811251881Speter
812251881Speter    # Do an absolute diff first to see if the files are actually different.
813251881Speter    # If they're not different, delete the one in temproot.
814251881Speter    #
815251881Speter    if diff -q "${DESTDIR}${COMPFILE#.}" "${COMPFILE}" > /dev/null 2>&1; then
816251881Speter      echo " *** Temp ${COMPFILE} and installed are the same, deleting"
817251881Speter      rm "${COMPFILE}"
818251881Speter    else
819251881Speter      # Ok, the files are different, so show the user where they differ.
820251881Speter      # Use user's choice of diff methods; and user's pager if they have one.
821251881Speter      # Use more if not.
822251881Speter      # Use unified diffs by default.  Context diffs give me a headache. :)
823251881Speter      #
824251881Speter      case "${AUTO_RUN}" in
825251881Speter      '')
826251881Speter        # prompt user to install/delete/merge changes
827251881Speter        diff_loop
828251881Speter        ;;
829251881Speter      *)
830251881Speter        # If this is an auto run, make it official
831251881Speter        echo "   *** ${COMPFILE} will remain for your consideration"
832251881Speter        ;;
833251881Speter      esac # Auto run test
834251881Speter    fi # Yes, the files are different
835251881Speter  fi # Yes, the file still remains to be checked
836251881Speterdone # This is for the do way up there at the beginning of the comparison
837251881Speter
838362181Sdimecho ''
839362181Sdimecho "*** Comparison complete"
840362181Sdimecho ''
841362181Sdim
842362181SdimTEST_FOR_FILES=`find ${TEMPROOT} -type f -size +0 2>/dev/null`
843362181Sdimif [ -n "${TEST_FOR_FILES}" ]; then
844251881Speter  echo "*** Files that remain for you to merge by hand:"
845362181Sdim  find "${TEMPROOT}" -type f -size +0
846362181Sdim  echo ''
847362181Sdimfi
848362181Sdim
849362181Sdimcase "${AUTO_RUN}" in
850251881Speter'')
851251881Speter  echo -n "Do you wish to delete what is left of ${TEMPROOT}? [no] "
852251881Speter  read DEL_TEMPROOT
853251881Speter
854251881Speter  case "${DEL_TEMPROOT}" in
855251881Speter  [yY]*)
856251881Speter    if delete_temproot; then
857251881Speter      echo " *** ${TEMPROOT} has been deleted"
858251881Speter    else
859251881Speter      echo " *** Unable to delete ${TEMPROOT}"
860251881Speter    fi
861251881Speter    ;;
862251881Speter  *)
863251881Speter    echo " *** ${TEMPROOT} will remain"
864251881Speter    ;;
865251881Speter  esac
866251881Speter  ;;
867251881Speter*) ;;
868251881Speteresac
869251881Speter
870251881Spetercase "${AUTO_INSTALLED_FILES}" in
871251881Speter'') ;;
872251881Speter*)
873251881Speter  case "${AUTO_RUN}" in
874251881Speter  '')
875251881Speter    (
876251881Speter      echo ''
877251881Speter      echo '*** You chose the automatic install option for files that did not'
878251881Speter      echo '    exist on your system.  The following were installed for you:'
879251881Speter      echo "${AUTO_INSTALLED_FILES}"
880251881Speter    ) | ${PAGER}
881251881Speter    ;;
882251881Speter  *)
883251881Speter    echo ''
884251881Speter    echo '*** You chose the automatic install option for files that did not'
885251881Speter    echo '    exist on your system.  The following were installed for you:'
886251881Speter    echo "${AUTO_INSTALLED_FILES}"
887251881Speter    ;;
888251881Speter  esac
889251881Speter  ;;
890251881Speteresac
891251881Speter
892251881Speterrun_it_now () {
893251881Speter  case "${AUTO_RUN}" in
894251881Speter  '')
895251881Speter    unset YES_OR_NO
896251881Speter    echo ''
897251881Speter    echo -n '    Would you like to run it now? y or n [n] '
898251881Speter    read YES_OR_NO
899251881Speter
900251881Speter    case "${YES_OR_NO}" in
901251881Speter    y)
902251881Speter      echo "    Running ${1}"
903251881Speter      echo ''
904251881Speter      eval "${1}"
905251881Speter      ;;
906251881Speter    ''|n)
907251881Speter      echo ''
908251881Speter      echo "       *** Cancelled"
909251881Speter      echo ''
910251881Speter      echo "    Make sure to run ${1} yourself"
911251881Speter      ;;
912251881Speter    *)
913251881Speter      echo ''
914251881Speter      echo "       *** Sorry, I do not understand your answer (${YES_OR_NO})"
915251881Speter      echo ''
916251881Speter      echo "    Make sure to run ${1} yourself"
917251881Speter    esac
918251881Speter    ;;
919251881Speter  *) ;;
920251881Speter  esac
921251881Speter}
922251881Speter
923251881Spetercase "${NEED_MAKEDEV}" in
924251881Speter'') ;;
925251881Speter*)
926251881Speter  echo ''
927251881Speter  echo "*** You installed a new ${DESTDIR}/dev/MAKEDEV script, so make sure that you run"
928251881Speter  echo "    'cd ${DESTDIR}/dev && /bin/sh MAKEDEV all' to rebuild your devices"
929251881Speter  run_it_now "cd ${DESTDIR}/dev && /bin/sh MAKEDEV all"
930251881Speter  ;;
931251881Speteresac
932251881Speter
933251881Spetercase "${NEED_NEWALIASES}" in
934251881Speter'') ;;
935251881Speter*)
936251881Speter  echo ''
937251881Speter  if [ -n "${DESTDIR}" ]; then
938251881Speter    echo "*** You installed a new aliases file into ${DESTDIR}/etc/mail, but"
939251881Speter    echo "    the newaliases command is limited to the directories configured"
940251881Speter    echo "    in sendmail.cf.  Make sure to create your aliases database by"
941251881Speter    echo "    hand when your sendmail configuration is done."
942251881Speter  else
943251881Speter    echo "*** You installed a new aliases file, so make sure that you run"
944251881Speter    echo "    '/usr/bin/newaliases' to rebuild your aliases database"
945251881Speter    run_it_now '/usr/bin/newaliases'
946251881Speter  fi
947251881Speter  ;;
948251881Speteresac
949251881Speter
950251881Spetercase "${NEED_CAP_MKDB}" in
951251881Speter'') ;;
952251881Speter*)
953251881Speter  echo ''
954251881Speter  echo "*** You installed a login.conf file, so make sure that you run"
955251881Speter  echo "    '/usr/bin/cap_mkdb ${DESTDIR}/etc/login.conf'"
956251881Speter  echo "     to rebuild your login.conf database"
957251881Speter  run_it_now "/usr/bin/cap_mkdb ${DESTDIR}/etc/login.conf"
958251881Speter  ;;
959251881Speteresac
960251881Speter
961251881Spetercase "${NEED_PWD_MKDB}" in
962289180Speter'') ;;
963251881Speter*)
964251881Speter  echo ''
965251881Speter  echo "*** You installed a new master.passwd file, so make sure that you run"
966251881Speter  if [ -n "${DESTDIR}" ]; then
967251881Speter    echo "    '/usr/sbin/pwd_mkdb -d ${DESTDIR}/etc -p ${DESTDIR}/etc/master.passwd'"
968251881Speter    echo "    to rebuild your password files"
969251881Speter    run_it_now "/usr/sbin/pwd_mkdb -d ${DESTDIR}/etc -p ${DESTDIR}/etc/master.passwd"
970251881Speter  else
971251881Speter    echo "    '/usr/sbin/pwd_mkdb -p /etc/master.passwd'"
972251881Speter    echo "     to rebuild your password files"
973251881Speter    run_it_now '/usr/sbin/pwd_mkdb -p /etc/master.passwd'
974251881Speter  fi
975251881Speter  ;;
976251881Speteresac
977251881Speter
978251881Speterecho ''
979251881Speter
980251881Speterif [ -r "${MM_EXIT_SCRIPT}" ]; then
981251881Speter  . "${MM_EXIT_SCRIPT}"
982251881Speterfi
983251881Speter
984251881Spetercase "${COMP_CONFS}" in
985251881Speter'') ;;
986251881Speter*)
987251881Speter  . ${DESTDIR}/etc/defaults/rc.conf
988251881Speter
989251881Speter  (echo ''
990251881Speter  echo "*** Comparing conf files: ${rc_conf_files}"
991251881Speter
992289180Speter  for CONF_FILE in ${rc_conf_files}; do
993289180Speter    if [ -r "${DESTDIR}${CONF_FILE}" ]; then
994251881Speter      echo ''
995251881Speter      echo "*** From ${DESTDIR}${CONF_FILE}"
996251881Speter      echo "*** From ${DESTDIR}/etc/defaults/rc.conf"
997251881Speter
998251881Speter      for RC_CONF_VAR in `grep -i ^[a-z] ${DESTDIR}${CONF_FILE} |
999251881Speter        cut -d '=' -f 1`; do
1000251881Speter        echo ''
1001251881Speter        grep -w ^${RC_CONF_VAR} ${DESTDIR}${CONF_FILE}
1002251881Speter        grep -w ^${RC_CONF_VAR} ${DESTDIR}/etc/defaults/rc.conf ||
1003251881Speter          echo ' * No default variable with this name'
1004251881Speter      done
1005251881Speter    fi
1006251881Speter  done) | ${PAGER}
1007251881Speter  echo ''
1008251881Speter  ;;
1009251881Speteresac
1010251881Speter
1011251881Spetercase "${PRE_WORLD}" in
1012251881Speter'') ;;
1013251881Speter*)
1014251881Speter  MAKE_CONF="${SOURCEDIR%etc}share/examples/etc/make.conf"
1015251881Speter
1016251881Speter  (echo ''
1017251881Speter  echo '*** Comparing make variables'
1018251881Speter  echo ''
1019251881Speter  echo "*** From ${DESTDIR}/etc/make.conf"
1020251881Speter  echo "*** From ${MAKE_CONF}"
1021251881Speter
1022251881Speter  for MAKE_VAR in `grep -i ^[a-z] ${DESTDIR}/etc/make.conf | cut -d '=' -f 1`; do
1023251881Speter    echo ''
1024362181Sdim    grep -w ^${MAKE_VAR} ${DESTDIR}/etc/make.conf
1025362181Sdim    grep -w ^#${MAKE_VAR} ${MAKE_CONF} ||
1026362181Sdim      echo ' * No example variable with this name'
1027362181Sdim  done) | ${PAGER}
1028251881Speter  ;;
1029251881Speteresac
1030251881Speter
1031251881Speterexit 0
1032251881Speter
1033251881Speter