Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
7.3 KiB

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