home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
rescue
/
sbin
/
modify_resolvconf
< prev
next >
Wrap
Text File
|
2006-11-29
|
26KB
|
816 lines
#!/bin/bash
#
# Copyright (c) 2001-2005 SuSE Linux Products GmbH, Nuernberg, Germany.
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
#
# Author: Christian Zoz <zoz@suse.de>
#
# $Id: modify_resolvconf 1405 2006-02-13 15:08:56Z zoz $
#
if ! touch /tmp &>/dev/null; then
echo "Filesystem read only: Cannot modify anything" >&2
exit 1
fi
RESOLVCONF=/etc/resolv.conf
NAMEDCONF=/etc/named.d/forwarders.conf
PROGNAME=${0##*/}
RETVAL=0
if [ -x /usr/bin/fmt ] ; then
FMT="/usr/bin/fmt -u -w 64"
else
FMT="cat"
fi
usage () {
cat << EOT >&2
usage: $PROGNAME <action> <options>
action: modify, restore, cleanup or check
options: mandatory for:
-s|--service <service> modify, restore
-e|--extension <string>
-p|--process <process> modify
-i|--pid <pid>
-f|--script <pathname of script> modify
-t|--text <text> modify
-l|--searchlist <list of domains>
-d|--domain <domain>
-n|--nameservers <addresses>
-o|--save_now <pathname of file>
-a|--save_later <pathname of file>
-k|--keep
--resolv
--named
--no_restart
-q|--quiet
-v|--verbose
-h|--help (does not need an action)
cleanup and check ignore all options except -q and -v
EOT
if [ -n "$1" ] ; then
echo >&2
ERROR=" ERROR: "
echo -e "$*\n" | while read line; do
echo "${ERROR}${line}" >&2
ERROR=" "
done
fi
exit 1
}
debug () {
test "$VERBOSE" = "yes" || return
echo -e "debug: $*" >&2
}
warn () {
test "$QUIET" = "yes" && return
echo -e "$*" >&2
}
log () {
logger -t "$PROGNAME" "$*"
debug "$*"
if [ "$ACTION" = "cleanup" -a "$QUIET" != "yes" ] ; then
echo -e "$*" >&2
fi
}
write_meta () {
# At first we prepend a default text to TEXT
TEXT="This is a temporary ${FILENAME##*/} created by service $SERVICE.\
The previous file has been saved and will be restored later.\n\n\
If you don't like your ${FILENAME##*/} to be changed, you\
can set MODIFY_{RESOLV,NAMED}_CONF_DYNAMICALLY=no. This variables\
are placed in /etc/sysconfig/network/config.\n\n\
You can also configure service $SERVICE not to modify it.\n\n\
$TEXT"
cat << EOT > $FILENAME
### BEGIN INFO
#
# Modified_by: $SERVICE
# Backup: $BACKUP
# Process: $PROC
# Process_id: $PID
# Script: $SCRIPT
# Saveto: $SAVELATER
EOT
infoline="# Info: "
echo -e "$TEXT" |
$FMT |
while read line ; do
echo "$infoline$line";
infoline="# "
done >> $FILENAME
cat << EOT >> $FILENAME
#
### END INFO
EOT
}
read_resolvconf () {
OLDDNS="`sed -n '/^[[:space:]]*nameserver[[:space:]]*/s///p' $TMP_DATA`"
}
write_resolvconf () {
# Only one of $DOMAIN and $SEARCH does contain something
if [ -n "$DOMAIN" ] ; then
mv $TMP_DATA $TMP_FILE
sed -e "/^[[:space:]]*\(domain\|search\)[[:space:]]/d" \
$TMP_FILE > $TMP_DATA
echo "domain $DOMAIN" >> $TMP_DATA
fi
if [ -n "$SEARCH" ] ; then
mv $TMP_DATA $TMP_FILE
sed -e "/^[[:space:]]*\(domain\|search\)[[:space:]]/d" \
$TMP_FILE > $TMP_DATA
echo "search $SEARCH" >> $TMP_DATA
fi
if [ -n "$DNS" ] ; then
mv $TMP_DATA $TMP_FILE
sed "/^[[:space:]]*nameserver[[:space:]]/d" $TMP_FILE > $TMP_DATA
for a in $MODIFY_RESOLV_CONF_STATIC_DNS $DNS; do
echo "nameserver $a" >> $TMP_DATA
done
fi
}
read_namedconf () {
# At first normalize the forwarders entry, i.e. remove all comments and
# linebreaks from it.
mv $TMP_DATA $TMP_FILE
sed -e '/^[[:space:]]*forwarders/{
h
:a
s-/\*.*\*/--g
s-#.*$--
s-//.*$--
s-[[:space:]\n]\+- -g
/} *; *$/bb
N
ba
:b
x
s-for.*$--
G
s-\n --
s- ;-;-g
} ' $TMP_FILE > $TMP_DATA
# Then get the old Nameservers
OLDDNS=`sed -n -e '/^[[:space:]]*forwarders/{
s-[^0-9. ]*--g
p
} ' $TMP_DATA | tr -d '\n'`
}
write_namedconf () {
# Put together a list of nameservers from the new servers and then the
# old one, but stop after the third
FORWDS=""
declare -i n=0
local a i
for a in $DNS; do # $OLDDNS
# named will fail if there are duplicate forwarders (bug 28459)
for i in $FORWDS ; do
if [ "$a;" == "$i" ] ; then
continue 2
fi
done
FORWDS="$FORWDS $a;"
n=$((n+1))
test $n = 3 && break
done
# replace the nameservers in the normalized file
mv $TMP_DATA $TMP_FILE
# Check whether there is an active "forwarders" directive
grep "^[[:space:]]*forwarders" $TMP_FILE >/dev/null
if [ $? == 0 ] ; then
# Yes, replace that directive's argument
sed -e "/^[[:space:]]*forwarders/{
s-\(^.*forwarders\).*\$-\1 {$FORWDS };-
} " $TMP_FILE > $TMP_DATA
else
# Check whether the default comment for the "forwarders" directive is present
grep "^[[:space:]]*# your provider's name server." $TMP_FILE >/dev/null
if [ $? == 0 ] ; then
# Yes, put the comment right after that comment
sed -e "/^[[:space:]]*# your provider's name server./a\ forwarders {$FORWDS };" $TMP_FILE > $TMP_DATA
else
# No, so just put the option right after the "options {" block opening
sed -e "/^options {/a\ forwarders {$FORWDS };" $TMP_FILE > $TMP_DATA
fi
fi
}
write_file () {
read_file
write_meta
case "$FILENAME" in
*resolv*) write_resolvconf; ;;
*named*) write_namedconf; ;;
esac
cat $TMP_DATA >> $FILENAME
chmod 644 $FILENAME
}
read_file () {
sed "/### BEGIN INFO/,/### END INFO/d" $FILENAME > $TMP_DATA
case "$FILENAME" in
*resolv*) read_resolvconf; ;;
*named*) read_namedconf; ;;
esac
}
notify_services () {
test "$NO_RESTART" = "yes" && return
case "$FILENAME" in
*resolv*)
if [ -d /var/spool/postfix/etc/ ] ; then
cp $RESOLVCONF /var/spool/postfix/etc/
fi
if [ -x /etc/init.d/lwresd ] ; then
warn "`/etc/init.d/lwresd reload`"
fi
;;
*named*)
warn "`/etc/init.d/named reload`"
;;
esac
}
remove_tmp_files () {
rm $TMP_DATA $TMP_FILE 2>/dev/null
}
trap remove_tmp_files EXIT SIGINT SIGSEGV SIGQUIT SIGTERM
TMP_DATA=`mktemp /tmp/${PROGNAME}.XXXXXX`
TMP_FILE=`mktemp /tmp/${PROGNAME}.XXXXXX`
###########################################################
# Parse commandline
###########################################################
# Now set the parsed args but save the original commandline for recursive calls
COMMANDLINE="$@"
ACTION=""
VARIABLE=""
while true ; do
case "$1" in
-s|--service) VARIABLE=SERVICE;;
-e|--extension) VARIABLE=EXT;;
-p|--process) VARIABLE=PROC;;
-i|--pid) VARIABLE=PID;;
-f|--script) VARIABLE=SCRIPT;;
-t|--text) VARIABLE=TEXT;;
-l|--searchlist) VARIABLE=SEARCH;;
-d|--domain) VARIABLE=DOMAIN;;
-n|--nameservers) VARIABLE=DNS;;
-q|--quiet) QUIET=yes;;
-v|--verbose) VERBOSE=yes;;
-h|--help) usage;;
-o|--save_now) VARIABLE=SAVENOW;;
-a|--save_later) VARIABLE=SAVELATER;;
-k|--keep) KEEP=yes;;
--resolv) FILENAME=$RESOLVCONF;;
--named) FILENAME=$NAMEDCONF;;
--no_restart) NO_RESTART=yes;;
"") break ;;
--)
shift
test -n "$ACTION" -o $# -gt 1 \
&& usage "Exactly one action may be given.\n"\
"Currently given actions: $ACTION $*"
ACTION="$1"
shift
break
;;
-*) usage Unknown option $1;;
*)
test -n "$ACTION" && usage "Exactly one action may be given.\n"\
"Currently given actions: $ACTION $1"
ACTION="$1"
;;
esac
if [ -n "$VARIABLE" ] ; then
test -z "$2" && usage Option $1 needs an argument
eval $VARIABLE=\$2
shift
VARIABLE=""
fi
shift
done
test -z "$ACTION" && usage No action was given
###########################################################
# Check if the arguments to the options are usefull
###########################################################
case $ACTION in
modify)
#z# case "$SERVICE" in
#z# dhclient|dhcpcd|pppd|ipppd|pcmcia|hotplug) ;;
#z# *) usage "service must be one of dhclient dhcpcd" \
#z# " pppd ipppd pcmcia hotplug";;
#z# esac
test -z "$SERVICE" && usage "a vaild service must be set with --service"
if [ "$SERVICE" != "hotplug" ] ; then
if [ -z "$PROC" ] ; then
usage "a running process/daemon must be set with --process"
else
PROCPID=`/sbin/pidofproc $PROC 2>/dev/null`
if [ -z "$PROCPID" ] ; then
usage "$PROC is not running currently, this may not happen"
else
debug "pid of prodess $PROC is $PROCPID"
fi
fi
fi
if [ -z "$PID" ] ; then
PID="$PROCPID"
# usage "you must set the pid of $PROC with --pid"
else
PIDPROC=`ps h $PID 2>/dev/null |(read a b c d e f; echo $e)`
if [ -z "$PIDPROC" ] ; then
warn "there is no process with id $PID"
else
debug "process with pid $PID is $PIDPROC"
fi
fi
# if [ -z "$SCRIPT" ] ; then
# usage "you must set the script that modifies $FILENAME with --script"
# else
if [ -n "$SCRIPT" ] ; then
if [ -e "$SCRIPT" ] ; then
debug "script $SCRIPT found"
else
usage "there is no script named $SCRIPT"
fi
fi
if [ -z "$TEXT" ] ; then
usage "You have to provide an descriptive text with --text\n" \
"With --text=- you can use a here document"
else
# If TEXT="-" read it as here document
if [ "$TEXT" = "-" ] ; then
TEXT=""
while read a; do
test -z "$a" && a="\n\n"
TEXT="$TEXT $a"
done
fi
fi
if [ -n "$DOMAIN" -a -n "$SEARCH" ] ; then
usage "only one of --domain and --searchlist may be used\n" \
"in resolv.conf search and domain are mutually exclusiv"
fi
FILENAME=""
;;
restore)
#z# case "$SERVICE" in
#z# dhclient|dhcpcd|pppd|ipppd|pcmcia|hotplug) ;;
#z# *) usage "service must be one of dhclient dhcpcd" \
#z# " pppd ipppd pcmcia hotplug";;
#z# esac
test -z "$SERVICE" && usage "a vaild service must be set with --service"
;;
cleanup)
if [ -z "$FILENAME" ] ; then
$0 $COMMANDLINE --resolv
$0 $COMMANDLINE --named
exit
fi
;;
check)
# ignore all options
if [ -z "$FILENAME" ] ; then
FILENAME=$RESOLVCONF
fi
KEEP=""
SAVENOW=""
;;
*) usage "$ACTION is not a valid action" ;;
esac
###########################################################
# respect variables in config and choose right filenames
###########################################################
debug "pre-config: FILENAME=$FILENAME"
eval `grep "^[[:space:]]*\(\
MODIFY_RESOLV_CONF_DYNAMICALLY\|\
MODIFY_NAMED_CONF_DYNAMICALLY\|\
MODIFY_RESOLV_CONF_STATIC_DNS\
\)=" /etc/sysconfig/network/config 2>/dev/null`
if [ "$MODIFY_NAMED_CONF_DYNAMICALLY" = "yes" ] ; then
test -z "$FILENAME" && FILENAME=$NAMEDCONF
fi
if [ "$MODIFY_RESOLV_CONF_DYNAMICALLY" = "yes" ] ; then
test -z "$FILENAME" && FILENAME=$RESOLVCONF
fi
debug "post-config: FILENAME=$FILENAME"
case "$FILENAME" in
"")
log "Service $SERVICE tried to modify resolver configuration, but it"
log "was not modified due to MODIFY_RESOLV\NAMED_CONF_DYNAMICALLY=no"
exit
;;
$NAMEDCONF)
if ! [ -r "$FILENAME" -a -x /etc/init.d/named ] ; then
if [ "$ACTION" = "cleanup" ] ; then
exit 0
else
log "Service $SERVICE tried to modify $FILENAME, but named seems" \
"not to be installed"
log "Check your settings of MODIFY_RESOLV\NAMED_CONF_DYNAMICALLY"
exit 1
fi
fi
;;
$RESOLVCONF)
if ! [ -r "$FILENAME" ] ; then
touch $FILENAME
chmod 644 $FILENAME
fi
;;
esac
BACKUP="${FILENAME}.saved.by.$SERVICE"
test -n "$EXT" && BACKUP="${BACKUP}.${EXT}"
###########################################################
# Read current resolv.conf
###########################################################
read_meta () {
if [ -e $FILENAME ] ; then
RC_BLOCK=`sed -n "/### BEGIN INFO/,/### END INFO/s/^[[:space:]#]*//p" \
$FILENAME`
if [ -n "$RC_BLOCK" ] ; then
while read NAME TOKEN; do
# Note the quotes around RC_BLOCK. Without it we get all in one line.
eval $NAME='`echo "$RC_BLOCK" | sed -n "/^$TOKEN:[[:space:]]*/s///p"`'
debug "$NAME=${!NAME}"
done << " EOL"
RC_SERVICE Modified_by
RC_BACKUP Backup
RC_PROC Process
RC_PID Process_id
RC_SCRIPT Script
RC_SAVELATER Saveto
EOL
# Here we want all in one line so we do not quote RC_BLOCK, but we lose
# all formatting of the text (to be enhanced).
RC_TEXT=`echo $RC_BLOCK | sed -e "s/^.*Info:[[:space:]]*//" \
-e "s/ END INFO.*$//"`
debug "RC_TEXT=${RC_TEXT:0:20} ..."
fi
fi
}
read_meta
###########################################################
# Divide all available backups
###########################################################
# . /sbin/modify_cf.lib
# Check all existing backups and divide them into valid direct, valid indirect
# and invalid backups.
# "all existing backups" = all files /etc/resolv.conf.saved.by.* and all
# files found in the backup field of another
# valid backup
# "valid direct" = file which the backup entry in resolv.conf points to
# "valid indirect" = file which the backup entry of another valid backup
# points to
# "invalid" = files /etc/resolv.conf.saved.by.* which are not valid
# All valid backups build a stack of files. These files are stored in three
# variables:
# DIRECT_BACKUP: Contains the only valid direct backup.
# INDIRECT_BACKUPS: Contains all indirect backups except the last of the stack.
# Files are ordered like the stack. The first is the backup
# of the valid direct backup.
# LAST_BACKUP: Contains the last file of the stack of valid indirect backups.
# This file does not contain an info block or has an invalid
# entry in its backup field.
# INVALID_BACKUPS: Contains all invalid backups sorted in chronological
# order, the newest first. This files are only used if there is no valid
# backup, but resolv.conf was modified dynamically.
read_field_backup () {
ls "$*" &>/dev/null || return
BAFI=`\
sed -n \
"/### BEGIN INFO/,/### END INFO/s/^[[:space:]#]*Backup:[[:space:]]*//p" \
"$*"`
ls "$BAFI" 2>/dev/null
}
# get all backups in chronoligical order, the newest first
for bp in `ls -t ${FILENAME}.saved.by* \
$(read_field_backup ${FILENAME}*) 2>/dev/null`; do
for abp in $ALL_BACKUPS; do
test "$bp" = "$abp" && continue 2
done
ALL_BACKUPS="$ALL_BACKUPS $bp"
done
test -r "$RC_BACKUP" && DIRECT_BACKUP="$RC_BACKUP"
debug "(0) DIRECT_BACKUP: $DIRECT_BACKUP"
debug "(0) ALL_BACKUPS: $ALL_BACKUPS"
if [ -n "$ALL_BACKUPS" ] ; then
# At first put all except DIRECT_BACKUP from ALL_BACKUPS to INVALID_BACKUPS
INVALID_BACKUPS=`\
for a in $ALL_BACKUPS; do
test "$a" != "$DIRECT_BACKUP" && echo "$a"
done`
# Then we are going to build a chain of backups and delete the chain elements
# from INVALID_BACKUPS.
NEXT_BACKUP=`read_field_backup "$DIRECT_BACKUP"`
while [ -r "$NEXT_BACKUP" ] ; do
debug "(searching stack) NEXT_BACKUP=$NEXT_BACKUP"
# At first delete NEXT_BACKUP from INVALID_BACKUPS
INVALID_BACKUPS=`\
for a in $INVALID_BACKUPS; do
test "$a" != "$NEXT_BACKUP" && echo "$a"
done`
# INDIRECT_BACKUPS contains all elements except the last ...
INDIRECT_BACKUPS="$INDIRECT_BACKUPS $LAST_BACKUP"
# ... which is always in LAST_BACKUP
LAST_BACKUP="$NEXT_BACKUP"
NEXT_BACKUP=`read_field_backup "$NEXT_BACKUP"`
# Detect a loop
for a in $DIRECT_BACKUP $INDIRECT_BACKUPS $LAST_BACKUP; do
test "$NEXT_BACKUP" = "$a" && NEXT_BACKUP=""
done
done
debug "(1) DIRECT_BACKUP: $DIRECT_BACKUP"
debug "(1) INDIRECT_BACKUPS: $INDIRECT_BACKUPS"
debug "(1) LAST_BACKUP: $LAST_BACKUP"
debug "(1) INVALID_BACKUPS: $INVALID_BACKUPS"
fi
# The remaining invalid backups have to be reordered. First all backups
# without an infoblock then those with info block, both groups
# still chronologically ordered.
unset IB_1 IB_2 IB_3
for a in $INVALID_BACKUPS; do
b=`sed -n "/### BEGIN INFO/,/### END INFO/p" $a`
if [ -z "$b" ] ; then
IB_1="$IB_1 $a"
else
IB_2="$IB_2 $a"
fi
done
INVALID_BACKUPS="$IB_1 $IB_2"
debug "(2) INVALID_BACKUPS: $INVALID_BACKUPS"
# Then we select all backups with the correct service in the filename. We now
# have two groups, both ordered as before.
# Then we split the first group in those which additionally contain the
# given extension in the filename still sustainig the old order.
unset IB_1 IB_2 IB_3
for a in $INVALID_BACKUPS; do
if echo $a | grep "$SERVICE" &>/dev/null; then
if echo $a | grep "$SERVICE.$EXT" &>/dev/null; then
IB_1="$IB_1 $a"
else
IB_2="$IB_2 $a"
fi
else
IB_3="$IB_3 $a"
fi
done
INVALID_BACKUPS="$IB_1 $IB_2 $IB_3"
debug "(3) INVALID_BACKUPS: $INVALID_BACKUPS"
# Now the list starts with backups that fit most regarding the name of the
# backup and then at first these which seem to be backups of unmodified files.
# Now we choose the first one. If it has an info block we try to find an
# according stack as before and then take the last element of it.
CHOOSEN_BACKUP=`echo "$INVALID_BACKUPS" | (read a b; echo "$a")`
SUCC_BACKUP=`read_field_backup "$CHOOSEN_BACKUP"`
unset LOOP_STOP
while [ -r "$SUCC_BACKUP" ] ; do
LOOP_STOP="$LOOP_STOP $SUCC_BACKUP"
CHOOSEN_BACKUP="$SUCC_BACKUP"
SUCC_BACKUP=`read_field_backup "$CHOOSEN_BACKUP"`
# detect a loop
for a in $LOOP_STOP; do
test "$a" = "$SUCC_BACKUP" && SUCC_BACKUP=""
done
done
# IMHO this should be the at least dynamically modified file of all invalid
# backups.
INVALID_BACKUPS="$CHOOSEN_BACKUP $INVALID_BACKUPS"
debug "(4) INVALID_BACKUPS: $INVALID_BACKUPS"
# x=wird auch au▀erhalb verwendet
#
# ALL_BACKUPS
# BAFI
# CHOOSEN_BACKUP
# x DIRECT_BACKUP
# x EXT ro
# x FILENAME ro
# IB_1
# IB_2
# IB_3
# x INDIRECT_BACKUPS
# x INVALID_BACKUPS
# x LAST_BACKUP
# LOOP_STOP
# NEXT_BACKUP
# x RC_BACKUP ro
# x SERVICE ro
# SUCC_BACKUP
###########################################################
# Finally execute the requested action
###########################################################
# If there is a resolv.conf and --save_now was set then lets do it:
test -n "$SAVENOW" -a -e "$FILENAME" && cp -p --backup=t $FILENAME $SAVENOW
debug "BACKUP=$BACKUP"
case $ACTION in
modify)
# maybe there is no resolv.conf or current resolv.conf points to
# the same backup file that should be used now
# We don't copy resolv.conf if there is an valid backup of the same
# service with the same private extension or ...
for a in $DIRECT_BACKUP $INDIRECT_BACKUPS $LAST_BACKUP; do
test "$BACKUP" = "$a" && SAVE="no"
done
# ... there isn't any
if [ -e $FILENAME -a "$SAVE" != "no" ] ; then
cp -p $FILENAME $BACKUP
debug "$FILENAME saved to $BACKUP"
fi
write_file
log "Service $SERVICE modified $FILENAME. See info block in this file"
notify_services
;;
restore)
# If __save_later was set when modifying then we save the temporary
# resolv.conf
test -n "$RC_SAVELATER" -a -e "$FILENAME" &&
cp -p --backup=t $FILENAME $RC_SAVELATER
# We only restore if a backup with the correct name (already in $BACKUP)
# exists. If this backup is valid we have to save the integrity of a
# possibly existing backup stack. If this backup is invalid (= not part
# of a stack) then we just restore it, even if we invalidate an existing
# stack.
if [ -e "$BACKUP" ] ; then
# Now we search the possibly existing stack and store the two
# predecessors and one successor of it.
# Don't remove the empty entry ("") from the list.
for a in $FILENAME $DIRECT_BACKUP $INDIRECT_BACKUPS \
$LAST_BACKUP ""; do
P="$C"
C="$S"
S="$a"
test "$C" = "$BACKUP" && break
done
# If we did not found the Backup in the stack of valid backups, we
# write BACKUP to C and set FILENAME as its predecessor (P). Because
# the Backup can have a successor even if it is called invalid, we have
# to look for it.
if [ "$C" != "$BACKUP" ] ; then
P="$FILENAME"
C="$BACKUP"
S=`read_field_backup "$BACKUP"`
fi
debug "(restore) P=$P C=$C S=$S"
# If we were called with --keep, we don't restore the backup but
# keep the temporary settings.
if [ "$KEEP" = "yes" ] ; then
# We have to keep the resolver settings, but not the meta information
# in the info block. There are two cases:
# 1) The Backup (C) was the last in the stack (S="") then we remove the
# info block from its predecessor (P) and remove C.
# 2) The Backup has itself a backup (S!="") then we have to replace the
# info block in the predecessor (P) with that from the Backup (C),
# but keep everything else from P. And remove C.
cp -p $P $TMP_FILE
if [ "$S" = "" ] ; then
sed "/### BEGIN INFO/,/### END INFO/d" $TMP_FILE > $P
log "kept $P and removed info block"
else
sed -n "/### BEGIN INFO/,/### END INFO/p" $C > $P
sed "/### BEGIN INFO/,/### END INFO/d" $TMP_FILE >> $P
log "kept $P and changed info block"
fi
rm $C
log "removed $C"
else
# Don't keep the temporary settings, restore.
# All we have to do is to move the Backup (C) to its predecessor (P),
# because the backup field of the previous predecessor already points
# to the filename of P and the backup field of C what then will be in
# P points to S (if existing).
mv $C $P
log "restored $C to $P"
fi
else
# If no extension was given we search for backup files of the calling
# service with private extensions and call us recursivle for every
# found extension.
if [ "$EXT" = "" ] ; then
for a in `ls -t "$BACKUP"* 2>/dev/null`; do
EXT=${a##$BACKUP.}
$0 $COMMANDLINE -e "$EXT" --no_restart
done
if [ "$EXT" = "" ] ; then
log "no matching backup found, left everything alone"
fi
fi
fi
# If there is no backup left, make sure that $FILENAME does not contain
# an info block
if [ -z "`ls ${FILENAME}.saved.by.* $LAST_BACKUP $INDIRECT_BACKUPS \
$DIRECT_BACKUP $INVALID_BACKUPS 2>/dev/null`" ] ; then
if grep -qs "### BEGIN INFO" $FILENAME 2>/dev/null; then
log "removing info block from $FILENAME, because there is" \
"no backup left"
cp -p $FILENAME $TMP_FILE
sed "/### BEGIN INFO/,/### END INFO/d" $TMP_FILE > $FILENAME
chmod 644 $FILENAME
fi
fi
notify_services
read_file
;;
cleanup)
# Peter wants to know the old nameservers before cleaning up
if [ "$DNS" = "show" ] ; then
read_file
test -n "$OLDDNS" && echo $OLDDNS
fi
# If $FILENAME was modified (= RC_BLOCK nonempty) we have to restore it
if [ -n "$RC_BLOCK" -a "$KEEP" != "yes" ] ; then
# If --save_later was set when modifying then we save the temporary
# resolv.conf
test -n "$RC_SAVELATER" -a -e "$FILENAME" &&
cp -p --backup=t $FILENAME $RC_SAVELATER
# Search the most reasonable backup. That is (if existing) the LAST_BACKUP
# then the DIRECT_BACKUP and last the first one of INVALID_BACKUPS
BACKUP=`echo "$LAST_BACKUP $DIRECT_BACKUP $INVALID_BACKUPS" \
| (read a b; echo $a)`
if [ -e "$BACKUP" ] ; then
mv $BACKUP $FILENAME
log "restored $FILENAME from $BACKUP"
fi
fi
# Now we remove all backups
MSG=`rm -v $LAST_BACKUP $INDIRECT_BACKUPS $DIRECT_BACKUP \
$INVALID_BACKUPS 2>/dev/null`
test -n "$MSG" && log "Deleted the following stale backups: $MSG"
# After cleaning up resolc.conf should not contain an INFO block that
# marks it as modified. If it somehow happens that it has it, we remove it.
if grep -qs "### BEGIN INFO" $FILENAME 2>/dev/null; then
cp -p $FILENAME $TMP_FILE
sed "/### BEGIN INFO/,/### END INFO/d" $TMP_FILE > $FILENAME
chmod 644 $FILENAME
fi
notify_services
read_file
;;
check)
if [ -z "$RC_BLOCK" ] ; then
warn "$FILENAME not modified"
else
warn $RC_TEXT
RETVAL=1
fi
;;
esac
# Don't delete empty file. See bug 40728
# test "`cat $FILENAME`" = "" && rm $FILENAME
debug "finished"
exit $RETVAL