Leaked source code of windows server 2003
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.

275 lines
7.5 KiB

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