line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Sys::Syslog; |
2
|
11
|
|
|
11
|
|
426604
|
use strict; |
|
11
|
|
|
|
|
72
|
|
|
11
|
|
|
|
|
272
|
|
3
|
11
|
|
|
11
|
|
47
|
use warnings; |
|
11
|
|
|
|
|
13
|
|
|
11
|
|
|
|
|
270
|
|
4
|
11
|
|
|
11
|
|
54
|
use warnings::register; |
|
11
|
|
|
|
|
16
|
|
|
11
|
|
|
|
|
953
|
|
5
|
11
|
|
|
11
|
|
88
|
use Carp; |
|
11
|
|
|
|
|
15
|
|
|
11
|
|
|
|
|
615
|
|
6
|
11
|
|
|
11
|
|
56
|
use Config; |
|
11
|
|
|
|
|
14
|
|
|
11
|
|
|
|
|
341
|
|
7
|
11
|
|
|
11
|
|
44
|
use Exporter (); |
|
11
|
|
|
|
|
14
|
|
|
11
|
|
|
|
|
175
|
|
8
|
11
|
|
|
11
|
|
45
|
use File::Basename; |
|
11
|
|
|
|
|
17
|
|
|
11
|
|
|
|
|
812
|
|
9
|
11
|
|
|
11
|
|
4708
|
use POSIX qw< strftime setlocale LC_TIME >; |
|
11
|
|
|
|
|
57967
|
|
|
11
|
|
|
|
|
48
|
|
10
|
11
|
|
|
11
|
|
16272
|
use Socket qw< :all >; |
|
11
|
|
|
|
|
20562
|
|
|
11
|
|
|
|
|
10175
|
|
11
|
|
|
|
|
|
|
require 5.005; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
*import = \&Exporter::import; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
|
17
|
11
|
|
|
11
|
|
157
|
{ no strict 'vars'; |
|
11
|
|
|
|
|
17
|
|
|
11
|
|
|
|
|
1736
|
|
18
|
|
|
|
|
|
|
$VERSION = '0.36'; |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
%EXPORT_TAGS = ( |
21
|
|
|
|
|
|
|
standard => [qw(openlog syslog closelog setlogmask)], |
22
|
|
|
|
|
|
|
extended => [qw(setlogsock)], |
23
|
|
|
|
|
|
|
macros => [ |
24
|
|
|
|
|
|
|
# levels |
25
|
|
|
|
|
|
|
qw( |
26
|
|
|
|
|
|
|
LOG_ALERT LOG_CRIT LOG_DEBUG LOG_EMERG LOG_ERR |
27
|
|
|
|
|
|
|
LOG_INFO LOG_NOTICE LOG_WARNING |
28
|
|
|
|
|
|
|
), |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# standard facilities |
31
|
|
|
|
|
|
|
qw( |
32
|
|
|
|
|
|
|
LOG_AUTH LOG_AUTHPRIV LOG_CRON LOG_DAEMON LOG_FTP LOG_KERN |
33
|
|
|
|
|
|
|
LOG_LOCAL0 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4 |
34
|
|
|
|
|
|
|
LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7 LOG_LPR LOG_MAIL LOG_NEWS |
35
|
|
|
|
|
|
|
LOG_SYSLOG LOG_USER LOG_UUCP |
36
|
|
|
|
|
|
|
), |
37
|
|
|
|
|
|
|
# Mac OS X specific facilities |
38
|
|
|
|
|
|
|
qw( LOG_INSTALL LOG_LAUNCHD LOG_NETINFO LOG_RAS LOG_REMOTEAUTH ), |
39
|
|
|
|
|
|
|
# modern BSD specific facilities |
40
|
|
|
|
|
|
|
qw( LOG_CONSOLE LOG_NTP LOG_SECURITY ), |
41
|
|
|
|
|
|
|
# IRIX specific facilities |
42
|
|
|
|
|
|
|
qw( LOG_AUDIT LOG_LFMT ), |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# options |
45
|
|
|
|
|
|
|
qw( |
46
|
|
|
|
|
|
|
LOG_CONS LOG_PID LOG_NDELAY LOG_NOWAIT LOG_ODELAY LOG_PERROR |
47
|
|
|
|
|
|
|
), |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# others macros |
50
|
|
|
|
|
|
|
qw( |
51
|
|
|
|
|
|
|
LOG_FACMASK LOG_NFACILITIES LOG_PRIMASK |
52
|
|
|
|
|
|
|
LOG_MASK LOG_UPTO |
53
|
|
|
|
|
|
|
), |
54
|
|
|
|
|
|
|
], |
55
|
|
|
|
|
|
|
); |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
@EXPORT = ( |
58
|
|
|
|
|
|
|
@{$EXPORT_TAGS{standard}}, |
59
|
|
|
|
|
|
|
); |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
@EXPORT_OK = ( |
62
|
|
|
|
|
|
|
@{$EXPORT_TAGS{extended}}, |
63
|
|
|
|
|
|
|
@{$EXPORT_TAGS{macros}}, |
64
|
|
|
|
|
|
|
); |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
eval { |
67
|
|
|
|
|
|
|
require XSLoader; |
68
|
|
|
|
|
|
|
XSLoader::load('Sys::Syslog', $VERSION); |
69
|
|
|
|
|
|
|
1 |
70
|
|
|
|
|
|
|
} or do { |
71
|
|
|
|
|
|
|
require DynaLoader; |
72
|
|
|
|
|
|
|
push @ISA, 'DynaLoader'; |
73
|
|
|
|
|
|
|
bootstrap Sys::Syslog $VERSION; |
74
|
|
|
|
|
|
|
}; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# |
79
|
|
|
|
|
|
|
# Constants |
80
|
|
|
|
|
|
|
# |
81
|
11
|
|
|
11
|
|
60
|
use constant HAVE_GETPROTOBYNAME => $Config::Config{d_getpbyname}; |
|
11
|
|
|
|
|
17
|
|
|
11
|
|
|
|
|
1415
|
|
82
|
11
|
|
|
11
|
|
78
|
use constant HAVE_GETPROTOBYNUMBER => $Config::Config{d_getpbynumber}; |
|
11
|
|
|
|
|
33
|
|
|
11
|
|
|
|
|
871
|
|
83
|
11
|
|
|
11
|
|
62
|
use constant HAVE_SETLOCALE => $Config::Config{d_setlocale}; |
|
11
|
|
|
|
|
77
|
|
|
11
|
|
|
|
|
1066
|
|
84
|
11
|
50
|
|
11
|
|
64
|
use constant HAVE_IPPROTO_TCP => defined &Socket::IPPROTO_TCP ? 1 : 0; |
|
11
|
|
|
|
|
21
|
|
|
11
|
|
|
|
|
657
|
|
85
|
11
|
50
|
|
11
|
|
61
|
use constant HAVE_IPPROTO_UDP => defined &Socket::IPPROTO_UDP ? 1 : 0; |
|
11
|
|
|
|
|
14
|
|
|
11
|
|
|
|
|
664
|
|
86
|
11
|
50
|
|
11
|
|
59
|
use constant HAVE_TCP_NODELAY => defined &Socket::TCP_NODELAY ? 1 : 0; |
|
11
|
|
|
|
|
34
|
|
|
11
|
|
|
|
|
652
|
|
87
|
|
|
|
|
|
|
|
88
|
11
|
|
|
|
|
588
|
use constant SOCKET_IPPROTO_TCP => |
89
|
|
|
|
|
|
|
HAVE_IPPROTO_TCP ? Socket::IPPROTO_TCP |
90
|
|
|
|
|
|
|
: HAVE_GETPROTOBYNAME ? scalar getprotobyname("tcp") |
91
|
11
|
|
|
11
|
|
54
|
: 6; |
|
11
|
|
|
|
|
16
|
|
92
|
|
|
|
|
|
|
|
93
|
11
|
|
|
|
|
507
|
use constant SOCKET_IPPROTO_UDP => |
94
|
|
|
|
|
|
|
HAVE_IPPROTO_UDP ? Socket::IPPROTO_UDP |
95
|
|
|
|
|
|
|
: HAVE_GETPROTOBYNAME ? scalar getprotobyname("udp") |
96
|
11
|
|
|
11
|
|
52
|
: 17; |
|
11
|
|
|
|
|
17
|
|
97
|
|
|
|
|
|
|
|
98
|
11
|
|
|
11
|
|
55
|
use constant SOCKET_TCP_NODELAY => HAVE_TCP_NODELAY ? Socket::TCP_NODELAY : 1; |
|
11
|
|
|
|
|
17
|
|
|
11
|
|
|
|
|
550
|
|
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# |
102
|
|
|
|
|
|
|
# Public variables |
103
|
|
|
|
|
|
|
# |
104
|
11
|
|
|
11
|
|
60
|
use vars qw($host); # host to send syslog messages to (see notes at end) |
|
11
|
|
|
|
|
13
|
|
|
11
|
|
|
|
|
609
|
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
# |
107
|
|
|
|
|
|
|
# Prototypes |
108
|
|
|
|
|
|
|
# |
109
|
|
|
|
|
|
|
sub silent_eval (&); |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# |
112
|
|
|
|
|
|
|
# Global variables |
113
|
|
|
|
|
|
|
# |
114
|
11
|
|
|
11
|
|
53
|
use vars qw($facility); |
|
11
|
|
|
|
|
16
|
|
|
11
|
|
|
|
|
3207
|
|
115
|
|
|
|
|
|
|
my $connected = 0; # flag to indicate if we're connected or not |
116
|
|
|
|
|
|
|
my $syslog_send; # coderef of the function used to send messages |
117
|
|
|
|
|
|
|
my $syslog_path = undef; # syslog path for "stream" and "unix" mechanisms |
118
|
|
|
|
|
|
|
my $syslog_xobj = undef; # if defined, holds the external object used to send messages |
119
|
|
|
|
|
|
|
my $transmit_ok = 0; # flag to indicate if the last message was transmitted |
120
|
|
|
|
|
|
|
my $sock_port = undef; # socket port |
121
|
|
|
|
|
|
|
my $sock_timeout = 0; # socket timeout, see below |
122
|
|
|
|
|
|
|
my $current_proto = undef; # current mechanism used to transmit messages |
123
|
|
|
|
|
|
|
my $ident = ''; # identifiant prepended to each message |
124
|
|
|
|
|
|
|
$facility = ''; # current facility |
125
|
|
|
|
|
|
|
my $maskpri = LOG_UPTO(&LOG_DEBUG); # current log mask |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
my %options = ( |
128
|
|
|
|
|
|
|
ndelay => 0, |
129
|
|
|
|
|
|
|
noeol => 0, |
130
|
|
|
|
|
|
|
nofatal => 0, |
131
|
|
|
|
|
|
|
nonul => 0, |
132
|
|
|
|
|
|
|
nowait => 0, |
133
|
|
|
|
|
|
|
perror => 0, |
134
|
|
|
|
|
|
|
pid => 0, |
135
|
|
|
|
|
|
|
); |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# Default is now to first use the native mechanism, so Perl programs |
138
|
|
|
|
|
|
|
# behave like other normal Unix programs, then try other mechanisms. |
139
|
|
|
|
|
|
|
my @connectMethods = qw(native tcp udp unix pipe stream console); |
140
|
|
|
|
|
|
|
if ($^O eq "freebsd" or $^O eq "linux") { |
141
|
|
|
|
|
|
|
@connectMethods = grep { $_ ne 'udp' } @connectMethods; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# And on Win32 systems, we try to use the native mechanism for this |
145
|
|
|
|
|
|
|
# platform, the events logger, available through Win32::EventLog. |
146
|
|
|
|
|
|
|
EVENTLOG: { |
147
|
|
|
|
|
|
|
my $verbose_if_Win32 = $^O =~ /Win32/i; |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
if (can_load_sys_syslog_win32($verbose_if_Win32)) { |
150
|
|
|
|
|
|
|
unshift @connectMethods, 'eventlog'; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
my @defaultMethods = @connectMethods; |
155
|
|
|
|
|
|
|
my @fallbackMethods = (); |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# The timeout in connection_ok() was pushed up to 0.25 sec in |
158
|
|
|
|
|
|
|
# Sys::Syslog v0.19 in order to address a heisenbug on MacOSX: |
159
|
|
|
|
|
|
|
# http://london.pm.org/pipermail/london.pm/Week-of-Mon-20061211/005961.html |
160
|
|
|
|
|
|
|
# |
161
|
|
|
|
|
|
|
# However, this also had the effect of slowing this test for |
162
|
|
|
|
|
|
|
# all other operating systems, which apparently impacted some |
163
|
|
|
|
|
|
|
# users (cf. CPAN-RT #34753). So, in order to make everybody |
164
|
|
|
|
|
|
|
# happy, the timeout is now zero by default on all systems |
165
|
|
|
|
|
|
|
# except on OSX where it is set to 250 msec, and can be set |
166
|
|
|
|
|
|
|
# with the infamous setlogsock() function. |
167
|
|
|
|
|
|
|
# |
168
|
|
|
|
|
|
|
# Update 2011-08: this issue is also been seen on multiprocessor |
169
|
|
|
|
|
|
|
# Debian GNU/kFreeBSD systems. See http://bugs.debian.org/627821 |
170
|
|
|
|
|
|
|
# and https://rt.cpan.org/Ticket/Display.html?id=69997 |
171
|
|
|
|
|
|
|
# Also, lowering the delay to 1 ms, which should be enough. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
$sock_timeout = 0.001 if $^O =~ /darwin|gnukfreebsd/; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
# Perl 5.6.0's warnings.pm doesn't have warnings::warnif() |
177
|
|
|
|
|
|
|
if (not defined &warnings::warnif) { |
178
|
|
|
|
|
|
|
*warnings::warnif = sub { |
179
|
|
|
|
|
|
|
goto &warnings::warn if warnings::enabled(__PACKAGE__) |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# coderef for a nicer handling of errors |
184
|
|
|
|
|
|
|
my $err_sub = $options{nofatal} ? \&warnings::warnif : \&croak; |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
sub AUTOLOAD { |
188
|
|
|
|
|
|
|
# This AUTOLOAD is used to 'autoload' constants from the constant() |
189
|
|
|
|
|
|
|
# XS function. |
190
|
11
|
|
|
11
|
|
66
|
no strict 'vars'; |
|
11
|
|
|
|
|
23
|
|
|
11
|
|
|
|
|
1121
|
|
191
|
3
|
|
|
3
|
|
788
|
my $constname; |
192
|
3
|
|
|
|
|
12
|
($constname = $AUTOLOAD) =~ s/.*:://; |
193
|
3
|
50
|
|
|
|
9
|
croak "Sys::Syslog::constant() not defined" if $constname eq 'constant'; |
194
|
3
|
|
|
|
|
12
|
my ($error, $val) = constant($constname); |
195
|
3
|
50
|
|
|
|
291
|
croak $error if $error; |
196
|
11
|
|
|
11
|
|
67
|
no strict 'refs'; |
|
11
|
|
|
|
|
14
|
|
|
11
|
|
|
|
|
24992
|
|
197
|
0
|
|
|
0
|
|
0
|
*$AUTOLOAD = sub { $val }; |
|
0
|
|
|
|
|
0
|
|
198
|
0
|
|
|
|
|
0
|
goto &$AUTOLOAD; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub openlog { |
203
|
11
|
|
|
11
|
1
|
6146
|
($ident, my $logopt, $facility) = @_; |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# default values |
206
|
11
|
|
0
|
|
|
150
|
$ident ||= basename($0) || getlogin() || getpwuid($<) || 'syslog'; |
|
|
|
66
|
|
|
|
|
207
|
11
|
|
100
|
|
|
44
|
$logopt ||= ''; |
208
|
11
|
|
66
|
|
|
41
|
$facility ||= LOG_USER(); |
209
|
|
|
|
|
|
|
|
210
|
11
|
|
|
|
|
50
|
for my $opt (split /\b/, $logopt) { |
211
|
10
|
100
|
|
|
|
37
|
$options{$opt} = 1 if exists $options{$opt} |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
11
|
50
|
|
|
|
44
|
$err_sub = delete $options{nofatal} ? \&warnings::warnif : \&croak; |
215
|
11
|
100
|
|
|
|
34
|
return 1 unless $options{ndelay}; |
216
|
6
|
|
|
|
|
20
|
connect_log(); |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
sub closelog { |
220
|
4
|
100
|
|
4
|
1
|
1595
|
disconnect_log() if $connected; |
221
|
4
|
|
|
|
|
20
|
$options{$_} = 0 for keys %options; |
222
|
4
|
|
|
|
|
9
|
$facility = $ident = ""; |
223
|
4
|
|
|
|
|
7
|
$connected = 0; |
224
|
4
|
|
|
|
|
7
|
return 1 |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub setlogmask { |
228
|
11
|
|
|
11
|
1
|
14780
|
my $oldmask = $maskpri; |
229
|
11
|
100
|
|
|
|
23
|
$maskpri = shift unless $_[0] == 0; |
230
|
11
|
|
|
|
|
18
|
$oldmask; |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
my %mechanism = ( |
235
|
|
|
|
|
|
|
console => { |
236
|
|
|
|
|
|
|
check => sub { 1 }, |
237
|
|
|
|
|
|
|
}, |
238
|
|
|
|
|
|
|
eventlog => { |
239
|
|
|
|
|
|
|
check => sub { return can_load_sys_syslog_win32() }, |
240
|
|
|
|
|
|
|
err_msg => "no Win32 API available", |
241
|
|
|
|
|
|
|
}, |
242
|
|
|
|
|
|
|
inet => { |
243
|
|
|
|
|
|
|
check => sub { 1 }, |
244
|
|
|
|
|
|
|
}, |
245
|
|
|
|
|
|
|
native => { |
246
|
|
|
|
|
|
|
check => sub { 1 }, |
247
|
|
|
|
|
|
|
}, |
248
|
|
|
|
|
|
|
pipe => { |
249
|
|
|
|
|
|
|
check => sub { |
250
|
|
|
|
|
|
|
($syslog_path) = grep { defined && length && -p && -w _ } |
251
|
|
|
|
|
|
|
$syslog_path, &_PATH_LOG, "/dev/log"; |
252
|
|
|
|
|
|
|
return $syslog_path ? 1 : 0 |
253
|
|
|
|
|
|
|
}, |
254
|
|
|
|
|
|
|
err_msg => "path not available", |
255
|
|
|
|
|
|
|
}, |
256
|
|
|
|
|
|
|
stream => { |
257
|
|
|
|
|
|
|
check => sub { |
258
|
|
|
|
|
|
|
if (not defined $syslog_path) { |
259
|
|
|
|
|
|
|
my @try = qw(/dev/log /dev/conslog); |
260
|
|
|
|
|
|
|
unshift @try, &_PATH_LOG if length &_PATH_LOG; |
261
|
|
|
|
|
|
|
($syslog_path) = grep { -w } @try; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
return defined $syslog_path && -w $syslog_path |
264
|
|
|
|
|
|
|
}, |
265
|
|
|
|
|
|
|
err_msg => "could not find any writable device", |
266
|
|
|
|
|
|
|
}, |
267
|
|
|
|
|
|
|
tcp => { |
268
|
|
|
|
|
|
|
check => sub { |
269
|
|
|
|
|
|
|
return 1 if defined $sock_port; |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
if (eval { local $SIG{__DIE__}; |
272
|
|
|
|
|
|
|
getservbyname('syslog','tcp') || getservbyname('syslogng','tcp') |
273
|
|
|
|
|
|
|
}) { |
274
|
|
|
|
|
|
|
$host = $syslog_path; |
275
|
|
|
|
|
|
|
return 1 |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
else { |
278
|
|
|
|
|
|
|
return |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
}, |
281
|
|
|
|
|
|
|
err_msg => "TCP service unavailable", |
282
|
|
|
|
|
|
|
}, |
283
|
|
|
|
|
|
|
udp => { |
284
|
|
|
|
|
|
|
check => sub { |
285
|
|
|
|
|
|
|
return 1 if defined $sock_port; |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
if (eval { local $SIG{__DIE__}; getservbyname('syslog', 'udp') }) { |
288
|
|
|
|
|
|
|
$host = $syslog_path; |
289
|
|
|
|
|
|
|
return 1 |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
else { |
292
|
|
|
|
|
|
|
return |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
}, |
295
|
|
|
|
|
|
|
err_msg => "UDP service unavailable", |
296
|
|
|
|
|
|
|
}, |
297
|
|
|
|
|
|
|
unix => { |
298
|
|
|
|
|
|
|
check => sub { |
299
|
|
|
|
|
|
|
my @try = ($syslog_path, &_PATH_LOG); |
300
|
|
|
|
|
|
|
($syslog_path) = grep { defined && length && -w } @try; |
301
|
|
|
|
|
|
|
return defined $syslog_path && -w $syslog_path |
302
|
|
|
|
|
|
|
}, |
303
|
|
|
|
|
|
|
err_msg => "path not available", |
304
|
|
|
|
|
|
|
}, |
305
|
|
|
|
|
|
|
); |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
sub setlogsock { |
308
|
22
|
|
|
22
|
1
|
43178
|
my %opt; |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
# handle arguments |
311
|
|
|
|
|
|
|
# - old API: setlogsock($sock_type, $sock_path, $sock_timeout) |
312
|
|
|
|
|
|
|
# - new API: setlogsock(\%options) |
313
|
22
|
100
|
66
|
|
|
380
|
croak "setlogsock(): Invalid number of arguments" |
314
|
|
|
|
|
|
|
unless @_ >= 1 and @_ <= 3; |
315
|
|
|
|
|
|
|
|
316
|
20
|
100
|
|
|
|
50
|
if (my $ref = ref $_[0]) { |
317
|
12
|
100
|
|
|
|
35
|
if ($ref eq "HASH") { |
|
|
100
|
|
|
|
|
|
318
|
2
|
|
|
|
|
3
|
%opt = %{ $_[0] }; |
|
2
|
|
|
|
|
6
|
|
319
|
2
|
50
|
|
|
|
143
|
croak "setlogsock(): No argument given" unless keys %opt; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
elsif ($ref eq "ARRAY") { |
322
|
8
|
|
|
|
|
22
|
@opt{qw< type path timeout >} = @_; |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
else { |
325
|
2
|
|
|
|
|
171
|
croak "setlogsock(): Unexpected \L$ref\E reference" |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
else { |
329
|
8
|
|
|
|
|
25
|
@opt{qw< type path timeout >} = @_; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# check socket type, remove invalid ones |
333
|
|
|
|
|
|
|
my $diag_invalid_type = "setlogsock(): Invalid type%s; must be one of " |
334
|
16
|
|
|
|
|
87
|
. join ", ", map { "'$_'" } sort keys %mechanism; |
|
144
|
|
|
|
|
242
|
|
335
|
16
|
100
|
|
|
|
192
|
croak sprintf $diag_invalid_type, "" unless defined $opt{type}; |
336
|
14
|
100
|
|
|
|
35
|
my @sock_types = ref $opt{type} eq "ARRAY" ? @{$opt{type}} : ($opt{type}); |
|
8
|
|
|
|
|
17
|
|
337
|
14
|
|
|
|
|
19
|
my @tmp; |
338
|
|
|
|
|
|
|
|
339
|
14
|
|
|
|
|
24
|
for my $sock_type (@sock_types) { |
340
|
|
|
|
|
|
|
carp sprintf $diag_invalid_type, " '$sock_type'" and next |
341
|
14
|
50
|
0
|
|
|
25
|
unless exists $mechanism{$sock_type}; |
342
|
14
|
100
|
50
|
|
|
36
|
push @tmp, "tcp", "udp" and next if $sock_type eq "inet"; |
343
|
12
|
|
|
|
|
26
|
push @tmp, $sock_type; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
14
|
|
|
|
|
18
|
@sock_types = @tmp; |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# set global options |
349
|
14
|
100
|
|
|
|
30
|
$syslog_path = $opt{path} if defined $opt{path}; |
350
|
14
|
50
|
|
|
|
25
|
$host = $opt{host} if defined $opt{host}; |
351
|
14
|
50
|
|
|
|
33
|
$sock_timeout = $opt{timeout} if defined $opt{timeout}; |
352
|
14
|
50
|
|
|
|
24
|
$sock_port = $opt{port} if defined $opt{port}; |
353
|
|
|
|
|
|
|
|
354
|
14
|
50
|
|
|
|
23
|
disconnect_log() if $connected; |
355
|
14
|
|
|
|
|
43
|
$transmit_ok = 0; |
356
|
14
|
|
|
|
|
93
|
@fallbackMethods = (); |
357
|
14
|
|
|
|
|
41
|
@connectMethods = (); |
358
|
14
|
|
|
|
|
23
|
my $found = 0; |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
# check each given mechanism and test if it can be used on the current system |
361
|
14
|
|
|
|
|
17
|
for my $sock_type (@sock_types) { |
362
|
16
|
100
|
|
|
|
38
|
if ( $mechanism{$sock_type}{check}->() ) { |
363
|
7
|
|
|
|
|
13
|
push @connectMethods, $sock_type; |
364
|
7
|
|
|
|
|
12
|
$found = 1; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
else { |
367
|
|
|
|
|
|
|
warnings::warnif("setlogsock(): type='$sock_type': " |
368
|
9
|
|
|
|
|
498
|
. $mechanism{$sock_type}{err_msg}); |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
} |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
# if no mechanism worked from the given ones, use the default ones |
373
|
14
|
100
|
|
|
|
40
|
@connectMethods = @defaultMethods unless @connectMethods; |
374
|
|
|
|
|
|
|
|
375
|
14
|
|
|
|
|
46
|
return $found; |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
sub syslog { |
379
|
15
|
|
|
15
|
1
|
7465
|
my ($priority, $mask, @args) = @_; |
380
|
15
|
|
|
|
|
37
|
my ($message, $buf); |
381
|
15
|
|
|
|
|
0
|
my (@words, $num, $numpri, $numfac, $sum); |
382
|
15
|
|
|
|
|
20
|
my $failed = undef; |
383
|
15
|
|
|
|
|
19
|
my $fail_time = undef; |
384
|
15
|
|
|
|
|
43
|
my $error = $!; |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
# if $ident is undefined, it means openlog() wasn't previously called |
387
|
|
|
|
|
|
|
# so do it now in order to have sensible defaults |
388
|
15
|
100
|
|
|
|
46
|
openlog() unless $ident; |
389
|
|
|
|
|
|
|
|
390
|
15
|
|
|
|
|
23
|
local $facility = $facility; # may need to change temporarily. |
391
|
|
|
|
|
|
|
|
392
|
15
|
100
|
|
|
|
312
|
croak "syslog: expecting argument \$priority" unless defined $priority; |
393
|
11
|
100
|
|
|
|
163
|
croak "syslog: expecting argument \$format" unless defined $mask; |
394
|
|
|
|
|
|
|
|
395
|
9
|
100
|
|
|
|
51
|
if ($priority =~ /^\d+$/) { |
|
|
100
|
|
|
|
|
|
396
|
2
|
|
|
|
|
8
|
$numpri = LOG_PRI($priority); |
397
|
2
|
|
|
|
|
6
|
$numfac = LOG_FAC($priority) << 3; |
398
|
2
|
100
|
|
|
|
7
|
undef $numfac if $numfac == 0; # no facility given => use default |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
elsif ($priority =~ /^\w+/) { |
401
|
|
|
|
|
|
|
# Allow "level" or "level|facility". |
402
|
6
|
|
|
|
|
21
|
@words = split /\W+/, $priority, 2; |
403
|
|
|
|
|
|
|
|
404
|
6
|
|
|
|
|
10
|
undef $numpri; |
405
|
6
|
|
|
|
|
7
|
undef $numfac; |
406
|
|
|
|
|
|
|
|
407
|
6
|
|
|
|
|
13
|
for my $word (@words) { |
408
|
9
|
50
|
|
|
|
15
|
next if length $word == 0; |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
# Translate word to number. |
411
|
9
|
|
|
|
|
19
|
$num = xlate($word); |
412
|
|
|
|
|
|
|
|
413
|
9
|
100
|
66
|
|
|
54
|
if ($num < 0) { |
|
|
100
|
|
|
|
|
|
414
|
1
|
|
|
|
|
65
|
croak "syslog: invalid level/facility: $word" |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
elsif ($num <= LOG_PRIMASK() and $word ne "kern") { |
417
|
5
|
100
|
|
|
|
85
|
croak "syslog: too many levels given: $word" |
418
|
|
|
|
|
|
|
if defined $numpri; |
419
|
4
|
|
|
|
|
10
|
$numpri = $num; |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
else { |
422
|
3
|
100
|
|
|
|
81
|
croak "syslog: too many facilities given: $word" |
423
|
|
|
|
|
|
|
if defined $numfac; |
424
|
2
|
50
|
|
|
|
7
|
$facility = $word if $word =~ /^[A-Za-z]/; |
425
|
2
|
|
|
|
|
5
|
$numfac = $num; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
else { |
430
|
1
|
|
|
|
|
84
|
croak "syslog: invalid level/facility: $priority" |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
5
|
50
|
|
|
|
10
|
croak "syslog: level must be given" unless defined $numpri; |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
# don't log if priority is below mask level |
436
|
5
|
50
|
|
|
|
21
|
return 0 unless LOG_MASK($numpri) & $maskpri; |
437
|
|
|
|
|
|
|
|
438
|
5
|
100
|
|
|
|
23
|
if (not defined $numfac) { # Facility not specified in this call. |
439
|
3
|
50
|
|
|
|
27
|
$facility = 'user' unless $facility; |
440
|
3
|
|
|
|
|
18
|
$numfac = xlate($facility); |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
5
|
100
|
|
|
|
14
|
connect_log() unless $connected; |
444
|
|
|
|
|
|
|
|
445
|
5
|
100
|
|
|
|
25
|
if ($mask =~ /%m/) { |
446
|
|
|
|
|
|
|
# escape percent signs for sprintf() |
447
|
1
|
50
|
|
|
|
2
|
$error =~ s/%/%%/g if @args; |
448
|
|
|
|
|
|
|
# replace %m with $error, if preceded by an even number of percent signs |
449
|
1
|
|
|
|
|
9
|
$mask =~ s/(?
|
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
# add (or not) a newline |
453
|
5
|
50
|
33
|
|
|
42
|
$mask .= "\n" if !$options{noeol} and rindex($mask, "\n") == -1; |
454
|
5
|
50
|
|
|
|
22
|
$message = @args ? sprintf($mask, @args) : $mask; |
455
|
|
|
|
|
|
|
|
456
|
5
|
50
|
|
|
|
14
|
if ($current_proto eq 'native') { |
|
|
0
|
|
|
|
|
|
457
|
5
|
|
|
|
|
9
|
$buf = $message; |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
elsif ($current_proto eq 'eventlog') { |
460
|
0
|
|
|
|
|
0
|
$buf = $message; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
else { |
463
|
0
|
|
|
|
|
0
|
my $whoami = $ident; |
464
|
0
|
0
|
|
|
|
0
|
$whoami .= "[$$]" if $options{pid}; |
465
|
|
|
|
|
|
|
|
466
|
0
|
|
|
|
|
0
|
$sum = $numpri + $numfac; |
467
|
|
|
|
|
|
|
|
468
|
0
|
|
|
|
|
0
|
my $oldlocale; |
469
|
0
|
|
|
|
|
0
|
if (HAVE_SETLOCALE) { |
470
|
0
|
|
|
|
|
0
|
$oldlocale = setlocale(LC_TIME); |
471
|
0
|
|
|
|
|
0
|
setlocale(LC_TIME, 'C'); |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
# %e format isn't available on all systems (Win32, cf. CPAN RT #69310) |
475
|
0
|
|
|
|
|
0
|
my $day = strftime "%e", localtime; |
476
|
|
|
|
|
|
|
|
477
|
0
|
0
|
|
|
|
0
|
if (index($day, "%") == 0) { |
478
|
0
|
|
|
|
|
0
|
$day = strftime "%d", localtime; |
479
|
0
|
|
|
|
|
0
|
$day =~ s/^0/ /; |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
0
|
|
|
|
|
0
|
my $timestamp = strftime "%b $day %H:%M:%S", localtime; |
483
|
0
|
|
|
|
|
0
|
setlocale(LC_TIME, $oldlocale) if HAVE_SETLOCALE; |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
# construct the stream that will be transmitted |
486
|
0
|
|
|
|
|
0
|
$buf = "<$sum>$timestamp $whoami: $message"; |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
# add (or not) a NUL character |
489
|
0
|
0
|
|
|
|
0
|
$buf .= "\0" if !$options{nonul}; |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
# handle PERROR option |
493
|
|
|
|
|
|
|
# "native" mechanism already handles it by itself |
494
|
5
|
50
|
33
|
|
|
15
|
if ($options{perror} and $current_proto ne 'native') { |
495
|
0
|
|
|
|
|
0
|
my $whoami = $ident; |
496
|
0
|
0
|
|
|
|
0
|
$whoami .= "[$$]" if $options{pid}; |
497
|
0
|
|
|
|
|
0
|
print STDERR "$whoami: $message"; |
498
|
0
|
0
|
|
|
|
0
|
print STDERR "\n" if rindex($message, "\n") == -1; |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
# it's possible that we'll get an error from sending |
502
|
|
|
|
|
|
|
# (e.g. if method is UDP and there is no UDP listener, |
503
|
|
|
|
|
|
|
# then we'll get ECONNREFUSED on the send). So what we |
504
|
|
|
|
|
|
|
# want to do at this point is to fallback onto a different |
505
|
|
|
|
|
|
|
# connection method. |
506
|
5
|
|
66
|
|
|
18
|
while (scalar @fallbackMethods || $syslog_send) { |
507
|
5
|
50
|
33
|
|
|
12
|
if ($failed && (time - $fail_time) > 60) { |
508
|
|
|
|
|
|
|
# it's been a while... maybe things have been fixed |
509
|
0
|
|
|
|
|
0
|
@fallbackMethods = (); |
510
|
0
|
|
|
|
|
0
|
disconnect_log(); |
511
|
0
|
|
|
|
|
0
|
$transmit_ok = 0; # make it look like a fresh attempt |
512
|
0
|
|
|
|
|
0
|
connect_log(); |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
5
|
50
|
33
|
|
|
35
|
if ($connected && !connection_ok()) { |
516
|
|
|
|
|
|
|
# Something was OK, but has now broken. Remember coz we'll |
517
|
|
|
|
|
|
|
# want to go back to what used to be OK. |
518
|
0
|
0
|
|
|
|
0
|
$failed = $current_proto unless $failed; |
519
|
0
|
|
|
|
|
0
|
$fail_time = time; |
520
|
0
|
|
|
|
|
0
|
disconnect_log(); |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
|
523
|
5
|
50
|
|
|
|
10
|
connect_log() unless $connected; |
524
|
5
|
50
|
33
|
|
|
27
|
$failed = undef if ($current_proto && $failed && $current_proto eq $failed); |
|
|
|
33
|
|
|
|
|
525
|
|
|
|
|
|
|
|
526
|
5
|
50
|
|
|
|
20
|
if ($syslog_send) { |
527
|
5
|
50
|
|
|
|
15
|
if ($syslog_send->($buf, $numpri, $numfac)) { |
528
|
5
|
|
|
|
|
9
|
$transmit_ok++; |
529
|
5
|
|
|
|
|
21
|
return 1; |
530
|
|
|
|
|
|
|
} |
531
|
|
|
|
|
|
|
# typically doesn't happen, since errors are rare from write(). |
532
|
0
|
|
|
|
|
0
|
disconnect_log(); |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
} |
535
|
|
|
|
|
|
|
# could not send, could not fallback onto a working |
536
|
|
|
|
|
|
|
# connection method. Lose. |
537
|
0
|
|
|
|
|
0
|
return 0; |
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
sub _syslog_send_console { |
541
|
0
|
|
|
0
|
|
0
|
my ($buf) = @_; |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
# The console print is a method which could block |
544
|
|
|
|
|
|
|
# so we do it in a child process and always return success |
545
|
|
|
|
|
|
|
# to the caller. |
546
|
0
|
0
|
|
|
|
0
|
if (my $pid = fork) { |
547
|
|
|
|
|
|
|
|
548
|
0
|
0
|
|
|
|
0
|
if ($options{nowait}) { |
549
|
0
|
|
|
|
|
0
|
return 1; |
550
|
|
|
|
|
|
|
} else { |
551
|
0
|
0
|
|
|
|
0
|
if (waitpid($pid, 0) >= 0) { |
552
|
0
|
|
|
|
|
0
|
return ($? >> 8); |
553
|
|
|
|
|
|
|
} else { |
554
|
|
|
|
|
|
|
# it's possible that the caller has other |
555
|
|
|
|
|
|
|
# plans for SIGCHLD, so let's not interfere |
556
|
0
|
|
|
|
|
0
|
return 1; |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
} |
559
|
|
|
|
|
|
|
} else { |
560
|
0
|
0
|
|
|
|
0
|
if (open(CONS, ">/dev/console")) { |
561
|
0
|
|
|
|
|
0
|
my $ret = print CONS $buf . "\r"; # XXX: should this be \x0A ? |
562
|
0
|
0
|
|
|
|
0
|
POSIX::_exit($ret) if defined $pid; |
563
|
0
|
|
|
|
|
0
|
close CONS; |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
|
566
|
0
|
0
|
|
|
|
0
|
POSIX::_exit(0) if defined $pid; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
sub _syslog_send_stream { |
571
|
0
|
|
|
0
|
|
0
|
my ($buf) = @_; |
572
|
|
|
|
|
|
|
# XXX: this only works if the OS stream implementation makes a write |
573
|
|
|
|
|
|
|
# look like a putmsg() with simple header. For instance it works on |
574
|
|
|
|
|
|
|
# Solaris 8 but not Solaris 7. |
575
|
|
|
|
|
|
|
# To be correct, it should use a STREAMS API, but perl doesn't have one. |
576
|
0
|
|
|
|
|
0
|
return syswrite(SYSLOG, $buf, length($buf)); |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub _syslog_send_pipe { |
580
|
0
|
|
|
0
|
|
0
|
my ($buf) = @_; |
581
|
0
|
|
|
|
|
0
|
return print SYSLOG $buf; |
582
|
|
|
|
|
|
|
} |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
sub _syslog_send_socket { |
585
|
2
|
|
|
2
|
|
5
|
my ($buf) = @_; |
586
|
2
|
|
|
|
|
134
|
return syswrite(SYSLOG, $buf, length($buf)); |
587
|
|
|
|
|
|
|
#return send(SYSLOG, $buf, 0); |
588
|
|
|
|
|
|
|
} |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
sub _syslog_send_native { |
591
|
5
|
|
|
5
|
|
13
|
my ($buf, $numpri, $numfac) = @_; |
592
|
5
|
|
|
|
|
290
|
syslog_xs($numpri|$numfac, $buf); |
593
|
5
|
|
|
|
|
24
|
return 1; |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
# xlate() |
598
|
|
|
|
|
|
|
# ----- |
599
|
|
|
|
|
|
|
# private function to translate names to numeric values |
600
|
|
|
|
|
|
|
# |
601
|
|
|
|
|
|
|
sub xlate { |
602
|
22
|
|
|
22
|
0
|
39
|
my ($name) = @_; |
603
|
|
|
|
|
|
|
|
604
|
22
|
50
|
|
|
|
59
|
return $name+0 if $name =~ /^\s*\d+\s*$/; |
605
|
22
|
|
|
|
|
37
|
$name = uc $name; |
606
|
22
|
50
|
|
|
|
52
|
$name = "LOG_$name" unless $name =~ /^LOG_/; |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
# ExtUtils::Constant 0.20 introduced a new way to implement |
609
|
|
|
|
|
|
|
# constants, called ProxySubs. When it was used to generate |
610
|
|
|
|
|
|
|
# the C code, the constant() function no longer returns the |
611
|
|
|
|
|
|
|
# correct value. Therefore, we first try a direct call to |
612
|
|
|
|
|
|
|
# constant(), and if the value is an error we try to call the |
613
|
|
|
|
|
|
|
# constant by its full name. |
614
|
22
|
|
|
|
|
80
|
my $value = constant($name); |
615
|
|
|
|
|
|
|
|
616
|
22
|
50
|
|
|
|
55
|
if (index($value, "not a valid") >= 0) { |
617
|
22
|
|
|
|
|
34
|
$name = "Sys::Syslog::$name"; |
618
|
11
|
|
|
11
|
|
79
|
$value = eval { no strict "refs"; &$name }; |
|
11
|
|
|
|
|
19
|
|
|
11
|
|
|
|
|
1395
|
|
|
22
|
|
|
|
|
27
|
|
|
22
|
|
|
|
|
86
|
|
619
|
22
|
100
|
|
|
|
53
|
$value = $@ unless defined $value; |
620
|
|
|
|
|
|
|
} |
621
|
|
|
|
|
|
|
|
622
|
22
|
100
|
|
|
|
53
|
$value = -1 if index($value, "not a valid") >= 0; |
623
|
|
|
|
|
|
|
|
624
|
22
|
50
|
|
|
|
186
|
return defined $value ? $value : -1; |
625
|
|
|
|
|
|
|
} |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
# connect_log() |
629
|
|
|
|
|
|
|
# ----------- |
630
|
|
|
|
|
|
|
# This function acts as a kind of front-end: it tries to connect to |
631
|
|
|
|
|
|
|
# a syslog service using the selected methods, trying each one in the |
632
|
|
|
|
|
|
|
# selected order. |
633
|
|
|
|
|
|
|
# |
634
|
|
|
|
|
|
|
sub connect_log { |
635
|
7
|
50
|
|
7
|
0
|
30
|
@fallbackMethods = @connectMethods unless scalar @fallbackMethods; |
636
|
|
|
|
|
|
|
|
637
|
7
|
50
|
33
|
|
|
25
|
if ($transmit_ok && $current_proto) { |
638
|
|
|
|
|
|
|
# Retry what we were on, because it has worked in the past. |
639
|
0
|
|
|
|
|
0
|
unshift(@fallbackMethods, $current_proto); |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
|
642
|
7
|
|
|
|
|
24
|
$connected = 0; |
643
|
7
|
|
|
|
|
11
|
my @errs = (); |
644
|
7
|
|
|
|
|
13
|
my $proto = undef; |
645
|
|
|
|
|
|
|
|
646
|
7
|
|
|
|
|
19
|
while ($proto = shift @fallbackMethods) { |
647
|
11
|
|
|
11
|
|
72
|
no strict 'refs'; |
|
11
|
|
|
|
|
15
|
|
|
11
|
|
|
|
|
15856
|
|
648
|
7
|
|
|
|
|
19
|
my $fn = "connect_$proto"; |
649
|
7
|
50
|
|
|
|
137
|
$connected = &$fn(\@errs) if defined &$fn; |
650
|
7
|
100
|
|
|
|
36
|
last if $connected; |
651
|
|
|
|
|
|
|
} |
652
|
|
|
|
|
|
|
|
653
|
7
|
|
|
|
|
13
|
$transmit_ok = 0; |
654
|
7
|
100
|
|
|
|
24
|
if ($connected) { |
655
|
4
|
|
|
|
|
6
|
$current_proto = $proto; |
656
|
4
|
|
|
|
|
18
|
my ($old) = select(SYSLOG); $| = 1; select($old); |
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
24
|
|
657
|
|
|
|
|
|
|
} else { |
658
|
3
|
|
|
|
|
6
|
@fallbackMethods = (); |
659
|
3
|
|
|
|
|
374
|
$err_sub->(join "\n\t- ", "no connection to syslog available", @errs); |
660
|
0
|
|
|
|
|
0
|
return undef; |
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
} |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
sub connect_tcp { |
665
|
0
|
|
|
0
|
0
|
0
|
my ($errs) = @_; |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
my $port = $sock_port |
668
|
|
|
|
|
|
|
|| eval { local $SIG{__DIE__}; getservbyname('syslog', 'tcp') } |
669
|
0
|
|
0
|
|
|
0
|
|| eval { local $SIG{__DIE__}; getservbyname('syslogng', 'tcp') }; |
670
|
0
|
0
|
|
|
|
0
|
if (!defined $port) { |
671
|
0
|
|
|
|
|
0
|
push @$errs, "getservbyname failed for syslog/tcp and syslogng/tcp"; |
672
|
0
|
|
|
|
|
0
|
return 0; |
673
|
|
|
|
|
|
|
} |
674
|
|
|
|
|
|
|
|
675
|
0
|
|
|
|
|
0
|
my $addr; |
676
|
0
|
0
|
|
|
|
0
|
if (defined $host) { |
677
|
0
|
|
|
|
|
0
|
$addr = inet_aton($host); |
678
|
0
|
0
|
|
|
|
0
|
if (!$addr) { |
679
|
0
|
|
|
|
|
0
|
push @$errs, "can't lookup $host"; |
680
|
0
|
|
|
|
|
0
|
return 0; |
681
|
|
|
|
|
|
|
} |
682
|
|
|
|
|
|
|
} else { |
683
|
0
|
|
|
|
|
0
|
$addr = INADDR_LOOPBACK; |
684
|
|
|
|
|
|
|
} |
685
|
0
|
|
|
|
|
0
|
$addr = sockaddr_in($port, $addr); |
686
|
|
|
|
|
|
|
|
687
|
0
|
0
|
|
|
|
0
|
if (!socket(SYSLOG, AF_INET, SOCK_STREAM, SOCKET_IPPROTO_TCP)) { |
688
|
0
|
|
|
|
|
0
|
push @$errs, "tcp socket: $!"; |
689
|
0
|
|
|
|
|
0
|
return 0; |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
|
692
|
0
|
|
|
|
|
0
|
setsockopt(SYSLOG, SOL_SOCKET, SO_KEEPALIVE, 1); |
693
|
0
|
|
|
|
|
0
|
setsockopt(SYSLOG, SOCKET_IPPROTO_TCP, SOCKET_TCP_NODELAY, 1); |
694
|
|
|
|
|
|
|
|
695
|
0
|
0
|
|
|
|
0
|
if (!connect(SYSLOG, $addr)) { |
696
|
0
|
|
|
|
|
0
|
push @$errs, "tcp connect: $!"; |
697
|
0
|
|
|
|
|
0
|
return 0; |
698
|
|
|
|
|
|
|
} |
699
|
|
|
|
|
|
|
|
700
|
0
|
|
|
|
|
0
|
$syslog_send = \&_syslog_send_socket; |
701
|
|
|
|
|
|
|
|
702
|
0
|
|
|
|
|
0
|
return 1; |
703
|
|
|
|
|
|
|
} |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
sub connect_udp { |
706
|
2
|
|
|
2
|
0
|
5
|
my ($errs) = @_; |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
my $port = $sock_port |
709
|
2
|
|
33
|
|
|
6
|
|| eval { local $SIG{__DIE__}; getservbyname('syslog', 'udp') }; |
710
|
2
|
50
|
|
|
|
9
|
if (!defined $port) { |
711
|
0
|
|
|
|
|
0
|
push @$errs, "getservbyname failed for syslog/udp"; |
712
|
0
|
|
|
|
|
0
|
return 0; |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
|
715
|
2
|
|
|
|
|
3
|
my $addr; |
716
|
2
|
50
|
|
|
|
5
|
if (defined $host) { |
717
|
0
|
|
|
|
|
0
|
$addr = inet_aton($host); |
718
|
0
|
0
|
|
|
|
0
|
if (!$addr) { |
719
|
0
|
|
|
|
|
0
|
push @$errs, "can't lookup $host"; |
720
|
0
|
|
|
|
|
0
|
return 0; |
721
|
|
|
|
|
|
|
} |
722
|
|
|
|
|
|
|
} else { |
723
|
2
|
|
|
|
|
4
|
$addr = INADDR_LOOPBACK; |
724
|
|
|
|
|
|
|
} |
725
|
2
|
|
|
|
|
9
|
$addr = sockaddr_in($port, $addr); |
726
|
|
|
|
|
|
|
|
727
|
2
|
50
|
|
|
|
106
|
if (!socket(SYSLOG, AF_INET, SOCK_DGRAM, SOCKET_IPPROTO_UDP)) { |
728
|
0
|
|
|
|
|
0
|
push @$errs, "udp socket: $!"; |
729
|
0
|
|
|
|
|
0
|
return 0; |
730
|
|
|
|
|
|
|
} |
731
|
2
|
50
|
|
|
|
41
|
if (!connect(SYSLOG, $addr)) { |
732
|
0
|
|
|
|
|
0
|
push @$errs, "udp connect: $!"; |
733
|
0
|
|
|
|
|
0
|
return 0; |
734
|
|
|
|
|
|
|
} |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
# We want to check that the UDP connect worked. However the only |
737
|
|
|
|
|
|
|
# way to do that is to send a message and see if an ICMP is returned |
738
|
2
|
|
|
|
|
9
|
_syslog_send_socket(""); |
739
|
2
|
50
|
|
|
|
57
|
if (!connection_ok()) { |
740
|
2
|
|
|
|
|
5
|
push @$errs, "udp connect: nobody listening"; |
741
|
2
|
|
|
|
|
6
|
return 0; |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
|
744
|
0
|
|
|
|
|
0
|
$syslog_send = \&_syslog_send_socket; |
745
|
|
|
|
|
|
|
|
746
|
0
|
|
|
|
|
0
|
return 1; |
747
|
|
|
|
|
|
|
} |
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
sub connect_stream { |
750
|
1
|
|
|
1
|
0
|
3
|
my ($errs) = @_; |
751
|
|
|
|
|
|
|
# might want syslog_path to be variable based on syslog.h (if only |
752
|
|
|
|
|
|
|
# it were in there!) |
753
|
1
|
50
|
|
|
|
3
|
$syslog_path = '/dev/conslog' unless defined $syslog_path; |
754
|
|
|
|
|
|
|
|
755
|
1
|
50
|
|
|
|
16
|
if (!-w $syslog_path) { |
756
|
1
|
|
|
|
|
4
|
push @$errs, "stream $syslog_path is not writable"; |
757
|
1
|
|
|
|
|
3
|
return 0; |
758
|
|
|
|
|
|
|
} |
759
|
|
|
|
|
|
|
|
760
|
0
|
|
|
|
|
0
|
require Fcntl; |
761
|
|
|
|
|
|
|
|
762
|
0
|
0
|
|
|
|
0
|
if (!sysopen(SYSLOG, $syslog_path, Fcntl::O_WRONLY(), 0400)) { |
763
|
0
|
|
|
|
|
0
|
push @$errs, "stream can't open $syslog_path: $!"; |
764
|
0
|
|
|
|
|
0
|
return 0; |
765
|
|
|
|
|
|
|
} |
766
|
|
|
|
|
|
|
|
767
|
0
|
|
|
|
|
0
|
$syslog_send = \&_syslog_send_stream; |
768
|
|
|
|
|
|
|
|
769
|
0
|
|
|
|
|
0
|
return 1; |
770
|
|
|
|
|
|
|
} |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
sub connect_pipe { |
773
|
0
|
|
|
0
|
0
|
0
|
my ($errs) = @_; |
774
|
|
|
|
|
|
|
|
775
|
0
|
|
0
|
|
|
0
|
$syslog_path ||= &_PATH_LOG || "/dev/log"; |
|
|
|
0
|
|
|
|
|
776
|
|
|
|
|
|
|
|
777
|
0
|
0
|
|
|
|
0
|
if (not -w $syslog_path) { |
778
|
0
|
|
|
|
|
0
|
push @$errs, "$syslog_path is not writable"; |
779
|
0
|
|
|
|
|
0
|
return 0; |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
|
782
|
0
|
0
|
|
|
|
0
|
if (not open(SYSLOG, ">$syslog_path")) { |
783
|
0
|
|
|
|
|
0
|
push @$errs, "can't write to $syslog_path: $!"; |
784
|
0
|
|
|
|
|
0
|
return 0; |
785
|
|
|
|
|
|
|
} |
786
|
|
|
|
|
|
|
|
787
|
0
|
|
|
|
|
0
|
$syslog_send = \&_syslog_send_pipe; |
788
|
|
|
|
|
|
|
|
789
|
0
|
|
|
|
|
0
|
return 1; |
790
|
|
|
|
|
|
|
} |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
sub connect_unix { |
793
|
0
|
|
|
0
|
0
|
0
|
my ($errs) = @_; |
794
|
|
|
|
|
|
|
|
795
|
0
|
0
|
0
|
|
|
0
|
$syslog_path ||= _PATH_LOG() if length _PATH_LOG(); |
796
|
|
|
|
|
|
|
|
797
|
0
|
0
|
|
|
|
0
|
if (not defined $syslog_path) { |
798
|
0
|
|
|
|
|
0
|
push @$errs, "_PATH_LOG not available in syslog.h and no user-supplied socket path"; |
799
|
0
|
|
|
|
|
0
|
return 0; |
800
|
|
|
|
|
|
|
} |
801
|
|
|
|
|
|
|
|
802
|
0
|
0
|
0
|
|
|
0
|
if (not (-S $syslog_path or -c _)) { |
803
|
0
|
|
|
|
|
0
|
push @$errs, "$syslog_path is not a socket"; |
804
|
0
|
|
|
|
|
0
|
return 0; |
805
|
|
|
|
|
|
|
} |
806
|
|
|
|
|
|
|
|
807
|
0
|
|
|
|
|
0
|
my $addr = sockaddr_un($syslog_path); |
808
|
0
|
0
|
|
|
|
0
|
if (!$addr) { |
809
|
0
|
|
|
|
|
0
|
push @$errs, "can't locate $syslog_path"; |
810
|
0
|
|
|
|
|
0
|
return 0; |
811
|
|
|
|
|
|
|
} |
812
|
0
|
0
|
|
|
|
0
|
if (!socket(SYSLOG, AF_UNIX, SOCK_STREAM, 0)) { |
813
|
0
|
|
|
|
|
0
|
push @$errs, "unix stream socket: $!"; |
814
|
0
|
|
|
|
|
0
|
return 0; |
815
|
|
|
|
|
|
|
} |
816
|
|
|
|
|
|
|
|
817
|
0
|
0
|
|
|
|
0
|
if (!connect(SYSLOG, $addr)) { |
818
|
0
|
0
|
|
|
|
0
|
if (!socket(SYSLOG, AF_UNIX, SOCK_DGRAM, 0)) { |
819
|
0
|
|
|
|
|
0
|
push @$errs, "unix dgram socket: $!"; |
820
|
0
|
|
|
|
|
0
|
return 0; |
821
|
|
|
|
|
|
|
} |
822
|
0
|
0
|
|
|
|
0
|
if (!connect(SYSLOG, $addr)) { |
823
|
0
|
|
|
|
|
0
|
push @$errs, "unix dgram connect: $!"; |
824
|
0
|
|
|
|
|
0
|
return 0; |
825
|
|
|
|
|
|
|
} |
826
|
|
|
|
|
|
|
} |
827
|
|
|
|
|
|
|
|
828
|
0
|
|
|
|
|
0
|
$syslog_send = \&_syslog_send_socket; |
829
|
|
|
|
|
|
|
|
830
|
0
|
|
|
|
|
0
|
return 1; |
831
|
|
|
|
|
|
|
} |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
sub connect_native { |
834
|
4
|
|
|
4
|
0
|
8
|
my ($errs) = @_; |
835
|
4
|
|
|
|
|
7
|
my $logopt = 0; |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
# reconstruct the numeric equivalent of the options |
838
|
4
|
|
|
|
|
16
|
for my $opt (keys %options) { |
839
|
24
|
100
|
|
|
|
48
|
$logopt += xlate($opt) if $options{$opt} |
840
|
|
|
|
|
|
|
} |
841
|
|
|
|
|
|
|
|
842
|
4
|
|
|
|
|
11
|
openlog_xs($ident, $logopt, xlate($facility)); |
843
|
4
|
|
|
|
|
61
|
$syslog_send = \&_syslog_send_native; |
844
|
|
|
|
|
|
|
|
845
|
4
|
|
|
|
|
44
|
return 1; |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
sub connect_eventlog { |
849
|
0
|
|
|
0
|
0
|
0
|
my ($errs) = @_; |
850
|
|
|
|
|
|
|
|
851
|
0
|
|
|
|
|
0
|
$syslog_xobj = Sys::Syslog::Win32::_install(); |
852
|
0
|
|
|
|
|
0
|
$syslog_send = \&Sys::Syslog::Win32::_syslog_send; |
853
|
|
|
|
|
|
|
|
854
|
0
|
|
|
|
|
0
|
return 1; |
855
|
|
|
|
|
|
|
} |
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
sub connect_console { |
858
|
0
|
|
|
0
|
0
|
0
|
my ($errs) = @_; |
859
|
0
|
0
|
|
|
|
0
|
if (!-w '/dev/console') { |
860
|
0
|
|
|
|
|
0
|
push @$errs, "console is not writable"; |
861
|
0
|
|
|
|
|
0
|
return 0; |
862
|
|
|
|
|
|
|
} |
863
|
0
|
|
|
|
|
0
|
$syslog_send = \&_syslog_send_console; |
864
|
0
|
|
|
|
|
0
|
return 1; |
865
|
|
|
|
|
|
|
} |
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
# To test if the connection is still good, we need to check if any |
868
|
|
|
|
|
|
|
# errors are present on the connection. The errors will not be raised |
869
|
|
|
|
|
|
|
# by a write. Instead, sockets are made readable and the next read |
870
|
|
|
|
|
|
|
# would cause the error to be returned. Unfortunately the syslog |
871
|
|
|
|
|
|
|
# 'protocol' never provides anything for us to read. But with |
872
|
|
|
|
|
|
|
# judicious use of select(), we can see if it would be readable... |
873
|
|
|
|
|
|
|
sub connection_ok { |
874
|
7
|
0
|
33
|
7
|
0
|
35
|
return 1 if defined $current_proto and ( |
|
|
|
66
|
|
|
|
|
875
|
|
|
|
|
|
|
$current_proto eq 'native' or $current_proto eq 'console' |
876
|
|
|
|
|
|
|
or $current_proto eq 'eventlog' |
877
|
|
|
|
|
|
|
); |
878
|
|
|
|
|
|
|
|
879
|
2
|
|
|
|
|
5
|
my $rin = ''; |
880
|
2
|
|
|
|
|
11
|
vec($rin, fileno(SYSLOG), 1) = 1; |
881
|
2
|
|
|
|
|
23
|
my $ret = select $rin, undef, $rin, $sock_timeout; |
882
|
2
|
50
|
|
|
|
10
|
return ($ret ? 0 : 1); |
883
|
|
|
|
|
|
|
} |
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
sub disconnect_log { |
886
|
3
|
|
|
3
|
0
|
7
|
$connected = 0; |
887
|
3
|
|
|
|
|
5
|
$syslog_send = undef; |
888
|
|
|
|
|
|
|
|
889
|
3
|
50
|
33
|
|
|
29
|
if (defined $current_proto and $current_proto eq 'native') { |
|
|
0
|
0
|
|
|
|
|
890
|
3
|
|
|
|
|
58
|
closelog_xs(); |
891
|
3
|
|
|
|
|
7
|
unshift @fallbackMethods, $current_proto; |
892
|
3
|
|
|
|
|
6
|
$current_proto = undef; |
893
|
3
|
|
|
|
|
5
|
return 1; |
894
|
|
|
|
|
|
|
} |
895
|
|
|
|
|
|
|
elsif (defined $current_proto and $current_proto eq 'eventlog') { |
896
|
0
|
|
|
|
|
0
|
$syslog_xobj->Close(); |
897
|
0
|
|
|
|
|
0
|
unshift @fallbackMethods, $current_proto; |
898
|
0
|
|
|
|
|
0
|
$current_proto = undef; |
899
|
0
|
|
|
|
|
0
|
return 1; |
900
|
|
|
|
|
|
|
} |
901
|
|
|
|
|
|
|
|
902
|
0
|
|
|
|
|
0
|
return close SYSLOG; |
903
|
|
|
|
|
|
|
} |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
# |
907
|
|
|
|
|
|
|
# Wrappers around eval() that makes sure that nobody, ever knows that |
908
|
|
|
|
|
|
|
# we wanted to poke & test if something was here or not. This is needed |
909
|
|
|
|
|
|
|
# because some applications are trying to be too smart, install their |
910
|
|
|
|
|
|
|
# own __DIE__ handler, and mysteriously, things are starting to fail |
911
|
|
|
|
|
|
|
# when they shouldn't. SpamAssassin among them. |
912
|
|
|
|
|
|
|
# |
913
|
|
|
|
|
|
|
sub silent_eval (&) { |
914
|
0
|
|
|
0
|
0
|
0
|
local($SIG{__DIE__}, $SIG{__WARN__}, $@); |
915
|
0
|
|
|
|
|
0
|
return eval { $_[0]->() } |
|
0
|
|
|
|
|
0
|
|
916
|
|
|
|
|
|
|
} |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
sub can_load_sys_syslog_win32 { |
919
|
12
|
|
|
12
|
0
|
25
|
my ($verbose) = @_; |
920
|
12
|
|
|
|
|
53
|
local($SIG{__DIE__}, $SIG{__WARN__}, $@); |
921
|
12
|
|
|
|
|
70
|
(my $module_path = __FILE__) =~ s:Syslog.pm$:Syslog/Win32.pm:; |
922
|
12
|
50
|
|
|
|
25
|
my $loaded = eval { require $module_path } ? 1 : 0; |
|
12
|
|
|
|
|
355
|
|
923
|
12
|
50
|
33
|
|
|
66
|
warn $@ if not $loaded and $verbose; |
924
|
12
|
|
|
|
|
71
|
return $loaded |
925
|
|
|
|
|
|
|
} |
926
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
"Eighth Rule: read the documentation." |
929
|
|
|
|
|
|
|
|
930
|
|
|
|
|
|
|
__END__ |