#!/bin/sh
#---------------------------------------------------------------
# Project         : Mandriva Linux
# Module          : rpm-helper
# File            : del-syslog
# Version         : 1
# Author          : Herton Ronaldo Krzesinski
#                   Thanks for Aurélio Marinho Jargas for
#                   helping me out with sed expressions,
#                   my first expressions were very slow to
#                   execute, parsing block oriented config files
#                   isn't very simple with line oriented tools
#                   like grep or sed
# Created On      : Fri Jul 22 20:25:36 2005
# Modified On     : Wed Aug 03 14:29:14 2005
# Purpose         : helper script for rpm scriptlets to del a
#                   entry filter for software from package into
#                   syslog (supported sysklogd and syslog-ng).
#---------------------------------------------------------------

if [ $# -lt 3 ]; then
	echo "usage: $0 <pkg name> <num installed> <source> <facility> <level> <log file>" 1>&2
	exit 1
fi

priority_order="debug info notice warn,warning err,error crit alert emerg,panic"

_del_source_sed() {

cat << EOF
/^[[:space:]]*source/ {
	:ini
	/}/! {
		N
		b ini
	}
	s#[[:space:]]*unix-stream[[:space:]]*([[:space:]]*"\?$2"\?[[:space:]]*)[[:space:]]*\;##g
	/[[:space:]]*source[[:space:]]*$1[[:space:]]*{[[:space:]]*}[[:space:]]*\;/d
}
EOF

}

delete_source() {

local name=$1
local sourcefile=$2
_del_source_sed $name $sourcefile | sed -i -f - /etc/syslog-ng.conf

}

_del_destination_sed() {

# argh: \\\ escape sequence because of shell
hdl=`echo $2 | sed 's#/#\\\/#g'`
cat << EOF
/^[[:space:]]*destination[[:space:]]\+$1/ {
	:ini
	/}/! {
		N
		b ini
	}
	/file[[:space:]]*([[:space:]]*"\?$hdl"\?[[:space:]]*)/d
}
EOF

}

# Below there are replacements on the form:
# `echo "$1" | sed "s/\\\*/\\\\\*/g"`
# They escape '*' because they are used inside the sed scripts and must not be
# interpreted as a regular expression/wildcard, as part of literal names.

delete_destination() {

local name=`echo "$1" | sed "s/\\\*/\\\\\*/g"`
local file=$2
_del_destination_sed $name $file | sed -i -f - /etc/syslog-ng.conf

}

_del_filter_sed() {

cat << EOF
/^[[:space:]]*filter[[:space:]]\+$1/ {
	:ini
	/}/! {
		N
		b ini
	}
	/facility[[:space:]]*([[:space:]]*"\?$2"\?[[:space:]]*)/ {
		/level[[:space:]]*([[:space:]]*"\?$3"\?[[:space:]]*)/d
	}
}
EOF

}

delete_filter() {

local name=`echo "$1" | sed "s/\\\*/\\\\\*/g"`
local facility=$2
local level=`echo "$3" | sed "s/\\\*/\\\\\*/g"`
_del_filter_sed $name $facility $level | sed -i -f - /etc/syslog-ng.conf

}

_del_log_sed() {

cat << EOF
/^[[:space:]]*log/{
	:ini
	/}/! {
		N
		b ini
	}
	/source[[:space:]]*([[:space:]]*"\?$1"\?[[:space:]]*)/ {
		/filter[[:space:]]*([[:space:]]*"\?$2"\?[[:space:]]*)/ {
			/destination[[:space:]]*([[:space:]]*"\?$3"\?[[:space:]]*)/d
		}
	}
}
EOF

}

delete_log() {

local source=$1
local filter=`echo "$2" | sed "s/\\\*/\\\\\*/g"`
local destination=`echo "$3" | sed "s/\\\*/\\\\\*/g"`
_del_log_sed $source $filter $destination | sed -i -f - /etc/syslog-ng.conf

}

pkg=$1                          # name of the package
num=$2                          # number of packages installed
source=$3                       # from where the log will come (log stream)
                                # NOTE: source must be a unix-stream
facility=$4                     # subclass of log source, like kern, mail...
level_begin=$5                  # log level, eg.: info, notice, critical,
level_end=$6                    # if a range was specified before,
                                # delete it
logfile=$7                      # log file, like /var/log/messages

# Don't remove entry on package updates
if [ "$num" -ne 0 ]; then
	exit 0
fi

# Just ignore if it's default unix domain socket
[ "$source" = "/dev/log" ] && source="" || :

# Handle level ranges
if [ -z "$level_begin" -a -n "$level_end" ]; then
	level_begin=`echo $priority_order | cut -d " " -f 1`
elif [ -n "$level_begin" -a -z "$level_end" ]; then
	level_end="$level_begin"
fi
if [ "$level_begin" = "debug" -a "$level_end" = "*" -o "$level_begin" = "*" -a "$level_end" = "emerg" ]; then
	level_begin="*"
	level_end="*"
elif [ "$level_begin" = "debug" -a "$level_end" = "emerg" ]; then
	level_begin="*"
	level_end="*"
elif [ "$level_begin" = "*" -a "$level_end" != "*" ]; then
	level_begin="debug"
elif [ "$level_begin" != "*" -a "$level_end" = "*" ]; then
	level_end="emerg"
fi

# sysklogd handler
if [ -f /etc/syslog.conf ]; then
	if [[ -n "$source" ]] && sed "s/#.*$//g" /etc/sysconfig/syslog | grep -q "$source"; then
		source /etc/sysconfig/syslog
		SYSLOGD_OPTIONS=`echo $SYSLOGD_OPTIONS | sed "s:[[:space:]]\+-a[[:space:]]\+$source::g"`
		sed -i -e :a -e \
		    "s:SYSLOGD_OPTIONS=\"[^\"]*\":SYSLOGD_OPTIONS=\"$SYSLOGD_OPTIONS\":g;/SYSLOGD_OPTIONS/N;//ba" \
		    /etc/sysconfig/syslog
	fi
	if [ -n "$facility" -a -n "$level_begin" -a -n "$logfile" ]; then
		lvl_begin="$level_begin"
		lvl_end="$level_end"
		if [ "$level_begin" = "*" -a "$level_end" = "*" -o \
		     "$level_begin" = "debug" -a "$level_end" = "emerge" -o "$level_end" = "panic" ]; then
			lnum=`grep -n "$logfile" /etc/syslog.conf | sed "s/#.*$//g" | grep "$facility\.\*" | cut -d ":" -f 1`;
			[ -n "$lnum" ] && sed -i "${lnum}d;" /etc/syslog.conf || :
			lvl_begin="debug"
			lvl_end="emerg"
		fi
		levels=`echo $priority_order | sed -n "s:\([^[:space:]]*$lvl_begin.*\):\1:p"`
		levels=`echo $levels | sed -n "s:\(.*$lvl_end[^[:space:]]*\):\1:p"`
		levels=`echo $levels | sed 's:,: :g'`
		for level in $levels; do
			LNUM=""
			for lnum in `grep -n "$logfile" /etc/syslog.conf | sed "s/#.*$//g" | grep "$facility" | grep "$level" | cut -d ":" -f 1`; do
				[ -n "$lnum" ] && LNUM="${LNUM}${lnum}d;" || :
			done
			[ -n "$LNUM" ] && sed -i "$LNUM" /etc/syslog.conf || :
		done
	fi
	[ -f "/etc/rc.d/init.d/syslog" ] && service syslog condrestart
fi

# syslog-ng handler
if [ -f /etc/syslog-ng.conf ]; then
	# First, make sure each directive is placed at each line, 
	# eg.: if we have to log directives on the same line (like
	# "log { ... }; log { ... };" place them in separate lines to
	# make file look better and make parsing easier
	sed -i \
	    -e ':ini' \
	    -e 's/}; *\(\(source\|destination\|filter\|log\).*\)/}\n\1/;t ini' \
	    /etc/syslog-ng.conf

	config=`sed "s/#.*$//g" /etc/syslog-ng.conf`
	if [ -n "$source" ]; then
		from=`echo $config | sed -n "s:\(.*source[[:space:]]\+\)\([[:alnum:]]\+\)\(.*$source.*\):\2:p"`
		delete_source $pkg $source
	else
		from=`echo $config | sed -n "s:\(.*source[[:space:]]\+\)\([[:alnum:]]\+\)\(.*/dev/log.*\):\2:p"`
	fi

	for level in $priority_order; do
		if [ -n "$level_begin" ]; then
			if echo $level | grep -q "$level_begin"; then
				lvl=`echo $level | sed "s:,: :"`
				c=0
				for depr in $lvl; do
					lvl_start[$c]="$depr"
					let c=c+1
				done
			fi
		fi
		if [ -n "$level_end" ]; then
			if echo $level | grep -q "$level_end"; then
				lvl=`echo $level | sed "s:,: :"`
				c=0
				for depr in $lvl; do
					lvl_end[$c]="$depr"
					let c=c+1
				done
			fi
		fi
	done

	# We must test all possibilities for the given range, as also
	# test for deprecated name levels.
	if [ "$level_begin" = "*" -a "$level_end" = "*" -o \
	     "$level_begin" = "debug" -a "$level_end" = "emerg" -o "$level_end" = "panic" ]; then
		lvl_range[0]="*"
		lvl_range[1]="debug..emerg"
		lvl_range[2]="debug..panic"
		lvl_label[0]="*"
		lvl_label[1]="*_*"
		lvl_label[2]="debug_emerg"
		lvl_label[3]="debug_panic"
	elif [ "${lvl_start[0]}" = "${lvl_end[0]}" -o "${lvl_start[0]}" = "${lvl_end[1]}" ]; then
		lvl_range[0]="${lvl_start[0]}"
		lvl_range[1]="${lvl_end[0]}"
		lvl_label[0]="${lvl_start[0]}"
		lvl_label[1]="${lvl_end[0]}"
	else
		if [ -n "${lvl_start[0]}" -a -n "${lvl_end[0]}" ]; then
			lvl_range[0]="${lvl_start[0]}..${lvl_end[0]}"
			lvl_label[0]="${lvl_start[0]}_${lvl_end[0]}"
		fi
		if [ -n "${lvl_start[0]}" -a -n "${lvl_end[1]}" ]; then
			lvl_range[1]="${lvl_start[0]}..${lvl_end[1]}"
			lvl_label[1]="${lvl_start[0]}_${lvl_end[1]}"
		fi
		if [ -n "${lvl_start[1]}" -a -n "${lvl_end[0]}" ]; then
			lvl_range[2]="${lvl_start[1]}..${lvl_end[0]}"
			lvl_label[2]="${lvl_start[1]}_${lvl_end[0]}"
		fi
		if [ -n "${lvl_start[1]}" -a -n "${lvl_end[1]}" ]; then
			lvl_range[3]="${lvl_start[1]}..${lvl_end[1]}"
			lvl_label[3]="${lvl_start[1]}_${lvl_end[1]}"
		fi
	fi

	# Remove destination
	i=0
	while [ "$i" -lt 4 -a -n "$logfile" ]; do
		if [ -n "${lvl_label[$i]}" ]; then
			delete_destination ${pkg}_${lvl_label[$i]} $logfile
		fi
		let i=i+1
	done

	# Remove filter
	i=0
	while [ "$i" -lt 4 -a -n "$facility" ]; do
		j=0
		while [ "$j" -lt 4 -a -n "${lvl_range[$i]}" ]; do
			if [ -n "${lvl_label[$j]}" ]; then
				delete_filter f_${pkg}_${lvl_label[$j]} $facility ${lvl_range[$i]}
			fi
			let j=j+1
		done
		let i=i+1
	done

	# Remove log directive
	if [ -n "$from" ]; then
		i=0
		while [ "$i" -lt 4 ]; do
			j=0
			while [ "$j" -lt 4 -a -n "${lvl_label[$i]}" ]; do
				if [ -n "${lvl_label[$j]}" ]; then
					delete_log $from f_${pkg}_${lvl_label[$i]} ${pkg}_${lvl_label[$j]}
				fi
				let j=j+1
			done
			let i=i+1
		done
	fi

	[ -f "/etc/rc.d/init.d/syslog-ng" ] && service syslog-ng condrestart
fi
