home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 7: Programming / CDAT7.iso / Share / Editores / Perl5 / perl / lib / Sys / Syslog.pm < prev   
Encoding:
Perl POD Document  |  1997-08-10  |  6.5 KB  |  258 lines

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