You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by mm...@apache.org on 2008/09/19 13:26:47 UTC

svn commit: r697056 [2/2] - in /spamassassin/trunk: ./ lib/Mail/ lib/Mail/SpamAssassin/ lib/Mail/SpamAssassin/BayesStore/ lib/Mail/SpamAssassin/Conf/ lib/Mail/SpamAssassin/Locker/ lib/Mail/SpamAssassin/Logger/ lib/Mail/SpamAssassin/Message/ lib/Mail/Sp...

Modified: spamassassin/trunk/sa-compile.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/sa-compile.raw?rev=697056&r1=697055&r2=697056&view=diff
==============================================================================
--- spamassassin/trunk/sa-compile.raw (original)
+++ spamassassin/trunk/sa-compile.raw Fri Sep 19 04:26:46 2008
@@ -56,7 +56,7 @@
 }
 
 use Mail::SpamAssassin;
-use Mail::SpamAssassin::Util qw(untaint_var);
+use Mail::SpamAssassin::Util qw(untaint_var exit_status_str);
 use Getopt::Long;
 use File::Copy;
 use File::Path;
@@ -65,7 +65,7 @@
 
 use vars qw( %opt );
 Mail::SpamAssassin::Util::clean_path_in_taint_mode();
-Mail::SpamAssassin::Util::untaint_var( \%ENV );
+untaint_var( \%ENV );
 
 ##############################################################################
 
@@ -105,7 +105,8 @@
   usage( 0, "For more information read the manual page" );
 }
 if ( defined $opt{'version'} ) {
-  print "SpamAssassin version " . Mail::SpamAssassin::Version() . "\n";
+  print "SpamAssassin version " . Mail::SpamAssassin::Version() . "\n"
+    or die "error writing: $!";
   exit 0;
 }
 
@@ -113,11 +114,13 @@
 # present
 eval("use ExtUtils::MakeMaker");
 if ($@) {
-  print "$0 requires ExtUtils::MakeMaker for proper operation.\n";
+  print "$0 requires ExtUtils::MakeMaker for proper operation.\n"
+    or die "error writing: $!";
   exit 1;
 }
 unless (qx(re2c -V)) {
-  print "$0 requires re2c for proper operation.\n";
+  print "$0 requires re2c for proper operation.\n"
+    or die "error writing: $!";
   exit 1;
 }
 
@@ -127,7 +130,7 @@
 
   if ($exitval == 0) {
     print_version();
-    print("\n");
+    print("\n")  or die "error writing: $!";
   }
   pod2usage(
     -verbose => 0,
@@ -213,6 +216,11 @@
 }
 
 $spamtest->finish();
+
+# make sure we notice any write errors while flushing output buffer
+close STDOUT  or die "error closing STDOUT: $!";
+close STDIN   or die "error closing STDIN: $!";
+
 exit;
 
 ##############################################################################
@@ -261,20 +269,25 @@
     my $basespath = "bases_$ruletype.in";
     $basespath =~ s/[^A-Za-z0-9_\.]/_/gs;
     open OUT, ">$dirpath/$basespath"
-          or die "cannot write to $dirpath/$basespath";
-    print OUT dump_base_strings($ruletype);
-    close OUT or die "cannot write to $dirpath/$basespath";
+      or die "cannot create $dirpath/$basespath: $!";
+    print OUT dump_base_strings($ruletype)
+      or die "error writing to $dirpath/$basespath: $!";
+    close OUT
+      or die "error closing $dirpath/$basespath: $!";
 
     # compile it...
 
-    chdir $dirpath; 
-    $quiet or print "cd $dirpath\n";
+    chdir $dirpath  or die "cannot chdir to $dirpath: $!";
+    if (!$quiet) { print "cd $dirpath\n"  or die "error writing: $!" }
+
     rule2xs($basespath);
 
     my $log = "";
     if ($quiet) {
       $log = ">>$dirpath/log";
-      open (ZERO, ">$dirpath/log"); close ZERO; # empty it
+      # empty it
+      open(ZERO, ">$dirpath/log")  or die "cannot create $dirpath/log: $!";
+      close ZERO  or die "error closing $dirpath/log: $!";
     }
 
     run(get_perl()." Makefile.PL ".
@@ -287,35 +300,41 @@
 
     my $plpath = "bases_$ruletype.pl";
     $plpath =~ s/[^A-Za-z0-9_\.]/_/gs;
-    open OUT, ">$dirpath/$plpath"
-          or die "cannot write to $dirpath/$plpath";
-    print OUT dump_as_perl($ruletype);
-    close OUT or die "cannot write to $dirpath/$plpath";
+    open(OUT, ">$dirpath/$plpath")
+      or die "cannot create $dirpath/$plpath: $!";
+    print OUT dump_as_perl($ruletype)
+      or die "error writing to $dirpath/$plpath: $!";
+    close OUT
+      or die "error closing $dirpath/$plpath: $!";
 
     run($sudo."cp $dirpath/$plpath $installdir/$plpath");
   }
 
   if (!$opt{'keep-tmps'}) {
     chdir '/'; 
-    $quiet or print "cd /\n";      # saves trouble on MacOS, possibly
+    if (!$quiet) {
+      # saves trouble on MacOS, possibly
+      print "cd /\n"  or die "error writing: $!";
+    }
     run($sudo."rm -rf $dirpath");       # cleanup
   }
   else {
-    print "temporary dir left due to --keep-tmps: $dirpath\n";
+    print "temporary dir left due to --keep-tmps: $dirpath\n"
+      or die "error writing: $!";
   }
 }
 
 sub run {
   my @cmd = @_;
-  $quiet or print join(' ',@cmd)."\n";
-  system(@cmd);
-  if ($?>>8 != 0) {
-    if ($quiet) {
-      die "command '".join(' ',@cmd)."' failed!";
-    } else {
-      die "command failed!";
-    }
+  if (!$quiet) { print join(' ',@cmd)."\n"  or die "error writing: $!" }
+  if (system(@cmd) != 0) {
+    my $msg = $? == -1 ? "failed to execute: $!"
+                       : "failed: ".exit_status_str($?);
+    if (!$quiet) { die "command ".$msg."\n" }
+    else { die "command '".join(' ',@cmd)."' ".$msg."\n" }
+    return 0;
   }
+  return 1;
 }
 
 sub get_perl {
@@ -339,10 +358,11 @@
   my $force = 1;
   my $FILE = shift;
 
-  open(my $fh, $FILE) || die "open($FILE): $!";
+  open(my $fh, $FILE)  or die "cannot open $FILE: $!";
 # read ruleset name from the first line in the file
   my $ruleset_name;
   $_ = <$fh>;
+  defined $_  or die "error reading $FILE: $!";
   local ($1);
   if (/^name\s+(\S+)/) {
     $ruleset_name = untaint_var($1);
@@ -363,7 +383,7 @@
   $force and rmtree $PATH;
   mkdir $PATH or (!$force and die "mkdir($PATH): $!");
   chdir $PATH;
-  $quiet or print "cd $PATH\n";
+  if (!$quiet) { print "cd $PATH\n" or die "error writing: $!" }
 
   my $cprefix = $modname; $cprefix =~ s/[^A-ZA-z0-9]+/_/gs;
 
@@ -373,9 +393,10 @@
   while (!eof($fh)) {
     $numscans++;
 
-    open(my $re, ">scanner${numscans}.re") || die "open(>scanner{$numscans}.re): $!";
+    open(my $re, ">scanner${numscans}.re")
+      or die "cannot create scanner${numscans}.re: $!";
 
-    print $re <<EOT;
+    print $re <<EOT  or die "error writing: $!";
 #define NULL            ((char*) 0)
 #define YYCTYPE         unsigned char
 #define YYCURSOR        *p
@@ -388,7 +409,7 @@
 #define RET(x)          { YYCURSOR = YYMARKER; return (x); }
 EOT
 
-    print $re <<EOT;
+    print $re <<EOT  or die "error writing: $!";
 char *${cprefix}_scan${numscans}(unsigned char **p){
 unsigned char *q;
 /*!re2c
@@ -396,7 +417,7 @@
 
     my $line = 0;
     my $rulecount = 0;
-    while (<$fh>) {
+    for ($!=0; <$fh>; $!=0) {
       next if /^#/;
 
       local ($1,$2);
@@ -414,14 +435,18 @@
       die "no 'r REGEXP:REASON' in $_" unless defined $regexp;
 
       eval {
-	print $re "\t", fixup_re($regexp), "            {RET(\"$reason\");}\n";
-	$line++;
+	print $re "\t", fixup_re($regexp), "            {RET(\"$reason\");}\n"
+          or die "error writing: $!";
+	$line++; 1;
+      } or do {
+        my $eval_stat = $@ ne '' ? $@ : "errno=$!";  chomp $eval_stat;
+        handle_fixup_error($eval_stat, $regexp, $reason);
       };
-      $@ and handle_fixup_error($@, $regexp, $reason);
       last if $line == MAX_RULES_PER_C_FILE;
     }
+    defined $_ || $!==0  or die "error reading from $FILE: $!";
 
-    print $re <<EOT;
+    print $re <<EOT  or die "error writing: $!";
   [\\000-\\377]        { return NULL; }
 */
 }
@@ -431,11 +456,9 @@
 
   for (1..$numscans) {
     my $cmd = "re2c -i -b -o scanner$_.c scanner$_.re";
-    run($cmd);
-
-    # this must be fatal; it can result in corrupt output modules missing
-    # scannerN() functions
-    if ($? >> 8 != 0) {
+    if (!run($cmd)) {
+      # this must be fatal; it can result in corrupt output modules missing
+      # scannerN() functions
       my $cwd = `pwd`; chop $cwd;
       die "'$cmd' failed, dying!\n".
           "Have you got a sufficiently-recent version of re2c?\n".
@@ -445,8 +468,8 @@
 
   my $ccopt = $Config{optimize};      # typically "-O2"
 
-  open(FILE, ">Makefile.PL") || die "write Makefile.PL: $!";
-  print FILE <<"EOT";
+  open(FILE, ">Makefile.PL")  or die "cannot create Makefile.PL: $!";
+  print FILE <<"EOT"  or die "error writing to Makefile.PL: $!";
     use ExtUtils::MakeMaker;
 
     WriteMakefile(
@@ -458,10 +481,10 @@
 	'AUTHOR' => 'A. U. Tomated <au...@example.com>',
     );
 EOT
-  close FILE or die "write Makefile.PL: $!";
+  close FILE  or die "error closing Makefile.PL: $!";
 
-  open(FILE, ">MANIFEST.SKIP") || die "write MANIFEST.SKIP: $!";
-  print FILE <<'EOT';
+  open(FILE, ">MANIFEST.SKIP")  or die "cannot create MANIFEST.SKIP: $!";
+  print FILE <<'EOT'  or die "error writing to MANIFEST.SKIP: $!";
 CVS/.*
 \.bak$
 \.sw[a-z]$
@@ -479,10 +502,10 @@
 ^pm_to_blib$
 ~$
 EOT
-  close FILE or die "write MANIFEST.SKIP: $!";
+  close FILE  or die "error closing MANIFEST.SKIP: $!";
 
-  open(my $re, ">$XSFILE") || die "write $XSFILE: $!";
-  print $re <<"EOT";
+  open(my $re, ">$XSFILE")  or die "cannot create $XSFILE: $!";
+  print $re <<"EOT"  or die "error writing to $XSFILE: $!";
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
@@ -567,17 +590,17 @@
 
   }
 
-  print $re $xscode;
-  print $re <<EOT;
+  print $re $xscode  or die "error writing: $!";
+  print $re <<EOT  or die "error writing: $!";;
 	  RETVAL = newRV((SV *) results);
       OUTPUT:
 	  RETVAL
 
 EOT
 
-  close($re);
+  close($re)  or die "error closing $XSFILE: $!";
 
-  open(FILE, ">$PMFILE") || die "write $PMFILE: $!";
+  open(FILE, ">$PMFILE")  or die "cannot create $PMFILE: $!";
   my $str =<<"EOT";
 
 package $modname;
@@ -625,14 +648,14 @@
 EOT
 
   $str =~ s/^fnord//gm;
-  print FILE $str;
-  close FILE or die "write $PMFILE: $!";
+  print FILE $str  or die "error writing to $PMFILE: $!";
+  close FILE  or die "error closing $PMFILE: $!";
 }
 
 sub fixup_re {
   my $re = shift;
   
-  $fixup_re_test and print "INPUT: /$re/\n";
+  if ($fixup_re_test) { print "INPUT: /$re/\n"  or die "error writing: $!" }
   
   my $output = "";
   my $TOK = qr([\"\\]);
@@ -666,7 +689,7 @@
       }
     }
     else {
-      print "PRE: $pre\nTOK: $tok\n";
+      print "PRE: $pre\nTOK: $tok\n"  or die "error writing: $!";
     }
   }
   
@@ -683,7 +706,7 @@
   $output =~ s/(?<!\\)""//g; # strip empty strings, or turn "abc""def" -> "abcdef"
   $output =~ s/\*\*BACKSLASH\*\*/\\\\/gs;
 
-  $fixup_re_test and print "OUTPUT: $output\n";
+  if ($fixup_re_test) { print "OUTPUT: $output\n"  or die "error writing: $!" }
   return $output;
 }
 

Modified: spamassassin/trunk/sa-learn.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/sa-learn.raw?rev=697056&r1=697055&r2=697056&view=diff
==============================================================================
--- spamassassin/trunk/sa-learn.raw (original)
+++ spamassassin/trunk/sa-learn.raw Fri Sep 19 04:26:46 2008
@@ -69,6 +69,8 @@
 
 ###########################################################################
 
+$SIG{PIPE} = 'IGNORE';
+
 # used to be CmdLearn::cmd_run() ...
 
 %opt = (
@@ -229,8 +231,8 @@
 $spamtest->init(1);
 
 if (Mail::SpamAssassin::Util::am_running_on_windows()) {
-  binmode(STDIN);       # bug 4363
-  binmode(STDOUT);
+  binmode(STDIN)  or die "cannot set binmode on STDIN: $!";  # bug 4363
+  binmode(STDOUT) or die "cannot set binmode on STDOUT: $!";
 }
 
 if ( defined $opt{'dump'} ) {
@@ -257,12 +259,18 @@
   }
 
   $spamtest->finish_learner();
+  # make sure we notice any write errors while flushing output buffer
+  close STDOUT  or die "error closing STDOUT: $!";
+  close STDIN   or die "error closing STDIN: $!";
   exit 0;
 }
 
 if ( defined $opt{'import'} ) {
   my $ret = $spamtest->{bayes_scanner}->{store}->perform_upgrade();
   $spamtest->finish_learner();
+  # make sure we notice any write errors while flushing output buffer
+  close STDOUT  or die "error closing STDOUT: $!";
+  close STDIN   or die "error closing STDIN: $!";
   exit( !$ret );
 }
 
@@ -273,6 +281,9 @@
   }
 
   $spamtest->finish_learner();
+  # make sure we notice any write errors while flushing output buffer
+  close STDOUT  or die "error closing STDOUT: $!";
+  close STDIN   or die "error closing STDIN: $!";
   exit 0;
 }
 
@@ -283,6 +294,9 @@
   }
 
   $spamtest->finish_learner();
+  # make sure we notice any write errors while flushing output buffer
+  close STDOUT  or die "error closing STDOUT: $!";
+  close STDIN   or die "error closing STDIN: $!";
   exit 0;
 }
 
@@ -301,6 +315,9 @@
   }
 
   $spamtest->finish_learner();
+  # make sure we notice any write errors while flushing output buffer
+  close STDOUT  or die "error closing STDOUT: $!";
+  close STDIN   or die "error closing STDIN: $!";
   exit 0;
 }
 
@@ -328,6 +345,9 @@
     }
   );
   $spamtest->finish_learner();
+  # make sure we notice any write errors while flushing output buffer
+  close STDOUT  or die "error closing STDOUT: $!";
+  close STDIN   or die "error closing STDIN: $!";
   exit 0;
 }
 
@@ -351,12 +371,13 @@
 # run this lot in an eval block, so we can catch die's and clear
 # up the dbs.
 eval {
+  $SIG{HUP}  = \&killed;
   $SIG{INT}  = \&killed;
   $SIG{TERM} = \&killed;
 
   if ( $opt{folders} ) {
-    open( F, $opt{folders} ) || die $!;
-    while (<F>) {
+    open( F, $opt{folders} )  or die "cannot open $opt{folders}: $!";
+    for ($!=0; <F>; $!=0) {
       chomp;
       next unless ($_);
       if (/^(?:ham|spam):\w*:/) {
@@ -366,7 +387,8 @@
         target($_);
       }
     }
-    close(F);
+    defined $_ || $!==0  or die "error reading from $opt{folders}: $!";
+    close(F)  or die "error closing $opt{folders}: $!";
   }
 
   ###########################################################################
@@ -389,11 +411,15 @@
       }
       else {
         my $handle;
-
-        local $/ = undef;    # go into slurp mode
         ( $tempfile, $handle ) = Mail::SpamAssassin::Util::secure_tmpfile();
-        print {$handle} <STDIN>;
-        close $handle;
+        binmode $handle  or die "cannot set binmode on file $tempfile: $!";
+
+        # avoid slurping the whole file into memory, copy chunk by chunk
+        my($inbuf,$nread);
+        while ( $nread=sysread(STDIN,$inbuf,16384) )
+          { print {$handle} $inbuf  or die "error writing to $tempfile: $!" }
+        defined $nread  or die "error reading from STDIN: $!";
+          close $handle  or die "error closing $tempfile: $!";
 
         # re-aim the targets at the tempfile instead of STDIN
         $targets[$elem] =~ s/-$/$tempfile/;
@@ -436,20 +462,23 @@
   print "$phrase tokens from $learnedcount message(s) ($messagecount message(s) examined)\n";
 
   # If we needed to make a tempfile, go delete it.
-  if ( defined $tempfile ) {
-    unlink $tempfile;
+  if (defined $tempfile) {
+    unlink $tempfile  or die "cannot unlink temporary file $tempfile: $!";
+    undef $tempfile;
   }
 
   if ($@) { die $@ unless ( $@ =~ /HITLIMIT/ ); }
-};
-
-if ($@) {
-  my $failure = $@;
+  1;
+} or do {
+  my $eval_stat = $@ ne '' ? $@ : "errno=$!";  chomp $eval_stat;
   $spamtest->finish_learner();
-  die $failure;
-}
+  die $eval_stat;
+};
 
 $spamtest->finish_learner();
+# make sure we notice any write errors while flushing output buffer
+close STDOUT  or die "error closing STDOUT: $!";
+close STDIN   or die "error closing STDIN: $!";
 exit $exit_status;
 
 ###########################################################################

Modified: spamassassin/trunk/sa-update.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/sa-update.raw?rev=697056&r1=697055&r2=697056&view=diff
==============================================================================
--- spamassassin/trunk/sa-update.raw (original)
+++ spamassassin/trunk/sa-update.raw Fri Sep 19 04:26:46 2008
@@ -39,6 +39,7 @@
 );
 
 # Standard perl modules
+use Errno qw(ENOENT EACCES);
 use File::Spec;
 use File::Path;
 use Getopt::Long;
@@ -885,6 +886,7 @@
 
         my @files = ();
         while(my $file = readdir(DIR)) {
+	  next if $file eq '.' || $file eq '..';
 	  local ($1);	# avoid random taint flagging of $1
           $file =~ /^(.+)$/;       # untaint
           $file = $1;
@@ -958,9 +960,14 @@
 
 # clear out the temp files if they still exist
 foreach ( $content_file, $UPDTmp ) {
-  next unless (defined $_ && -e $_);
+  next unless defined $_;
+  my $stat_errn = stat($_) ? 0 : 0+$!;
+  next if $stat_errn == ENOENT;
 
-  if (-d _) {
+  if ($stat_errn != 0) {
+    warn "error: can't access $_: $!\n";
+  }
+  elsif (-d _) {
     rmdir $_ || warn "error: can't remove directory $_: $!\n";
   }
   elsif (-f _) {
@@ -1303,6 +1310,7 @@
     return;
   }
   while(my $file = readdir(DIR)) {
+    next if $file eq '.' || $file eq '..';
     local ($1); # bug 5216: prevent random taint flagging of $1
     $file =~ /^(.+)$/;       # untaint
     $file = $1;

Modified: spamassassin/trunk/spamassassin.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/spamassassin.raw?rev=697056&r1=697055&r2=697056&view=diff
==============================================================================
--- spamassassin/trunk/spamassassin.raw (original)
+++ spamassassin/trunk/spamassassin.raw Fri Sep 19 04:26:46 2008
@@ -112,7 +112,8 @@
 
 sub print_version {
   print "SpamAssassin version " . Mail::SpamAssassin::Version() . "\n"
-      . "  running on Perl version " . join(".", map { $_||=0; $_*1 } ($] =~ /(\d)\.(\d{3})(\d{3})?/ )) . "\n";
+      . "  running on Perl version " . join(".", map { $_||=0; $_*1 } ($] =~ /(\d)\.(\d{3})(\d{3})?/ )) . "\n"
+    or die "error writing: $!";
 }
 
 sub print_usage_and_exit {
@@ -121,7 +122,7 @@
 
   if ($respnam eq 'EX_OK' ) {
     print_version();
-    print("\n");
+    print("\n")  or die "error writing: $!";
   }
   pod2usage(
     -verbose => 0,
@@ -138,7 +139,7 @@
   my ( $verbose, $message ) = @_;
   my $ver = Mail::SpamAssassin::Version();
 
-  print "SpamAssassin version $ver\n";
+  print "SpamAssassin version $ver\n"  or die "error writing: $!";
   pod2usage( -verbose => $verbose, -message => $message, -exitval => 64, -input => "spamassassin-run.pod", -pathlist => \@INC );
 
 }
@@ -235,8 +236,8 @@
 }
 
 if (Mail::SpamAssassin::Util::am_running_on_windows()) {
-  binmode(STDIN);       # bug 4363
-  binmode(STDOUT);
+  binmode(STDIN)  or die "cannot set binmode on STDIN: $!";  # bug 4363
+  binmode(STDOUT) or die "cannot set binmode on STDOUT: $!";
 }
 
 # bug 5048: --lint should not cause network accesses
@@ -265,6 +266,9 @@
   $spamtest->debug_diagnostics();
   my $res = $spamtest->lint_rules();
   warn "lint: $res issues detected, please rerun with debug enabled for more information\n" if ($res);
+  # make sure we notice any write errors while flushing output buffer
+  close STDOUT  or die "error closing STDOUT: $!";
+  close STDIN   or die "error closing STDIN: $!";
   exit $res ? 1 : 0;
 }
 
@@ -288,6 +292,9 @@
   }
 
   $spamtest->finish();
+  # make sure we notice any write errors while flushing output buffer
+  close STDOUT  or die "error closing STDOUT: $!";
+  close STDIN   or die "error closing STDIN: $!";
   exit(0);
 }
 
@@ -329,12 +336,15 @@
     }
     else {
       my $handle;
-
-      local $/ = undef;    # go into slurp mode
       ( $tempfile, $handle ) = Mail::SpamAssassin::Util::secure_tmpfile();
-      binmode $handle;
-      print {$handle} <STDIN>;
-      close $handle;
+      binmode $handle  or die "cannot set binmode on file $tempfile: $!";
+
+      # avoid slurping the whole file into memory, copy chunk by chunk
+      my($inbuf,$nread);
+      while ( $nread=sysread(STDIN,$inbuf,16384) )
+        { print {$handle} $inbuf  or die "error writing to $tempfile: $!" }
+      defined $nread  or die "error reading from STDIN: $!";
+      close $handle   or die "cannot close $tempfile: $!";
 
       # re-aim the targets at the tempfile instead of STDIN
       $targets[$elem] =~ s/-$/$tempfile/;
@@ -366,26 +376,35 @@
 # bug 4930: use a temp variable since "||=" decides whether or not to set the
 # value before the RHS is actually run, so if the RHS separately sets the LHS
 # variable, things don't work right.  Stupid global variables. ;)
-eval { my $runreturn = !$iter->run(@targets);  $exitvalue ||= $runreturn; };
+my $eval_stat;
+eval {
+  my $runreturn = !$iter->run(@targets);  $exitvalue ||= $runreturn;  1;
+} or do {
+  $eval_stat = $@ ne '' ? $@ : "errno=$!";  chomp $eval_stat;
+};
 
 $progress->final() if ($opt{progress} && $progress);
 
 # If we needed to make a tempfile, go delete it now.
-if ( defined $tempfile ) {
-  unlink $tempfile;
+if (defined $tempfile) {
+  unlink $tempfile  or die "cannot unlink temporary file $tempfile: $!";
+  undef $tempfile;
 }
 
 # Let folks know how many messages were handled, as long as the handling
 # didn't produce output (ala: check, test, or remove_markup ...)
 if ( $opt{'report'} || $opt{'revoke'} || $doing_whitelist_operation ) {
-  print "$count message(s) examined.\n";
+  print "$count message(s) examined.\n"  or die "error writing: $!";
 }
 
 # if the eval died from something, report it here and return an error.
-if ($@) { die $@; }
+if (defined $eval_stat) { die $eval_stat; }
 
 $spamtest->finish()  if $spamtest;
 
+# make sure we notice any write errors while flushing output buffer
+close STDOUT  or die "error closing STDOUT: $!";
+close STDIN   or die "error closing STDIN: $!";
 # Ok, exit!
 exit( $exitvalue || 0 );
 
@@ -496,11 +515,11 @@
 
   # OK, do checks and put out the message.
   my $status = $spamtest->check($mail);
-  print $status->rewrite_mail ();
+  print $status->rewrite_mail()  or die "error writing: $!";
 
   if ( $opt{'test-mode'} ) {
     use bytes;
-    print $status->get_report();
+    print $status->get_report()  or die "error writing: $!";
   }
 
   # if this message was spam, set the exit value appropriately.
@@ -524,7 +543,8 @@
   $SIG{HUP}  = \&kill_handler;
   $SIG{INT}  = \&kill_handler;
   $SIG{TERM} = \&kill_handler;
-  $SIG{PIPE} = \&kill_handler;
+# $SIG{PIPE} = \&kill_handler;
+  $SIG{PIPE} = 'IGNORE';
 }
 
 sub kill_handler {
@@ -535,9 +555,10 @@
     $mail = undef;
   }
   if (defined $tempfile) {      # bug 5557: additional paranoia about tmpfiles
-    unlink $tempfile;
-    $tempfile = undef;
+    unlink $tempfile  or warn "cannot unlink temporary file $tempfile: $!";
+    undef $tempfile;
   }
+  close STDOUT; close STDIN;  # ignoring status
   exit 0;
 }