]> git.somenet.org - root/pub/somesible.git/blob - roles/base/apt/files/default/ucf.bin
[roles/util] ----- meta ----- No dependencies
[root/pub/somesible.git] / roles / base / apt / files / default / ucf.bin
1 #!/bin/sh
2 #
3 ################################################
4 ### Managed by someone's ansible provisioner ###
5 ################################################
6 # Part of: https://git.somenet.org/root/pub/somesible.git
7 # 2017-2024 by someone <someone@somenet.org>
8 #
9
10 #                               -*- Mode: Sh -*-
11 # updateConfFile.sh ---
12 # Author           : Manoj Srivastava ( srivasta@glaurung.green-gryphon.com )
13 # Created On       : Fri Feb  1 03:41:47 2002
14 # Created On Node  : glaurung.green-gryphon.com
15 # Last Modified By : Manoj Srivastava
16 # Last Modified On : Tue Jun  6 09:48:22 2006
17 # Last Machine Used: glaurung.internal.golden-gryphon.com
18 # Update Count     : 186
19 # Status           : Unknown, Use with caution!
20 # HISTORY          :
21 # Description      :
22 #
23 # This script attempts to provide conffile like handling for files not
24 # shipped in a Debian package, but handled by the postinst. Using this
25 # script, one may ship a bunch of default cofiguration files somewhere
26 # in /usr (/usr/share/<pkg> is a good location), and maintain files in
27 # /etc.
28 #
29 # The motivation for this script was to provide conffile like handling
30 # for start files for emacs lisp packages (for example,
31 # /etc/emacs21/site-stard.d/50psgml-init.el) These start files are not
32 # shipped with the package, instead, they are installed during the
33 # post installation configuration phase by the script
34 # /usr/lib/emacsen-common/emacs-package-install $package_name.
35 #
36 # This script is meant to be invoked by the packages install script at
37 # /usr/lib/emacsen-common/packages/install/$package_name for each
38 # flavour of installed emacsen by calling it with the proper values of
39 # new file (/usr/share/emacs/site-lisp/<pkg>/<pkg>-init.el), and dest file
40 # (/etc/emacs21/site-stard.d/50<pkg>-init.el)), and it should do the rest.
41 #
42
43 # make sure we exit on error
44 set -e
45
46 # set the version and revision
47 progname="$(basename $0)"
48 pversion='Revision: 3.00 '
49
50 unset GREP_OPTIONS
51
52 ######################################################################
53 ########                                                     #########
54 ########              Utility functions                      #########
55 ########                                                     #########
56 ######################################################################
57 setq() {
58     # Variable Value Doc_string
59     if [ "x$2" = "x" ]; then
60         echo >&2 "$progname: Unable to determine $3"
61         exit 1;
62     else
63         if [ "x$VERBOSE" != "x" ]; then
64             echo >&2 "$progname: $3 is $2";
65         fi
66         eval "$1=\"\$2\"";
67     fi
68 }
69
70 # Usage: get_file_metadate file_name
71 get_file_metadata()
72 {
73     if [ -e "$1" ]; then
74         # get file modification date without the nanoseconds and timezone info
75         local moddate="$(date +"%F %T" --date $(stat --format '@%Y' "$1"))"
76         # print file_name user.group permissions above_date
77         stat --format "%n %U.%G 0%a $moddate" "$1"
78     else
79         echo "/dev/null"
80     fi
81 }
82
83 # Runs the diff command with approrpiate arguments
84 # Usage run_diff diff|sdiff diff_opts old_file new_file
85 run_diff()
86 {
87     local diff_cmd="$1"
88     local diff_opt="$2"
89     local old_file="$3"
90     local new_file="$4"
91
92     # Note: get_file_metadata not in quotes to ignore "\n" characters
93     local old_file_label="$(get_file_metadata "$old_file")"
94     local new_file_label="$(get_file_metadata "$new_file")"
95
96     [ -e "$old_file" ] || old_file=/dev/null
97     [ -e "$new_file" ] || new_file=/dev/null
98
99     if [ "$diff_cmd" = "diff" ] ; then
100       diff "$diff_opt" --label "$old_file_label" "$old_file" \
101             --label "$new_file_label" "$new_file" || true
102     elif [ "$diff_cmd" = "sdiff" ] ; then
103       # unfortunatelly the sdiff command does not support --label option
104       local out="$(sdiff "$diff_opt" "$old_file" "$new_file")" || true
105       [ -z "$out" ] || printf "Old file: %s\nNew file: %s\n\n%s" \
106                                "$old_file_label" "$new_file_label" "$out"
107     else
108       echo "Unknown diff command: $diff_cmd" >&2
109       exit 1
110     fi
111 }
112
113
114 # Use debconf to show the differences
115 # Usage: show_diff actual_file_differences file_stat_differences
116 show_diff() {
117     if [ -z "$1" ]; then
118         DIFF="There are no non-white space differences in the files."
119     else
120         if  [ 99999 -lt "$(echo $1 | wc -c | awk '{print $1; }')" ]; then
121             DIFF="The differences between the files are too large to display."
122         else
123             DIFF="$1"
124         fi
125     fi
126     if [ "$DEBCONF_OK" = "YES" ] && [ "$DEBIAN_HAS_FRONTEND" ]; then
127         templ=ucf/show_diff
128         db_capb escape
129         db_subst $templ DIFF "$(printf %s "$DIFF" | debconf-escape -e)"
130         db_fset $templ seen false
131         db_input critical $templ || true
132         db_go || true
133         db_get $templ
134         # may contain sensitive information, so clear
135         # immediatly after use so it is never written
136         # to disk
137         db_subst $templ DIFF ""
138         db_reset $templ
139         db_capb
140     else
141         if [ -z "$my_pager" ]; then
142             echo "$DIFF" | sensible-pager
143         else
144             echo "$DIFF" | $my_pager
145         fi
146     fi
147 }
148
149 withecho () {
150         echo "$@" >&2
151         "$@"
152 }
153
154 usageversion () {
155         cat >&2 <<END
156 Debian GNU/Linux $progname $pversion.
157            Copyright (C) 2002-2005 Manoj Srivastava.
158 This is free software; see the GNU General Public Licence for copying
159 conditions.  There is NO warranty.
160
161 Usage: $progname  [options] new_file  destination
162 Options:
163      -h,     --help          print this message
164      -s foo, --src-dir  foo  Set the src dir (historical md5sums live here)
165              --sum-file bar  Force the historical md5sums to be read from
166                              this file.  Overrides any setting of --src-dir.
167      -d[n], --debug=[n]      Set the Debug level to N. Please note there must
168                              be no spaces before the debug level
169      -n,     --no-action     Dry run. No action is actually taken.
170      -P foo, --package foo   Don't follow dpkg-divert diversions by package foo.
171      -v,     --verbose       Make the script verbose
172              --three-way     Register this file in the cache, and turn on the
173                              diff3 option allowing the merging of maintainer
174                              changes into a (potentially modified) local
175                              configuration file. )
176              --state-dir bar Set the state directory to bar instead of the
177                              default '/var/lib/ucf'. Used mostly for testing.
178              --debconf-ok    Indicate that it is ok for ucf to use an already
179                              running debconf instance for prompting.
180              --debconf-template bar
181                              Specify an alternate, caller-provided debconf
182                              template to use for prompting.
183 Usage: $progname  -p  destination
184      -p,     --purge         Remove any reference to destination from records
185
186 By default, the directory the new_file lives in is assumed to be the src-dir,
187 which is where we look for any historical md5sums.
188
189 END
190
191 }
192
193 ######################################################################
194 ########                                                     #########
195 ########        file and hash save/restore functions         #########
196 ########                                                     #########
197 ######################################################################
198 purge_md5sum () {
199     for i in $(/usr/bin/seq 6 -1 0); do
200         if [ -e "${statedir}/hashfile.${i}" ]; then
201             if [ "X$docmd" = "XYES" ]; then
202                 cp -pf "${statedir}/hashfile.${i}" \
203                     "${statedir}/hashfile.$(($i+1))"
204             else
205                 echo cp -pf "${statedir}/hashfile.${i}" \
206                           "${statedir}/hashfile.$(($i+1))"
207             fi
208         fi
209     done
210     if [ -e "$statedir/hashfile" ]; then
211         if [ "X$docmd" = "XYES" ]; then
212             cp -pf "$statedir/hashfile"  "$statedir/hashfile.0"
213         else
214             echo cp -pf "$statedir/hashfile"  "$statedir/hashfile.0"
215         fi
216         if [ "X$docmd" = "XYES" ]; then
217             set +e
218             if [ "X$VERBOSE" != "X" ]; then
219                 echo >&2 "grep -Ev [[:space:]]${safe_dest_file}$ $statedir/hashfile"
220                 grep -Ev "[[:space:]]${safe_dest_file}$"  "$statedir/hashfile" >&2 \
221                     || true;
222             fi
223             #echo "grep -Ev [[:space:]]${safe_dest_file}$ $statedir/hashfile"
224             grep -Ev "[[:space:]]${safe_dest_file}$" "$statedir/hashfile" > \
225                 "$statedir/hashfile.tmp" || true;
226             if [ "X$docmd" = "XYES" ]; then
227                 mv -f "$statedir/hashfile.tmp"  "$statedir/hashfile"
228             else
229                 echo mv -f "$statedir/hashfile.tmp"  "$statedir/hashfile"
230             fi
231             set -e
232         fi
233     fi
234     test -n "$VERBOSE" && echo >&2 "The cache file is $cached_file"
235     if [ ! -z "$cached_file" -a -f "$statedir/cache/$cached_file" ]; then
236         $action rm -f "$statedir/cache/$cached_file"
237     fi
238 }
239
240 replace_md5sum () {
241     for i in $(/usr/bin/seq 6 -1 0); do
242         if [ -e "${statedir}/hashfile.${i}" ]; then
243             if [ "X$docmd" = "XYES" ]; then
244                 cp -pf "${statedir}/hashfile.${i}" \
245                     "${statedir}/hashfile.$(($i+1))"
246             else
247                 echo cp -pf "${statedir}/hashfile.${i}" \
248                     "${statedir}/hashfile.$(($i+1))"
249             fi
250         fi
251     done
252     if [ -e "$statedir/hashfile" ]; then
253         if [ "X$docmd" = "XYES" ]; then
254             cp -pf "$statedir/hashfile"  "$statedir/hashfile.0"
255         else
256             echo cp -pf "$statedir/hashfile"  "$statedir/hashfile.0"
257         fi
258         if [ "X$docmd" = "XYES" ]; then
259             set +e
260             if [ "X$VERBOSE" != "X" ]; then
261                 echo >&2 "(grep -Ev \"[[:space:]]${safe_dest_file}$\" \"$statedir/hashfile\";"
262                 grep -Ev "[[:space:]]${safe_dest_file}$"  "$statedir/hashfile" >&2 || true;
263                 md5sum "$orig_new_file" | sed "s|$orig_new_file|$dest_file|" >&2;
264             fi
265             grep -Ev "[[:space:]]${safe_dest_file}$" "$statedir/hashfile" > \
266                 "$statedir/hashfile.tmp" || true;
267             md5sum "$orig_new_file" | sed "s|$orig_new_file|$dest_file|" >> \
268                 "$statedir/hashfile.tmp";
269             mv -f "$statedir/hashfile.tmp"  "$statedir/hashfile"
270             set -e
271         else
272             echo "(grep -Ev \"[[:space:]]${safe_dest_file}$\" \"$statedir/hashfile\""
273             echo " md5sum \"$orig_new_file\" | sed \"s|$orig_new_file|$dest_file|\"; "
274             echo ") | sort > \"$statedir/hashfile\""
275         fi
276     else
277         if [ "X$docmd" = "XYES" ]; then
278             md5sum "$orig_new_file" | sed "s|$orig_new_file|$dest_file|"  > \
279                 "$statedir/hashfile"
280         else
281             echo " md5sum \"$orig_new_file\" | sed \"s|$orig_new_file|$dest_file|\" >" \
282                 "\"$statedir/hashfile\""
283         fi
284     fi
285     file_size=$(stat -c '%s' "$orig_new_file")
286     if [ "X$THREEWAY" != "X" ] || [ "$file_size" -lt 25600 ]; then
287         $action cp -pf "$orig_new_file" "$statedir/cache/$cached_file"
288     fi
289     # cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}"
290 }
291
292 replace_conf_file () {
293     # do not mangle $dest_file since it's the one registered in the hashfile
294     # or we have been ask to register
295     real_file="$dest_file"
296     if [ -L "$dest_file" ]; then
297         real_file="$(readlink -nf $dest_file || :)"
298         if [ "x$real_file" = "x" ]; then
299             echo >&2 "$dest_file is a broken symlink!"
300             $action rm -f "$dest_file";
301             real_file="$dest_file"
302         fi
303     fi
304     if [ -e "$real_file" ]; then
305         if [ -z "$RETAIN_OLD" ]; then
306             #echo "Saving  ${real_file}.${OLD_SUFFIX},  in case."
307             if [ "x$VERBOSE" != "x" ]; then
308                 echo >&2 "Not saving ${real_file}, since it was unmodified"
309             fi
310         else
311             $action cp -pf $selinux "${real_file}" "${real_file}.${OLD_SUFFIX}"
312         fi
313     fi
314     if [ -e "${real_file}" ]; then
315         # Do not change the permissions and attributes of the destination
316         $action cp -f $selinux "$new_file" "${real_file}"
317     else
318         # No destination file exists
319         $action cp -pf $selinux "$new_file" "${real_file}"
320     fi
321     replace_md5sum;
322 }
323
324 # Escape single quotes in the arguments passed in
325 quote_single() {
326     printf "%s\n" "$1" | sed -e "s,','\\\\'',g"
327 }
328
329
330
331 ######################################################################
332 ########                                                     #########
333 ########              Command line args                      #########
334 ########                                                     #########
335 ######################################################################
336 #
337 # Long term variables#
338 #
339 docmd='YES'
340 action='withecho'
341 action=
342 selinux=''
343 DEBUG=0
344 VERBOSE=''
345 statedir='/var/lib/ucf';
346 THREEWAY=
347
348 DIST_SUFFIX="ucf-dist"
349 NEW_SUFFIX="ucf-new"
350 OLD_SUFFIX="ucf-old"
351 ERR_SUFFIX="merge-error"
352 # save up the cmdline with proper quoting/escaping
353 for arg in "$@"; do
354     saved="${saved:+$saved }'$(quote_single "$arg")'"
355 done
356
357 # Note that we use `"$@"' to let each command-line parameter expand to a
358 # separate word. The quotes around `$@' are essential!
359 # We need TEMP as the `eval set --' would nuke the return value of getopt.
360 TEMP=$(getopt -a -o hs:d::D::npP:Zv -n "$progname" \
361       --long help,src-dir:,sum-file:,dest-dir:,debug::,DEBUG::,no-action,package:,purge,verbose,three-way,debconf-ok,debconf-template:,state-dir: \
362              -- "$@")
363
364 # Note the quotes around `$TEMP': they are essential!
365 eval set -- "$TEMP"
366
367 while true ; do
368     case "$1" in
369         -h|--help) usageversion;                        exit 0 ;;
370         -n|--no-action) action='echo'; docmd='NO';      shift  ;;
371         -v|--verbose) VERBOSE=1;                        shift  ;;
372         -P|--package)
373             opt_package="$2";                          shift 2 ;;
374         -s|--src-dir)
375             opt_source_dir="$2";                       shift 2 ;;
376         --sum-file)
377             opt_old_mdsum_file="$2";              shift 2 ;;
378         --state-dir)
379             opt_state_dir="$2";                        shift 2 ;;
380         --debconf-template)
381             override_template="$2";                    shift 2 ;;
382         -D|-d|--debug|--DEBUG)
383             # d has an optional argument. As we are in quoted mode,
384             # an empty parameter will be generated if its optional
385             # argument is not found.
386             case "$2" in
387                 "") setq DEBUG 1    "The Debug value"; shift 2 ;;
388                 *)  setq DEBUG "$2" "The Debug value"; shift 2 ;;
389             esac ;;
390         -p|--purge) PURGE=YES;                         shift   ;;
391        --three-way) THREEWAY=YES;                       shift   ;;
392        --debconf-ok) DEBCONF_OK=YES;                    shift   ;;
393        -Z) selinux='-Z';                                shift   ;;
394         --)  shift ;                                   break   ;;
395         *) echo >&2 "Internal error!" ; exit 1 ;;
396     esac
397 done
398
399
400 ######################################################################
401 ########                                                     #########
402 ########              Sanity checking                        #########
403 ########                                                     #########
404 ######################################################################
405 # Need to run as root, or else the
406 if test "$(id -u)" != 0; then
407     if [ "$docmd" = "YES" ]; then
408         echo "$progname: Need to be run as root." >&2
409         echo "$progname: Setting up no action mode." >&2
410         action='echo'; docmd='NO';
411     fi
412 fi
413
414 if [ "X$PURGE" = "XYES" ]; then
415     if [ $# != 1 ]; then
416         echo >&2 "*** ERROR: Need exactly one argument when purging, got $#";
417         echo >&2 ""
418         usageversion;
419         exit 2 ;
420     fi
421     temp_dest_file="$1";
422     if [ -e "$temp_dest_file" ]; then
423         setq dest_file "$(readlink -q -m $temp_dest_file)" "The Destination file";
424     else
425         setq dest_file "$temp_dest_file" "The Destination file";
426     fi
427 else
428     if [ $# != 2 ]; then
429         echo >&2 "*** ERROR: Need exactly two arguments, got $#";
430         echo >&2 ""
431         usageversion;
432         exit 2 ;
433     fi
434     temp_new_file="$1";
435     temp_dest_file="$2";
436
437     if [ ! -e "${temp_new_file}" ]; then
438         echo >&2 "Error: The new file ${temp_new_file} does not exist!";
439         exit 1;
440     fi
441     setq new_file  "$(readlink -q -m $temp_new_file)"  "The new file";
442     if [ -e "$temp_dest_file" ]; then
443         setq dest_file "$(readlink -q -m $temp_dest_file)" "The Destination file";
444     else
445         setq dest_file "$temp_dest_file" "The Destination file";
446     fi
447 fi
448
449 # Follow dpkg-divert as though we are installed as part of $opt_package
450 divert_line=$(dpkg-divert --listpackage "$dest_file")
451 if [ -n "$divert_line" ]; then
452    # name of the package or 'LOCAL' for a local diversion
453    divert_package="$divert_line"
454
455    if [ "$divert_package" != "$opt_package" ]; then
456        dest_file=$(dpkg-divert --truename "$dest_file")
457    fi
458 fi
459 safe_dest_file=$(echo "$dest_file" | perl -nle 'print "\Q$_\E\n"')
460
461
462 ######################################################################
463 ########                                                     #########
464 ########              Set Default Values                     #########
465 ########                                                     #########
466 ######################################################################
467 # Load site defaults and over rides.
468 if [ -f /etc/ucf.conf ]; then
469     . /etc/ucf.conf
470 fi
471
472 # Command line, env variable, config file, or default
473 if [ ! "x$opt_source_dir" = "x" ]; then
474     setq source_dir "$opt_source_dir" "The Source directory"
475 elif [ ! "x$UCF_SOURCE_DIR" = "x" ]; then
476     setq source_dir "$UCF_SOURCE_DIR" "The Source directory"
477 elif [ ! "x$conf_source_dir" = "x" ]; then
478     setq source_dir "$conf_source_dir" "The Source directory"
479 else
480     if [ "X$new_file" != "X" ]; then
481         setq source_dir "$(dirname $new_file)" "The Source directory"
482     else
483         setq source_dir "/tmp" "The Source directory"
484     fi
485
486 fi
487
488 if [ "X$PAGER" != "X" ] && which "$PAGER" >/dev/null 2>&1 ; then
489     my_pager="$(which $PAGER)";
490 elif [ -s /usr/bin/pager ] &&
491      [ "X$(readlink -e /usr/bin/pager || :)" != "X" ]; then
492     my_pager=/usr/bin/pager
493 elif [ -x /usr/bin/sensible-pager ]; then
494     my_pager=/usr/bin/sensible-pager
495 elif [ -x /bin/more ]; then
496     my_pager=/bin/more
497 else
498     my_pager=
499 fi
500
501
502 # Command line, env variable, config file, or default
503 if [ ! "x$opt_state_dir" = "x" ]; then
504     setq statedir "$opt_state_dir" "The State directory"
505 elif [ ! "x$UCF_STATE_DIR" = "x" ]; then
506     setq statedir "$UCF_STATE_DIR" "The State directory"
507 elif [ ! "x$conf_state_dir" = "x" ]; then
508     setq statedir "$conf_state_dir" "The State directory"
509 else
510     setq statedir '/var/lib/ucf'  "The State directory"
511 fi
512
513 # Command line, env variable, config file, or default
514 if [ ! "x$opt_force_conffold" = "x" ]; then
515     setq force_conffold "$opt_force_conffold" "Keep the old file"
516 elif [ ! "x$UCF_FORCE_CONFFOLD" = "x" ]; then
517     setq force_conffold "$UCF_FORCE_CONFFOLD" "Keep the old file"
518 elif [ ! "x$conf_force_conffold" = "x" ]; then
519     setq force_conffold "$conf_force_conffold" "Keep the old file"
520 else
521     force_conffold=''
522 fi
523
524 # Command line, env variable, config file, or default
525 if [ ! "x$opt_force_conffnew" = "x" ]; then
526     setq force_conffnew "$opt_force_conffnew" "Replace the old file"
527 elif [ ! "x$UCF_FORCE_CONFFNEW" = "x" ]; then
528     setq force_conffnew "$UCF_FORCE_CONFFNEW" "Replace the old file"
529 elif [ ! "x$conf_force_conffnew" = "x" ]; then
530     setq force_conffnew "$conf_force_conffnew" "Replace the old file"
531 else
532     force_conffnew=''
533 fi
534
535 # Command line, env variable, config file, or default
536 if [ ! "x$opt_force_conffmiss" = "x" ]; then
537     setq force_conffmiss "$opt_force_conffmiss" "Replace any missing files"
538 elif [ ! "x$UCF_FORCE_CONFFMISS" = "x" ]; then
539     setq force_conffmiss "$UCF_FORCE_CONFFMISS" "Replace any missing files"
540 elif [ ! "x$conf_force_conffmiss" = "x" ]; then
541     setq force_conffmiss "$conf_force_conffmiss" "Replace any missing files"
542 else
543     force_conffmiss=''
544 fi
545
546 if [ -n "$opt_old_mdsum_file" ]; then
547     setq old_mdsum_file "$opt_old_mdsum_file" "The md5sum is found here"
548 elif [ ! "x$UCF_OLD_MDSUM_FILE" = "x" ]; then
549     setq old_mdsum_file "$UCF_OLD_MDSUM_FILE" "The md5sum is found here"
550 elif [ ! "x$conf_old_mdsum_file" = "x" ]; then
551     setq old_mdsum_file "$conf_old_mdsum_file" "Replace the old file"
552 elif [ ! "x${new_file}" = "x" ]; then
553     old_mdsum_file="$source_dir/$(basename ${new_file}).md5sum";
554 else
555     old_mdsum_file="";
556 fi
557
558
559 ######################################################################
560 ########                                                     #########
561 ########               More Sanity checking                  #########
562 ########                                                     #########
563 ######################################################################
564
565 # someone's hack: always use new file!
566 force_conffold=''
567
568 if [ "X$force_conffold" != "X" -a "X$force_conffnew" != "X" ]; then
569     echo >&2 "Error: Only one of force_conffold and force_conffnew should";
570     echo >&2 "       be set";
571     exit 1;
572 fi
573
574 # VERBOSE of 0 is supposed to be the same as not setting VERBOSE
575 if [ "X$VERBOSE" = "X0" ]; then
576     VERBOSE=''
577 fi
578
579
580 #
581 if [ -e "$statedir/hashfile" -a ! -w "$statedir/hashfile" ]; then
582     echo >&2 "ucf: do not have write privilege to the state data"
583     if [ "X$docmd" = "XYES" ]; then
584         exit 1;
585     fi
586 fi
587
588 if [ ! -d $statedir/cache ]; then
589     $action mkdir -p $statedir/cache ;
590 fi
591
592 # test and see if this file exists in the database
593 if [ -e "$statedir/hashfile" ]; then
594     if [ "X$VERBOSE" != "X" ]; then
595         echo >&2 "The hash file exists"
596         echo >&2 "grep -E" "[[:space:]]${safe_dest_file}$" "$statedir/hashfile"
597         grep -E "[[:space:]]${safe_dest_file}$" "$statedir/hashfile" >&2 || true
598     fi
599     lastsum=$(grep -E "[[:space:]]${safe_dest_file}$" "$statedir/hashfile" | \
600                    awk '{print $1;}' )
601 fi
602
603 if [ ! "x${new_file}" = "x" ]; then
604     old_mdsum_dir="$source_dir/"$(basename "${new_file}")".md5sum.d";
605 else
606     old_mdsum_dir="";
607 fi
608
609 cached_file="$(echo $dest_file | tr / :)"
610 ######################################################################
611 ########                                                     #########
612 ########                  Debugging dump                     #########
613 ########                                                     #########
614 ######################################################################
615
616 if [ $DEBUG -gt 0 ]; then
617     cat >&2 <<EOF
618 The new start file is      \`$new_file\'
619 The destination is         \`$dest_file\' (\`$safe_dest_file\')
620 The history is kept under  \'$source_dir\'
621 The file may be cached at \'$statedir/cache/$cached_file\'
622 EOF
623     if [ -s "$dest_file" ]; then
624         echo "The destination file exists, and has md5sum:"
625         md5sum "$dest_file"
626     else
627         echo "The destination file does not exist."
628     fi
629     if [ "X$lastsum" != "X" ]; then
630         echo "The old md5sum exists, and is:"
631         echo "$lastsum"
632     else
633         echo "The old md5sum does not exist."
634         if [ -d "$old_mdsum_dir" -o -f "$old_mdsum_file" ]; then
635             echo "However, there are historical md5sums around."
636         fi
637     fi
638     if [ -e "$new_file" ]; then
639         echo "The new file exists, and has md5sum:"
640         md5sum "$new_file"
641     else
642         echo "The new file does not exist."
643     fi
644     if [ -d "$old_mdsum_dir" ]; then
645         echo "The historical md5sum dir $old_mdsum_dir exists"
646     elif [ -f "$old_mdsum_file" ]; then
647         echo "The historical md5sum file $old_mdsum_file exists"
648     else
649         echo "Historical md5sums are not available"
650     fi
651 fi
652
653 ######################################################################
654 ########                                                     #########
655 ########        Short circuit if we are purging              #########
656 ########                                                     #########
657 ######################################################################
658
659 if [ "X$PURGE" = "XYES" ]; then
660     if [ "X$VERBOSE" != "X" ]; then
661         echo >&2 "Preparing to purge ${dest_file}"
662     fi
663     purge_md5sum;
664     exit 0;
665 fi
666
667
668 # now we can restore $@
669 eval set -- "$saved"
670
671 ######################################################################
672 ########                                                     #########
673 ########                  DebConf stuff                      #########
674 ########                                                     #########
675 ######################################################################
676
677 # Is debconf already running? Kinda tricky, because it will be after the
678 # confmodule is sourced, so only test before that.
679 if [ -z "$DEBCONF_ALREADY_RUNNING" ]; then
680     if [ "$DEBIAN_HAS_FRONTEND" ]; then
681         DEBCONF_ALREADY_RUNNING='YES'
682     else
683         DEBCONF_ALREADY_RUNNING='NO'
684     fi
685 fi
686
687 export DEBCONF_ALREADY_RUNNING
688
689 if [ -z "$DEBCONF_OK" ]; then
690     if [ "$DEBCONF_ALREADY_RUNNING" = 'YES' ]; then
691         DEBCONF_OK='NO'
692     else
693         DEBCONF_OK='YES'
694     fi
695 fi
696
697 # Time to start nagging the users who call ucf without debconf-ok
698 if [ "$DEBCONF_ALREADY_RUNNING"  = 'YES' ] && [ "$DEBCONF_OK" = NO ]; then
699         # Commented out for now, uncomment after a while to begin nagging
700         # maintainers to fix their scripts.
701         cat \
702 <<END
703 *** WARNING: ucf was run from a maintainer script that uses debconf, but
704              the script did not pass --debconf-ok to ucf. The maintainer
705              script should be fixed to not stop debconf before calling ucf,
706              and pass it this parameter. For now, ucf will revert to using
707              old-style, non-debconf prompting. Ugh!
708
709              Please inform the package maintainer about this problem.
710 END
711 fi
712
713 # Start up debconf or at least get the db_* commands available
714 if [ -e /usr/share/debconf/confmodule ]; then
715     if test "$(id -u)" = 0; then
716         . /usr/share/debconf/confmodule
717
718         # Load our templates, just in case our template has
719         # not been loaded or the Debconf DB lost or corrupted
720         # since then, but only if it is OK to use debconf.
721         if [ "$DEBCONF_OK" = 'YES' ]; then
722             db_x_loadtemplatefile "$(dpkg-query --control-path ucf templates)" ucf
723         fi
724     else
725         echo >&2 "$progname: Not loading confmodule, since we are not running as root."
726     fi
727     # Only set the title if debconf was not already running.
728     # If it was running, then we do not want to clobber the
729     # title used for configuring the whole package with debconf.
730     if [ "$DEBCONF_ALREADY_RUNNING" = 'NO' ]; then
731         if ! db_settitle ucf/title 2>/dev/null; then
732             # Older debconf that does not support that command.
733             if test "$(id -u)" = 0; then
734                 db_title "Modified configuration file"
735             else
736                 echo >&2 "$progname: Not changing title, since we are not running as root."
737             fi
738         fi
739     fi
740 fi
741
742
743
744 ######################################################################
745 ########                                                     #########
746 ########                Start Processing                     #########
747 ########                                                     #########
748 ######################################################################
749
750 orig_new_file="$new_file"       # Since sometimes we replace the newfile below
751 newsum=$(md5sum "$new_file" | awk '{print $1}')
752
753 # Determine the action for the current file. The default is to ask,
754 # with non-replacement being the norm.
755 # If the config dir exists
756 #   if file in always overwrite, state +=1;
757 #   fi
758 #   if file in never overwrite, state +=2;
759 #   fi
760 #   if file in ask; state +=4
761 #   fi
762 #   if state == 0; then state = default
763 #   if state >= 4; ask
764 #   if state == 3;  ask
765 #   if state == 2; exit
766 #   if state == 1; then replace_conffile; exit
767
768 ######################################################################
769 ########                                                     #########
770 ########               Do the replacement                    #########
771 ########                                                     #########
772 ######################################################################
773 # Step 1: If we have no record of this file, and dest file
774 #         does, We need to determine how to initialize the
775 #         ${old_mdsum_prefix}.old file..
776 if [ -e "$dest_file" ]; then
777     destsum=$(md5sum "$dest_file"  | awk '{print $1}');
778     if [ "X$lastsum" = "X" ]; then
779 #      a: If we have a directory containing historical md5sums of this
780 #         file in question, we should look and see if the currently
781 #         installed file matches any of the old md5sums; in which case
782 #         it can be silently replaced.
783         if [ -d "$old_mdsum_dir" -o -f "$old_mdsum_file" ]; then
784             if [ -d "$old_mdsum_dir"  ]; then
785                 for file in ${old_mdsum_dir}/*; do
786                     oldsum="$(awk '{print $1}' $file)";
787                     if [ "$oldsum" = "$destsum"  ]; then
788                         if [ "X$force_conffold" = "X" ]; then
789 #                           Bingo! replace, set the md5sum, and we are done
790                             if [ "X$VERBOSE" != "X" ]; then
791                                 echo >&2 \
792                                     "Replacing config file $dest_file with new version"
793                             fi
794                             replace_conf_file;
795                             exit 0;
796                         else
797                             replace_md5sum;
798                             cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}"
799                             exit 0;
800                         fi
801                     fi
802                 done
803             elif [ -f "$old_mdsum_file" ]; then
804                 oldsum=$(grep -E "^${destsum}" "$old_mdsum_file" || true)
805                 if [ "X$oldsum" != "X" ]; then
806 #                    Bingo
807                     if [ "X$force_conffold" = "X" ]; then
808                         if [ "X$VERBOSE" != "X" ]; then
809                             echo >&2 \
810                                 "Replacing config file $dest_file with new version"
811                         fi
812                         replace_conf_file;
813                         exit 0;
814                     else
815                         replace_md5sum;
816                         cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}"
817                         exit 0;
818                     fi
819                 fi
820             fi
821 #          Well, nothing matched. We now check to see if the
822 #          maintainer has an opinion on how to set the ``md5sum of the
823 #          previously installed version'', since we have no way of
824 #          determining that automatically. Please note that unless
825 #          there are limited number of previously released packages
826 #          (like just one), the maintainer is also making a guess at
827 #          this point by supplying a historical md5sum default file.
828             if [ "X$VERBOSE" != "X" ]; then
829                 echo >&2 "Historical md5sums did not match."
830             fi
831             if [ -d "$old_mdsum_dir"  ]; then
832                 if [ -e "${old_mdsum_dir}/default" ]; then
833                     if [ "X$VERBOSE" != "X" ]; then
834                         echo >&2 "However, a default entry exists, using it."
835                     fi
836                     lastsum="$(awk '{print $1;}' ${old_mdsum_dir}/default)"
837                     do_replace_md5sum=1;
838                 fi
839             elif [ -f "$old_mdsum_file" ]; then
840                 oldsum=$(grep -E "[[:space:]]default$" "$old_mdsum_file" | \
841                     awk '{print $1;}')
842                 if [ "X$oldsum" != "X" ]; then
843 #                    Bingo
844                     lastsum=$oldsum;
845                     do_replace_md5sum=1;
846                 fi
847             fi
848         fi
849
850 #       At this point, we are almost certain that either the
851 #       historical record of md5sums is not complete, or the user has
852 #       changed the configuration file. Rather than guessing and
853 #       chosing one of the historical md5sums, we fall through to the
854 #       solution used if there had been no historical md5sums
855 #       directory/file.
856         if [ "X$lastsum" = "X" ]; then
857 #      b: We do not have a historical list of md5sums, or none
858 #         matched, and we still need to initialize the
859 #         ${old_mdsum_prefix}.old file. We can't determine whther or
860 #         not they made any changes, so we err on the side of caution
861 #         and ask'
862             if [ "X$VERBOSE" != "X" ]; then
863                 echo >&2 "No match found, we shall ask."
864             fi
865             lastsum='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
866         fi # the old md5sum file does not exist, and the historical
867            # record failed
868     fi # the old md5sum file does not exist (bug))
869 else  # "$dest_file" does not exist
870 # Step 2: If destfile does not exist, create it, set the file
871 #         "${old_mdsum_prefix}.old" to the md5sum of the new file, and we
872 #         are done
873     if [ "X$lastsum" = "X" ]; then
874         # Ok, so there is no indication that the package was ever
875         # installed on this machine.
876         echo >&2 ""
877         echo >&2 "Creating config file $dest_file with new version"
878         replace_conf_file;
879         exit 0;
880     elif [ "$lastsum" = "$newsum" ]; then
881         # OK, new version of the file is the same as the last version
882         # we saw. Since the user apparently has deleted the file,
883         # nothing needs be done, unless we have been told differently
884         if [ "X$force_conffmiss" != "X" ]; then
885             echo >&2 ""
886             echo >&2 "Recreating deleted config file $dest_file with new version, as asked"
887             replace_conf_file;
888             exit 0;
889         else
890             echo >&2 "Not replacing deleted config file $dest_file";
891         fi
892
893     else
894         # OK. New upstream version.
895         if [ "X$force_conffmiss" != "X" ]; then
896             # User has said to replace missing files, so we do so, no
897             # questions asked.
898             echo >&2 ""
899             echo >&2 "Recreating deleted config file $dest_file with new version, as asked"
900             replace_conf_file;
901             exit 0;
902         else
903             # Even though the user has deleted this file, they should
904             # be asked now, unless specified otherwise.
905             if [ "X$force_conffold" = "X" ]; then
906                 destsum='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
907             else
908                 exit 0;
909             fi
910         fi
911     fi
912 fi
913
914 # Here, the destfile exists.
915
916 # step 3: If the old md5sum and the md5sum of the new file
917 #         do not match, we need to take action.
918 if [ "$lastsum" = "$newsum" ]; then
919     if [ "X$VERBOSE" != "X" ]; then
920         echo >&2 "md5sums match, nothing needs be done."
921     fi
922     if [ "X$do_replace_md5sum" != "X" ]; then
923         replace_md5sum;
924     fi
925     exit 0;                     # Hah. Match. We are done.
926 fi
927 #      a: If the md5sum of the dest file is the same as lastsum, replace the
928 #         destfile, saying we are replacing old config files
929 if [ "$destsum" = "$lastsum" ]; then
930     if [ "X$force_conffold" = "X" ]; then
931         echo >&2 "Replacing config file $dest_file with new version"
932         replace_conf_file;
933         exit 0;
934     else
935         replace_md5sum;
936         cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}"
937         exit 0;
938     fi
939 else
940 #      b: If the md5sum of the dest file differs from lastsum, we need to ask
941 #         the user what action to take.
942     if [ "X$force_conffnew" != "X" ]; then
943         echo >&2 "Replacing config file $dest_file with new version"
944         echo >&2 "since you asked for it."
945         if [ "$destsum" = "$newsum" ]; then
946             echo >&2 "The new and the old files are identical, AFAICS"
947         else
948             echo >&2 "The new and the old files are different"
949         fi
950         replace_conf_file;
951         exit 0;
952     fi
953     if [ "X$force_conffold" != "X" ]; then
954         replace_md5sum;
955         cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}"
956         exit 0;
957     fi
958 #      c: If the destination file is the same as the new maintianer provided one,
959 #         we need do nothing.
960     if [ "$newsum" = "$destsum" ]; then
961         if [ "X$VERBOSE" != "X" ]; then
962             echo >&2 "md5sums of the file in place matches, nothing needs be done."
963         fi
964         replace_md5sum;
965         exit 0;                 # Hah. Match. We are done.
966     fi
967
968
969     done='NO';
970     while [ "X$done" = "XNO" ]; do
971         if [ "$DEBCONF_OK" = "YES" ] && [ "$DEBIAN_HAS_FRONTEND" ]; then
972                 # Use debconf to prompt.
973                 if [ -e "$statedir/cache/$cached_file" ] && [ "X$THREEWAY" != "X" ]; then
974                         templ=ucf/changeprompt_threeway
975                 else
976                         templ=ucf/changeprompt
977                 fi
978                 if [ "X$override_template" != "X" ]; then
979                         choices="$(db_metaget $templ Choices-C)"
980                         choices2="$(db_metaget $override_template Choices-C)"
981                         if [ "$choices" = "$choices2" ]; then
982                                 templ=$override_template
983                         fi
984                 fi
985                 db_fset "$templ" seen false
986                 db_reset "$templ"
987                 db_subst "$templ" FILE "$dest_file"
988                 db_subst "$templ" NEW  "$new_file"
989                 db_subst "$templ" BASENAME "$(basename $dest_file)"
990                 db_input critical "$templ" || true
991                 if ! db_go; then
992                         # The current ucf interface does not provide a way for it
993                         # to tell its caller that the user chose to back up.
994                         # However, we could get here, if the caller turned on
995                         # debconf's backup capb. The best thing to do seems to be
996                         # to ignore requests to back up.
997                         continue
998                 fi
999                 db_get "$templ"
1000                 ANSWER="$RET"
1001         else
1002             echo >&2 "Need debconf to interact"
1003             exit 2
1004 ########################################################################################
1005 #               # Prompt without using debconf.                                        #
1006 #               cat >&2 <<EOPRMT                                                       #
1007 # Configuration file \`$dest_file'                                                     #
1008 #  ==> File on system created by you or by a script.                                   #
1009 #  ==> File also in package provided by package maintainer.                            #
1010 #    What would you like to do about it ?  Your options are:                           #
1011 #     Y or I  : install the package maintainer's version                               #
1012 #     N or O  : keep your currently-installed version                                  #
1013 #       D     : show the differences between the versions                              #
1014 #       S     : show the side-by-side differences between the versions                 #
1015 # EOPRMT                                                                               #
1016 #               if [ "X$THREEWAY" != "X" -a -e "$statedir/cache/$cached_file" ]; then  #
1017 #                       cat >&2 <<EOTD                                                 #
1018 #     3 or T  : show a three way difference between current, older,                    #
1019 #               and new versions of the file                                           #
1020 #       M     : Do a 3 way merge between current, older,                               #
1021 #               and new versions of the file [Very Experimental]                       #
1022 # EOTD                                                                                 #
1023 #               fi                                                                     #
1024 #               cat >&2 <<EOPEND                                                       #
1025 #       Z     : start a new shell to examine the situation                             #
1026 #  The default action is to keep your current version.                                 #
1027 # EOPEND                                                                               #
1028 #               if [ "X$THREEWAY" != "X" -a -e "$statedir/cache/$cached_file" ]; then  #
1029 #                       echo -n >&2 "*** " $(basename "$dest_file") \                  #
1030 #                           " (Y/I/N/O/D/3/T/M/Z) [default=N] ?"                       #
1031 #               else                                                                   #
1032 #                       echo -n >&2 "*** " $(basename "$dest_file") \                  #
1033 #                           " (Y/I/N/O/D/Z) [default=N] ?"                             #
1034 #               fi                                                                     #
1035 #               read -e ANSWER </dev/tty                                               #
1036 ########################################################################################
1037         fi
1038
1039         case "$ANSWER" in
1040             install_new|y|Y|I|i)
1041                 echo >&2 "Replacing config file $dest_file with new version"
1042                 RETAIN_OLD=YES
1043                 replace_conf_file;
1044                 exit 0;
1045                 ;;
1046             diff|D|d)
1047                 DIFF="$(run_diff diff -uBbwt "$dest_file" "$new_file")"
1048                 show_diff "$DIFF"
1049                 ;;
1050             sdiff|S|s)
1051                 DIFF="$(run_diff sdiff -BbW "$dest_file" "$new_file")"
1052                 show_diff "$DIFF"
1053                 ;;
1054             diff_threeway|3|t|T)
1055                 if [ -e "$statedir/cache/$cached_file" \
1056                     -a "X$THREEWAY" != "X" ]; then
1057                     if [ -e "$dest_file" ]; then
1058                         DIFF="$(diff3 -L Current -L Older -L New -A \
1059                             "$dest_file" "$statedir/cache/$cached_file" \
1060                             "$new_file")"  || true
1061                     else
1062                         DIFF="$(diff3 -L Current -L Older -L New -A \
1063                             /dev/null "$statedir/cache/$cached_file" \
1064                             "$new_file")"  || true
1065                     fi
1066                     show_diff "$DIFF"
1067                 else
1068                     DIFF="$(run_diff diff -uBbwt "$dest_file" "$new_file")"
1069                     show_diff "$DIFF"
1070                 fi
1071                 ;;
1072             merge_threeway|M|m)
1073                 echo >&2 "Merging changes into the new version"
1074                 if [ -e "$statedir/cache/$cached_file" \
1075                     -a "X$THREEWAY" != "X" ]; then
1076                     ret=0
1077                     diff3 -L Current -L Older -L New -m \
1078                         "$dest_file" "$statedir/cache/$cached_file" \
1079                         "$new_file" > "$dest_file.${NEW_SUFFIX}" || ret=$?
1080                     case "$ret" in
1081                         0)
1082                             new_file="$dest_file.${NEW_SUFFIX}"
1083                             RETAIN_OLD=YES
1084                             replace_conf_file
1085                             rm -f "$dest_file.${NEW_SUFFIX}" # don't need this around no mo'
1086                             exit 0
1087                             ;;
1088                         *)
1089                             mv "$dest_file.${NEW_SUFFIX}" "$dest_file.${ERR_SUFFIX}"
1090                             db_subst ucf/conflicts_found dest_file "$dest_file"
1091                             db_subst ucf/conflicts_found ERR_SUFFIX "${ERR_SUFFIX}"
1092                             db_input critical ucf/conflicts_found || true
1093                             db_go || true
1094                             ;;
1095                     esac
1096                 else
1097                     replace_conf_file
1098                     rm -f "$dest_file.${NEW_SUFFIX}" # don't need this around no mo'
1099                     exit 0
1100                 fi
1101                 ;;
1102             shell|Z|z)
1103                 # We explicitly connect STDIN and STDOUT to the
1104                 # script's controlling terminal, so even if STDIN is
1105                 # fed by a pipe, as is the case when run from
1106                 # /usr/bin/debconf, the shell should be fully
1107                 # functional. However, the test for a controlling
1108                 # terminal uses /usr/bin/tty, which consults only
1109                 # STDIN. As far as I can tell, when run from debconf,
1110                 # ucf will _never_ use the current terminal. If the
1111                 # goal is to check for access to a terminal, the test
1112                 # should be for foreground process group membership,
1113                 # not a terminal connected to STDIN (tty -s), and not
1114                 # a terminal it doesn't necessarily own (tty -s
1115                 # </dev/tty). The easiest way do this from a shell is
1116                 # probably with /bin/ps.
1117                 if ps -o stat= --ppid $$ | grep -q '+'; then
1118                     export UCF_CONFFILE_OLD="$dest_file"
1119                     export UCF_CONFFILE_NEW="$new_file"
1120                     bash >/dev/tty </dev/tty || true
1121                 elif [ -n "$DISPLAY" ]; then
1122                     x-terminal-emulator || true
1123                 else
1124                     # Don't know what to do
1125                     echo >&2 "No terminal, and no DISPLAY set, can't fork shell."
1126                     sleep 3;
1127                 fi
1128                 ;;
1129             keep_current|n|N|o|O|'')
1130                 replace_md5sum;
1131
1132                 cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}"
1133                 exit 0;
1134                 ;;
1135             *)
1136                 if [ "$DEBCONF_OK" = "YES" ]; then
1137                         echo "Error: unknown response from debconf:'$RET'" >&2
1138                         exit 1
1139                 else
1140                         echo
1141                         echo "Please answer with one of the single letters listed." >&2
1142                         echo
1143                 fi
1144         esac
1145     done
1146 fi
1147
1148 db_stop
1149
1150 exit 0;