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.

253 lines
6.8 KiB

  1. #---------------------------------------------------------------------
  2. package Logmsg;
  3. #
  4. # Copyright (c) Microsoft Corporation. All rights reserved.
  5. #
  6. # Version: 2.00 07/20/2000 JeremyD new version
  7. # 2.01 12/27/2000 JeremyD remove compatibility hooks
  8. # 2.02 02/02/2001 JeremyD add logfile_append function
  9. #---------------------------------------------------------------------
  10. use strict;
  11. use vars qw(@ISA @EXPORT $VERSION $DEBUG);
  12. use Carp;
  13. use Exporter;
  14. use Win32::Mutex;
  15. use IO::File;
  16. use File::Basename;
  17. @ISA = qw(Exporter);
  18. @EXPORT = qw(dbgmsg infomsg logmsg wrnmsg errmsg timemsg append_file);
  19. $VERSION = '2.02';
  20. sub timestamp() {
  21. my ($sec,$min,$hour,$day,$mon,$year) = localtime;
  22. $year %= 100;
  23. $mon++;
  24. return sprintf("%02d/%02d/%02d %02d:%02d:%02d", $mon, $day, $year,
  25. $hour, $min, $sec);
  26. }
  27. sub scriptname() {
  28. $ENV{SCRIPT_NAME} || basename($0);
  29. }
  30. sub sync_write {
  31. my $data = shift;
  32. my $filename = shift;
  33. # validate data
  34. return unless $data;
  35. return unless $filename;
  36. # get a global mutex for this file, this breaks down if
  37. # relative paths are used, so don't use them
  38. my $mutexname = $filename;
  39. $mutexname =~ tr/A-Z\\/a-z\//;
  40. $mutexname = "Global\\$mutexname";
  41. my $mutex = Win32::Mutex->new(0, $mutexname);
  42. if (defined $mutex) {
  43. if ($mutex->wait(60000)) {
  44. if (my $fh = IO::File->new($filename, "a")) {
  45. $fh->print($data);
  46. undef $fh;
  47. } else {
  48. carp "Failed to open $filename: $!";
  49. }
  50. $mutex->release;
  51. } else {
  52. carp "Timed out trying to get mutex for $filename, skipping";
  53. }
  54. } else {
  55. carp "Failed to create mutex $mutexname for log access";
  56. }
  57. }
  58. sub sync_write_multiple {
  59. my $data = shift;
  60. my @filenames = @_;
  61. for my $filename (@filenames) {
  62. sync_write($data, $filename);
  63. }
  64. }
  65. sub dbgmsg {
  66. my $message = shift;
  67. return unless ($DEBUG or $ENV{DEBUG});
  68. my $line = sprintf("(%s) [%s] $message\n", scriptname(), timestamp());
  69. print $line;
  70. sync_write_multiple($line,
  71. $ENV{LOGFILE}, $ENV{INTERLEAVE_LOG});
  72. return $line;
  73. }
  74. sub infomsg {
  75. my $message = shift;
  76. my $line = sprintf("(%s) [%s] $message\n", scriptname(), timestamp());
  77. sync_write_multiple($line,
  78. $ENV{LOGFILE}, $ENV{INTERLEAVE_LOG});
  79. return $line;
  80. }
  81. sub logmsg {
  82. my $message = shift;
  83. my $line = sprintf("(%s) $message\n", scriptname());
  84. print $line;
  85. sync_write_multiple($line,
  86. $ENV{LOGFILE}, $ENV{INTERLEAVE_LOG});
  87. return $line;
  88. }
  89. sub timemsg {
  90. my $message = shift;
  91. my $line = sprintf("(%s) [%s] $message\n", scriptname(), timestamp());
  92. print $line;
  93. sync_write_multiple($line,
  94. $ENV{LOGFILE}, $ENV{INTERLEAVE_LOG});
  95. return $line;
  96. }
  97. sub wrnmsg {
  98. my $message = shift;
  99. my $line = sprintf("(%s) WARNING: $message\n", scriptname());
  100. print $line;
  101. sync_write_multiple($line,
  102. $ENV{LOGFILE}, $ENV{INTERLEAVE_LOG});
  103. return $line;
  104. }
  105. sub errmsg {
  106. my $message = shift;
  107. my $line = sprintf("(%s) ERROR: $message\n", scriptname());
  108. print $line;
  109. sync_write_multiple($line,
  110. $ENV{ERRFILE}, $ENV{LOGFILE}, $ENV{INTERLEAVE_LOG});
  111. $ENV{ERRORS}++;
  112. return $line;
  113. # maybe this should croak?
  114. }
  115. sub append_file {
  116. my $filename = shift;
  117. my $shortname = basename($filename);
  118. my $content = sprintf("(%s) [%s] appending $filename\n", scriptname(), timestamp());
  119. open FILE, $filename or die $!;
  120. while (<FILE>) {
  121. $content .= "$shortname: $_";
  122. }
  123. close FILE;
  124. sync_write_multiple($content,
  125. $ENV{LOGFILE}, $ENV{INTERLEAVE_LOG});
  126. return $filename;
  127. }
  128. 1;
  129. __END__
  130. =head1 NAME
  131. Logmsg - An interface for writing to log files
  132. =head1 SYNOPSIS
  133. use Logmsg;
  134. logmsg "the text to be logged";
  135. =head1 DESCRIPTION
  136. The Logmsg module provides an interface for writing to log files.
  137. The functions exported by Logmsg all take exactly one scalar, the message to
  138. be logged and return the text that was logged.
  139. The name of the running script is logged at the beginning of each message. The
  140. script name is set to either the SCRIPT_NAME environment variable or $0 if
  141. SCRIPT_NAME is not set.
  142. If a filename is available but the file does not exist it will be created.
  143. If a logfile environment variable (LOGFILE, INTERLEAVE_LOG, ERRFILE) is not set
  144. no attempt will be made to log to the file that it doesn't specify. No error or
  145. warning is generated.
  146. Any files that cannot be logged to (unable to obtain a lock within timeout) are
  147. skipped printing a warning to STDERR.
  148. =over 4
  149. =item logmsg( $message )
  150. Logs to STDOUT and the files specified by LOGFILE and INTERLEAVE_LOG.
  151. =item errmsg( $message )
  152. Logs to STDOUT and the files specified by ERRFILE, LOGFILE and INTERLEAVE_LOG. The
  153. message text is preceeded by "ERROR: " and the ERRORS environment variable is
  154. incremented.
  155. =item wrnmsg( $message )
  156. Logs to STDOUT and the files specified by LOGFILE and INTERLEAVE_LOG. The message
  157. text is preceeded by "WARNING: ".
  158. =item infomsg( $message )
  159. Logs to files specified by LOGFILE and INTERLEAVE_LOG. infomsg is similar to logmsg
  160. but can be used when output to STDOUT is not desirable.
  161. =item dbgmsg( $message )
  162. Logs to STDOUT and the files specified by LOGFILE and INTERLEAVE_LOG only if
  163. $Logmsg::DEBUG or the DEBUG environment variable is set.
  164. =item timemsg( $message )
  165. Logs to STDOUT and the files specified by LOGFILE and INTERLEAVE_LOG. The message
  166. text is preceeded by a date/time stamp.
  167. =item append_file( $filename )
  168. The contents of $filename are appended to LOGFILE and INTERLEAVE_LOG. The time and
  169. filename passed in are logged first followed by the contents of the file. Each
  170. line is prefixed with the base filename.
  171. =back
  172. =head1 ENVIRONMENT
  173. The environment variable SCRIPT_NAME is used to determine the script name to be
  174. logged with each message. The base filename of $0 is used if this is not set.
  175. If neither the DEBUG environment variable nor $Logfile::DEBUG is set then dbgmsg
  176. returns immediately and does not log.
  177. The environment variables LOGFILE, INTERLEAVE_LOG and ERRFILE specify the filenames
  178. to be used for logging. Any or all of these may be left unset without generating a
  179. warning or error.
  180. The errmsg function increments the ERRORS environment variable each time it is called.
  181. =head1 NOTES
  182. All file access is syncronized with a mutex based on the filename given. If different
  183. relative paths are used for a filename than locking protection will not work. In this
  184. case it is possible that some data may be corrupted by simultaneous writes to the same
  185. file.
  186. =head1 AUTHOR
  187. Jeremy Devenport <JeremyD>
  188. =head1 COPYRIGHT
  189. Copyright (c) Microsoft Corporation. All rights reserved.
  190. =cut