aboutsummaryrefslogtreecommitdiffstats
path: root/add-syslog
blob: 9f1a7e1d3d9c353d19e0738c30ff413116c24749 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/bin/sh
#---------------------------------------------------------------
# Project         : Mandriva Linux
# Module          : rpm-helper
# File            : add-syslog
# Version         : 1
# Author          : Herton Ronaldo Krzesinski
# Created On      : Tue Jul 19 23:24:48 2005
# Modified On     : Sat Jul 30 22:25:00 2005
# Purpose         : helper script for rpm scriptlets to add a
#                   entry filter for software from package into
#                   syslog (supported sysklogd and syslog-ng).
#---------------------------------------------------------------

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

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

# check range of level priority, example, an level mail.notice in
# syslog.conf will filter and log notice or greater level of messages
not_existing_entry() {
	if [ "$3" = "*" -o "$4" = "*" ]; then
		if sed "s/#.*$//g" /etc/syslog.conf | grep "$1" | grep -q "$2\.\*" ||
		   sed "s/#.*$//g" /etc/syslog.conf | grep "$1" | grep -q "$2\.=\*"; then
		   return 1
		fi
		lvl_start=`echo $priority_order | cut -d " " -f 1 | sed "s:,.*::"`
		num_levels=`echo $priority_order | wc -w`
		lvl_end=`echo $priority_order | cut -d " " -f $num_levels | sed "s:,.*::"`
	else
		lvl_start=$3
		lvl_end=$4
	fi
	local begin=0
	for x in $priority_order; do
		if [[ "$begin" -eq 0 ]] && ! echo $x | grep -q "$lvl_start"; then
			continue
		fi
		begin=1
		x=`echo $x | sed "s:,: :g"`
		for y in $x; do
			if sed "s/#.*$//g" /etc/syslog.conf | grep "$1"	| grep -q "$2\.$y"; then
				return 1
			fi
			if sed "s/#.*$//g" /etc/syslog.conf | grep "$1"	| grep -q "$2\.=$y"; then
				return 1
			fi
		done
		if echo $x | grep -q "$lvl_end"; then
			return 0
		fi
	done
}

add_blank_line() {
	[ -n "`tail -n 1 $1`" ] && echo >> $1 || :
}

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 in a range, you especify level_end
                                # like when you log from level debug
				# untill notice. if not in a range
				# you must specify level_end the same as
				# level_begin or leave level_end empty
logfile=$7                      # log file, like /var/log/messages

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

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

# if we only have level_end, assume that level_begin is the lowest
# priority level order
if [ -z "$level_begin" -a -n "$level_end" ]; then
	level_begin=`echo $priority_order | cut -d " " -f 1 | sed "s:,.*::"`
fi

# Do not use deprecated level names, set also label for syslog-ng levels
for loglevel in $priority_order; do
	if echo $loglevel | grep -q "$level_begin"; then
		level_begin=`echo $loglevel | sed s:,.*::`
		break
	fi
done
if [ -n "$level_end" ]; then
	for loglevel in $priority_order; do
		if echo $loglevel | grep -q "$level_end"; then
			level_end=`echo $loglevel | sed s:,.*::`
			break
		fi
	done
	level_label=${level_begin}_${level_end}
else
	level_label=$level_begin
fi

# Wildcards on begin or end means we want levels until a limit on either side
# Just use wildcard if range of levels contains all levels
if [ "$level_begin" = "debug" -a "$level_end" = "*" -o "$level_begin" =	"*" -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"
elif [ "$level_begin" = "debug" -a "$level_end" = "emerg" ]; then
	level_begin="*"
	level_end="*"
fi

# sysklogd handler
if [ -f /etc/syslog.conf ]; then
	if [[ -n "$source" ]] && ! grep -q "$source" /etc/sysconfig/syslog; then
		. /etc/sysconfig/syslog
		SYSLOGD_OPTIONS="$SYSLOGD_OPTIONS -a $source"
		sed -i -e :a -e \
		    "s:SYSLOGD_OPTIONS=\"[^\"]*\":SYSLOGD_OPTIONS=\"$SYSLOGD_OPTIONS\":g;/SYSLOGD_OPTIONS/N;//ba" \
		    /etc/sysconfig/syslog
	fi
	# we first verify if there isn't already a log entry for the
	# logfile/facility/level provided, and then add the entry to
	# syslog.conf. Note that we must always remove comments,
	# otherwise commented lines are interpreted as active
	if not_existing_entry "$logfile" "$facility" "$level_begin" "$level_end"; then
		add_blank_line /etc/syslog.conf
		if [ "$level_begin" = "*" -a "$level_end" = "*" ]; then
			echo -e "$facility.*\t\t\t\t\t\t\t$logfile" >> /etc/syslog.conf
		elif [ -n "$level_begin" -a -n "$level_end" -a "$level_begin" != "$level_end" -a "$level_end" = "emerg" ]; then
			echo -e "$facility.$level_begin\t\t\t\t\t\t\t$logfile" >> /etc/syslog.conf
		elif [ -n "$level_begin" -a -n "$level_end" -a "$level_begin" != "$level_end" ]; then
			count=0
			for loglevel in $priority_order; do
				if [[ "$count" -eq 0 ]] && ! echo "$loglevel" | grep -q "$level_begin"; then
					continue
				fi
				let count=count+1
				current_level=`echo $loglevel | sed "s:,.*::"`
				if ! echo "$loglevel" | grep -q "$level_end"; then
					echo -n	"$facility.=$current_level;" >> /etc/syslog.conf
				else
					echo -n "$facility.=$current_level " >> /etc/syslog.conf
					break
				fi
			done
			let count=8-count
			while [ "$count" -gt 0 ]; do
				echo -ne "\t" >> /etc/syslog.conf
				let count=count-1
			done
			echo -n "$logfile" >> /etc/syslog.conf
		elif [ -n "$level_begin" ]; then
			echo -e	"$facility.=$level_begin\t\t\t\t\t\t\t$logfile" >> /etc/syslog.conf
		fi
	fi
fi

# syslog-ng handler
if [ -f /etc/syslog-ng.conf ]; then
	config=`sed "s/#.*$//g" /etc/syslog-ng.conf`
	add_blank_line /etc/syslog-ng.conf
	if ! sed "s/#.*$//g" /etc/syslog-ng.conf | grep -q "$source"; then
		if [ -n "$facility" -o -n "$level_begin" -a -n "$logfile" ]; then
			echo "source $pkg { unix-stream (\"$source\"); };" >> /etc/syslog-ng.conf
			from=$pkg
		else
			from=`echo $config | sed -n "s:\(.*source[[:space:]]\+\)\([[:alnum:]]\+\)\(.*/dev/log.*\):\2:p"`
		fi
	else
		from=`echo $config | sed -n "s:\(.*source[[:space:]]\+\)\([[:alnum:]]\+\)\(.*$source.*\):\2:p"`
	fi
	if [ -n "$facility" -o -n "$level_begin" -a -n "$logfile" ]; then
		if ! sed "s/#.*$//g" /etc/syslog-ng.conf | grep -q "$logfile"; then
			echo "destination ${pkg}_${level_label} { file(\"$logfile\"); };" >> /etc/syslog-ng.conf
			dest=${pkg}_${level_label}
		else
			dest=`echo $config | sed -n "s:\(.*destination[[:space:]]\+\)\([[:alnum:]]\+\)\(.*$logfile.*\):\2:p"`
		fi

		if [ -n "$level_begin" -a -n "$level_end" -a "$level_begin" != "$level_end" ]; then
			level_str="$level_begin..$level_end"
		elif [ "$level_begin" = "*" -a "$level_end" = "*" ]; then
			level_str="debug..emerg"
		elif [ -n "$level_begin" ]; then
			level_str="$level_begin"
		fi
		if ! sed "s/#.*$//g" /etc/syslog-ng.conf | grep "$facility" | grep -q filter; then
			echo "filter f_${pkg}_${level_label} { facility($facility) and level($level_str); };" >> /etc/syslog-ng.conf
			filter=f_${pkg}_${level_label}
		else
			filter=`echo $config | sed -n "s:\(.*filter[[:space:]]\+\)\([[:alnum:]]\+\)\(.*$facility.*\):\2:p"`
			curfilt=`echo $config | sed -n "s:\(.*\)\(filter[[:space:]]\+$filter[^}]*};\)\(.*\):\2:gp"`
			has_level=0
			levels=`echo $priority_order | sed -n "s:\($level_begin.*\):\1:p"`
			levels=`echo $levels | sed -n "s:\(.*$level_end\):\1:p"`
			for log_level in $levels; do
				if echo $curfilt | grep -q "$log_level"; then
					has_level=1
					break
				fi
			done
			if [ "$has_level" -eq 0 ]; then
				echo "filter f_${pkg}_${level_label} { facility($facility) and level($level_str); };" >> /etc/syslog-ng.conf
				filter=f_${pkg}_${level_label}
			fi
		fi
		if [ -n "$from" -a -n "$dest" -a -n "$filter" ]; then
			if ! sed "s/#.*$//g" /etc/syslog-ng.conf | grep "$from"	\
			   | grep "$dest" | grep "$filter" | grep -q "^[[:space:]]*log"; then
				echo "log { source($from); filter($filter); destination($dest); };" \
				     >> /etc/syslog-ng.conf
			fi
		fi
	elif [ -n "$source" ]; then
		from=`echo $config | sed -n "s:\(.*source[[:space:]]\+\)\([[:alnum:]]\+\)\(.*/dev/log.*\):\2:p"`
		if [ -n "$from" ]; then
			sed -i -e :a -e \
			    "s:\(source[[:space:]]\+$from[[:space:]]*{[^}]*\)\(}[[:space:]]*\);:\1 unix-stream (\"$source\"); };:g;/source/N;//ba" \
			    /etc/syslog-ng.conf
		fi
	fi
fi

exit 0