Beta release 4.39.4

Rick Cooper rcooper at DWFORD.COM
Wed Mar 2 23:07:55 GMT 2005


    [ The following text is in the "iso-8859-1" character set. ]
    [ Your display is set for the "US-ASCII" character set.  ]
    [ Some characters may be displayed incorrectly. ]

> -----Original Message-----
> From: MailScanner mailing list [mailto:MAILSCANNER at JISCMAIL.AC.UK]On
> Behalf Of Julian Field
> Sent: Wednesday, March 02, 2005 9:18 AM
> To: MAILSCANNER at JISCMAIL.AC.UK
> Subject: Re: Beta release 4.39.4
>
>
> I always try to at least reply, but good ideas do get lost sometimes.
> The unrar code would require another timeout wrapper round it, which I
> would have to copy from elsewhere, so it isn't trivial.
> I can't remember if I came up with a solution to the duplicated
> filenames problem or not, it was quite a long time ago.
>
<snip>

How about this for a timeout wrapper. It should work as a general purpose
wrapper for commands that use system or backticks. I put it together from
code you use eleswhere. So a line like:

$unrar =`which unrar`;
           return 0 unless $unrar !~ /no unrar in)/i && $unrar ne "";

would be $unrar = SafePipe("which unrar",30,"ST");
            return 0 unless $unrar !~ /(no unrar in|^COMMAND_TIMED_OUT$)/i &&
$unrar ne "";
and
        system("$unrar e -p- -idp $safename 2>&1");
        unless ("$?" == 0 && !$IsEncrypted) {

would be

        unless (RcSafePipe("$unrar e -p- -idp $safename 2>&1",30,"EC") == 0 &&
!$IsEncrypted) {

It appears to work fine, and handles the time out fine as well.

Rick

sub SafePipe{
# Modified Julian's code from SweepOther.pm
# Changed to allow execution of a given command line with a time
# control
#
# $Cmd  = command line to execute
# $timeout      = max time in seconds to allow execution
# $ReturnType = ST For String or Anything else for error code
#
# Replaces backtick or system calls that are looking for both
# string output or an error code

  my ($Cmd, $TimeOut,$ReturnType) = @_;
  my($Kid, $pid, $TimedOut, $PipeReturn, $Str);
  $Kid  = new FileHandle;
  $TimedOut = 0;

  eval {
    die "Can't fork: $!" unless defined($pid = open($Kid, '-|'));
    if ($pid) {
      # In the parent
      local $SIG{ALRM} = sub { $TimedOut = 1; die "Command Timed Out" };
      alarm $TimeOut;
      # Only process the output if we are scanning, not disinfecting
      while(<$Kid>) {
                $Str .= $_;
        #print STDERR "Processing line \"$_\"\n";
      }
      close $Kid;
      $PipeReturn = $?;
      $pid = 0; # 2.54
      alarm 0;
      # Workaround for bug in perl shipped with Solaris 9,
      # it doesn't unblock the SIGALRM after handling it.
      eval {
        my $unblockset = POSIX::SigSet->new(SIGALRM);
        sigprocmask(SIG_UNBLOCK, $unblockset)
          or die "Could not unblock alarm: $!\n";
      };
    } else {
      # In the child
      POSIX::setsid();
      # for testing time out
      # sleep 40;      exec $Cmd;
      MailScanner::Log::WarnLog("Can't run $Cmd command! ");
      exit 1;
    }
  };
  alarm 0; # 2.53

  # Note to self: I only close the KID in the parent, not in the child.
  MailScanner::Log::DebugLog("Completed $Cmd");

  # Catch failures other than the alarm
  MailScanner::Log::DieLog("$Cmd failed with real error: $@")
    if $@ and $@ !~ /Command Timed Out/;

  #print STDERR "pid = $pid and \@ = $@\n";

  # In which case any failures must be the alarm
  if ($@ or $pid>0) {
    # Kill the running child process
    my($i);
    kill -15, $pid;
    # Wait for up to 5 seconds for it to die
    for ($i=0; $i<5; $i++) {
      sleep 1;
      waitpid($pid, &POSIX::WNOHANG);
      ($pid=0),last unless kill(0, $pid);
      kill -15, $pid;
    }
    # And if it didn't respond to 11 nice kills, we kill -9 it
    if ($pid) {
      kill -9, $pid;
      waitpid $pid, 0; # 2.53
    }
  }

  # Return failure if the command timed out, otherwise return success

if ($TimedOut){
        MailScanner::Log::WarnLog("$Cmd timed out!");
        return "COMMAND_TIMED_OUT";
}
        if($ReturnType eq "ST"){
                return $Str;
        }else{
                return $PipeReturn;
        }
}


--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

------------------------ MailScanner list ------------------------
To unsubscribe, email jiscmail at jiscmail.ac.uk with the words:
'leave mailscanner' in the body of the email.
Before posting, read the MAQ (http://www.mailscanner.biz/maq/) and
the archives (http://www.jiscmail.ac.uk/lists/mailscanner.html).

Support MailScanner development - buy the book off the website!




More information about the MailScanner mailing list