xref: /openbsd-src/gnu/usr.bin/perl/cpan/Sys-Syslog/Syslog.pm (revision 56d68f1e19ff848c889ecfa71d3a06340ff64892)
1b39c5158Smillertpackage Sys::Syslog;
2b39c5158Smillertuse strict;
3b39c5158Smillertuse warnings;
4b39c5158Smillertuse warnings::register;
5b39c5158Smillertuse Carp;
69f11ffb7Safresh1use Config;
79f11ffb7Safresh1use Exporter        ();
8b39c5158Smillertuse File::Basename;
9898184e3Ssthenuse POSIX           qw< strftime setlocale LC_TIME >;
10898184e3Ssthenuse Socket          qw< :all >;
11b39c5158Smillertrequire 5.005;
12b39c5158Smillert
13898184e3Ssthen
149f11ffb7Safresh1*import = \&Exporter::import;
159f11ffb7Safresh1
169f11ffb7Safresh1
17b39c5158Smillert{   no strict 'vars';
18*56d68f1eSafresh1    $VERSION = '0.36';
19b39c5158Smillert
20b39c5158Smillert    %EXPORT_TAGS = (
21b39c5158Smillert        standard => [qw(openlog syslog closelog setlogmask)],
22b39c5158Smillert        extended => [qw(setlogsock)],
23b39c5158Smillert        macros => [
24b39c5158Smillert            # levels
25b39c5158Smillert            qw(
26b39c5158Smillert                LOG_ALERT LOG_CRIT LOG_DEBUG LOG_EMERG LOG_ERR
27b39c5158Smillert                LOG_INFO LOG_NOTICE LOG_WARNING
28b39c5158Smillert            ),
29b39c5158Smillert
30b39c5158Smillert            # standard facilities
31b39c5158Smillert            qw(
32b39c5158Smillert                LOG_AUTH LOG_AUTHPRIV LOG_CRON LOG_DAEMON LOG_FTP LOG_KERN
33b39c5158Smillert                LOG_LOCAL0 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4
34b39c5158Smillert                LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7 LOG_LPR LOG_MAIL LOG_NEWS
35b39c5158Smillert                LOG_SYSLOG LOG_USER LOG_UUCP
36b39c5158Smillert            ),
37b39c5158Smillert            # Mac OS X specific facilities
38b39c5158Smillert            qw( LOG_INSTALL LOG_LAUNCHD LOG_NETINFO LOG_RAS LOG_REMOTEAUTH ),
39b39c5158Smillert            # modern BSD specific facilities
40b39c5158Smillert            qw( LOG_CONSOLE LOG_NTP LOG_SECURITY ),
41b39c5158Smillert            # IRIX specific facilities
42b39c5158Smillert            qw( LOG_AUDIT LOG_LFMT ),
43b39c5158Smillert
44b39c5158Smillert            # options
45b39c5158Smillert            qw(
46b39c5158Smillert                LOG_CONS LOG_PID LOG_NDELAY LOG_NOWAIT LOG_ODELAY LOG_PERROR
47b39c5158Smillert            ),
48b39c5158Smillert
49b39c5158Smillert            # others macros
50b39c5158Smillert            qw(
51b39c5158Smillert                LOG_FACMASK LOG_NFACILITIES LOG_PRIMASK
52b39c5158Smillert                LOG_MASK LOG_UPTO
53b39c5158Smillert            ),
54b39c5158Smillert        ],
55b39c5158Smillert    );
56b39c5158Smillert
57b39c5158Smillert    @EXPORT = (
58b39c5158Smillert        @{$EXPORT_TAGS{standard}},
59b39c5158Smillert    );
60b39c5158Smillert
61b39c5158Smillert    @EXPORT_OK = (
62b39c5158Smillert        @{$EXPORT_TAGS{extended}},
63b39c5158Smillert        @{$EXPORT_TAGS{macros}},
64b39c5158Smillert    );
65b39c5158Smillert
66b39c5158Smillert    eval {
67b39c5158Smillert        require XSLoader;
68b39c5158Smillert        XSLoader::load('Sys::Syslog', $VERSION);
69b39c5158Smillert        1
70b39c5158Smillert    } or do {
71b39c5158Smillert        require DynaLoader;
72b39c5158Smillert        push @ISA, 'DynaLoader';
73b39c5158Smillert        bootstrap Sys::Syslog $VERSION;
74b39c5158Smillert    };
75b39c5158Smillert}
76b39c5158Smillert
77b39c5158Smillert
78b39c5158Smillert#
799f11ffb7Safresh1# Constants
809f11ffb7Safresh1#
819f11ffb7Safresh1use constant HAVE_GETPROTOBYNAME     => $Config::Config{d_getpbyname};
829f11ffb7Safresh1use constant HAVE_GETPROTOBYNUMBER   => $Config::Config{d_getpbynumber};
839f11ffb7Safresh1use constant HAVE_SETLOCALE          => $Config::Config{d_setlocale};
849f11ffb7Safresh1use constant HAVE_IPPROTO_TCP        => defined &Socket::IPPROTO_TCP ? 1 : 0;
859f11ffb7Safresh1use constant HAVE_IPPROTO_UDP        => defined &Socket::IPPROTO_UDP ? 1 : 0;
869f11ffb7Safresh1use constant HAVE_TCP_NODELAY        => defined &Socket::TCP_NODELAY ? 1 : 0;
879f11ffb7Safresh1
889f11ffb7Safresh1use constant SOCKET_IPPROTO_TCP =>
899f11ffb7Safresh1      HAVE_IPPROTO_TCP      ? Socket::IPPROTO_TCP
909f11ffb7Safresh1    : HAVE_GETPROTOBYNAME   ? scalar getprotobyname("tcp")
919f11ffb7Safresh1    : 6;
929f11ffb7Safresh1
939f11ffb7Safresh1use constant SOCKET_IPPROTO_UDP =>
949f11ffb7Safresh1      HAVE_IPPROTO_UDP      ? Socket::IPPROTO_UDP
959f11ffb7Safresh1    : HAVE_GETPROTOBYNAME   ? scalar getprotobyname("udp")
969f11ffb7Safresh1    : 17;
979f11ffb7Safresh1
989f11ffb7Safresh1use constant SOCKET_TCP_NODELAY => HAVE_TCP_NODELAY ? Socket::TCP_NODELAY : 1;
999f11ffb7Safresh1
1009f11ffb7Safresh1
1019f11ffb7Safresh1#
102b39c5158Smillert# Public variables
103b39c5158Smillert#
104b39c5158Smillertuse vars qw($host);             # host to send syslog messages to (see notes at end)
105b39c5158Smillert
106b39c5158Smillert#
107b39c5158Smillert# Prototypes
108b39c5158Smillert#
109b39c5158Smillertsub silent_eval (&);
110b39c5158Smillert
111b39c5158Smillert#
112b39c5158Smillert# Global variables
113b39c5158Smillert#
114b39c5158Smillertuse vars qw($facility);
115b39c5158Smillertmy $connected       = 0;        # flag to indicate if we're connected or not
116b39c5158Smillertmy $syslog_send;                # coderef of the function used to send messages
117b39c5158Smillertmy $syslog_path     = undef;    # syslog path for "stream" and "unix" mechanisms
118b39c5158Smillertmy $syslog_xobj     = undef;    # if defined, holds the external object used to send messages
11991f110e0Safresh1my $transmit_ok     = 0;        # flag to indicate if the last message was transmitted
120898184e3Ssthenmy $sock_port       = undef;    # socket port
121b39c5158Smillertmy $sock_timeout    = 0;        # socket timeout, see below
122b39c5158Smillertmy $current_proto   = undef;    # current mechanism used to transmit messages
123b39c5158Smillertmy $ident           = '';       # identifiant prepended to each message
124b39c5158Smillert$facility           = '';       # current facility
125b39c5158Smillertmy $maskpri         = LOG_UPTO(&LOG_DEBUG);     # current log mask
126b39c5158Smillert
127b39c5158Smillertmy %options = (
128b39c5158Smillert    ndelay  => 0,
129898184e3Ssthen    noeol   => 0,
130b39c5158Smillert    nofatal => 0,
131898184e3Ssthen    nonul   => 0,
132b39c5158Smillert    nowait  => 0,
133b39c5158Smillert    perror  => 0,
134b39c5158Smillert    pid     => 0,
135b39c5158Smillert);
136b39c5158Smillert
137b39c5158Smillert# Default is now to first use the native mechanism, so Perl programs
138b39c5158Smillert# behave like other normal Unix programs, then try other mechanisms.
139b39c5158Smillertmy @connectMethods = qw(native tcp udp unix pipe stream console);
140898184e3Ssthenif ($^O eq "freebsd" or $^O eq "linux") {
141b39c5158Smillert    @connectMethods = grep { $_ ne 'udp' } @connectMethods;
142b39c5158Smillert}
143b39c5158Smillert
144b39c5158Smillert# And on Win32 systems, we try to use the native mechanism for this
145b39c5158Smillert# platform, the events logger, available through Win32::EventLog.
146b39c5158SmillertEVENTLOG: {
1479f11ffb7Safresh1    my $verbose_if_Win32 = $^O =~ /Win32/i;
148b39c5158Smillert
1499f11ffb7Safresh1    if (can_load_sys_syslog_win32($verbose_if_Win32)) {
150b39c5158Smillert        unshift @connectMethods, 'eventlog';
151b39c5158Smillert    }
152b39c5158Smillert}
153b39c5158Smillert
154b39c5158Smillertmy @defaultMethods = @connectMethods;
155b39c5158Smillertmy @fallbackMethods = ();
156b39c5158Smillert
157b39c5158Smillert# The timeout in connection_ok() was pushed up to 0.25 sec in
158b39c5158Smillert# Sys::Syslog v0.19 in order to address a heisenbug on MacOSX:
159b39c5158Smillert# http://london.pm.org/pipermail/london.pm/Week-of-Mon-20061211/005961.html
160b39c5158Smillert#
161b39c5158Smillert# However, this also had the effect of slowing this test for
162b39c5158Smillert# all other operating systems, which apparently impacted some
163b39c5158Smillert# users (cf. CPAN-RT #34753). So, in order to make everybody
164b39c5158Smillert# happy, the timeout is now zero by default on all systems
165b39c5158Smillert# except on OSX where it is set to 250 msec, and can be set
166b39c5158Smillert# with the infamous setlogsock() function.
16791f110e0Safresh1#
16891f110e0Safresh1# Update 2011-08: this issue is also been seen on multiprocessor
16991f110e0Safresh1# Debian GNU/kFreeBSD systems. See http://bugs.debian.org/627821
17091f110e0Safresh1# and https://rt.cpan.org/Ticket/Display.html?id=69997
17191f110e0Safresh1# Also, lowering the delay to 1 ms, which should be enough.
17291f110e0Safresh1
17391f110e0Safresh1$sock_timeout = 0.001 if $^O =~ /darwin|gnukfreebsd/;
17491f110e0Safresh1
17591f110e0Safresh1
17691f110e0Safresh1# Perl 5.6.0's warnings.pm doesn't have warnings::warnif()
17791f110e0Safresh1if (not defined &warnings::warnif) {
17891f110e0Safresh1    *warnings::warnif = sub {
17991f110e0Safresh1        goto &warnings::warn if warnings::enabled(__PACKAGE__)
18091f110e0Safresh1    }
18191f110e0Safresh1}
182b39c5158Smillert
183b39c5158Smillert# coderef for a nicer handling of errors
184b39c5158Smillertmy $err_sub = $options{nofatal} ? \&warnings::warnif : \&croak;
185b39c5158Smillert
186b39c5158Smillert
187b39c5158Smillertsub AUTOLOAD {
188b39c5158Smillert    # This AUTOLOAD is used to 'autoload' constants from the constant()
189b39c5158Smillert    # XS function.
190b39c5158Smillert    no strict 'vars';
191b39c5158Smillert    my $constname;
192b39c5158Smillert    ($constname = $AUTOLOAD) =~ s/.*:://;
193b39c5158Smillert    croak "Sys::Syslog::constant() not defined" if $constname eq 'constant';
194b39c5158Smillert    my ($error, $val) = constant($constname);
195b39c5158Smillert    croak $error if $error;
196b39c5158Smillert    no strict 'refs';
197b39c5158Smillert    *$AUTOLOAD = sub { $val };
198b39c5158Smillert    goto &$AUTOLOAD;
199b39c5158Smillert}
200b39c5158Smillert
201b39c5158Smillert
202b39c5158Smillertsub openlog {
203b39c5158Smillert    ($ident, my $logopt, $facility) = @_;
204b39c5158Smillert
205b39c5158Smillert    # default values
206b39c5158Smillert    $ident    ||= basename($0) || getlogin() || getpwuid($<) || 'syslog';
207b39c5158Smillert    $logopt   ||= '';
208b39c5158Smillert    $facility ||= LOG_USER();
209b39c5158Smillert
210b39c5158Smillert    for my $opt (split /\b/, $logopt) {
211b39c5158Smillert        $options{$opt} = 1 if exists $options{$opt}
212b39c5158Smillert    }
213b39c5158Smillert
214b39c5158Smillert    $err_sub = delete $options{nofatal} ? \&warnings::warnif : \&croak;
215b39c5158Smillert    return 1 unless $options{ndelay};
216b39c5158Smillert    connect_log();
217b39c5158Smillert}
218b39c5158Smillert
219b39c5158Smillertsub closelog {
220898184e3Ssthen    disconnect_log() if $connected;
221898184e3Ssthen    $options{$_} = 0 for keys %options;
222898184e3Ssthen    $facility = $ident = "";
223898184e3Ssthen    $connected = 0;
224898184e3Ssthen    return 1
225b39c5158Smillert}
226b39c5158Smillert
227b39c5158Smillertsub setlogmask {
228b39c5158Smillert    my $oldmask = $maskpri;
229b39c5158Smillert    $maskpri = shift unless $_[0] == 0;
230b39c5158Smillert    $oldmask;
231b39c5158Smillert}
232b39c5158Smillert
233898184e3Ssthen
234898184e3Ssthenmy %mechanism = (
235898184e3Ssthen    console => {
236898184e3Ssthen        check   => sub { 1 },
237898184e3Ssthen    },
238898184e3Ssthen    eventlog => {
2399f11ffb7Safresh1        check   => sub { return can_load_sys_syslog_win32() },
240898184e3Ssthen        err_msg => "no Win32 API available",
241898184e3Ssthen    },
242898184e3Ssthen    inet => {
243898184e3Ssthen        check   => sub { 1 },
244898184e3Ssthen    },
245898184e3Ssthen    native => {
246898184e3Ssthen        check   => sub { 1 },
247898184e3Ssthen    },
248898184e3Ssthen    pipe => {
249898184e3Ssthen        check   => sub {
250898184e3Ssthen            ($syslog_path) = grep { defined && length && -p && -w _ }
251898184e3Ssthen                                $syslog_path, &_PATH_LOG, "/dev/log";
252898184e3Ssthen            return $syslog_path ? 1 : 0
253898184e3Ssthen        },
254898184e3Ssthen        err_msg => "path not available",
255898184e3Ssthen    },
256898184e3Ssthen    stream => {
257898184e3Ssthen        check   => sub {
258898184e3Ssthen            if (not defined $syslog_path) {
259898184e3Ssthen                my @try = qw(/dev/log /dev/conslog);
260898184e3Ssthen                unshift @try, &_PATH_LOG  if length &_PATH_LOG;
261898184e3Ssthen                ($syslog_path) = grep { -w } @try;
262898184e3Ssthen            }
263898184e3Ssthen            return defined $syslog_path && -w $syslog_path
264898184e3Ssthen        },
265898184e3Ssthen        err_msg => "could not find any writable device",
266898184e3Ssthen    },
267898184e3Ssthen    tcp => {
268898184e3Ssthen        check   => sub {
26991f110e0Safresh1            return 1 if defined $sock_port;
27091f110e0Safresh1
2719f11ffb7Safresh1            if (eval { local $SIG{__DIE__};
2729f11ffb7Safresh1                getservbyname('syslog','tcp') || getservbyname('syslogng','tcp')
2739f11ffb7Safresh1            }) {
274898184e3Ssthen                $host = $syslog_path;
275898184e3Ssthen                return 1
276898184e3Ssthen            }
277898184e3Ssthen            else {
278898184e3Ssthen                return
279898184e3Ssthen            }
280898184e3Ssthen        },
281898184e3Ssthen        err_msg => "TCP service unavailable",
282898184e3Ssthen    },
283898184e3Ssthen    udp => {
284898184e3Ssthen        check   => sub {
28591f110e0Safresh1            return 1 if defined $sock_port;
28691f110e0Safresh1
2879f11ffb7Safresh1            if (eval { local $SIG{__DIE__}; getservbyname('syslog', 'udp') }) {
288898184e3Ssthen                $host = $syslog_path;
289898184e3Ssthen                return 1
290898184e3Ssthen            }
291898184e3Ssthen            else {
292898184e3Ssthen                return
293898184e3Ssthen            }
294898184e3Ssthen        },
295898184e3Ssthen        err_msg => "UDP service unavailable",
296898184e3Ssthen    },
297898184e3Ssthen    unix => {
298898184e3Ssthen        check   => sub {
299898184e3Ssthen            my @try = ($syslog_path, &_PATH_LOG);
300898184e3Ssthen            ($syslog_path) = grep { defined && length && -w } @try;
301898184e3Ssthen            return defined $syslog_path && -w $syslog_path
302898184e3Ssthen        },
303898184e3Ssthen        err_msg => "path not available",
304898184e3Ssthen    },
305898184e3Ssthen);
306898184e3Ssthen
307b39c5158Smillertsub setlogsock {
308898184e3Ssthen    my %opt;
309b39c5158Smillert
310898184e3Ssthen    # handle arguments
311898184e3Ssthen    # - old API: setlogsock($sock_type, $sock_path, $sock_timeout)
312898184e3Ssthen    # - new API: setlogsock(\%options)
313898184e3Ssthen    croak "setlogsock(): Invalid number of arguments"
314898184e3Ssthen        unless @_ >= 1 and @_ <= 3;
315b39c5158Smillert
316898184e3Ssthen    if (my $ref = ref $_[0]) {
317898184e3Ssthen        if ($ref eq "HASH") {
318898184e3Ssthen            %opt = %{ $_[0] };
319898184e3Ssthen            croak "setlogsock(): No argument given" unless keys %opt;
320898184e3Ssthen        }
321898184e3Ssthen        elsif ($ref eq "ARRAY") {
322898184e3Ssthen            @opt{qw< type path timeout >} = @_;
323898184e3Ssthen        }
324898184e3Ssthen        else {
325898184e3Ssthen            croak "setlogsock(): Unexpected \L$ref\E reference"
326898184e3Ssthen        }
327898184e3Ssthen    }
328898184e3Ssthen    else {
329898184e3Ssthen        @opt{qw< type path timeout >} = @_;
330898184e3Ssthen    }
331898184e3Ssthen
33291f110e0Safresh1    # check socket type, remove invalid ones
333898184e3Ssthen    my $diag_invalid_type = "setlogsock(): Invalid type%s; must be one of "
334898184e3Ssthen                          . join ", ", map { "'$_'" } sort keys %mechanism;
335898184e3Ssthen    croak sprintf $diag_invalid_type, "" unless defined $opt{type};
336898184e3Ssthen    my @sock_types = ref $opt{type} eq "ARRAY" ? @{$opt{type}} : ($opt{type});
337898184e3Ssthen    my @tmp;
338898184e3Ssthen
339898184e3Ssthen    for my $sock_type (@sock_types) {
340898184e3Ssthen        carp sprintf $diag_invalid_type, " '$sock_type'" and next
341898184e3Ssthen            unless exists $mechanism{$sock_type};
342898184e3Ssthen        push @tmp, "tcp", "udp" and next  if $sock_type eq "inet";
343898184e3Ssthen        push @tmp, $sock_type;
344898184e3Ssthen    }
345898184e3Ssthen
346898184e3Ssthen    @sock_types = @tmp;
347898184e3Ssthen
348898184e3Ssthen    # set global options
349898184e3Ssthen    $syslog_path  = $opt{path}    if defined $opt{path};
350898184e3Ssthen    $host         = $opt{host}    if defined $opt{host};
351898184e3Ssthen    $sock_timeout = $opt{timeout} if defined $opt{timeout};
352898184e3Ssthen    $sock_port    = $opt{port}    if defined $opt{port};
353b39c5158Smillert
354b39c5158Smillert    disconnect_log() if $connected;
355b39c5158Smillert    $transmit_ok = 0;
356b39c5158Smillert    @fallbackMethods = ();
35791f110e0Safresh1    @connectMethods = ();
35891f110e0Safresh1    my $found = 0;
359b39c5158Smillert
36091f110e0Safresh1    # check each given mechanism and test if it can be used on the current system
361898184e3Ssthen    for my $sock_type (@sock_types) {
362898184e3Ssthen        if ( $mechanism{$sock_type}{check}->() ) {
36391f110e0Safresh1            push @connectMethods, $sock_type;
36491f110e0Safresh1            $found = 1;
365b39c5158Smillert        }
366898184e3Ssthen        else {
36791f110e0Safresh1            warnings::warnif("setlogsock(): type='$sock_type': "
36891f110e0Safresh1                           . $mechanism{$sock_type}{err_msg});
369b39c5158Smillert        }
370b39c5158Smillert    }
371b39c5158Smillert
37291f110e0Safresh1    # if no mechanism worked from the given ones, use the default ones
37391f110e0Safresh1    @connectMethods = @defaultMethods unless @connectMethods;
37491f110e0Safresh1
37591f110e0Safresh1    return $found;
376b39c5158Smillert}
377b39c5158Smillert
378b39c5158Smillertsub syslog {
37991f110e0Safresh1    my ($priority, $mask, @args) = @_;
380b39c5158Smillert    my ($message, $buf);
381b39c5158Smillert    my (@words, $num, $numpri, $numfac, $sum);
382b39c5158Smillert    my $failed = undef;
383b39c5158Smillert    my $fail_time = undef;
384b39c5158Smillert    my $error = $!;
385b39c5158Smillert
386b39c5158Smillert    # if $ident is undefined, it means openlog() wasn't previously called
387b39c5158Smillert    # so do it now in order to have sensible defaults
388b39c5158Smillert    openlog() unless $ident;
389b39c5158Smillert
390b39c5158Smillert    local $facility = $facility;    # may need to change temporarily.
391b39c5158Smillert
392b39c5158Smillert    croak "syslog: expecting argument \$priority" unless defined $priority;
393b39c5158Smillert    croak "syslog: expecting argument \$format"   unless defined $mask;
394b39c5158Smillert
395898184e3Ssthen    if ($priority =~ /^\d+$/) {
396898184e3Ssthen        $numpri = LOG_PRI($priority);
39791f110e0Safresh1        $numfac = LOG_FAC($priority) << 3;
3989f11ffb7Safresh1        undef $numfac if $numfac == 0;  # no facility given => use default
399898184e3Ssthen    }
400898184e3Ssthen    elsif ($priority =~ /^\w+/) {
401898184e3Ssthen        # Allow "level" or "level|facility".
402898184e3Ssthen        @words = split /\W+/, $priority, 2;
403898184e3Ssthen
404b39c5158Smillert        undef $numpri;
405b39c5158Smillert        undef $numfac;
406b39c5158Smillert
407b39c5158Smillert        for my $word (@words) {
408b39c5158Smillert            next if length $word == 0;
409b39c5158Smillert
410898184e3Ssthen            # Translate word to number.
411898184e3Ssthen            $num = xlate($word);
412b39c5158Smillert
413b39c5158Smillert            if ($num < 0) {
414b39c5158Smillert                croak "syslog: invalid level/facility: $word"
415b39c5158Smillert            }
41691f110e0Safresh1            elsif ($num <= LOG_PRIMASK() and $word ne "kern") {
417898184e3Ssthen                croak "syslog: too many levels given: $word"
418898184e3Ssthen                    if defined $numpri;
419b39c5158Smillert                $numpri = $num;
420b39c5158Smillert            }
421b39c5158Smillert            else {
422898184e3Ssthen                croak "syslog: too many facilities given: $word"
423898184e3Ssthen                    if defined $numfac;
424898184e3Ssthen                $facility = $word if $word =~ /^[A-Za-z]/;
42591f110e0Safresh1                $numfac = $num;
426b39c5158Smillert            }
427b39c5158Smillert        }
428898184e3Ssthen    }
429898184e3Ssthen    else {
430898184e3Ssthen        croak "syslog: invalid level/facility: $priority"
431898184e3Ssthen    }
432b39c5158Smillert
433b39c5158Smillert    croak "syslog: level must be given" unless defined $numpri;
434b39c5158Smillert
43591f110e0Safresh1    # don't log if priority is below mask level
43691f110e0Safresh1    return 0 unless LOG_MASK($numpri) & $maskpri;
43791f110e0Safresh1
438b39c5158Smillert    if (not defined $numfac) {  # Facility not specified in this call.
439b39c5158Smillert	$facility = 'user' unless $facility;
440b39c5158Smillert	$numfac = xlate($facility);
441b39c5158Smillert    }
442b39c5158Smillert
443b39c5158Smillert    connect_log() unless $connected;
444b39c5158Smillert
445b39c5158Smillert    if ($mask =~ /%m/) {
446b39c5158Smillert        # escape percent signs for sprintf()
44791f110e0Safresh1        $error =~ s/%/%%/g if @args;
448b39c5158Smillert        # replace %m with $error, if preceded by an even number of percent signs
449b39c5158Smillert        $mask =~ s/(?<!%)((?:%%)*)%m/$1$error/g;
450b39c5158Smillert    }
451b39c5158Smillert
4529f11ffb7Safresh1    # add (or not) a newline
4539f11ffb7Safresh1    $mask .= "\n" if !$options{noeol} and rindex($mask, "\n") == -1;
45491f110e0Safresh1    $message = @args ? sprintf($mask, @args) : $mask;
455b39c5158Smillert
456b39c5158Smillert    if ($current_proto eq 'native') {
457b39c5158Smillert        $buf = $message;
458b39c5158Smillert    }
459b39c5158Smillert    elsif ($current_proto eq 'eventlog') {
460b39c5158Smillert        $buf = $message;
461b39c5158Smillert    }
462b39c5158Smillert    else {
463b39c5158Smillert        my $whoami = $ident;
464b39c5158Smillert        $whoami .= "[$$]" if $options{pid};
465b39c5158Smillert
466b39c5158Smillert        $sum = $numpri + $numfac;
4679f11ffb7Safresh1
4689f11ffb7Safresh1        my $oldlocale;
4699f11ffb7Safresh1        if (HAVE_SETLOCALE) {
4709f11ffb7Safresh1            $oldlocale = setlocale(LC_TIME);
471b39c5158Smillert            setlocale(LC_TIME, 'C');
4729f11ffb7Safresh1        }
4739f11ffb7Safresh1
4749f11ffb7Safresh1        # %e format isn't available on all systems (Win32, cf. CPAN RT #69310)
4759f11ffb7Safresh1        my $day = strftime "%e", localtime;
4769f11ffb7Safresh1
4779f11ffb7Safresh1        if (index($day, "%") == 0) {
4789f11ffb7Safresh1            $day = strftime "%d", localtime;
4799f11ffb7Safresh1            $day =~ s/^0/ /;
4809f11ffb7Safresh1        }
4819f11ffb7Safresh1
4829f11ffb7Safresh1        my $timestamp = strftime "%b $day %H:%M:%S", localtime;
4839f11ffb7Safresh1        setlocale(LC_TIME, $oldlocale) if HAVE_SETLOCALE;
484898184e3Ssthen
485898184e3Ssthen        # construct the stream that will be transmitted
486898184e3Ssthen        $buf = "<$sum>$timestamp $whoami: $message";
487898184e3Ssthen
488898184e3Ssthen        # add (or not) a NUL character
489898184e3Ssthen        $buf .= "\0" if !$options{nonul};
490b39c5158Smillert    }
491b39c5158Smillert
492b39c5158Smillert    # handle PERROR option
493b39c5158Smillert    # "native" mechanism already handles it by itself
494b39c5158Smillert    if ($options{perror} and $current_proto ne 'native') {
495b39c5158Smillert        my $whoami = $ident;
496b39c5158Smillert        $whoami .= "[$$]" if $options{pid};
4979f11ffb7Safresh1        print STDERR "$whoami: $message";
4989f11ffb7Safresh1        print STDERR "\n" if rindex($message, "\n") == -1;
499b39c5158Smillert    }
500b39c5158Smillert
501b39c5158Smillert    # it's possible that we'll get an error from sending
502b39c5158Smillert    # (e.g. if method is UDP and there is no UDP listener,
503b39c5158Smillert    # then we'll get ECONNREFUSED on the send). So what we
504b39c5158Smillert    # want to do at this point is to fallback onto a different
505b39c5158Smillert    # connection method.
506b39c5158Smillert    while (scalar @fallbackMethods || $syslog_send) {
507b39c5158Smillert	if ($failed && (time - $fail_time) > 60) {
508b39c5158Smillert	    # it's been a while... maybe things have been fixed
509b39c5158Smillert	    @fallbackMethods = ();
510b39c5158Smillert	    disconnect_log();
511b39c5158Smillert	    $transmit_ok = 0; # make it look like a fresh attempt
512b39c5158Smillert	    connect_log();
513b39c5158Smillert        }
514b39c5158Smillert
515b39c5158Smillert	if ($connected && !connection_ok()) {
516b39c5158Smillert	    # Something was OK, but has now broken. Remember coz we'll
517b39c5158Smillert	    # want to go back to what used to be OK.
518b39c5158Smillert	    $failed = $current_proto unless $failed;
519b39c5158Smillert	    $fail_time = time;
520b39c5158Smillert	    disconnect_log();
521b39c5158Smillert	}
522b39c5158Smillert
523b39c5158Smillert	connect_log() unless $connected;
524b39c5158Smillert	$failed = undef if ($current_proto && $failed && $current_proto eq $failed);
525b39c5158Smillert
526b39c5158Smillert	if ($syslog_send) {
527b39c5158Smillert            if ($syslog_send->($buf, $numpri, $numfac)) {
528b39c5158Smillert		$transmit_ok++;
529b39c5158Smillert		return 1;
530b39c5158Smillert	    }
531b39c5158Smillert	    # typically doesn't happen, since errors are rare from write().
532b39c5158Smillert	    disconnect_log();
533b39c5158Smillert	}
534b39c5158Smillert    }
535b39c5158Smillert    # could not send, could not fallback onto a working
536b39c5158Smillert    # connection method. Lose.
537b39c5158Smillert    return 0;
538b39c5158Smillert}
539b39c5158Smillert
540b39c5158Smillertsub _syslog_send_console {
541b39c5158Smillert    my ($buf) = @_;
542898184e3Ssthen
543b39c5158Smillert    # The console print is a method which could block
544b39c5158Smillert    # so we do it in a child process and always return success
545b39c5158Smillert    # to the caller.
546b39c5158Smillert    if (my $pid = fork) {
547b39c5158Smillert
548b39c5158Smillert	if ($options{nowait}) {
549b39c5158Smillert	    return 1;
550b39c5158Smillert	} else {
551b39c5158Smillert	    if (waitpid($pid, 0) >= 0) {
552b39c5158Smillert	    	return ($? >> 8);
553b39c5158Smillert	    } else {
554b39c5158Smillert		# it's possible that the caller has other
555b39c5158Smillert		# plans for SIGCHLD, so let's not interfere
556b39c5158Smillert		return 1;
557b39c5158Smillert	    }
558b39c5158Smillert	}
559b39c5158Smillert    } else {
560b39c5158Smillert        if (open(CONS, ">/dev/console")) {
561b39c5158Smillert	    my $ret = print CONS $buf . "\r";  # XXX: should this be \x0A ?
5626fb12b70Safresh1	    POSIX::_exit($ret) if defined $pid;
563b39c5158Smillert	    close CONS;
564b39c5158Smillert	}
565898184e3Ssthen
5666fb12b70Safresh1	POSIX::_exit(0) if defined $pid;
567b39c5158Smillert    }
568b39c5158Smillert}
569b39c5158Smillert
570b39c5158Smillertsub _syslog_send_stream {
571b39c5158Smillert    my ($buf) = @_;
572b39c5158Smillert    # XXX: this only works if the OS stream implementation makes a write
573b39c5158Smillert    # look like a putmsg() with simple header. For instance it works on
574b39c5158Smillert    # Solaris 8 but not Solaris 7.
575b39c5158Smillert    # To be correct, it should use a STREAMS API, but perl doesn't have one.
576b39c5158Smillert    return syswrite(SYSLOG, $buf, length($buf));
577b39c5158Smillert}
578b39c5158Smillert
579b39c5158Smillertsub _syslog_send_pipe {
580b39c5158Smillert    my ($buf) = @_;
581b39c5158Smillert    return print SYSLOG $buf;
582b39c5158Smillert}
583b39c5158Smillert
584b39c5158Smillertsub _syslog_send_socket {
585b39c5158Smillert    my ($buf) = @_;
586b39c5158Smillert    return syswrite(SYSLOG, $buf, length($buf));
587b39c5158Smillert    #return send(SYSLOG, $buf, 0);
588b39c5158Smillert}
589b39c5158Smillert
590b39c5158Smillertsub _syslog_send_native {
591898184e3Ssthen    my ($buf, $numpri, $numfac) = @_;
592898184e3Ssthen    syslog_xs($numpri|$numfac, $buf);
593b39c5158Smillert    return 1;
594b39c5158Smillert}
595b39c5158Smillert
596b39c5158Smillert
597b39c5158Smillert# xlate()
598b39c5158Smillert# -----
599b39c5158Smillert# private function to translate names to numeric values
600b39c5158Smillert#
601b39c5158Smillertsub xlate {
602b39c5158Smillert    my ($name) = @_;
603b39c5158Smillert
604b39c5158Smillert    return $name+0 if $name =~ /^\s*\d+\s*$/;
605b39c5158Smillert    $name = uc $name;
606b39c5158Smillert    $name = "LOG_$name" unless $name =~ /^LOG_/;
607b39c5158Smillert
608b39c5158Smillert    # ExtUtils::Constant 0.20 introduced a new way to implement
609b39c5158Smillert    # constants, called ProxySubs.  When it was used to generate
610b39c5158Smillert    # the C code, the constant() function no longer returns the
611b39c5158Smillert    # correct value.  Therefore, we first try a direct call to
612b39c5158Smillert    # constant(), and if the value is an error we try to call the
613b39c5158Smillert    # constant by its full name.
614b39c5158Smillert    my $value = constant($name);
615b39c5158Smillert
616b39c5158Smillert    if (index($value, "not a valid") >= 0) {
617b39c5158Smillert        $name = "Sys::Syslog::$name";
618b39c5158Smillert        $value = eval { no strict "refs"; &$name };
619b39c5158Smillert        $value = $@ unless defined $value;
620b39c5158Smillert    }
621b39c5158Smillert
622b39c5158Smillert    $value = -1 if index($value, "not a valid") >= 0;
623b39c5158Smillert
624b39c5158Smillert    return defined $value ? $value : -1;
625b39c5158Smillert}
626b39c5158Smillert
627b39c5158Smillert
628b39c5158Smillert# connect_log()
629b39c5158Smillert# -----------
630b39c5158Smillert# This function acts as a kind of front-end: it tries to connect to
631b39c5158Smillert# a syslog service using the selected methods, trying each one in the
632b39c5158Smillert# selected order.
633b39c5158Smillert#
634b39c5158Smillertsub connect_log {
635b39c5158Smillert    @fallbackMethods = @connectMethods unless scalar @fallbackMethods;
636b39c5158Smillert
637b39c5158Smillert    if ($transmit_ok && $current_proto) {
638b39c5158Smillert        # Retry what we were on, because it has worked in the past.
639b39c5158Smillert	unshift(@fallbackMethods, $current_proto);
640b39c5158Smillert    }
641b39c5158Smillert
642b39c5158Smillert    $connected = 0;
643b39c5158Smillert    my @errs = ();
644b39c5158Smillert    my $proto = undef;
645b39c5158Smillert
646b39c5158Smillert    while ($proto = shift @fallbackMethods) {
647b39c5158Smillert	no strict 'refs';
648b39c5158Smillert	my $fn = "connect_$proto";
649b39c5158Smillert	$connected = &$fn(\@errs) if defined &$fn;
650b39c5158Smillert	last if $connected;
651b39c5158Smillert    }
652b39c5158Smillert
653b39c5158Smillert    $transmit_ok = 0;
654b39c5158Smillert    if ($connected) {
655b39c5158Smillert	$current_proto = $proto;
656b39c5158Smillert        my ($old) = select(SYSLOG); $| = 1; select($old);
657b39c5158Smillert    } else {
658b39c5158Smillert	@fallbackMethods = ();
659b39c5158Smillert        $err_sub->(join "\n\t- ", "no connection to syslog available", @errs);
660b39c5158Smillert        return undef;
661b39c5158Smillert    }
662b39c5158Smillert}
663b39c5158Smillert
664b39c5158Smillertsub connect_tcp {
665b39c5158Smillert    my ($errs) = @_;
666b39c5158Smillert
6679f11ffb7Safresh1    my $port = $sock_port
6689f11ffb7Safresh1            || eval { local $SIG{__DIE__}; getservbyname('syslog',   'tcp') }
6699f11ffb7Safresh1            || eval { local $SIG{__DIE__}; getservbyname('syslogng', 'tcp') };
670898184e3Ssthen    if (!defined $port) {
671b39c5158Smillert	push @$errs, "getservbyname failed for syslog/tcp and syslogng/tcp";
672b39c5158Smillert	return 0;
673b39c5158Smillert    }
674b39c5158Smillert
675b39c5158Smillert    my $addr;
676b39c5158Smillert    if (defined $host) {
677b39c5158Smillert        $addr = inet_aton($host);
678b39c5158Smillert        if (!$addr) {
679b39c5158Smillert	    push @$errs, "can't lookup $host";
680b39c5158Smillert	    return 0;
681b39c5158Smillert	}
682b39c5158Smillert    } else {
683b39c5158Smillert        $addr = INADDR_LOOPBACK;
684b39c5158Smillert    }
685898184e3Ssthen    $addr = sockaddr_in($port, $addr);
686b39c5158Smillert
6879f11ffb7Safresh1    if (!socket(SYSLOG, AF_INET, SOCK_STREAM, SOCKET_IPPROTO_TCP)) {
688b39c5158Smillert	push @$errs, "tcp socket: $!";
689b39c5158Smillert	return 0;
690b39c5158Smillert    }
691b39c5158Smillert
692b39c5158Smillert    setsockopt(SYSLOG, SOL_SOCKET, SO_KEEPALIVE, 1);
6939f11ffb7Safresh1    setsockopt(SYSLOG, SOCKET_IPPROTO_TCP, SOCKET_TCP_NODELAY, 1);
6949f11ffb7Safresh1
695b39c5158Smillert    if (!connect(SYSLOG, $addr)) {
696b39c5158Smillert	push @$errs, "tcp connect: $!";
697b39c5158Smillert	return 0;
698b39c5158Smillert    }
699b39c5158Smillert
700b39c5158Smillert    $syslog_send = \&_syslog_send_socket;
701b39c5158Smillert
702b39c5158Smillert    return 1;
703b39c5158Smillert}
704b39c5158Smillert
705b39c5158Smillertsub connect_udp {
706b39c5158Smillert    my ($errs) = @_;
707b39c5158Smillert
7089f11ffb7Safresh1    my $port = $sock_port
7099f11ffb7Safresh1            || eval { local $SIG{__DIE__}; getservbyname('syslog', 'udp') };
710898184e3Ssthen    if (!defined $port) {
711b39c5158Smillert	push @$errs, "getservbyname failed for syslog/udp";
712b39c5158Smillert	return 0;
713b39c5158Smillert    }
714b39c5158Smillert
715b39c5158Smillert    my $addr;
716b39c5158Smillert    if (defined $host) {
717b39c5158Smillert        $addr = inet_aton($host);
718b39c5158Smillert        if (!$addr) {
719b39c5158Smillert	    push @$errs, "can't lookup $host";
720b39c5158Smillert	    return 0;
721b39c5158Smillert	}
722b39c5158Smillert    } else {
723b39c5158Smillert        $addr = INADDR_LOOPBACK;
724b39c5158Smillert    }
725898184e3Ssthen    $addr = sockaddr_in($port, $addr);
726b39c5158Smillert
7279f11ffb7Safresh1    if (!socket(SYSLOG, AF_INET, SOCK_DGRAM, SOCKET_IPPROTO_UDP)) {
728b39c5158Smillert	push @$errs, "udp socket: $!";
729b39c5158Smillert	return 0;
730b39c5158Smillert    }
731b39c5158Smillert    if (!connect(SYSLOG, $addr)) {
732b39c5158Smillert	push @$errs, "udp connect: $!";
733b39c5158Smillert	return 0;
734b39c5158Smillert    }
735b39c5158Smillert
736b39c5158Smillert    # We want to check that the UDP connect worked. However the only
737b39c5158Smillert    # way to do that is to send a message and see if an ICMP is returned
738b39c5158Smillert    _syslog_send_socket("");
739b39c5158Smillert    if (!connection_ok()) {
740b39c5158Smillert	push @$errs, "udp connect: nobody listening";
741b39c5158Smillert	return 0;
742b39c5158Smillert    }
743b39c5158Smillert
744b39c5158Smillert    $syslog_send = \&_syslog_send_socket;
745b39c5158Smillert
746b39c5158Smillert    return 1;
747b39c5158Smillert}
748b39c5158Smillert
749b39c5158Smillertsub connect_stream {
750b39c5158Smillert    my ($errs) = @_;
751b39c5158Smillert    # might want syslog_path to be variable based on syslog.h (if only
752b39c5158Smillert    # it were in there!)
753b39c5158Smillert    $syslog_path = '/dev/conslog' unless defined $syslog_path;
7546fb12b70Safresh1
755b39c5158Smillert    if (!-w $syslog_path) {
756b39c5158Smillert	push @$errs, "stream $syslog_path is not writable";
757b39c5158Smillert	return 0;
758b39c5158Smillert    }
7596fb12b70Safresh1
7606fb12b70Safresh1    require Fcntl;
7616fb12b70Safresh1
7626fb12b70Safresh1    if (!sysopen(SYSLOG, $syslog_path, Fcntl::O_WRONLY(), 0400)) {
763b39c5158Smillert	push @$errs, "stream can't open $syslog_path: $!";
764b39c5158Smillert	return 0;
765b39c5158Smillert    }
7666fb12b70Safresh1
767b39c5158Smillert    $syslog_send = \&_syslog_send_stream;
7686fb12b70Safresh1
769b39c5158Smillert    return 1;
770b39c5158Smillert}
771b39c5158Smillert
772b39c5158Smillertsub connect_pipe {
773b39c5158Smillert    my ($errs) = @_;
774b39c5158Smillert
775b39c5158Smillert    $syslog_path ||= &_PATH_LOG || "/dev/log";
776b39c5158Smillert
777b39c5158Smillert    if (not -w $syslog_path) {
778b39c5158Smillert        push @$errs, "$syslog_path is not writable";
779b39c5158Smillert        return 0;
780b39c5158Smillert    }
781b39c5158Smillert
782b39c5158Smillert    if (not open(SYSLOG, ">$syslog_path")) {
783b39c5158Smillert        push @$errs, "can't write to $syslog_path: $!";
784b39c5158Smillert        return 0;
785b39c5158Smillert    }
786b39c5158Smillert
787b39c5158Smillert    $syslog_send = \&_syslog_send_pipe;
788b39c5158Smillert
789b39c5158Smillert    return 1;
790b39c5158Smillert}
791b39c5158Smillert
792b39c5158Smillertsub connect_unix {
793b39c5158Smillert    my ($errs) = @_;
794b39c5158Smillert
795b39c5158Smillert    $syslog_path ||= _PATH_LOG() if length _PATH_LOG();
796b39c5158Smillert
797b39c5158Smillert    if (not defined $syslog_path) {
798b39c5158Smillert        push @$errs, "_PATH_LOG not available in syslog.h and no user-supplied socket path";
799b39c5158Smillert	return 0;
800b39c5158Smillert    }
801b39c5158Smillert
802b39c5158Smillert    if (not (-S $syslog_path or -c _)) {
803b39c5158Smillert        push @$errs, "$syslog_path is not a socket";
804b39c5158Smillert	return 0;
805b39c5158Smillert    }
806b39c5158Smillert
807b39c5158Smillert    my $addr = sockaddr_un($syslog_path);
808b39c5158Smillert    if (!$addr) {
809b39c5158Smillert	push @$errs, "can't locate $syslog_path";
810b39c5158Smillert	return 0;
811b39c5158Smillert    }
812b39c5158Smillert    if (!socket(SYSLOG, AF_UNIX, SOCK_STREAM, 0)) {
813b39c5158Smillert        push @$errs, "unix stream socket: $!";
814b39c5158Smillert	return 0;
815b39c5158Smillert    }
816b39c5158Smillert
817b39c5158Smillert    if (!connect(SYSLOG, $addr)) {
818b39c5158Smillert        if (!socket(SYSLOG, AF_UNIX, SOCK_DGRAM, 0)) {
819b39c5158Smillert	    push @$errs, "unix dgram socket: $!";
820b39c5158Smillert	    return 0;
821b39c5158Smillert	}
822b39c5158Smillert        if (!connect(SYSLOG, $addr)) {
823b39c5158Smillert	    push @$errs, "unix dgram connect: $!";
824b39c5158Smillert	    return 0;
825b39c5158Smillert	}
826b39c5158Smillert    }
827b39c5158Smillert
828b39c5158Smillert    $syslog_send = \&_syslog_send_socket;
829b39c5158Smillert
830b39c5158Smillert    return 1;
831b39c5158Smillert}
832b39c5158Smillert
833b39c5158Smillertsub connect_native {
834b39c5158Smillert    my ($errs) = @_;
835b39c5158Smillert    my $logopt = 0;
836b39c5158Smillert
837b39c5158Smillert    # reconstruct the numeric equivalent of the options
838b39c5158Smillert    for my $opt (keys %options) {
839b39c5158Smillert        $logopt += xlate($opt) if $options{$opt}
840b39c5158Smillert    }
841b39c5158Smillert
842b39c5158Smillert    openlog_xs($ident, $logopt, xlate($facility));
843b39c5158Smillert    $syslog_send = \&_syslog_send_native;
844b39c5158Smillert
845b39c5158Smillert    return 1;
846b39c5158Smillert}
847b39c5158Smillert
848b39c5158Smillertsub connect_eventlog {
849b39c5158Smillert    my ($errs) = @_;
850b39c5158Smillert
851b39c5158Smillert    $syslog_xobj = Sys::Syslog::Win32::_install();
852b39c5158Smillert    $syslog_send = \&Sys::Syslog::Win32::_syslog_send;
853b39c5158Smillert
854b39c5158Smillert    return 1;
855b39c5158Smillert}
856b39c5158Smillert
857b39c5158Smillertsub connect_console {
858b39c5158Smillert    my ($errs) = @_;
859b39c5158Smillert    if (!-w '/dev/console') {
860b39c5158Smillert	push @$errs, "console is not writable";
861b39c5158Smillert	return 0;
862b39c5158Smillert    }
863b39c5158Smillert    $syslog_send = \&_syslog_send_console;
864b39c5158Smillert    return 1;
865b39c5158Smillert}
866b39c5158Smillert
867b39c5158Smillert# To test if the connection is still good, we need to check if any
868b39c5158Smillert# errors are present on the connection. The errors will not be raised
869b39c5158Smillert# by a write. Instead, sockets are made readable and the next read
870b39c5158Smillert# would cause the error to be returned. Unfortunately the syslog
871b39c5158Smillert# 'protocol' never provides anything for us to read. But with
872b39c5158Smillert# judicious use of select(), we can see if it would be readable...
873b39c5158Smillertsub connection_ok {
874b39c5158Smillert    return 1 if defined $current_proto and (
875b39c5158Smillert        $current_proto eq 'native' or $current_proto eq 'console'
876b39c5158Smillert        or $current_proto eq 'eventlog'
877b39c5158Smillert    );
878b39c5158Smillert
879b39c5158Smillert    my $rin = '';
880b39c5158Smillert    vec($rin, fileno(SYSLOG), 1) = 1;
881b39c5158Smillert    my $ret = select $rin, undef, $rin, $sock_timeout;
882b39c5158Smillert    return ($ret ? 0 : 1);
883b39c5158Smillert}
884b39c5158Smillert
885b39c5158Smillertsub disconnect_log {
886b39c5158Smillert    $connected = 0;
887b39c5158Smillert    $syslog_send = undef;
888b39c5158Smillert
889b39c5158Smillert    if (defined $current_proto and $current_proto eq 'native') {
890b39c5158Smillert        closelog_xs();
891898184e3Ssthen        unshift @fallbackMethods, $current_proto;
892898184e3Ssthen        $current_proto = undef;
893b39c5158Smillert        return 1;
894b39c5158Smillert    }
895b39c5158Smillert    elsif (defined $current_proto and $current_proto eq 'eventlog') {
896b39c5158Smillert        $syslog_xobj->Close();
897898184e3Ssthen        unshift @fallbackMethods, $current_proto;
898898184e3Ssthen        $current_proto = undef;
899b39c5158Smillert        return 1;
900b39c5158Smillert    }
901b39c5158Smillert
902b39c5158Smillert    return close SYSLOG;
903b39c5158Smillert}
904b39c5158Smillert
905b39c5158Smillert
906b39c5158Smillert#
9079f11ffb7Safresh1# Wrappers around eval() that makes sure that nobody, ever knows that
9089f11ffb7Safresh1# we wanted to poke & test if something was here or not. This is needed
9099f11ffb7Safresh1# because some applications are trying to be too smart, install their
9109f11ffb7Safresh1# own __DIE__ handler, and mysteriously, things are starting to fail
9119f11ffb7Safresh1# when they shouldn't. SpamAssassin among them.
912b39c5158Smillert#
913b39c5158Smillertsub silent_eval (&) {
914b39c5158Smillert    local($SIG{__DIE__}, $SIG{__WARN__}, $@);
915b39c5158Smillert    return eval { $_[0]->() }
916b39c5158Smillert}
917b39c5158Smillert
9189f11ffb7Safresh1sub can_load_sys_syslog_win32 {
9199f11ffb7Safresh1    my ($verbose) = @_;
920b39c5158Smillert    local($SIG{__DIE__}, $SIG{__WARN__}, $@);
9219f11ffb7Safresh1    (my $module_path = __FILE__) =~ s:Syslog.pm$:Syslog/Win32.pm:;
9229f11ffb7Safresh1    my $loaded = eval { require $module_path } ? 1 : 0;
923898184e3Ssthen    warn $@ if not $loaded and $verbose;
924898184e3Ssthen    return $loaded
925b39c5158Smillert}
926b39c5158Smillert
927b39c5158Smillert
928b39c5158Smillert"Eighth Rule: read the documentation."
929b39c5158Smillert
930b39c5158Smillert__END__
931b39c5158Smillert
932b39c5158Smillert=head1 NAME
933b39c5158Smillert
934b39c5158SmillertSys::Syslog - Perl interface to the UNIX syslog(3) calls
935b39c5158Smillert
936b39c5158Smillert=head1 VERSION
937b39c5158Smillert
938*56d68f1eSafresh1This is the documentation of version 0.36
939b39c5158Smillert
940b39c5158Smillert=head1 SYNOPSIS
941b39c5158Smillert
942898184e3Ssthen    use Sys::Syslog;                        # all except setlogsock()
943898184e3Ssthen    use Sys::Syslog qw(:standard :macros);  # standard functions & macros
944b39c5158Smillert
945898184e3Ssthen    openlog($ident, $logopt, $facility);    # don't forget this
946898184e3Ssthen    syslog($priority, $format, @args);
947898184e3Ssthen    $oldmask = setlogmask($mask_priority);
948898184e3Ssthen    closelog();
949b39c5158Smillert
950b39c5158Smillert
951b39c5158Smillert=head1 DESCRIPTION
952b39c5158Smillert
953b39c5158SmillertC<Sys::Syslog> is an interface to the UNIX C<syslog(3)> program.
954b39c5158SmillertCall C<syslog()> with a string priority and a list of C<printf()> args
955b39c5158Smillertjust like C<syslog(3)>.
956b39c5158Smillert
957b39c5158Smillert
958b39c5158Smillert=head1 EXPORTS
959b39c5158Smillert
960b39c5158SmillertC<Sys::Syslog> exports the following C<Exporter> tags:
961b39c5158Smillert
962b39c5158Smillert=over 4
963b39c5158Smillert
964b39c5158Smillert=item *
965b39c5158Smillert
966b39c5158SmillertC<:standard> exports the standard C<syslog(3)> functions:
967b39c5158Smillert
968b39c5158Smillert    openlog closelog setlogmask syslog
969b39c5158Smillert
970b39c5158Smillert=item *
971b39c5158Smillert
972b39c5158SmillertC<:extended> exports the Perl specific functions for C<syslog(3)>:
973b39c5158Smillert
974b39c5158Smillert    setlogsock
975b39c5158Smillert
976b39c5158Smillert=item *
977b39c5158Smillert
978b39c5158SmillertC<:macros> exports the symbols corresponding to most of your C<syslog(3)>
979b39c5158Smillertmacros and the C<LOG_UPTO()> and C<LOG_MASK()> functions.
980b39c5158SmillertSee L<"CONSTANTS"> for the supported constants and their meaning.
981b39c5158Smillert
982b39c5158Smillert=back
983b39c5158Smillert
984b39c5158SmillertBy default, C<Sys::Syslog> exports the symbols from the C<:standard> tag.
985b39c5158Smillert
986b39c5158Smillert
987b39c5158Smillert=head1 FUNCTIONS
988b39c5158Smillert
989b39c5158Smillert=over 4
990b39c5158Smillert
991b39c5158Smillert=item B<openlog($ident, $logopt, $facility)>
992b39c5158Smillert
993b39c5158SmillertOpens the syslog.
994b39c5158SmillertC<$ident> is prepended to every message.  C<$logopt> contains zero or
995b39c5158Smillertmore of the options detailed below.  C<$facility> specifies the part
996b39c5158Smillertof the system to report about, for example C<LOG_USER> or C<LOG_LOCAL0>:
997b39c5158Smillertsee L<"Facilities"> for a list of well-known facilities, and your
998b39c5158SmillertC<syslog(3)> documentation for the facilities available in your system.
999b39c5158SmillertCheck L<"SEE ALSO"> for useful links. Facility can be given as a string
1000b39c5158Smillertor a numeric macro.
1001b39c5158Smillert
1002b39c5158SmillertThis function will croak if it can't connect to the syslog daemon.
1003b39c5158Smillert
1004b39c5158SmillertNote that C<openlog()> now takes three arguments, just like C<openlog(3)>.
1005b39c5158Smillert
1006b39c5158SmillertB<You should use C<openlog()> before calling C<syslog()>.>
1007b39c5158Smillert
1008b39c5158SmillertB<Options>
1009b39c5158Smillert
1010b39c5158Smillert=over 4
1011b39c5158Smillert
1012b39c5158Smillert=item *
1013b39c5158Smillert
1014b39c5158SmillertC<cons> - This option is ignored, since the failover mechanism will drop
1015b39c5158Smillertdown to the console automatically if all other media fail.
1016b39c5158Smillert
1017b39c5158Smillert=item *
1018b39c5158Smillert
1019b39c5158SmillertC<ndelay> - Open the connection immediately (normally, the connection is
1020b39c5158Smillertopened when the first message is logged).
1021b39c5158Smillert
1022b39c5158Smillert=item *
1023b39c5158Smillert
1024898184e3SsthenC<noeol> - When set to true, no end of line character (C<\n>) will be
10259f11ffb7Safresh1appended to the message. This can be useful for some syslog daemons.
10269f11ffb7Safresh1Added in C<Sys::Syslog> 0.29.
1027898184e3Ssthen
1028898184e3Ssthen=item *
1029898184e3Ssthen
1030b39c5158SmillertC<nofatal> - When set to true, C<openlog()> and C<syslog()> will only
1031b39c5158Smillertemit warnings instead of dying if the connection to the syslog can't
10329f11ffb7Safresh1be established. Added in C<Sys::Syslog> 0.15.
1033b39c5158Smillert
1034b39c5158Smillert=item *
1035b39c5158Smillert
1036898184e3SsthenC<nonul> - When set to true, no C<NUL> character (C<\0>) will be
10379f11ffb7Safresh1appended to the message. This can be useful for some syslog daemons.
10389f11ffb7Safresh1Added in C<Sys::Syslog> 0.29.
1039898184e3Ssthen
1040898184e3Ssthen=item *
1041898184e3Ssthen
1042b39c5158SmillertC<nowait> - Don't wait for child processes that may have been created
1043b39c5158Smillertwhile logging the message.  (The GNU C library does not create a child
1044b39c5158Smillertprocess, so this option has no effect on Linux.)
1045b39c5158Smillert
1046b39c5158Smillert=item *
1047b39c5158Smillert
1048b39c5158SmillertC<perror> - Write the message to standard error output as well to the
10499f11ffb7Safresh1system log. Added in C<Sys::Syslog> 0.22.
1050b39c5158Smillert
1051b39c5158Smillert=item *
1052b39c5158Smillert
1053b39c5158SmillertC<pid> - Include PID with each message.
1054b39c5158Smillert
1055b39c5158Smillert=back
1056b39c5158Smillert
1057b39c5158SmillertB<Examples>
1058b39c5158Smillert
1059b39c5158SmillertOpen the syslog with options C<ndelay> and C<pid>, and with facility C<LOCAL0>:
1060b39c5158Smillert
1061b39c5158Smillert    openlog($name, "ndelay,pid", "local0");
1062b39c5158Smillert
1063b39c5158SmillertSame thing, but this time using the macro corresponding to C<LOCAL0>:
1064b39c5158Smillert
1065b39c5158Smillert    openlog($name, "ndelay,pid", LOG_LOCAL0);
1066b39c5158Smillert
1067b39c5158Smillert
1068b39c5158Smillert=item B<syslog($priority, $message)>
1069b39c5158Smillert
1070b39c5158Smillert=item B<syslog($priority, $format, @args)>
1071b39c5158Smillert
1072b39c5158SmillertIf C<$priority> permits, logs C<$message> or C<sprintf($format, @args)>
1073b39c5158Smillertwith the addition that C<%m> in $message or C<$format> is replaced with
1074b39c5158SmillertC<"$!"> (the latest error message).
1075b39c5158Smillert
1076b39c5158SmillertC<$priority> can specify a level, or a level and a facility.  Levels and
1077b39c5158Smillertfacilities can be given as strings or as macros.  When using the C<eventlog>
1078b39c5158Smillertmechanism, priorities C<DEBUG> and C<INFO> are mapped to event type
1079898184e3SsthenC<informational>, C<NOTICE> and C<WARNING> to C<warning> and C<ERR> to
1080b39c5158SmillertC<EMERG> to C<error>.
1081b39c5158Smillert
1082b39c5158SmillertIf you didn't use C<openlog()> before using C<syslog()>, C<syslog()> will
1083b39c5158Smillerttry to guess the C<$ident> by extracting the shortest prefix of
1084b39c5158SmillertC<$format> that ends in a C<":">.
1085b39c5158Smillert
1086b39c5158SmillertB<Examples>
1087b39c5158Smillert
1088898184e3Ssthen    # informational level
1089898184e3Ssthen    syslog("info", $message);
1090898184e3Ssthen    syslog(LOG_INFO, $message);
1091b39c5158Smillert
1092898184e3Ssthen    # information level, Local0 facility
1093898184e3Ssthen    syslog("info|local0", $message);
1094898184e3Ssthen    syslog(LOG_INFO|LOG_LOCAL0, $message);
1095b39c5158Smillert
1096b39c5158Smillert=over 4
1097b39c5158Smillert
1098b39c5158Smillert=item B<Note>
1099b39c5158Smillert
1100b39c5158SmillertC<Sys::Syslog> version v0.07 and older passed the C<$message> as the
1101b39c5158Smillertformatting string to C<sprintf()> even when no formatting arguments
1102b39c5158Smillertwere provided.  If the code calling C<syslog()> might execute with
1103b39c5158Smillertolder versions of this module, make sure to call the function as
1104b39c5158SmillertC<syslog($priority, "%s", $message)> instead of C<syslog($priority,
1105b39c5158Smillert$message)>.  This protects against hostile formatting sequences that
1106b39c5158Smillertmight show up if $message contains tainted data.
1107b39c5158Smillert
1108b39c5158Smillert=back
1109b39c5158Smillert
1110b39c5158Smillert
1111b39c5158Smillert=item B<setlogmask($mask_priority)>
1112b39c5158Smillert
1113b39c5158SmillertSets the log mask for the current process to C<$mask_priority> and
1114b39c5158Smillertreturns the old mask.  If the mask argument is 0, the current log mask
1115b39c5158Smillertis not modified.  See L<"Levels"> for the list of available levels.
1116b39c5158SmillertYou can use the C<LOG_UPTO()> function to allow all levels up to a
1117b39c5158Smillertgiven priority (but it only accept the numeric macros as arguments).
1118b39c5158Smillert
1119b39c5158SmillertB<Examples>
1120b39c5158Smillert
1121b39c5158SmillertOnly log errors:
1122b39c5158Smillert
1123b39c5158Smillert    setlogmask( LOG_MASK(LOG_ERR) );
1124b39c5158Smillert
1125b39c5158SmillertLog everything except informational messages:
1126b39c5158Smillert
1127b39c5158Smillert    setlogmask( ~(LOG_MASK(LOG_INFO)) );
1128b39c5158Smillert
1129b39c5158SmillertLog critical messages, errors and warnings:
1130b39c5158Smillert
1131898184e3Ssthen    setlogmask( LOG_MASK(LOG_CRIT)
1132898184e3Ssthen              | LOG_MASK(LOG_ERR)
1133898184e3Ssthen              | LOG_MASK(LOG_WARNING) );
1134b39c5158Smillert
1135b39c5158SmillertLog all messages up to debug:
1136b39c5158Smillert
1137b39c5158Smillert    setlogmask( LOG_UPTO(LOG_DEBUG) );
1138b39c5158Smillert
1139b39c5158Smillert
1140898184e3Ssthen=item B<setlogsock()>
1141b39c5158Smillert
1142898184e3SsthenSets the socket type and options to be used for the next call to C<openlog()>
1143898184e3Ssthenor C<syslog()>.  Returns true on success, C<undef> on failure.
1144b39c5158Smillert
1145898184e3SsthenBeing Perl-specific, this function has evolved along time.  It can currently
1146898184e3Ssthenbe called as follow:
1147b39c5158Smillert
1148898184e3Ssthen=over
1149898184e3Ssthen
1150898184e3Ssthen=item *
1151898184e3Ssthen
1152898184e3SsthenC<setlogsock($sock_type)>
1153898184e3Ssthen
1154898184e3Ssthen=item *
1155898184e3Ssthen
1156898184e3SsthenC<setlogsock($sock_type, $stream_location)> (added in Perl 5.004_02)
1157898184e3Ssthen
1158898184e3Ssthen=item *
1159898184e3Ssthen
1160898184e3SsthenC<setlogsock($sock_type, $stream_location, $sock_timeout)> (added in
1161898184e3SsthenC<Sys::Syslog> 0.25)
1162898184e3Ssthen
1163898184e3Ssthen=item *
1164898184e3Ssthen
1165898184e3SsthenC<setlogsock(\%options)> (added in C<Sys::Syslog> 0.28)
1166898184e3Ssthen
1167898184e3Ssthen=back
1168898184e3Ssthen
1169898184e3SsthenThe available options are:
1170898184e3Ssthen
1171898184e3Ssthen=over
1172898184e3Ssthen
1173898184e3Ssthen=item *
1174898184e3Ssthen
1175898184e3SsthenC<type> - equivalent to C<$sock_type>, selects the socket type (or
1176898184e3Ssthen"mechanism").  An array reference can be passed to specify several
1177898184e3Ssthenmechanisms to try, in the given order.
1178898184e3Ssthen
1179898184e3Ssthen=item *
1180898184e3Ssthen
1181898184e3SsthenC<path> - equivalent to C<$stream_location>, sets the stream location.
1182898184e3SsthenDefaults to standard Unix location, or C<_PATH_LOG>.
1183898184e3Ssthen
1184898184e3Ssthen=item *
1185898184e3Ssthen
1186898184e3SsthenC<timeout> - equivalent to C<$sock_timeout>, sets the socket timeout
1187898184e3Ssthenin seconds.  Defaults to 0 on all systems except S<Mac OS X> where it
1188898184e3Ssthenis set to 0.25 sec.
1189898184e3Ssthen
1190898184e3Ssthen=item *
1191898184e3Ssthen
1192898184e3SsthenC<host> - sets the hostname to send the messages to.  Defaults to
1193898184e3Ssthenthe local host.
1194898184e3Ssthen
1195898184e3Ssthen=item *
1196898184e3Ssthen
1197898184e3SsthenC<port> - sets the TCP or UDP port to connect to.  Defaults to the
1198898184e3Ssthenfirst standard syslog port available on the system.
1199898184e3Ssthen
1200898184e3Ssthen=back
1201898184e3Ssthen
1202898184e3Ssthen
1203898184e3SsthenThe available mechanisms are:
1204b39c5158Smillert
1205b39c5158Smillert=over
1206b39c5158Smillert
1207b39c5158Smillert=item *
1208b39c5158Smillert
1209b39c5158SmillertC<"native"> - use the native C functions from your C<syslog(3)> library
1210b39c5158Smillert(added in C<Sys::Syslog> 0.15).
1211b39c5158Smillert
1212b39c5158Smillert=item *
1213b39c5158Smillert
1214b39c5158SmillertC<"eventlog"> - send messages to the Win32 events logger (Win32 only;
1215b39c5158Smillertadded in C<Sys::Syslog> 0.19).
1216b39c5158Smillert
1217b39c5158Smillert=item *
1218b39c5158Smillert
1219b39c5158SmillertC<"tcp"> - connect to a TCP socket, on the C<syslog/tcp> or C<syslogng/tcp>
1220898184e3Ssthenservice.  See also the C<host>, C<port> and C<timeout> options.
1221b39c5158Smillert
1222b39c5158Smillert=item *
1223b39c5158Smillert
1224b39c5158SmillertC<"udp"> - connect to a UDP socket, on the C<syslog/udp> service.
1225898184e3SsthenSee also the C<host>, C<port> and C<timeout> options.
1226b39c5158Smillert
1227b39c5158Smillert=item *
1228b39c5158Smillert
1229b39c5158SmillertC<"inet"> - connect to an INET socket, either TCP or UDP, tried in that
1230898184e3Ssthenorder.  See also the C<host>, C<port> and C<timeout> options.
1231b39c5158Smillert
1232b39c5158Smillert=item *
1233b39c5158Smillert
1234b39c5158SmillertC<"unix"> - connect to a UNIX domain socket (in some systems a character
1235898184e3Ssthenspecial device).  The name of that socket is given by the C<path> option
1236898184e3Ssthenor, if omitted, the value returned by the C<_PATH_LOG> macro (if your
1237898184e3Ssthensystem defines it), F</dev/log> or F</dev/conslog>, whichever is writable.
1238b39c5158Smillert
1239b39c5158Smillert=item *
1240b39c5158Smillert
1241898184e3SsthenC<"stream"> - connect to the stream indicated by the C<path> option, or,
1242898184e3Ssthenif omitted, the value returned by the C<_PATH_LOG> macro (if your system
1243898184e3Ssthendefines it), F</dev/log> or F</dev/conslog>, whichever is writable.  For
1244898184e3Ssthenexample Solaris and IRIX system may prefer C<"stream"> instead of C<"unix">.
1245b39c5158Smillert
1246b39c5158Smillert=item *
1247b39c5158Smillert
1248898184e3SsthenC<"pipe"> - connect to the named pipe indicated by the C<path> option,
1249898184e3Ssthenor, if omitted, to the value returned by the C<_PATH_LOG> macro (if your
1250898184e3Ssthensystem defines it), or F</dev/log> (added in C<Sys::Syslog> 0.21).
1251898184e3SsthenHP-UX is a system which uses such a named pipe.
1252b39c5158Smillert
1253b39c5158Smillert=item *
1254b39c5158Smillert
1255b39c5158SmillertC<"console"> - send messages directly to the console, as for the C<"cons">
1256b39c5158Smillertoption of C<openlog()>.
1257b39c5158Smillert
1258b39c5158Smillert=back
1259b39c5158Smillert
1260b39c5158SmillertThe default is to try C<native>, C<tcp>, C<udp>, C<unix>, C<pipe>, C<stream>,
1261b39c5158SmillertC<console>.
1262b39c5158SmillertUnder systems with the Win32 API, C<eventlog> will be added as the first
1263b39c5158Smillertmechanism to try if C<Win32::EventLog> is available.
1264b39c5158Smillert
1265b39c5158SmillertGiving an invalid value for C<$sock_type> will C<croak>.
1266b39c5158Smillert
1267b39c5158SmillertB<Examples>
1268b39c5158Smillert
1269b39c5158SmillertSelect the UDP socket mechanism:
1270b39c5158Smillert
1271b39c5158Smillert    setlogsock("udp");
1272b39c5158Smillert
1273898184e3SsthenSend messages using the TCP socket mechanism on a custom port:
1274898184e3Ssthen
1275898184e3Ssthen    setlogsock({ type => "tcp", port => 2486 });
1276898184e3Ssthen
1277898184e3SsthenSend messages to a remote host using the TCP socket mechanism:
1278898184e3Ssthen
1279898184e3Ssthen    setlogsock({ type => "tcp", host => $loghost });
1280898184e3Ssthen
1281898184e3SsthenTry the native, UDP socket then UNIX domain socket mechanisms:
1282b39c5158Smillert
1283b39c5158Smillert    setlogsock(["native", "udp", "unix"]);
1284b39c5158Smillert
1285b39c5158Smillert=over
1286b39c5158Smillert
1287b39c5158Smillert=item B<Note>
1288b39c5158Smillert
1289b39c5158SmillertNow that the "native" mechanism is supported by C<Sys::Syslog> and selected
1290b39c5158Smillertby default, the use of the C<setlogsock()> function is discouraged because
1291b39c5158Smillertother mechanisms are less portable across operating systems.  Authors of
1292b39c5158Smillertmodules and programs that use this function, especially its cargo-cult form
12936fb12b70Safresh1C<setlogsock("unix")>, are advised to remove any occurrence of it unless they
1294b39c5158Smillertspecifically want to use a given mechanism (like TCP or UDP to connect to
1295b39c5158Smillerta remote host).
1296b39c5158Smillert
1297b39c5158Smillert=back
1298b39c5158Smillert
1299b39c5158Smillert=item B<closelog()>
1300b39c5158Smillert
1301b39c5158SmillertCloses the log file and returns true on success.
1302b39c5158Smillert
1303b39c5158Smillert=back
1304b39c5158Smillert
1305b39c5158Smillert
1306b39c5158Smillert=head1 THE RULES OF SYS::SYSLOG
1307b39c5158Smillert
1308b39c5158SmillertI<The First Rule of Sys::Syslog is:>
1309b39c5158SmillertYou do not call C<setlogsock>.
1310b39c5158Smillert
1311b39c5158SmillertI<The Second Rule of Sys::Syslog is:>
1312b39c5158SmillertYou B<do not> call C<setlogsock>.
1313b39c5158Smillert
1314b39c5158SmillertI<The Third Rule of Sys::Syslog is:>
1315b39c5158SmillertThe program crashes, C<die>s, calls C<closelog>, the log is over.
1316b39c5158Smillert
1317b39c5158SmillertI<The Fourth Rule of Sys::Syslog is:>
1318b39c5158SmillertOne facility, one priority.
1319b39c5158Smillert
1320b39c5158SmillertI<The Fifth Rule of Sys::Syslog is:>
1321b39c5158SmillertOne log at a time.
1322b39c5158Smillert
1323b39c5158SmillertI<The Sixth Rule of Sys::Syslog is:>
1324b39c5158SmillertNo C<syslog> before C<openlog>.
1325b39c5158Smillert
1326b39c5158SmillertI<The Seventh Rule of Sys::Syslog is:>
1327b39c5158SmillertLogs will go on as long as they have to.
1328b39c5158Smillert
1329b39c5158SmillertI<The Eighth, and Final Rule of Sys::Syslog is:>
1330b39c5158SmillertIf this is your first use of Sys::Syslog, you must read the doc.
1331b39c5158Smillert
1332b39c5158Smillert
1333b39c5158Smillert=head1 EXAMPLES
1334b39c5158Smillert
1335b39c5158SmillertAn example:
1336b39c5158Smillert
1337b39c5158Smillert    openlog($program, 'cons,pid', 'user');
1338b39c5158Smillert    syslog('info', '%s', 'this is another test');
1339b39c5158Smillert    syslog('mail|warning', 'this is a better test: %d', time);
1340b39c5158Smillert    closelog();
1341b39c5158Smillert
1342b39c5158Smillert    syslog('debug', 'this is the last test');
1343b39c5158Smillert
1344b39c5158SmillertAnother example:
1345b39c5158Smillert
1346b39c5158Smillert    openlog("$program $$", 'ndelay', 'user');
1347b39c5158Smillert    syslog('notice', 'fooprogram: this is really done');
1348b39c5158Smillert
1349b39c5158SmillertExample of use of C<%m>:
1350b39c5158Smillert
1351b39c5158Smillert    $! = 55;
1352b39c5158Smillert    syslog('info', 'problem was %m');   # %m == $! in syslog(3)
1353b39c5158Smillert
1354b39c5158SmillertLog to UDP port on C<$remotehost> instead of logging locally:
1355b39c5158Smillert
1356b39c5158Smillert    setlogsock("udp", $remotehost);
1357b39c5158Smillert    openlog($program, 'ndelay', 'user');
1358b39c5158Smillert    syslog('info', 'something happened over here');
1359b39c5158Smillert
1360b39c5158Smillert
1361b39c5158Smillert=head1 CONSTANTS
1362b39c5158Smillert
1363b39c5158Smillert=head2 Facilities
1364b39c5158Smillert
1365b39c5158Smillert=over 4
1366b39c5158Smillert
1367b39c5158Smillert=item *
1368b39c5158Smillert
1369b39c5158SmillertC<LOG_AUDIT> - audit daemon (IRIX); falls back to C<LOG_AUTH>
1370b39c5158Smillert
1371b39c5158Smillert=item *
1372b39c5158Smillert
1373b39c5158SmillertC<LOG_AUTH> - security/authorization messages
1374b39c5158Smillert
1375b39c5158Smillert=item *
1376b39c5158Smillert
1377b39c5158SmillertC<LOG_AUTHPRIV> - security/authorization messages (private)
1378b39c5158Smillert
1379b39c5158Smillert=item *
1380b39c5158Smillert
1381b39c5158SmillertC<LOG_CONSOLE> - C</dev/console> output (FreeBSD); falls back to C<LOG_USER>
1382b39c5158Smillert
1383b39c5158Smillert=item *
1384b39c5158Smillert
1385b39c5158SmillertC<LOG_CRON> - clock daemons (B<cron> and B<at>)
1386b39c5158Smillert
1387b39c5158Smillert=item *
1388b39c5158Smillert
1389b39c5158SmillertC<LOG_DAEMON> - system daemons without separate facility value
1390b39c5158Smillert
1391b39c5158Smillert=item *
1392b39c5158Smillert
1393b39c5158SmillertC<LOG_FTP> - FTP daemon
1394b39c5158Smillert
1395b39c5158Smillert=item *
1396b39c5158Smillert
1397b39c5158SmillertC<LOG_KERN> - kernel messages
1398b39c5158Smillert
1399b39c5158Smillert=item *
1400b39c5158Smillert
1401b39c5158SmillertC<LOG_INSTALL> - installer subsystem (Mac OS X); falls back to C<LOG_USER>
1402b39c5158Smillert
1403b39c5158Smillert=item *
1404b39c5158Smillert
1405b39c5158SmillertC<LOG_LAUNCHD> - launchd - general bootstrap daemon (Mac OS X);
1406b39c5158Smillertfalls back to C<LOG_DAEMON>
1407b39c5158Smillert
1408b39c5158Smillert=item *
1409b39c5158Smillert
1410b39c5158SmillertC<LOG_LFMT> - logalert facility; falls back to C<LOG_USER>
1411b39c5158Smillert
1412b39c5158Smillert=item *
1413b39c5158Smillert
1414b39c5158SmillertC<LOG_LOCAL0> through C<LOG_LOCAL7> - reserved for local use
1415b39c5158Smillert
1416b39c5158Smillert=item *
1417b39c5158Smillert
1418b39c5158SmillertC<LOG_LPR> - line printer subsystem
1419b39c5158Smillert
1420b39c5158Smillert=item *
1421b39c5158Smillert
1422b39c5158SmillertC<LOG_MAIL> - mail subsystem
1423b39c5158Smillert
1424b39c5158Smillert=item *
1425b39c5158Smillert
1426b39c5158SmillertC<LOG_NETINFO> - NetInfo subsystem (Mac OS X); falls back to C<LOG_DAEMON>
1427b39c5158Smillert
1428b39c5158Smillert=item *
1429b39c5158Smillert
1430b39c5158SmillertC<LOG_NEWS> - USENET news subsystem
1431b39c5158Smillert
1432b39c5158Smillert=item *
1433b39c5158Smillert
1434b39c5158SmillertC<LOG_NTP> - NTP subsystem (FreeBSD, NetBSD); falls back to C<LOG_DAEMON>
1435b39c5158Smillert
1436b39c5158Smillert=item *
1437b39c5158Smillert
1438b39c5158SmillertC<LOG_RAS> - Remote Access Service (VPN / PPP) (Mac OS X);
1439b39c5158Smillertfalls back to C<LOG_AUTH>
1440b39c5158Smillert
1441b39c5158Smillert=item *
1442b39c5158Smillert
1443b39c5158SmillertC<LOG_REMOTEAUTH> - remote authentication/authorization (Mac OS X);
1444b39c5158Smillertfalls back to C<LOG_AUTH>
1445b39c5158Smillert
1446b39c5158Smillert=item *
1447b39c5158Smillert
1448b39c5158SmillertC<LOG_SECURITY> - security subsystems (firewalling, etc.) (FreeBSD);
1449b39c5158Smillertfalls back to C<LOG_AUTH>
1450b39c5158Smillert
1451b39c5158Smillert=item *
1452b39c5158Smillert
1453b39c5158SmillertC<LOG_SYSLOG> - messages generated internally by B<syslogd>
1454b39c5158Smillert
1455b39c5158Smillert=item *
1456b39c5158Smillert
1457b39c5158SmillertC<LOG_USER> (default) - generic user-level messages
1458b39c5158Smillert
1459b39c5158Smillert=item *
1460b39c5158Smillert
1461b39c5158SmillertC<LOG_UUCP> - UUCP subsystem
1462b39c5158Smillert
1463b39c5158Smillert=back
1464b39c5158Smillert
1465b39c5158Smillert
1466b39c5158Smillert=head2 Levels
1467b39c5158Smillert
1468b39c5158Smillert=over 4
1469b39c5158Smillert
1470b39c5158Smillert=item *
1471b39c5158Smillert
1472b39c5158SmillertC<LOG_EMERG> - system is unusable
1473b39c5158Smillert
1474b39c5158Smillert=item *
1475b39c5158Smillert
1476b39c5158SmillertC<LOG_ALERT> - action must be taken immediately
1477b39c5158Smillert
1478b39c5158Smillert=item *
1479b39c5158Smillert
1480b39c5158SmillertC<LOG_CRIT> - critical conditions
1481b39c5158Smillert
1482b39c5158Smillert=item *
1483b39c5158Smillert
1484b39c5158SmillertC<LOG_ERR> - error conditions
1485b39c5158Smillert
1486b39c5158Smillert=item *
1487b39c5158Smillert
1488b39c5158SmillertC<LOG_WARNING> - warning conditions
1489b39c5158Smillert
1490b39c5158Smillert=item *
1491b39c5158Smillert
1492b39c5158SmillertC<LOG_NOTICE> - normal, but significant, condition
1493b39c5158Smillert
1494b39c5158Smillert=item *
1495b39c5158Smillert
1496b39c5158SmillertC<LOG_INFO> - informational message
1497b39c5158Smillert
1498b39c5158Smillert=item *
1499b39c5158Smillert
1500b39c5158SmillertC<LOG_DEBUG> - debug-level message
1501b39c5158Smillert
1502b39c5158Smillert=back
1503b39c5158Smillert
1504b39c5158Smillert
1505b39c5158Smillert=head1 DIAGNOSTICS
1506b39c5158Smillert
1507b39c5158Smillert=over
1508b39c5158Smillert
1509b39c5158Smillert=item C<Invalid argument passed to setlogsock>
1510b39c5158Smillert
1511b39c5158SmillertB<(F)> You gave C<setlogsock()> an invalid value for C<$sock_type>.
1512b39c5158Smillert
1513b39c5158Smillert=item C<eventlog passed to setlogsock, but no Win32 API available>
1514b39c5158Smillert
1515b39c5158SmillertB<(W)> You asked C<setlogsock()> to use the Win32 event logger but the
1516b39c5158Smillertoperating system running the program isn't Win32 or does not provides Win32
1517b39c5158Smillertcompatible facilities.
1518b39c5158Smillert
1519b39c5158Smillert=item C<no connection to syslog available>
1520b39c5158Smillert
1521b39c5158SmillertB<(F)> C<syslog()> failed to connect to the specified socket.
1522b39c5158Smillert
1523b39c5158Smillert=item C<stream passed to setlogsock, but %s is not writable>
1524b39c5158Smillert
1525b39c5158SmillertB<(W)> You asked C<setlogsock()> to use a stream socket, but the given
1526b39c5158Smillertpath is not writable.
1527b39c5158Smillert
1528b39c5158Smillert=item C<stream passed to setlogsock, but could not find any device>
1529b39c5158Smillert
1530b39c5158SmillertB<(W)> You asked C<setlogsock()> to use a stream socket, but didn't
1531b39c5158Smillertprovide a path, and C<Sys::Syslog> was unable to find an appropriate one.
1532b39c5158Smillert
1533b39c5158Smillert=item C<tcp passed to setlogsock, but tcp service unavailable>
1534b39c5158Smillert
1535b39c5158SmillertB<(W)> You asked C<setlogsock()> to use a TCP socket, but the service
1536b39c5158Smillertis not available on the system.
1537b39c5158Smillert
1538b39c5158Smillert=item C<syslog: expecting argument %s>
1539b39c5158Smillert
1540b39c5158SmillertB<(F)> You forgot to give C<syslog()> the indicated argument.
1541b39c5158Smillert
1542b39c5158Smillert=item C<syslog: invalid level/facility: %s>
1543b39c5158Smillert
1544b39c5158SmillertB<(F)> You specified an invalid level or facility.
1545b39c5158Smillert
1546b39c5158Smillert=item C<syslog: too many levels given: %s>
1547b39c5158Smillert
1548b39c5158SmillertB<(F)> You specified too many levels.
1549b39c5158Smillert
1550b39c5158Smillert=item C<syslog: too many facilities given: %s>
1551b39c5158Smillert
1552b39c5158SmillertB<(F)> You specified too many facilities.
1553b39c5158Smillert
1554b39c5158Smillert=item C<syslog: level must be given>
1555b39c5158Smillert
1556b39c5158SmillertB<(F)> You forgot to specify a level.
1557b39c5158Smillert
1558b39c5158Smillert=item C<udp passed to setlogsock, but udp service unavailable>
1559b39c5158Smillert
1560b39c5158SmillertB<(W)> You asked C<setlogsock()> to use a UDP socket, but the service
1561b39c5158Smillertis not available on the system.
1562b39c5158Smillert
1563b39c5158Smillert=item C<unix passed to setlogsock, but path not available>
1564b39c5158Smillert
1565b39c5158SmillertB<(W)> You asked C<setlogsock()> to use a UNIX socket, but C<Sys::Syslog>
1566b39c5158Smillertwas unable to find an appropriate an appropriate device.
1567b39c5158Smillert
1568b39c5158Smillert=back
1569b39c5158Smillert
1570b39c5158Smillert
1571898184e3Ssthen=head1 HISTORY
1572898184e3Ssthen
1573898184e3SsthenC<Sys::Syslog> is a core module, part of the standard Perl distribution
1574898184e3Ssthensince 1990.  At this time, modules as we know them didn't exist, the
1575898184e3SsthenPerl library was a collection of F<.pl> files, and the one for sending
1576898184e3Ssthensyslog messages with was simply F<lib/syslog.pl>, included with Perl 3.0.
1577898184e3SsthenIt was converted as a module with Perl 5.0, but had a version number
1578898184e3Ssthenonly starting with Perl 5.6.  Here is a small table with the matching
1579898184e3SsthenPerl and C<Sys::Syslog> versions.
1580898184e3Ssthen
1581898184e3Ssthen    Sys::Syslog     Perl
1582898184e3Ssthen    -----------     ----
158391f110e0Safresh1       undef        5.0.0 ~ 5.5.4
158491f110e0Safresh1       0.01         5.6.*
1585898184e3Ssthen       0.03         5.8.0
1586898184e3Ssthen       0.04         5.8.1, 5.8.2, 5.8.3
1587898184e3Ssthen       0.05         5.8.4, 5.8.5, 5.8.6
1588898184e3Ssthen       0.06         5.8.7
1589898184e3Ssthen       0.13         5.8.8
1590898184e3Ssthen       0.22         5.10.0
15919f11ffb7Safresh1       0.27         5.8.9, 5.10.1 ~ 5.14.*
15929f11ffb7Safresh1       0.29         5.16.*
15939f11ffb7Safresh1       0.32         5.18.*
15949f11ffb7Safresh1       0.33         5.20.*
15959f11ffb7Safresh1       0.33         5.22.*
1596898184e3Ssthen
1597898184e3Ssthen
1598b39c5158Smillert=head1 SEE ALSO
1599b39c5158Smillert
16006fb12b70Safresh1=head2 Other modules
16016fb12b70Safresh1
16026fb12b70Safresh1L<Log::Log4perl> - Perl implementation of the Log4j API
16036fb12b70Safresh1
16046fb12b70Safresh1L<Log::Dispatch> - Dispatches messages to one or more outputs
16056fb12b70Safresh1
16066fb12b70Safresh1L<Log::Report> - Report a problem, with exceptions and language support
16076fb12b70Safresh1
1608b39c5158Smillert=head2 Manual Pages
1609b39c5158Smillert
1610b39c5158SmillertL<syslog(3)>
1611b39c5158Smillert
1612b39c5158SmillertSUSv3 issue 6, IEEE Std 1003.1, 2004 edition,
1613b39c5158SmillertL<http://www.opengroup.org/onlinepubs/000095399/basedefs/syslog.h.html>
1614b39c5158Smillert
1615b39c5158SmillertGNU C Library documentation on syslog,
1616b39c5158SmillertL<http://www.gnu.org/software/libc/manual/html_node/Syslog.html>
1617b39c5158Smillert
16189f11ffb7Safresh1FreeBSD documentation on syslog,
16199f11ffb7Safresh1L<https://www.freebsd.org/cgi/man.cgi?query=syslog>
16209f11ffb7Safresh1
16219f11ffb7Safresh1Solaris 11 documentation on syslog,
16229f11ffb7Safresh1L<https://docs.oracle.com/cd/E53394_01/html/E54766/syslog-3c.html>
1623b39c5158Smillert
1624b39c5158SmillertMac OS X documentation on syslog,
1625b39c5158SmillertL<http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/syslog.3.html>
1626b39c5158Smillert
16279f11ffb7Safresh1IRIX documentation on syslog,
16289f11ffb7Safresh1L<http://nixdoc.net/man-pages/IRIX/man3/syslog.3c.html>
1629b39c5158Smillert
1630b39c5158SmillertAIX 5L 5.3 documentation on syslog,
1631b39c5158SmillertL<http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf2/syslog.htm>
1632b39c5158Smillert
1633b39c5158SmillertHP-UX 11i documentation on syslog,
1634b39c5158SmillertL<http://docs.hp.com/en/B2355-60130/syslog.3C.html>
1635b39c5158Smillert
16369f11ffb7Safresh1Tru64 documentation on syslog,
16379f11ffb7Safresh1L<http://nixdoc.net/man-pages/Tru64/man3/syslog.3.html>
1638b39c5158Smillert
1639b39c5158SmillertStratus VOS 15.1,
1640b39c5158SmillertL<http://stratadoc.stratus.com/vos/15.1.1/r502-01/wwhelp/wwhimpl/js/html/wwhelp.htm?context=r502-01&file=ch5r502-01bi.html>
1641b39c5158Smillert
1642b39c5158Smillert=head2 RFCs
1643b39c5158Smillert
1644b39c5158SmillertI<RFC 3164 - The BSD syslog Protocol>, L<http://www.faqs.org/rfcs/rfc3164.html>
1645b39c5158Smillert-- Please note that this is an informational RFC, and therefore does not
1646b39c5158Smillertspecify a standard of any kind.
1647b39c5158Smillert
1648b39c5158SmillertI<RFC 3195 - Reliable Delivery for syslog>, L<http://www.faqs.org/rfcs/rfc3195.html>
1649b39c5158Smillert
1650b39c5158Smillert=head2 Articles
1651b39c5158Smillert
1652b39c5158SmillertI<Syslogging with Perl>, L<http://lexington.pm.org/meetings/022001.html>
1653b39c5158Smillert
1654b39c5158Smillert=head2 Event Log
1655b39c5158Smillert
1656b39c5158SmillertWindows Event Log,
1657b39c5158SmillertL<http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wes/wes/windows_event_log.asp>
1658b39c5158Smillert
1659b39c5158Smillert
1660b39c5158Smillert=head1 AUTHORS & ACKNOWLEDGEMENTS
1661b39c5158Smillert
1662b39c5158SmillertTom Christiansen E<lt>F<tchrist (at) perl.com>E<gt> and Larry Wall
1663b39c5158SmillertE<lt>F<larry (at) wall.org>E<gt>.
1664b39c5158Smillert
1665b39c5158SmillertUNIX domain sockets added by Sean Robinson
1666b39c5158SmillertE<lt>F<robinson_s (at) sc.maricopa.edu>E<gt> with support from Tim Bunce
1667b39c5158SmillertE<lt>F<Tim.Bunce (at) ig.co.uk>E<gt> and the C<perl5-porters> mailing list.
1668b39c5158Smillert
1669b39c5158SmillertDependency on F<syslog.ph> replaced with XS code by Tom Hughes
1670b39c5158SmillertE<lt>F<tom (at) compton.nu>E<gt>.
1671b39c5158Smillert
1672b39c5158SmillertCode for C<constant()>s regenerated by Nicholas Clark E<lt>F<nick (at) ccl4.org>E<gt>.
1673b39c5158Smillert
1674b39c5158SmillertFailover to different communication modes by Nick Williams
1675b39c5158SmillertE<lt>F<Nick.Williams (at) morganstanley.com>E<gt>.
1676b39c5158Smillert
1677b39c5158SmillertExtracted from core distribution for publishing on the CPAN by
1678b39c5158SmillertSE<eacute>bastien Aperghis-Tramoni E<lt>sebastien (at) aperghis.netE<gt>.
1679b39c5158Smillert
1680b39c5158SmillertXS code for using native C functions borrowed from C<L<Unix::Syslog>>,
1681b39c5158Smillertwritten by Marcus Harnisch E<lt>F<marcus.harnisch (at) gmx.net>E<gt>.
1682b39c5158Smillert
1683b39c5158SmillertYves Orton suggested and helped for making C<Sys::Syslog> use the native
1684b39c5158Smillertevent logger under Win32 systems.
1685b39c5158Smillert
1686b39c5158SmillertJerry D. Hedden and Reini Urban provided greatly appreciated help to
1687b39c5158Smillertdebug and polish C<Sys::Syslog> under Cygwin.
1688b39c5158Smillert
1689b39c5158Smillert
1690b39c5158Smillert=head1 BUGS
1691b39c5158Smillert
1692b39c5158SmillertPlease report any bugs or feature requests to
1693b39c5158SmillertC<bug-sys-syslog (at) rt.cpan.org>, or through the web interface at
1694b39c5158SmillertL<http://rt.cpan.org/Public/Dist/Display.html?Name=Sys-Syslog>.
1695b39c5158SmillertI will be notified, and then you'll automatically be notified of progress on
1696b39c5158Smillertyour bug as I make changes.
1697b39c5158Smillert
1698b39c5158Smillert
1699b39c5158Smillert=head1 SUPPORT
1700b39c5158Smillert
1701b39c5158SmillertYou can find documentation for this module with the perldoc command.
1702b39c5158Smillert
1703b39c5158Smillert    perldoc Sys::Syslog
1704b39c5158Smillert
1705b39c5158SmillertYou can also look for information at:
1706b39c5158Smillert
17079f11ffb7Safresh1=over
17089f11ffb7Safresh1
17099f11ffb7Safresh1=item * Perl Documentation
17109f11ffb7Safresh1
17119f11ffb7Safresh1L<http://perldoc.perl.org/Sys/Syslog.html>
17129f11ffb7Safresh1
17139f11ffb7Safresh1=item * MetaCPAN
17149f11ffb7Safresh1
17159f11ffb7Safresh1L<https://metacpan.org/module/Sys::Syslog>
17169f11ffb7Safresh1
17179f11ffb7Safresh1=item * Search CPAN
17189f11ffb7Safresh1
17199f11ffb7Safresh1L<http://search.cpan.org/dist/Sys-Syslog/>
1720b39c5158Smillert
1721b39c5158Smillert=item * AnnoCPAN: Annotated CPAN documentation
1722b39c5158Smillert
1723b39c5158SmillertL<http://annocpan.org/dist/Sys-Syslog>
1724b39c5158Smillert
1725b39c5158Smillert=item * CPAN Ratings
1726b39c5158Smillert
1727b39c5158SmillertL<http://cpanratings.perl.org/d/Sys-Syslog>
1728b39c5158Smillert
1729b39c5158Smillert=item * RT: CPAN's request tracker
1730b39c5158Smillert
1731898184e3SsthenL<http://rt.cpan.org/Dist/Display.html?Queue=Sys-Syslog>
1732b39c5158Smillert
1733b39c5158Smillert=back
1734b39c5158Smillert
17359f11ffb7Safresh1The source code is available on Git Hub:
17369f11ffb7Safresh1L<https://github.com/maddingue/Sys-Syslog/>
17379f11ffb7Safresh1
1738b39c5158Smillert
1739b39c5158Smillert=head1 COPYRIGHT
1740b39c5158Smillert
174191f110e0Safresh1Copyright (C) 1990-2012 by Larry Wall and others.
1742b39c5158Smillert
1743b39c5158Smillert
1744b39c5158Smillert=head1 LICENSE
1745b39c5158Smillert
1746b39c5158SmillertThis program is free software; you can redistribute it and/or modify it
1747b39c5158Smillertunder the same terms as Perl itself.
1748b39c5158Smillert
1749b39c5158Smillert=cut
1750b39c5158Smillert
1751b39c5158Smillert=begin comment
1752b39c5158Smillert
1753b39c5158SmillertNotes for the future maintainer (even if it's still me..)
1754b39c5158Smillert- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1755b39c5158Smillert
1756b39c5158SmillertUsing Google Code Search, I search who on Earth was relying on $host being
1757b39c5158Smillertpublic. It found 5 hits:
1758b39c5158Smillert
1759b39c5158Smillert* First was inside Indigo Star Perl2exe documentation. Just an old version
1760b39c5158Smillertof Sys::Syslog.
1761b39c5158Smillert
1762b39c5158Smillert
1763b39c5158Smillert* One real hit was inside DalWeathDB, a weather related program. It simply
1764b39c5158Smillertdoes a
1765b39c5158Smillert
1766b39c5158Smillert    $Sys::Syslog::host = '127.0.0.1';
1767b39c5158Smillert
1768b39c5158Smillert- L<http://www.gallistel.net/nparker/weather/code/>
1769b39c5158Smillert
1770b39c5158Smillert
1771b39c5158Smillert* Two hits were in TPC, a fax server thingy. It does a
1772b39c5158Smillert
1773b39c5158Smillert    $Sys::Syslog::host = $TPC::LOGHOST;
1774b39c5158Smillert
1775b39c5158Smillertbut also has this strange piece of code:
1776b39c5158Smillert
1777b39c5158Smillert    # work around perl5.003 bug
1778b39c5158Smillert    sub Sys::Syslog::hostname {}
1779b39c5158Smillert
1780b39c5158SmillertI don't know what bug the author referred to.
1781b39c5158Smillert
1782b39c5158Smillert- L<http://www.tpc.int/>
1783b39c5158Smillert- L<ftp://ftp-usa.tpc.int/pub/tpc/server/UNIX/>
1784b39c5158Smillert
1785b39c5158Smillert
1786b39c5158Smillert* Last hit was in Filefix, which seems to be a FIDOnet mail program (!).
1787b39c5158SmillertThis one does not use $host, but has the following piece of code:
1788b39c5158Smillert
1789b39c5158Smillert    sub Sys::Syslog::hostname
1790b39c5158Smillert    {
1791b39c5158Smillert        use Sys::Hostname;
1792b39c5158Smillert        return hostname;
1793b39c5158Smillert    }
1794b39c5158Smillert
1795b39c5158SmillertI guess this was a more elaborate form of the previous bit, maybe because
1796b39c5158Smillertof a bug in Sys::Syslog back then?
1797b39c5158Smillert
1798b39c5158Smillert- L<ftp://ftp.kiae.su/pub/unix/fido/>
1799b39c5158Smillert
1800b39c5158Smillert
1801b39c5158SmillertLinks
1802b39c5158Smillert-----
1803b39c5158SmillertLinux Fast-STREAMS
1804b39c5158Smillert- L<http://www.openss7.org/streams.html>
1805b39c5158Smillert
1806b39c5158SmillertII12021: SYSLOGD HOWTO TCPIPINFO (z/OS, OS/390, MVS)
1807b39c5158Smillert- L<http://www-1.ibm.com/support/docview.wss?uid=isg1II12021>
1808b39c5158Smillert
1809b39c5158SmillertGetting the most out of the Event Viewer
1810b39c5158Smillert- L<http://www.codeproject.com/dotnet/evtvwr.asp?print=true>
1811b39c5158Smillert
1812b39c5158SmillertLog events to the Windows NT Event Log with JNI
1813b39c5158Smillert- L<http://www.javaworld.com/javaworld/jw-09-2001/jw-0928-ntmessages.html>
1814b39c5158Smillert
1815b39c5158Smillert=end comment
1816b39c5158Smillert
1817