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.

236 lines
6.8 KiB

  1. #---------------------------------------------------------------------
  2. package PbuildEnv;
  3. #
  4. # Copyright (c) Microsoft Corporation. All rights reserved.
  5. #
  6. # Version: 1.00 (07/06/2000) : (JeremyD) inital version
  7. # 1.01 (07/13/2000) : (JeremyD) do as little as possible
  8. # 1.02 (07/26/2000) : (JeremyD) new logging style
  9. #---------------------------------------------------------------------
  10. use strict;
  11. use vars qw($VERSION);
  12. use lib $ENV{RAZZLETOOLPATH};
  13. use Carp;
  14. use File::Basename;
  15. use Logmsg;
  16. use cklang;
  17. $VERSION = '1.02';
  18. my ($DoNothing, $StartTime);
  19. BEGIN {
  20. # avoid running in a -c syntax check
  21. if ($^C) {
  22. $DoNothing++;
  23. return;
  24. }
  25. # required for logging
  26. $ENV{SCRIPT_NAME} = basename($0);
  27. # save a copy of the command line for logging
  28. my $command_line = join ' ', $0, @ARGV;
  29. # mini-parser to pull -l out of @ARGV at
  30. # compile time and set $ENV{LANG}
  31. my $lang;
  32. for (my $i=0; $i<@ARGV; $i++) {
  33. if ($ARGV[$i] =~ /^[\/-]l(?::(.*))?$/) {
  34. $lang = $1;
  35. if (!$lang and $ARGV[$i+1] !~ /^[\/-]/) {
  36. $lang = $ARGV[$i+1];
  37. splice @ARGV, $i+1, 1;
  38. }
  39. splice @ARGV, $i, 1;
  40. $ENV{LANG} = $lang;
  41. } elsif ($ARGV[$i] =~ /^[\/-]?\?/) {
  42. # snoop ahead for -? to avoid work, all scripts should print
  43. # usage and halt so we don't need to set up the environment
  44. $DoNothing++;
  45. return;
  46. }
  47. }
  48. # 'usa' is the default language
  49. $ENV{LANG} ||= 'usa';
  50. # validate language, bad languages are fatal
  51. if (!&cklang::CkLang($ENV{LANG})) {
  52. croak "Language $ENV{LANG} is not listed in codes.txt.";
  53. }
  54. # set up a unique value to be used in log file names, this
  55. # has the horrific side effect of making log names unbearably
  56. # long and irritating to type
  57. # BUGBUG: this is not unique enough, multiple instances of
  58. # the same script in the same postbuild will clobber each
  59. # other's file
  60. my $unique_name =
  61. "$ENV{SCRIPT_NAME}.$ENV{_BUILDARCH}.$ENV{_BUILDTYPE}.$ENV{LANG}";
  62. # select postbuild dir using our language (usa is a special case)
  63. $ENV{_NTPOSTBLD_BAK} ||= $ENV{_NTPOSTBLD};
  64. $ENV{_NTPOSTBLD} = $ENV{_NTPOSTBLD_BAK};
  65. # usa is not a special case in service pack mode
  66. # if (lc($ENV{LANG}) ne 'usa') {
  67. # Add this for Thin release
  68. if (!$ENV{dont_modify_ntpostbld} ) {
  69. $ENV{_NTPOSTBLD} .= "\\$ENV{LANG}";
  70. }
  71. # }
  72. # select a temp dir using our language
  73. $ENV{TEMP_BAK} ||= $ENV{TEMP};
  74. $ENV{TEMP} = $ENV{TMP} = "$ENV{TEMP_BAK}\\$ENV{LANG}";
  75. # create the directories for our logs if nescessary
  76. # BUGBUG perl mkdir will not recursively create dirs
  77. if (!-d $ENV{TEMP}) { mkdir $ENV{TEMP}, 0777 }
  78. # select the final logfile we will append to when finished
  79. # save the parent logfile to append to
  80. if ($ENV{LOGFILE}) {
  81. $ENV{LOGFILE_BAK} = $ENV{LOGFILE};
  82. }
  83. # we are the top level, select a filename and clear
  84. else {
  85. $ENV{LOGFILE_BAK} = "$ENV{TEMP}\\$unique_name.log";
  86. if (-e $ENV{LOGFILE_BAK}) { unlink $ENV{LOGFILE_BAK} }
  87. }
  88. # select the final errfile we will append to when finished
  89. # save the parent errfile to append to
  90. if ($ENV{ERRFILE}) {
  91. $ENV{ERRFILE_BAK} = $ENV{ERRFILE};
  92. }
  93. # we are the top level, select a filename and clear
  94. else {
  95. $ENV{ERRFILE_BAK} = "$ENV{TEMP}\\$unique_name.err";
  96. if (-e $ENV{ERRFILE_BAK}) { unlink $ENV{ERRFILE_BAK} }
  97. }
  98. # we will acutally log to a tempfile during script execution
  99. # we need to clear/create our temporary logging file
  100. $ENV{LOGFILE} = "$ENV{TEMP}\\$unique_name.tmp";
  101. unlink $ENV{LOGFILE};
  102. $ENV{ERRFILE} = "$ENV{TEMP}\\$unique_name.err.tmp";
  103. unlink $ENV{ERRFILE};
  104. $SIG{__WARN__} = sub {
  105. if ($^S or !defined $^S) { return }
  106. wrnmsg($_[0]);
  107. };
  108. $SIG{__DIE__} = sub {
  109. if ($^S or !defined $^S) { return }
  110. errmsg(Carp::longmess($_[0]));
  111. };
  112. $StartTime = time();
  113. infomsg("START \"$command_line\"" );
  114. }
  115. END {
  116. # avoid running in a -c syntax check
  117. return if $DoNothing;
  118. my $elapsed_time = time() - $StartTime;
  119. my $time_string = sprintf("(%d %s)", $elapsed_time,
  120. ($elapsed_time == 1 ? 'second' : 'seconds'));
  121. my $error_string = '';
  122. if (-e $ENV{ERRFILE}) {
  123. $error_string = "errors encountered";
  124. $? ||= 1;
  125. } elsif ($?) {
  126. $error_string = "nonzero exit code ($?)";
  127. } else {
  128. $error_string = "success";
  129. }
  130. infomsg("END $time_string $error_string");
  131. # Append all our temporarily logged data to the actual log file
  132. # save the names of the files we were using temporarily
  133. my $temp_logfile = $ENV{LOGFILE};
  134. my $temp_errfile = $ENV{ERRFILE};
  135. # set the logging environment to the final locations
  136. $ENV{ERRFILE} = $ENV{ERRFILE_BAK};
  137. $ENV{LOGFILE} = $ENV{LOGFILE_BAK};
  138. # append from our temporary log to the final log
  139. open LOGFILE, ">>$ENV{LOGFILE}";
  140. open TMPFILE, $temp_logfile;
  141. print LOGFILE <TMPFILE>;
  142. close LOGFILE;
  143. close TMPFILE;
  144. unlink($temp_logfile);
  145. # if there were any errors, append them back to the final error log
  146. if (-e $temp_errfile) { # /should/ only exist if there is an error
  147. if (!-z $temp_errfile) { # we don't want to propagate without cause
  148. open ERRFILE, ">>$ENV{ERRFILE}";
  149. open TMPFILE, $temp_errfile;
  150. print ERRFILE <TMPFILE>;
  151. close ERRFILE;
  152. close TMPFILE;
  153. }
  154. unlink($temp_errfile);
  155. }
  156. }
  157. 1;
  158. __END__
  159. =head1 NAME
  160. PbuildEnv - Set up a local environment for postbuild scripts
  161. =head1 SYNOPSIS
  162. use PbuildEnv;
  163. =head1 DESCRIPTION
  164. PbuildEnv sets a BEGIN and END block that provide the nescessary framework for
  165. running a script in the postbuild environment.
  166. Be sure to use this module before any other postbuild specific modules. Otherwise,
  167. some required variables may not be set up before the other module tries to use them
  168. At compile time PbuildEnv will parse any language switches on the command line. This
  169. means that E<-l is reserved in scripts using PbuildEnv>, it also means you get $ENV{LANG}
  170. set for free!
  171. PbuildEnv also sets the environment variables used by Logmsg, logs a beginning and
  172. ending message with elapsed time, and propogates errors back to the calling context.
  173. =head1 NOTES
  174. Does not handle multiple invocations of the same script (within the same arch
  175. / type / language) correctly. Unique names should be created more carefully/randomly
  176. to prevent temp file collisions.
  177. Bad languages specified with -l cause a rather ungraceful exit.
  178. =head1 SEE ALSO
  179. LocalEnvEx.pm
  180. =head1 AUTHOR
  181. Jeremy Devenport <JeremyD>
  182. =head1 COPYRIGHT
  183. Copyright (c) Microsoft Corporation. All rights reserved.
  184. =cut