#!/bin/sh # make sure we exit on error set -e # Sanitise environment while read -r env ; do case "$env" in '') continue ;; OPTIND) ;; # Dash croaks when unsetting OPTIND. See #985478 PATH|PWD|TERM) ;; LANGUAGE|LANG|LC_*) ;; DEB_*|DEBIAN_*|DEBCONF_*) ;; DPKG_FORCE) ;; UCF_*) ;; *) unset "$env" ;; esac done<&2 exit 1 fi } # Use debconf to show the differences # Usage: show_diff actual_file_differences file_stat_differences show_diff() { if [ -z "$1" ]; then DIFF="There are no non-white space differences in the files." else if [ 99999 -lt "$(echo "$1" | wc -c | awk '{print $1; }')" ]; then DIFF="The differences between the files are too large to display." else # Try to convert non-breaking space to current locale nbsp=$(printf '\302\240' | iconv -c --from-code=UTF-8 --to-code=//TRANSLIT) DIFF="$(printf "%s" "$1" | sed "s/ /${nbsp:- }/g" | debconf-escape -e )" fi fi if [ "$DEBCONF_OK" = "YES" ] && [ "$DEBIAN_HAS_FRONTEND" ]; then templ=ucf/show_diff db_capb escape db_subst $templ DIFF "$DIFF" db_fset $templ seen false db_input critical $templ || true db_go || true db_get $templ # may contain sensitive information, so clear # immediatly after use so it is never written # to disk db_subst $templ DIFF "" db_reset $templ db_capb else if [ -z "$my_pager" ]; then echo "$DIFF" | sensible-pager else echo "$DIFF" | $my_pager fi fi } usageversion () { cat >&2 <&2 "grep -v ${dest_file_bre} $statedir/hashfile" grep -v "${dest_file_bre}" "$statedir/hashfile" >&2 \ || true fi grep -v "${dest_file_bre}" "$statedir/hashfile" > \ "$statedir/hashfile.tmp" || true mv -f "$statedir/hashfile.tmp" "$statedir/hashfile" fi fi [ "$VERBOSE" ] && echo >&2 "The cache file is $cached_file" if [ "$cached_file" ] && [ -f "$statedir/cache/$cached_file" ]; then $action rm -f "$statedir/cache/$cached_file" fi } replace_md5sum () { for i in $(/usr/bin/seq 6 -1 0); do if [ -e "${statedir}/hashfile.${i}" ]; then if [ "$docmd" = "YES" ]; then cp -pf "${statedir}/hashfile.${i}" \ "${statedir}/hashfile.$(($i+1))" else echo cp -pf "${statedir}/hashfile.${i}" \ "${statedir}/hashfile.$(($i+1))" fi fi done if [ -e "$statedir/hashfile" ]; then if [ "$docmd" = "YES" ]; then cp -pf "$statedir/hashfile" "$statedir/hashfile.0" else echo cp -pf "$statedir/hashfile" "$statedir/hashfile.0" fi if [ "$docmd" = "YES" ]; then if [ "$VERBOSE" ]; then echo >&2 "grep -v \"${dest_file_bre}\" \"$statedir/hashfile\"" grep -v "${dest_file_bre}" "$statedir/hashfile" >&2 || true md5sum "$orig_new_file" | sed "s|$orig_new_file|$dest_file|" >&2 fi grep -v "${dest_file_bre}" "$statedir/hashfile" > \ "$statedir/hashfile.tmp" || true md5sum "$orig_new_file" | sed "s|$orig_new_file|$dest_file|" >> \ "$statedir/hashfile.tmp" mv -f "$statedir/hashfile.tmp" "$statedir/hashfile" else echo "(grep -v \"${dest_file_bre}\" \"$statedir/hashfile\"" echo " md5sum \"$orig_new_file\" | sed \"s|$orig_new_file|$dest_file|\"; " echo ") | sort > \"$statedir/hashfile\"" fi else if [ "$docmd" = "YES" ]; then md5sum "$orig_new_file" | sed "s|$orig_new_file|$dest_file|" > \ "$statedir/hashfile" else echo " md5sum \"$orig_new_file\" | sed \"s|$orig_new_file|$dest_file|\" >" \ "\"$statedir/hashfile\"" fi fi file_size=$(stat -c '%s' "$orig_new_file") if [ "$THREEWAY" ] || [ "$file_size" -lt 25600 ]; then $action cp -pf "$orig_new_file" "$statedir/cache/$cached_file" fi # cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}" } replace_conf_file () { # do not mangle $dest_file since it's the one registered in the hashfile # or we have been ask to register real_file="$dest_file" if [ -L "$dest_file" ]; then real_file="$(readlink -nf "$dest_file" || :)" if [ ! "$real_file" ]; then echo >&2 "$dest_file is a broken symlink!" $action rm -f "$dest_file" real_file="$dest_file" fi fi if [ -e "$real_file" ]; then if [ -z "$RETAIN_OLD" ]; then #echo "Saving ${real_file}.${OLD_SUFFIX}, in case." [ "$VERBOSE" ] && echo >&2 "Not saving ${real_file}, since it was unmodified" else $action cp -pf $selinux "${real_file}" "${real_file}.${OLD_SUFFIX}" fi fi if [ -e "${real_file}" ]; then # Do not change the permissions and attributes of the destination $action cp -f $selinux "$new_file" "${real_file}" else # No destination file exists $action cp -pf $selinux "$new_file" "${real_file}" fi replace_md5sum } ###################################################################### ######## ######### ######## Command line args ######### ######## ######### ###################################################################### # # Long term variables # docmd='YES' # action='withecho' action= selinux='' DEBUG=0 VERBOSE='' statedir='/var/lib/ucf' THREEWAY= DIST_SUFFIX="ucf-dist" NEW_SUFFIX="ucf-new" OLD_SUFFIX="ucf-old" ERR_SUFFIX="merge-error" handle_file_args() { if [ "$PURGE" = "YES" ]; then if [ $# -ne 1 ]; then echo >&2 "*** ERROR: Need exactly one file argument when purging, got $#" echo >&2 "" usageversion exit 2 fi temp_dest_file="$1" if [ -e "$temp_dest_file" ]; then dest_file=$(vset "$(readlink -q -m "$temp_dest_file")" "The Destination file") else dest_file=$(vset "$temp_dest_file" "The Destination file") fi else if [ $# -ne 2 ]; then echo >&2 "*** ERROR: Need exactly two file arguments, got $#" echo >&2 "" usageversion exit 2 fi temp_new_file="$1" temp_dest_file="$2" if [ ! -e "${temp_new_file}" ]; then echo >&2 "Error: The new file ${temp_new_file} does not exist!" exit 1 fi new_file=$(vset "$(readlink -q -m "$temp_new_file")" "The new file") if [ -e "$temp_dest_file" ]; then dest_file=$(vset "$(readlink -q -m "$temp_dest_file")" "The Destination file") else dest_file=$(vset "$temp_dest_file" "The Destination file") fi fi } handle_opts() { # Arguments are from getopt(1) in quoted mode. eval set -- "$*" while [ $# -gt 0 ] ; do case "$1" in -h|--help) usageversion; exit 0 ;; -n|--no-action) action='echo'; docmd='NO'; shift ;; -v|--verbose) VERBOSE=1; shift ;; -P|--package) opt_package="$2"; shift 2 ;; -s|--src-dir) opt_source_dir="$2"; shift 2 ;; --sum-file) opt_old_mdsum_file="$2"; shift 2 ;; --state-dir) opt_state_dir="$2"; shift 2 ;; --debconf-template) override_template="$2"; shift 2 ;; -D|-d|--debug|--DEBUG) # d has an optional argument. As we are in quoted mode, # an empty parameter will be generated if its optional # argument is not found. case "$2" in "") DEBUG=$(vset 1 "The Debug value"); shift 2 ;; *) DEBUG=$(vset "$2" "The Debug value"); shift 2 ;; esac ;; -p|--purge) PURGE=YES; shift ;; --three-way) THREEWAY=YES; shift ;; --debconf-ok) DEBCONF_OK=YES; shift ;; -Z) selinux='-Z'; shift ;; --) shift ; handle_file_args "$@"; return ;; *) echo >&2 "Internal error!" ; exit 1 ;; esac done } # A separate assignment is essential to ensure getopt(1) error status isn't # lost. UCF_OPTS="$(getopt -a -o hs:d::D::npP:Zv -n "$progname" \ --long help,src-dir:,sum-file:,dest-dir:,debug::,DEBUG::,no-action,package:,purge,verbose,three-way,debconf-ok,debconf-template:,state-dir: \ -- "$@")" handle_opts "$UCF_OPTS" ###################################################################### ######## ######### ######## Sanity checking ######### ######## ######### ###################################################################### # Need to run as root, or else the if test "$(id -u)" != 0; then if [ "$docmd" = "YES" ]; then echo "$progname: Need to be run as root." >&2 echo "$progname: Setting up no action mode." >&2 action='echo'; docmd='NO' fi fi # Follow dpkg-divert as though we are installed as part of $opt_package divert_line=$(dpkg-divert --listpackage "$dest_file") if [ -n "$divert_line" ]; then # name of the package or 'LOCAL' for a local diversion divert_package="$divert_line" if [ "$divert_package" != "$opt_package" ]; then dest_file=$(dpkg-divert --truename "$dest_file") fi fi dest_file_bre="[[:space:]]$(escape_bre "$dest_file")"'$' ###################################################################### ######## ######### ######## Set Default Values ######### ######## ######### ###################################################################### # Load site defaults and overrides. if [ -f /etc/ucf.conf ]; then . /etc/ucf.conf fi # Command line, env variable, config file, or default if [ "$opt_source_dir" ]; then source_dir=$(vset "$opt_source_dir" "The Source directory") elif [ "$UCF_SOURCE_DIR" ]; then source_dir=$(vset "$UCF_SOURCE_DIR" "The Source directory") elif [ "$conf_source_dir" ]; then source_dir=$(vset "$conf_source_dir" "The Source directory") else if [ "$new_file" ]; then source_dir=$(vset "$(dirname "$new_file")" "The Source directory") else source_dir=$(vset "/tmp" "The Source directory") fi fi if [ "$PAGER" ] && which "$PAGER" >/dev/null 2>&1 ; then my_pager="$(which "$PAGER")" elif [ -s /usr/bin/pager ] && [ "$(readlink -e /usr/bin/pager || :)" ]; then my_pager=/usr/bin/pager elif [ -x /usr/bin/sensible-pager ]; then my_pager=/usr/bin/sensible-pager elif [ -x /bin/more ]; then my_pager=/bin/more else my_pager= fi # Command line, env variable, config file, or default if [ "$opt_state_dir" ]; then statedir=$(vset "$opt_state_dir" "The State directory") elif [ "$UCF_STATE_DIR" ]; then statedir=$(vset "$UCF_STATE_DIR" "The State directory") elif [ "$conf_state_dir" ]; then statedir=$(vset "$conf_state_dir" "The State directory") else statedir=$(vset '/var/lib/ucf' "The State directory") fi # Handle conffold and conffnew together. See #980996 # Default force_conff= # Config file if [ "$conf_force_conffold" ]; then if [ "$conf_force_conffnew" ]; then echo >&2 "Error: Only one of conf_force_conffold and conf_force_conffnew should" echo >&2 " be set in the config file" exit 1 fi force_conff=$(vset "old" "Force keep file") elif [ "$conf_force_conffnew" ]; then force_conff=$(vset "new" "Force keep file") fi # Environment if [ "$UCF_FORCE_CONFFOLD" ]; then if [ "$UCF_FORCE_CONFFNEW" ]; then echo >&2 "Error: Only one of UCF_FORCE_CONFFOLD and UCF_FORCE_CONFFNEW should" echo >&2 " be set in the environment" exit 1 fi force_conff=$(vset "old" "Force keep file") elif [ "$UCF_FORCE_CONFFNEW" ]; then force_conff=$(vset "new" "Force keep file") fi # Env variable, config file, or default if [ "$UCF_FORCE_CONFFMISS" ]; then force_conffmiss=$(vset "$UCF_FORCE_CONFFMISS" "Replace any missing files") elif [ "$conf_force_conffmiss" ]; then force_conffmiss=$(vset "$conf_force_conffmiss" "Replace any missing files") else force_conffmiss='' fi # DPKG_FORCE overrides all others: see #925375. IFS=, for f in $DPKG_FORCE ; do case $f in confmiss) force_conffmiss=$(vset 1 "DPKG_FORCE replace missing files") ;; confold) force_conff=$(vset "old" "DPKG_FORCE keep file") ;; confnew) force_conff=$(vset "new" "DPKG_FORCE keep file") ;; # The following override other settings, so break out of loop. confdef) unset force_conff [ "$VERBOSE" ] && echo >&2 "DPKG_FORCE keep file default" break ;; confask) force_conff=$(vset "ask" "DPKG_FORCE keep file"); break ;; esac done unset IFS if [ -n "$opt_old_mdsum_file" ]; then old_mdsum_file=$(vset "$opt_old_mdsum_file" "The md5sum is found here") elif [ "$UCF_OLD_MDSUM_FILE" ]; then old_mdsum_file=$(vset "$UCF_OLD_MDSUM_FILE" "The md5sum is found here") elif [ "$conf_old_mdsum_file" ]; then old_mdsum_file=$(vset "$conf_old_mdsum_file" "Replace the old file") elif [ "${new_file}" ]; then old_mdsum_file="$source_dir/$(basename "${new_file}").md5sum" else old_mdsum_file="" fi ###################################################################### ######## ######### ######## More Sanity checking ######### ######## ######### ###################################################################### # VERBOSE of 0 is supposed to be the same as not setting VERBOSE if [ "$VERBOSE" = "0" ]; then VERBOSE='' fi if [ -e "$statedir/hashfile" ] && [ ! -w "$statedir/hashfile" ]; then echo >&2 "ucf: do not have write privilege to the state data" if [ "$docmd" = "YES" ]; then exit 1 fi fi if [ ! -d "$statedir/cache" ]; then $action mkdir -p "$statedir/cache" fi # test and see if this file exists in the database if [ -e "$statedir/hashfile" ]; then if [ "$VERBOSE" ]; then echo >&2 "The hash file exists" echo >&2 "grep ${dest_file_bre} $statedir/hashfile" grep "${dest_file_bre}" "$statedir/hashfile" >&2 || true fi lastsum=$(grep "${dest_file_bre}" "$statedir/hashfile" | \ awk '{print $1;}' ) fi if [ "${new_file}" ]; then old_mdsum_dir="$source_dir/$(basename "${new_file}").md5sum.d" else old_mdsum_dir="" fi cached_file="$(echo "$dest_file" | tr / :)" ###################################################################### ######## ######### ######## Debugging dump ######### ######## ######### ###################################################################### if [ "$DEBUG" -gt 0 ]; then cat >&2 <&2 "Preparing to purge ${dest_file}" purge_md5sum exit 0 fi ###################################################################### ######## ######### ######## DebConf stuff ######### ######## ######### ###################################################################### # Is debconf already running? Kinda tricky, because it will be after the # confmodule is sourced, so only test before that. if [ -z "$DEBCONF_ALREADY_RUNNING" ]; then if [ "$DEBIAN_HAS_FRONTEND" ]; then DEBCONF_ALREADY_RUNNING='YES' else DEBCONF_ALREADY_RUNNING='NO' fi fi export DEBCONF_ALREADY_RUNNING if [ -z "$DEBCONF_OK" ]; then if [ "$DEBCONF_ALREADY_RUNNING" = 'YES' ]; then DEBCONF_OK='NO' else DEBCONF_OK='YES' fi fi # Time to start nagging the users who call ucf without debconf-ok if [ "$DEBCONF_ALREADY_RUNNING" = 'YES' ] && [ "$DEBCONF_OK" = NO ]; then # Commented out for now, uncomment after a while to begin nagging # maintainers to fix their scripts. cat \ <&2 "$progname: Not loading confmodule, since we are not running as root." fi # Only set the title if debconf was not already running. # If it was running, then we do not want to clobber the # title used for configuring the whole package with debconf. if [ "$DEBCONF_ALREADY_RUNNING" = 'NO' ]; then if ! db_settitle ucf/title 2>/dev/null; then # Older debconf that does not support that command. if test "$(id -u)" = 0; then db_title "Modified configuration file" else echo >&2 "$progname: Not changing title, since we are not running as root." fi fi fi fi ###################################################################### ######## ######### ######## Start Processing ######### ######## ######### ###################################################################### orig_new_file="$new_file" # Since sometimes we replace the newfile below newsum=$(md5sum "$new_file" | awk '{print $1}') ###################################################################### ######## ######### ######## Do the replacement ######### ######## ######### ###################################################################### # Step 1: If we have no record of this file, and dest file # does, We need to determine how to initialize the # ${old_mdsum_prefix}.old file.. if [ -e "$dest_file" ]; then destsum=$(md5sum "$dest_file" | awk '{print $1}') if [ ! "$lastsum" ]; then # a: If we have a directory containing historical md5sums of this # file in question, we should look and see if the currently # installed file matches any of the old md5sums; in which case # it can be silently replaced. if [ -d "$old_mdsum_dir" ] || [ -f "$old_mdsum_file" ]; then if [ -d "$old_mdsum_dir" ]; then for file in "${old_mdsum_dir}/"*; do oldsum="$(awk '{print $1}' "$file")" if [ "$oldsum" = "$destsum" ]; then if [ "$force_conff" != "old" ]; then # Bingo! replace, set the md5sum, and we are done [ "$VERBOSE" ] && echo >&2 \ "Replacing config file $dest_file with new version" replace_conf_file exit 0 else replace_md5sum cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}" exit 0 fi fi done elif [ -f "$old_mdsum_file" ]; then oldsum=$(grep -E "^${destsum}" "$old_mdsum_file" || true) if [ "$oldsum" ]; then # Bingo if [ "$force_conff" != old ]; then [ "$VERBOSE" ] && echo >&2 \ "Replacing config file $dest_file with new version" replace_conf_file exit 0 else replace_md5sum cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}" exit 0 fi fi fi # Well, nothing matched. We now check to see if the # maintainer has an opinion on how to set the ``md5sum of the # previously installed version'', since we have no way of # determining that automatically. Please note that unless # there are limited number of previously released packages # (like just one), the maintainer is also making a guess at # this point by supplying a historical md5sum default file. [ "$VERBOSE" ] && echo >&2 "Historical md5sums did not match." if [ -d "$old_mdsum_dir" ]; then if [ -e "${old_mdsum_dir}/default" ]; then [ "$VERBOSE" ] && echo >&2 "However, a default entry exists, using it." lastsum="$(awk '{print $1;}' "${old_mdsum_dir}"/default)" do_replace_md5sum=1 fi elif [ -f "$old_mdsum_file" ]; then oldsum=$(grep -E "[[:space:]]default$" "$old_mdsum_file" | \ awk '{print $1;}') if [ "$oldsum" ]; then # Bingo lastsum=$oldsum do_replace_md5sum=1 fi fi fi # At this point, we are almost certain that either the # historical record of md5sums is not complete, or the user has # changed the configuration file. Rather than guessing and # chosing one of the historical md5sums, we fall through to the # solution used if there had been no historical md5sums # directory/file. if [ ! "$lastsum" ]; then # b: We do not have a historical list of md5sums, or none # matched, and we still need to initialize the # ${old_mdsum_prefix}.old file. We can't determine whther or # not they made any changes, so we err on the side of caution # and ask. [ "$VERBOSE" ] && echo >&2 "No match found, we shall ask." lastsum='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' fi # the old md5sum file does not exist, and the historical # record failed fi # the old md5sum file does not exist (bug)) else # "$dest_file" does not exist # Step 2: If destfile does not exist, create it, set the file # "${old_mdsum_prefix}.old" to the md5sum of the new file, and we # are done if [ ! "$lastsum" ]; then # Ok, so there is no indication that the package was ever # installed on this machine. echo >&2 "Creating config file $dest_file with new version" replace_conf_file exit 0 elif [ "$lastsum" = "$newsum" ]; then # OK, new version of the file is the same as the last version # we saw. Since the user apparently has deleted the file, # nothing needs be done, unless we have been told differently if [ "$force_conffmiss" ]; then echo >&2 "Recreating deleted config file $dest_file with new version, as asked" replace_conf_file exit 0 else echo >&2 "Not replacing deleted config file $dest_file" fi else # OK. New upstream version. if [ "$force_conffmiss" ]; then # User has said to replace missing files, so we do so, no # questions asked. echo >&2 "Recreating deleted config file $dest_file with new version, as asked" replace_conf_file exit 0 else # Even though the user has deleted this file, they should # be asked now, unless specified otherwise. if [ "$force_conff" != "old" ]; then destsum='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' else exit 0 fi fi fi fi # Here, the destfile exists. # step 3: If the old md5sum and the md5sum of the new file # do not match, we need to take action. if [ "$lastsum" = "$newsum" ]; then if [ "$force_conff" = 'ask' ]; then [ "$VERBOSE" ] && echo >&2 "Forced to ask even though md5sums match." destsum='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' else [ "$VERBOSE" ] && echo >&2 "md5sums match, nothing needs be done." if [ "$do_replace_md5sum" ]; then replace_md5sum fi exit 0; # Hah. Match. We are done. fi fi # a: If the md5sum of the dest file is the same as lastsum, replace the # destfile, saying we are replacing old config files if [ "$destsum" = "$lastsum" ]; then if [ "$force_conff" != old ]; then echo >&2 "Replacing config file $dest_file with new version" replace_conf_file exit 0 else replace_md5sum cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}" exit 0 fi else # b: If the md5sum of the dest file differs from lastsum, we need to ask # the user what action to take. if [ "$force_conff" = "new" ]; then echo >&2 "Replacing config file $dest_file with new version" echo >&2 "since you asked for it." if [ "$destsum" = "$newsum" ]; then echo >&2 "The new and the old files are identical, AFAICS" else echo >&2 "The new and the old files are different" fi replace_conf_file exit 0 fi if [ "$force_conff" = "old" ]; then replace_md5sum cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}" exit 0 fi # c: If the destination file is the same as the new maintianer provided one, # we need do nothing. if [ "$newsum" = "$destsum" ]; then [ "$VERBOSE" ] && echo >&2 "md5sums of the file in place matches, nothing needs be done." replace_md5sum exit 0; # Hah. Match. We are done. fi done='NO' while [ "$done" = "NO" ]; do if [ "$DEBCONF_OK" = "YES" ] && [ "$DEBIAN_HAS_FRONTEND" ]; then # Use debconf to prompt. if [ -e "$statedir/cache/$cached_file" ] && [ "$THREEWAY" ]; then templ=ucf/changeprompt_threeway else templ=ucf/changeprompt fi if [ "$override_template" ]; then choices="$(db_metaget $templ Choices-C)" choices2="$(db_metaget "$override_template" Choices-C)" if [ "$choices" = "$choices2" ]; then templ=$override_template fi fi db_fset "$templ" seen false db_reset "$templ" db_subst "$templ" FILE "$dest_file" db_subst "$templ" NEW "$new_file" db_subst "$templ" BASENAME "$(basename "$dest_file")" db_input critical "$templ" || true if ! db_go; then # The current ucf interface does not provide a way for it # to tell its caller that the user chose to back up. # However, we could get here, if the caller turned on # debconf's backup capb. The best thing to do seems to be # to ignore requests to back up. continue fi db_get "$templ" ANSWER="$RET" else echo >&2 "Need debconf to interact" exit 2 fi case "$ANSWER" in install_new|y|Y|I|i) echo >&2 "Replacing config file $dest_file with new version" RETAIN_OLD=YES replace_conf_file; exit 0; ;; diff|D|d) DIFF="$(run_diff diff -uBbwt "$dest_file" "$new_file")" show_diff "$DIFF" ;; sdiff|S|s) DIFF="$(run_diff sdiff -BbWt "$dest_file" "$new_file")" show_diff "$DIFF" ;; diff_threeway|3|t|T) if [ -e "$statedir/cache/$cached_file" ] && \ [ "$THREEWAY" ]; then if [ -e "$dest_file" ]; then DIFF="$(diff3 -L Current -L Older -L New -A \ "$dest_file" "$statedir/cache/$cached_file" \ "$new_file")" || true else DIFF="$(diff3 -L Current -L Older -L New -A \ /dev/null "$statedir/cache/$cached_file" \ "$new_file")" || true fi show_diff "$DIFF" else DIFF="$(run_diff diff -uBbwt "$dest_file" "$new_file")" show_diff "$DIFF" fi ;; merge_threeway|M|m) echo >&2 "Merging changes into the new version" if [ -e "$statedir/cache/$cached_file" ] && \ [ "$THREEWAY" ]; then ret=0 diff3 -L Current -L Older -L New -m \ "$dest_file" "$statedir/cache/$cached_file" \ "$new_file" > "$dest_file.${NEW_SUFFIX}" || ret=$? case "$ret" in 0) new_file="$dest_file.${NEW_SUFFIX}" RETAIN_OLD=YES replace_conf_file rm -f "$dest_file.${NEW_SUFFIX}" # don't need this around no mo' exit 0 ;; *) mv "$dest_file.${NEW_SUFFIX}" "$dest_file.${ERR_SUFFIX}" db_subst ucf/conflicts_found dest_file "$dest_file" db_subst ucf/conflicts_found ERR_SUFFIX "${ERR_SUFFIX}" db_input critical ucf/conflicts_found || true db_go || true ;; esac else replace_conf_file rm -f "$dest_file.${NEW_SUFFIX}" # don't need this around no mo' exit 0 fi ;; shell|Z|z) # We explicitly connect STDIN and STDOUT to the # script's controlling terminal, so even if STDIN is # fed by a pipe, as is the case when run from # /usr/bin/debconf, the shell should be fully # functional. However, the test for a controlling # terminal uses /usr/bin/tty, which consults only # STDIN. As far as I can tell, when run from debconf, # ucf will _never_ use the current terminal. If the # goal is to check for access to a terminal, the test # should be for foreground process group membership, # not a terminal connected to STDIN (tty -s), and not # a terminal it doesn't necessarily own (tty -s # /dev/tty &2 "No terminal, and no DISPLAY set, can't fork shell." sleep 3 fi ;; keep_current|n|N|o|O|'') replace_md5sum cp -pf "$orig_new_file" "$dest_file.${DIST_SUFFIX}" exit 0 ;; *) if [ "$DEBCONF_OK" = "YES" ]; then echo "Error: unknown response from debconf:'$RET'" >&2 exit 1 else echo echo "Please answer with one of the single letters listed." >&2 echo fi esac done fi db_stop exit 0