home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / perl_mlb.zip / Sys / Syslog.pm < prev   
Text File  |  1997-11-25  |  7KB  |  264 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 (added in 5.004_03)
  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 by
  63. C<_PATH_LOG> in F<syslog.ph>. If F<syslog.ph> fails to define
  64. C<_PATH_LOG>, C<setlogsock> returns C<undef>; otherwise a true value is
  65. returned. A value of 'inet' will connect to an INET socket returned by
  66. getservbyname().  Any other value croaks.
  67.  
  68. The default is for the INET socket to be used.
  69.  
  70.  
  71. =item closelog
  72.  
  73. Closes the log file.
  74.  
  75. =back
  76.  
  77. Note that C<openlog> now takes three arguments, just like C<openlog(3)>.
  78.  
  79. =head1 EXAMPLES
  80.  
  81.     openlog($program, 'cons,pid', 'user');
  82.     syslog('info', 'this is another test');
  83.     syslog('mail|warning', 'this is a better test: %d', time);
  84.     closelog();
  85.  
  86.     syslog('debug', 'this is the last test');
  87.  
  88.     setlogsock('unix');
  89.     openlog("$program $$", 'ndelay', 'user');
  90.     syslog('notice', 'fooprogram: this is really done');
  91.  
  92.     setlogsock('inet');
  93.     $! = 55;
  94.     syslog('info', 'problem was %m'); # %m == $! in syslog(3)
  95.  
  96. =head1 DEPENDENCIES
  97.  
  98. B<Sys::Syslog> needs F<syslog.ph>, which can be created with C<h2ph>.
  99.  
  100. =head1 SEE ALSO
  101.  
  102. L<syslog(3)>
  103.  
  104. =head1 AUTHOR
  105.  
  106. Tom Christiansen E<lt>F<tchrist@perl.com>E<gt> and Larry Wall E<lt>F<larry@wall.org>E<gt>.
  107. UNIX domain sockets added by Sean Robinson E<lt>F<robinson_s@sc.maricopa.edu>E<gt>
  108. with support from Tim Bunce <Tim.Bunce@ig.co.uk> and the perl5-porters mailing list.
  109.  
  110. =cut
  111.  
  112. require 'syslog.ph';
  113.  
  114. $maskpri = &LOG_UPTO(&LOG_DEBUG);
  115.  
  116. sub openlog {
  117.     ($ident, $logopt, $facility) = @_;  # package vars
  118.     $lo_pid = $logopt =~ /\bpid\b/;
  119.     $lo_ndelay = $logopt =~ /\bndelay\b/;
  120.     $lo_cons = $logopt =~ /\bcons\b/;
  121.     $lo_nowait = $logopt =~ /\bnowait\b/;
  122.     &connect if $lo_ndelay;
  123.  
  124. sub closelog {
  125.     $facility = $ident = '';
  126.     &disconnect;
  127.  
  128. sub setlogmask {
  129.     local($oldmask) = $maskpri;
  130.     $maskpri = shift;
  131.     $oldmask;
  132. }
  133.  
  134. sub setlogsock {
  135.     local($setsock) = shift;
  136.     if (lc($setsock) eq 'unix') {
  137.     if (defined &_PATH_LOG) {
  138.         $sock_unix = 1;
  139.     } else {
  140.         return undef;
  141.     }
  142.     } elsif (lc($setsock) eq 'inet') {
  143.         undef($sock_unix);
  144.     } else {
  145.         croak "Invalid argument passed to setlogsock; must be 'unix' or 'inet'";
  146.     }
  147.     return 1;
  148. }
  149.  
  150. sub syslog {
  151.     local($priority) = shift;
  152.     local($mask) = shift;
  153.     local($message, $whoami);
  154.     local(@words, $num, $numpri, $numfac, $sum);
  155.     local($facility) = $facility;    # may need to change temporarily.
  156.  
  157.     croak "syslog: expected both priority and mask" unless $mask && $priority;
  158.  
  159.     @words = split(/\W+/, $priority, 2);# Allow "level" or "level|facility".
  160.     undef $numpri;
  161.     undef $numfac;
  162.     foreach (@words) {
  163.     $num = &xlate($_);        # Translate word to number.
  164.     if (/^kern$/ || $num < 0) {
  165.         croak "syslog: invalid level/facility: $_";
  166.     }
  167.     elsif ($num <= &LOG_PRIMASK) {
  168.         croak "syslog: too many levels given: $_" if defined($numpri);
  169.         $numpri = $num;
  170.         return 0 unless &LOG_MASK($numpri) & $maskpri;
  171.     }
  172.     else {
  173.         croak "syslog: too many facilities given: $_" if defined($numfac);
  174.         $facility = $_;
  175.         $numfac = $num;
  176.     }
  177.     }
  178.  
  179.     croak "syslog: level must be given" unless defined($numpri);
  180.  
  181.     if (!defined($numfac)) {    # Facility not specified in this call.
  182.     $facility = 'user' unless $facility;
  183.     $numfac = &xlate($facility);
  184.     }
  185.  
  186.     &connect unless $connected;
  187.  
  188.     $whoami = $ident;
  189.  
  190.     if (!$whoami && $mask =~ /^(\S.*?):\s?(.*)/) {
  191.     $whoami = $1;
  192.     $mask = $2;
  193.     } 
  194.  
  195.     unless ($whoami) {
  196.     ($whoami = getlogin) ||
  197.         ($whoami = getpwuid($<)) ||
  198.         ($whoami = 'syslog');
  199.     }
  200.  
  201.     $whoami .= "[$$]" if $lo_pid;
  202.  
  203.     $mask =~ s/%m/$!/g;
  204.     $mask .= "\n" unless $mask =~ /\n$/;
  205.     $message = sprintf ($mask, @_);
  206.  
  207.     $sum = $numpri + $numfac;
  208.     unless (send(SYSLOG,"<$sum>$whoami: $message\0",0)) {
  209.     if ($lo_cons) {
  210.         if ($pid = fork) {
  211.         unless ($lo_nowait) {
  212.             $died = waitpid($pid, 0);
  213.         }
  214.         }
  215.         else {
  216.         open(CONS,">/dev/console");
  217.         print CONS "<$facility.$priority>$whoami: $message\r";
  218.         exit if defined $pid;        # if fork failed, we're parent
  219.         close CONS;
  220.         }
  221.     }
  222.     }
  223. }
  224.  
  225. sub xlate {
  226.     local($name) = @_;
  227.     $name = uc $name;
  228.     $name = "LOG_$name" unless $name =~ /^LOG_/;
  229.     $name = "Sys::Syslog::$name";
  230.     defined &$name ? &$name : -1;
  231. }
  232.  
  233. sub connect {
  234.     unless ($host) {
  235.     require Sys::Hostname;
  236.     my($host_uniq) = Sys::Hostname::hostname();
  237.     ($host) = $host_uniq =~ /([A-Za-z0-9_.-]+)/; # allow FQDN (inc _)
  238.     }
  239.     unless ( $sock_unix ) {
  240.         my $udp = getprotobyname('udp');
  241.         my $syslog = getservbyname('syslog','udp');
  242.         my $this = sockaddr_in($syslog, INADDR_ANY);
  243.         my $that = sockaddr_in($syslog, inet_aton($host) || croak "Can't lookup $host");
  244.         socket(SYSLOG,AF_INET,SOCK_DGRAM,$udp)           || croak "socket: $!";
  245.         connect(SYSLOG,$that)                            || croak "connect: $!";
  246.     } else {
  247.         my $syslog = &_PATH_LOG                          || croak "_PATH_LOG not found in syslog.ph";
  248.         my $that = sockaddr_un($syslog)                  || croak "Can't locate $syslog";
  249.         socket(SYSLOG,AF_UNIX,SOCK_STREAM,0)             || croak "open: $!";
  250.         connect(SYSLOG,$that)                            || croak "connect: $!";
  251.     }
  252.     local($old) = select(SYSLOG); $| = 1; select($old);
  253.     $connected = 1;
  254. }
  255.  
  256. sub disconnect {
  257.     close SYSLOG;
  258.     $connected = 0;
  259. }
  260.  
  261. 1;
  262.