5.005_03-MAINT_TRIAL_5 utils/h2xs fixing -A & more
[p5sagit/p5-mst-13.2.git] / lib / Sys / Syslog.pm
CommitLineData
a0d0e21e 1package Sys::Syslog;
2require 5.000;
3require Exporter;
4use Carp;
5
6@ISA = qw(Exporter);
7@EXPORT = qw(openlog closelog setlogmask syslog);
3ffabb8c 8@EXPORT_OK = qw(setlogsock);
a0d0e21e 9
37120919 10use Socket;
55497cff 11use Sys::Hostname;
37120919 12
5be1dfc7 13# adapted from syslog.pl
a0d0e21e 14#
5be1dfc7 15# Tom Christiansen <tchrist@convex.com>
a0d0e21e 16# modified to use sockets by Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
17# NOTE: openlog now takes three arguments, just like openlog(3)
3ffabb8c 18# Modified to add UNIX domain sockets by Sean Robinson <robinson_s@sc.maricopa.edu>
19# with support from Tim Bunce <Tim.Bunce@ig.co.uk> and the perl5-porters mailing list
20
21# Todo: enable connect to try all three types before failing (auto setlogsock)?
5be1dfc7 22
23=head1 NAME
24
25Sys::Syslog, openlog, closelog, setlogmask, syslog - Perl interface to the UNIX syslog(3) calls
26
27=head1 SYNOPSIS
28
3ffabb8c 29 use Sys::Syslog; # all except setlogsock, or:
30 use Sys::Syslog qw(:DEFAULT setlogsock); # default set, plus setlogsock
5be1dfc7 31
3ffabb8c 32 setlogsock $sock_type;
5be1dfc7 33 openlog $ident, $logopt, $facility;
2eae817d 34 syslog $priority, $format, @args;
5be1dfc7 35 $oldmask = setlogmask $mask_priority;
36 closelog;
37
38=head1 DESCRIPTION
39
40Sys::Syslog is an interface to the UNIX C<syslog(3)> program.
41Call C<syslog()> with a string priority and a list of C<printf()> args
42just like C<syslog(3)>.
43
44Syslog provides the functions:
45
46=over
47
48=item openlog $ident, $logopt, $facility
49
50I<$ident> is prepended to every message.
b12e51c8 51I<$logopt> contains zero or more of the words I<pid>, I<ndelay>, I<cons>, I<nowait>.
5be1dfc7 52I<$facility> specifies the part of the system
53
2eae817d 54=item syslog $priority, $format, @args
5be1dfc7 55
2eae817d 56If I<$priority> permits, logs I<($format, @args)>
5be1dfc7 57printed as by C<printf(3V)>, with the addition that I<%m>
58is replaced with C<"$!"> (the latest error message).
59
60=item setlogmask $mask_priority
61
62Sets log mask I<$mask_priority> and returns the old mask.
63
3ffabb8c 64=item setlogsock $sock_type (added in 5.004_02)
65
cb63fe9d 66Sets the socket type to be used for the next call to
3ffabb8c 67C<openlog()> or C<syslog()> and returns TRUE on success,
68undef on failure.
69
f8b75b0c 70A value of 'unix' will connect to the UNIX domain socket returned by
3ffabb8c 71C<_PATH_LOG> in F<syslog.ph>. A value of 'inet' will connect to an
72INET socket returned by getservbyname(). Any other value croaks.
cb63fe9d 73
74The default is for the INET socket to be used.
75
5be1dfc7 76=item closelog
77
78Closes the log file.
79
80=back
81
82Note that C<openlog> now takes three arguments, just like C<openlog(3)>.
83
84=head1 EXAMPLES
85
86 openlog($program, 'cons,pid', 'user');
87 syslog('info', 'this is another test');
88 syslog('mail|warning', 'this is a better test: %d', time);
89 closelog();
90
91 syslog('debug', 'this is the last test');
cb63fe9d 92
93 setlogsock('unix');
5be1dfc7 94 openlog("$program $$", 'ndelay', 'user');
95 syslog('notice', 'fooprogram: this is really done');
96
cb63fe9d 97 setlogsock('inet');
5be1dfc7 98 $! = 55;
99 syslog('info', 'problem was %m'); # %m == $! in syslog(3)
100
101=head1 DEPENDENCIES
102
103B<Sys::Syslog> needs F<syslog.ph>, which can be created with C<h2ph>.
104
105=head1 SEE ALSO
106
107L<syslog(3)>
108
109=head1 AUTHOR
110
cb63fe9d 111Tom Christiansen E<lt>F<tchrist@perl.com>E<gt> and Larry Wall E<lt>F<larry@wall.org>E<gt>.
112UNIX domain sockets added by Sean Robinson E<lt>F<robinson_s@sc.maricopa.edu>E<gt>
113with support from Tim Bunce <Tim.Bunce@ig.co.uk> and the perl5-porters mailing list.
5be1dfc7 114
115=cut
a0d0e21e 116
a0d0e21e 117require 'syslog.ph';
118
119$maskpri = &LOG_UPTO(&LOG_DEBUG);
120
121sub openlog {
122 ($ident, $logopt, $facility) = @_; # package vars
123 $lo_pid = $logopt =~ /\bpid\b/;
124 $lo_ndelay = $logopt =~ /\bndelay\b/;
125 $lo_cons = $logopt =~ /\bcons\b/;
126 $lo_nowait = $logopt =~ /\bnowait\b/;
a8710ca1 127 return 1 unless $lo_ndelay;
128 &connect;
a0d0e21e 129}
130
131sub closelog {
132 $facility = $ident = '';
133 &disconnect;
134}
135
136sub setlogmask {
137 local($oldmask) = $maskpri;
138 $maskpri = shift;
139 $oldmask;
140}
141
cb63fe9d 142sub setlogsock {
143 local($setsock) = shift;
3ffabb8c 144 &disconnect if $connected;
cb63fe9d 145 if (lc($setsock) eq 'unix') {
3ffabb8c 146 if (defined &_PATH_LOG) {
147 $sock_type = 1;
148 } else {
149 return undef;
150 }
cb63fe9d 151 } elsif (lc($setsock) eq 'inet') {
3ffabb8c 152 if (getservbyname('syslog','udp')) {
153 undef($sock_type);
154 } else {
155 return undef;
156 }
cb63fe9d 157 } else {
158 croak "Invalid argument passed to setlogsock; must be 'unix' or 'inet'";
159 }
f8b75b0c 160 return 1;
cb63fe9d 161}
162
a0d0e21e 163sub syslog {
164 local($priority) = shift;
165 local($mask) = shift;
166 local($message, $whoami);
167 local(@words, $num, $numpri, $numfac, $sum);
168 local($facility) = $facility; # may need to change temporarily.
169
170 croak "syslog: expected both priority and mask" unless $mask && $priority;
171
172 @words = split(/\W+/, $priority, 2);# Allow "level" or "level|facility".
173 undef $numpri;
174 undef $numfac;
175 foreach (@words) {
176 $num = &xlate($_); # Translate word to number.
177 if (/^kern$/ || $num < 0) {
178 croak "syslog: invalid level/facility: $_";
179 }
180 elsif ($num <= &LOG_PRIMASK) {
181 croak "syslog: too many levels given: $_" if defined($numpri);
182 $numpri = $num;
183 return 0 unless &LOG_MASK($numpri) & $maskpri;
184 }
185 else {
186 croak "syslog: too many facilities given: $_" if defined($numfac);
187 $facility = $_;
188 $numfac = $num;
189 }
190 }
191
192 croak "syslog: level must be given" unless defined($numpri);
193
194 if (!defined($numfac)) { # Facility not specified in this call.
195 $facility = 'user' unless $facility;
196 $numfac = &xlate($facility);
197 }
198
199 &connect unless $connected;
200
201 $whoami = $ident;
202
5dad0344 203 if (!$whoami && $mask =~ /^(\S.*?):\s?(.*)/) {
a0d0e21e 204 $whoami = $1;
205 $mask = $2;
206 }
207
208 unless ($whoami) {
209 ($whoami = getlogin) ||
210 ($whoami = getpwuid($<)) ||
211 ($whoami = 'syslog');
212 }
213
214 $whoami .= "[$$]" if $lo_pid;
215
216 $mask =~ s/%m/$!/g;
217 $mask .= "\n" unless $mask =~ /\n$/;
218 $message = sprintf ($mask, @_);
219
220 $sum = $numpri + $numfac;
cb63fe9d 221 unless (send(SYSLOG,"<$sum>$whoami: $message\0",0)) {
a0d0e21e 222 if ($lo_cons) {
223 if ($pid = fork) {
224 unless ($lo_nowait) {
cb1a09d0 225 $died = waitpid($pid, 0);
a0d0e21e 226 }
227 }
228 else {
229 open(CONS,">/dev/console");
230 print CONS "<$facility.$priority>$whoami: $message\r";
231 exit if defined $pid; # if fork failed, we're parent
232 close CONS;
233 }
234 }
235 }
236}
237
238sub xlate {
239 local($name) = @_;
55497cff 240 $name = uc $name;
a0d0e21e 241 $name = "LOG_$name" unless $name =~ /^LOG_/;
748a9306 242 $name = "Sys::Syslog::$name";
36477c24 243 defined &$name ? &$name : -1;
a0d0e21e 244}
245
246sub connect {
4fc7577b 247 unless ($host) {
248 require Sys::Hostname;
2eae817d 249 my($host_uniq) = Sys::Hostname::hostname();
3e3baf6d 250 ($host) = $host_uniq =~ /([A-Za-z0-9_.-]+)/; # allow FQDN (inc _)
4fc7577b 251 }
3ffabb8c 252 unless ( $sock_type ) {
cb63fe9d 253 my $udp = getprotobyname('udp');
254 my $syslog = getservbyname('syslog','udp');
255 my $this = sockaddr_in($syslog, INADDR_ANY);
256 my $that = sockaddr_in($syslog, inet_aton($host) || croak "Can't lookup $host");
257 socket(SYSLOG,AF_INET,SOCK_DGRAM,$udp) || croak "socket: $!";
258 connect(SYSLOG,$that) || croak "connect: $!";
259 } else {
260 my $syslog = &_PATH_LOG || croak "_PATH_LOG not found in syslog.ph";
261 my $that = sockaddr_un($syslog) || croak "Can't locate $syslog";
3ffabb8c 262 socket(SYSLOG,AF_UNIX,SOCK_STREAM,0) || croak "socket: $!";
263 if (!connect(SYSLOG,$that)) {
264 socket(SYSLOG,AF_UNIX,SOCK_DGRAM,0) || croak "socket: $!";
265 connect(SYSLOG,$that) || croak "connect: $! (SOCK_DGRAM after trying SOCK_STREAM)";
266 }
cb63fe9d 267 }
a0d0e21e 268 local($old) = select(SYSLOG); $| = 1; select($old);
269 $connected = 1;
270}
271
272sub disconnect {
273 close SYSLOG;
274 $connected = 0;
275}
276
2771;