[Exim] Re: Exiscan Patch - multiple spamd servers and/or vir…

Pàgina inicial
Delete this message
Reply to this message
Autor: Dagfinn Ilmari Mannsåker
Data:  
A: exim-users
CC: exiscanusers
Assumpte: [Exim] Re: Exiscan Patch - multiple spamd servers and/or virus scanners
ilmari@??? (Dagfinn Ilmari Mannsåker) writes:

> Also, the indentation and coding style is quite inconsistent, since
> stuff has been written by different people, and I didn't reindent the
> scanning functions after splitting them out. I'll follow-up with a
> cleanup patch on top of this one.


Here it is, compile-tested and portions not ignored by 'diff -w'
carefully reviewed.

diff -ur exim-4.34/src/malware.c exiscan-4.34-22/src/malware.c
--- exim-4.34/src/malware.c    2004-06-19 01:45:36.000000000 +0200
+++ exiscan-4.34-22/src/malware.c    2004-06-19 02:00:42.000000000 +0200
@@ -24,16 +24,16 @@
 #define DRWEBD_SCAN_CMD     0x0001
 #define DRWEBD_RETURN_VIRUSES    0x0001


-/* Routine to check whether a system is big- or litte-endian.
+/* Routine to check whether a system is big- or litte-endian.
    Ripped from http://www.faqs.org/faqs/graphics/fileformats-faq/part4/section-7.html
    Needed for proper kavdaemon implementation. Sigh. */
 #define BIG_MY_ENDIAN      0
 #define LITTLE_MY_ENDIAN   1
 int test_byte_order(void);
 int test_byte_order() {
-      short int word = 0x0001;
-      char *byte = (char *) &word;
-      return(byte[0] ? LITTLE_MY_ENDIAN : BIG_MY_ENDIAN);
+  short int word = 0x0001;
+  char *byte = (char *) &word;
+  return(byte[0] ? LITTLE_MY_ENDIAN : BIG_MY_ENDIAN);
 }


 uschar malware_name_buffer[256];
@@ -61,35 +61,35 @@
   int roffset;
   const pcre *re;
   const uschar *rerror;
-
+
   /* make sure the eml mbox file is spooled up */
   mbox_file = spool_mbox(&mbox_size);
   if (mbox_file == NULL) {
     /* error while spooling */
     log_write(0, LOG_MAIN|LOG_PANIC,
-           "malware acl condition: error while creating mbox spool file");
-    return DEFER;
+              "malware acl condition: error while creating mbox spool file");
+    return DEFER;
   };
   /* none of our current scanners need the mbox
      file as a stream, so we can close it right away */
   fclose(mbox_file);
-
+
   /* extract the malware regex to match against from the option list */
   if ((malware_regex = string_nextinlist(&list, &sep,
                                          malware_regex_buffer,
                                          sizeof(malware_regex_buffer))) != NULL) {
-
+
     /* parse 1st option */
-    if ( (strcmpic(malware_regex,US"false") == 0) ||
-         (Ustrcmp(malware_regex,"0") == 0) ) {
+    if ((strcmpic(malware_regex, US "false") == 0) ||
+        (Ustrcmp(malware_regex, "0") == 0)) {
       /* explicitly no matching */
       return FAIL;
     };
-
+
     /* special cases (match anything except empty) */
-    if ( (strcmpic(malware_regex,US"true") == 0) ||
-         (Ustrcmp(malware_regex,"*") == 0) ||
-         (Ustrcmp(malware_regex,"1") == 0) ) {
+    if ((strcmpic(malware_regex, US "true") == 0) ||
+        (Ustrcmp(malware_regex, "*") == 0) ||
+        (Ustrcmp(malware_regex, "1") == 0)) {
       malware_regex = malware_regex_default;
     };
   }
@@ -99,10 +99,14 @@
   };


   /* compile the regex, see if it works */
-  re = pcre_compile(CS malware_regex, PCRE_COPT, (const char **)&rerror, &roffset, NULL);
+  re = pcre_compile(CS malware_regex,
+                    PCRE_COPT,
+                    (const char **)&rerror,
+                    &roffset, NULL);
   if (re == NULL) {
     log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: regular expression error in '%s': %s at offset %d", malware_regex, rerror, roffset);
+              "malware acl condition: regular expression error in '%s': %s at offset %d",
+              malware_regex, rerror, roffset);
     return DEFER;
   };


@@ -122,6 +126,7 @@
         if (rc != OK)
           return rc;
       }
+
       /* "kavdaemon" scanner type ------------------------------------------------ */
       else if (strcmpic(scanner_name, US "kavdaemon") == 0) {
         rc = scan_kavdaemon(&av_scanner_work, &sep);
@@ -164,15 +169,15 @@
         return DEFER;
       }
       n++;
-    }
+    };


     if (malware_name == NULL && n == 0) {
       /* no scanner given */
       log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: av_scanner configuration variable is empty");
+                "malware acl condition: av_scanner configuration variable is empty");
       return DEFER;
     };
-
+
     /* set "been here, done that" marker */
     malware_ok = 1;
   };
@@ -187,884 +192,901 @@
   };
 }


-    /* "drweb" scanner type ----------------------------------------------- */
-    /* v0.1 - added support for tcp sockets                    */
-    /* v0.0 - initial release -- support for unix sockets            */
-static int scan_drweb(uschar ** pscanner, int *psep)
-{
-        uschar *drweb_options;
-        uschar drweb_options_buffer[1024];
-        uschar drweb_options_default[] = "/usr/local/drweb/run/drwebd.sock";
-        struct sockaddr_un server;
-        int sock, port, result, ovector[30];
-        unsigned int fsize;
-        uschar tmpbuf[1024], *drweb_fbuf;
-        uschar scanrequest[1024];
-        uschar drweb_match_string[128];
-        int drweb_rc, drweb_cmd, drweb_flags = 0x0000, drweb_fd,
-            drweb_vnum, drweb_slen, drweb_fin = 0x0000;
-        unsigned long bread;
-        uschar hostname[256];
-        struct hostent *he;
-        struct in_addr in;
-        pcre *drweb_re;
-            int roffset;
-        uschar *rerror;
-
-        if ((drweb_options = string_nextinlist(pscanner, psep,
-            drweb_options_buffer, sizeof(drweb_options_buffer))) == NULL) {
-            /* no options supplied, use default options */
-            drweb_options = drweb_options_default;
-        };
-
-        if (*drweb_options != '/') {
-
-            /* extract host and port part */
-            if( sscanf(CS drweb_options, "%s %u", hostname, &port) != 2 ) {
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: drweb: invalid socket '%s'", drweb_options);
-                return DEFER;
-                }
-
-            /* Lookup the host */
-            if((he = gethostbyname(CS hostname)) == 0) {
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: drweb: failed to lookup host '%s'", hostname);
-                return DEFER;
-            }
-
-            in = *(struct in_addr *) he->h_addr_list[0];
-
-            /* Open the drwebd TCP socket */
-            if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: drweb: unable to acquire socket (%s)",
-                    strerror(errno));
-                return DEFER;
-            }
-
-            if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
-                close(sock);
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: drweb: connection to %s, port %u failed (%s)",
-                    inet_ntoa(in), port, strerror(errno));
-                return DEFER;
-            }
-
-            /* prepare variables */
-            drweb_cmd = htonl(DRWEBD_SCAN_CMD);
-            drweb_flags = htonl(DRWEBD_RETURN_VIRUSES);
-            snprintf(CS scanrequest, 1024,CS"%s/scan/%s/%s.eml",
-                    spool_directory, message_id, message_id);
-
-            /* calc file size */
-            drweb_fd = open(CS scanrequest, O_RDONLY);
-            if (drweb_fd == -1) {
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                            "malware acl condition: drweb: can't open spool file %s: %s",
-                    scanrequest, strerror(errno));
-                return DEFER;
-            }
-            fsize = lseek(drweb_fd, 0, SEEK_END);
-            if (fsize == -1) {
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                            "malware acl condition: drweb: can't seek spool file %s: %s",
-                    scanrequest, strerror(errno));
-                return DEFER;
-            }
-            drweb_slen = htonl(fsize);
-            lseek(drweb_fd, 0, SEEK_SET);
-
-            /* send scan request */
-            if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
-                (send(sock, &drweb_flags, sizeof(drweb_flags), 0) < 0) ||
-                (send(sock, &drweb_fin, sizeof(drweb_fin), 0) < 0) ||
-                (send(sock, &drweb_slen, sizeof(drweb_slen), 0) < 0)) {
-                close(sock);
-                close(drweb_fd);
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: drweb: unable to send commands to socket (%s)", drweb_options);
-                return DEFER;
-            }
-
-            drweb_fbuf = (uschar *) malloc (fsize);
-            if (!drweb_fbuf) {
-                close(sock);
-                close(drweb_fd);
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: drweb: unable to allocate memory %u for file (%s)",
-                    fsize, scanrequest);
-                return DEFER;
-            }
-
-            result = read (drweb_fd, drweb_fbuf, fsize);
-            if (result == -1) {
-                close(sock);
-                close(drweb_fd);
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                            "malware acl condition: drweb: can't read spool file %s: %s",
-                    scanrequest, strerror(errno));
-                return DEFER;
-            }
-
-            /* send file body to socket */
-            if (send(sock, drweb_fbuf, fsize, 0) < 0) {
-                close(sock);
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: drweb: unable to send file body to socket (%s)", drweb_options);
-                return DEFER;
-            }
-            close(drweb_fd);
-            free(drweb_fbuf);
-        }
-            else {
-            /* open the drwebd UNIX socket */
-            sock = socket(AF_UNIX, SOCK_STREAM, 0);
-            if (sock < 0) {
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                            "malware acl condition: drweb: can't open UNIX socket");
-                return DEFER;
-            }
-            server.sun_family = AF_UNIX;
-            Ustrcpy(server.sun_path, drweb_options);
-            if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
-                close(sock);
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: drweb: unable to connect to socket (%s). errno=%d", drweb_options, errno);
-                return DEFER;
-            }
-
-            /* prepare variables */
-            drweb_cmd = htonl(DRWEBD_SCAN_CMD);
-            drweb_flags = htonl(DRWEBD_RETURN_VIRUSES);
-            snprintf(CS scanrequest, 1024,CS"%s/scan/%s/%s.eml", spool_directory, message_id, message_id);
-            drweb_slen = htonl(Ustrlen(scanrequest));
-
-            /* send scan request */
-            if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
-                (send(sock, &drweb_flags, sizeof(drweb_flags), 0) < 0) ||
-                (send(sock, &drweb_slen, sizeof(drweb_slen), 0) < 0) ||
-                (send(sock, scanrequest, Ustrlen(scanrequest), 0) < 0) ||
-                (send(sock, &drweb_fin, sizeof(drweb_fin), 0) < 0)) {
-                close(sock);
-                log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: drweb: unable to send commands to socket (%s)", drweb_options);
-                return DEFER;
-            }
-        }
-
-        /* wait for result */
-        if ((bread = recv(sock, &drweb_rc, sizeof(drweb_rc), 0) != sizeof(drweb_rc))) {
-            close(sock);
-            log_write(0, LOG_MAIN|LOG_PANIC,
-                "malware acl condition: drweb: unable to read return code");
-            return DEFER;
-        }
-        drweb_rc = ntohl(drweb_rc);
-
-        if ((bread = recv(sock, &drweb_vnum, sizeof(drweb_vnum), 0) != sizeof(drweb_vnum))) {
-            close(sock);
-            log_write(0, LOG_MAIN|LOG_PANIC,
-                "malware acl condition: drweb: unable to read the number of viruses");
-            return DEFER;
-        }
-        drweb_vnum = ntohl(drweb_vnum);
-
-        /* "virus(es) found" if virus number is > 0 */
-        if (drweb_vnum)
-        {
-            int i;
-            uschar pre_malware_nb[256];
-
-            malware_name = malware_name_buffer;
-
-            /* setup default virus name */
-            Ustrcpy(malware_name_buffer,"unknown");
-
-            /* read and concatenate virus names into one string */
-            for (i=0;i<drweb_vnum;i++)
-            {
-                /* read the size of report */
-                if ((bread = recv(sock, &drweb_slen, sizeof(drweb_slen), 0) != sizeof(drweb_slen))) {
-                    close(sock);
-                    log_write(0, LOG_MAIN|LOG_PANIC,
-                        "malware acl condition: drweb: cannot read report size");
-                    return DEFER;
-                };
-                drweb_slen = ntohl(drweb_slen);
-
-                /* read report body */
-                if ((bread = recv(sock, tmpbuf, drweb_slen, 0)) != drweb_slen) {
-                    close(sock);
-                    log_write(0, LOG_MAIN|LOG_PANIC,
-                        "malware acl condition: drweb: cannot read report string");
-                    return DEFER;
-                };
-                tmpbuf[drweb_slen] = '\0';
-
-                /* set up match regex, depends on retcode */
-                Ustrcpy(drweb_match_string, "infected\\swith\\s*(.+?)$");
-
-                drweb_re = pcre_compile( CS drweb_match_string,
-                                PCRE_COPT,
-                                    (const char **)&rerror,
-                                    &roffset,
-                                    NULL );
-
-                /* try matcher on the line, grab substring */
-                result = pcre_exec(drweb_re, NULL, CS tmpbuf, Ustrlen(tmpbuf), 0, 0, ovector, 30);
-                if (result >= 2) {
-                    pcre_copy_substring(CS tmpbuf, ovector, result, 1, CS pre_malware_nb, 255);
-                }
-                /* the first name we just copy to malware_name */
-                if (i==0)
-                    Ustrcpy(CS malware_name_buffer, CS pre_malware_nb);
-                else {
-                    /* concatenate each new virus name to previous */
-                    int slen = Ustrlen(malware_name_buffer);
-                    if (slen < (slen+Ustrlen(pre_malware_nb))) {
-                        Ustrcat(malware_name_buffer, "/");
-                        Ustrcat(malware_name_buffer, pre_malware_nb);
-                    }
-                }
-            }
-        }
-        else {
-            /* no virus found */
-            malware_name = NULL;
-        };
-        close(sock);
-    return OK;
-}
-
-    /* "kavdaemon" scanner type ------------------------------------------------ */
-static int scan_kavdaemon(uschar ** pscanner, int *psep)
-{
-      uschar *kav_options;
-      uschar kav_options_buffer[1024];
-      uschar kav_options_default[] = "/var/run/AvpCtl";
-      struct sockaddr_un server;
-      int sock;
-      time_t t;
-      uschar tmpbuf[1024];
-      uschar scanrequest[1024];
-      uschar kav_match_string[128];
-      int kav_rc;
-      unsigned long kav_reportlen, bread;
-      pcre *kav_re;
-      int roffset;
-      uschar *rerror;
-
-      if ((kav_options = string_nextinlist(pscanner, psep,
-                                           kav_options_buffer,
-                                           sizeof(kav_options_buffer))) == NULL) {
-        /* no options supplied, use default options */
-        kav_options = kav_options_default;
-      };
-
-      /* open the kavdaemon socket */
-      sock = socket(AF_UNIX, SOCK_STREAM, 0);
-      if (sock < 0) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: can't open UNIX socket.");
-        return DEFER;
-      }
-      server.sun_family = AF_UNIX;
-      Ustrcpy(server.sun_path, kav_options);
-      if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
-        close(sock);
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: unable to connect to kavdaemon UNIX socket (%s). errno=%d", kav_options, errno);
-        return DEFER;
-      }
-
-      /* get current date and time, build scan request */
-      time(&t);
-      strftime(CS tmpbuf, sizeof(tmpbuf), "<0>%d %b %H:%M:%S:%%s/scan/%%s", localtime(&t));
-      snprintf(CS scanrequest, 1024,CS tmpbuf, spool_directory, message_id);
-
-      /* send scan request */
-      if (send(sock, scanrequest, Ustrlen(scanrequest)+1, 0) < 0) {
-        close(sock);
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: unable to write to kavdaemon UNIX socket (%s)", kav_options);
-        return DEFER;
-      }
-
-      /* wait for result */
-      if ((bread = recv(sock, tmpbuf, 2, 0) != 2)) {
+/* "drweb" scanner type ----------------------------------------------- */
+/* v0.1 - added support for tcp sockets                                 */
+/* v0.0 - initial release -- support for unix sockets                   */
+static int scan_drweb(uschar ** pscanner, int *psep) {
+  uschar *drweb_options;
+  uschar drweb_options_buffer[1024];
+  uschar drweb_options_default[] = "/usr/local/drweb/run/drwebd.sock";
+  struct sockaddr_un server;
+  int sock, port, result, ovector[30];
+  unsigned int fsize;
+  uschar tmpbuf[1024], *drweb_fbuf;
+  uschar scanrequest[1024];
+  uschar drweb_match_string[128];
+  int drweb_rc, drweb_cmd, drweb_flags = 0x0000, drweb_fd,
+    drweb_vnum, drweb_slen, drweb_fin = 0x0000;
+  unsigned long bread;
+  uschar hostname[256];
+  struct hostent *he;
+  struct in_addr in;
+  pcre *drweb_re;
+  int roffset;
+  uschar *rerror;
+
+  if ((drweb_options = string_nextinlist(pscanner, psep,
+                                         drweb_options_buffer,
+                                         sizeof(drweb_options_buffer))) == NULL) {
+    /* no options supplied, use default options */
+    drweb_options = drweb_options_default;
+  };
+
+  if (*drweb_options != '/') {
+
+    /* extract host and port part */
+    if (sscanf(CS drweb_options, "%s %u", hostname, &port) != 2) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: invalid socket '%s'", drweb_options);
+      return DEFER;
+    };
+
+    /* Lookup the host */
+    if ((he = gethostbyname(CS hostname)) == 0) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: failed to lookup host '%s'", hostname);
+      return DEFER;
+    };
+
+    in = *(struct in_addr *) he->h_addr_list[0];
+
+    /* Open the drwebd TCP socket */
+    if ((sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: unable to acquire socket (%s)",
+                strerror(errno));
+      return DEFER;
+    };
+
+    if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
+      close(sock);
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: connection to %s, port %u failed (%s)",
+                inet_ntoa(in), port, strerror(errno));
+      return DEFER;
+    };
+
+    /* prepare variables */
+    drweb_cmd = htonl(DRWEBD_SCAN_CMD);
+    drweb_flags = htonl(DRWEBD_RETURN_VIRUSES);
+    snprintf(CS scanrequest, 1024, CS "%s/scan/%s/%s.eml",
+             spool_directory, message_id, message_id);
+
+    /* calc file size */
+    drweb_fd = open(CS scanrequest, O_RDONLY);
+    if (drweb_fd == -1) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: can't open spool file %s: %s",
+                scanrequest, strerror(errno));
+      return DEFER;
+    };
+    fsize = lseek(drweb_fd, 0, SEEK_END);
+    if (fsize == -1) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: can't seek spool file %s: %s",
+                scanrequest, strerror(errno));
+      return DEFER;
+    };
+    drweb_slen = htonl(fsize);
+    lseek(drweb_fd, 0, SEEK_SET);
+
+    /* send scan request */
+    if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
+        (send(sock, &drweb_flags, sizeof(drweb_flags), 0) < 0) ||
+        (send(sock, &drweb_fin, sizeof(drweb_fin), 0) < 0) ||
+        (send(sock, &drweb_slen, sizeof(drweb_slen), 0) < 0)) {
+      close(sock);
+      close(drweb_fd);
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: unable to send commands to socket (%s)",
+                drweb_options);
+      return DEFER;
+    };
+
+    drweb_fbuf = (uschar *) malloc (fsize);
+    if (!drweb_fbuf) {
+      close(sock);
+      close(drweb_fd);
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: unable to allocate memory %u for file (%s)",
+                fsize, scanrequest);
+      return DEFER;
+    };
+
+    result = read(drweb_fd, drweb_fbuf, fsize);
+    if (result == -1) {
+      close(sock);
+      close(drweb_fd);
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: can't read spool file %s: %s",
+                scanrequest, strerror(errno));
+      return DEFER;
+    };
+
+    /* send file body to socket */
+    if (send(sock, drweb_fbuf, fsize, 0) < 0) {
+      close(sock);
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: unable to send file body to socket (%s)",
+                drweb_options);
+      return DEFER;
+    };
+    close(drweb_fd);
+    free(drweb_fbuf);
+  }
+  else {
+    /* open the drwebd UNIX socket */
+    sock = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: can't open UNIX socket");
+      return DEFER;
+    };
+    server.sun_family = AF_UNIX;
+    Ustrcpy(server.sun_path, drweb_options);
+    if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
+      close(sock);
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: unable to connect to socket (%s). errno=%d",
+                drweb_options, errno);
+      return DEFER;
+    };
+
+    /* prepare variables */
+    drweb_cmd = htonl(DRWEBD_SCAN_CMD);
+    drweb_flags = htonl(DRWEBD_RETURN_VIRUSES);
+    snprintf(CS scanrequest, 1024, CS "%s/scan/%s/%s.eml",
+             spool_directory, message_id, message_id);
+    drweb_slen = htonl(Ustrlen(scanrequest));
+
+    /* send scan request */
+    if ((send(sock, &drweb_cmd, sizeof(drweb_cmd), 0) < 0) ||
+        (send(sock, &drweb_flags, sizeof(drweb_flags), 0) < 0) ||
+        (send(sock, &drweb_slen, sizeof(drweb_slen), 0) < 0) ||
+        (send(sock, scanrequest, Ustrlen(scanrequest), 0) < 0) ||
+        (send(sock, &drweb_fin, sizeof(drweb_fin), 0) < 0)) {
+      close(sock);
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: drweb: unable to send commands to socket (%s)",
+                drweb_options);
+      return DEFER;
+    };
+  };
+
+  /* wait for result */
+  if ((bread = recv(sock, &drweb_rc, sizeof(drweb_rc), 0) != sizeof(drweb_rc))) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: drweb: unable to read return code");
+    return DEFER;
+  };
+  drweb_rc = ntohl(drweb_rc);
+
+  if ((bread = recv(sock, &drweb_vnum, sizeof(drweb_vnum), 0) != sizeof(drweb_vnum))) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: drweb: unable to read the number of viruses");
+    return DEFER;
+  };
+  drweb_vnum = ntohl(drweb_vnum);
+
+  /* "virus(es) found" if virus number is > 0 */
+  if (drweb_vnum) {
+    int i;
+    uschar pre_malware_nb[256];
+
+    malware_name = malware_name_buffer;
+
+    /* setup default virus name */
+    Ustrcpy(malware_name_buffer, "unknown");
+
+    /* read and concatenate virus names into one string */
+    for (i=0;i<drweb_vnum;i++) {
+      /* read the size of report */
+      if ((bread = recv(sock, &drweb_slen, sizeof(drweb_slen), 0) != sizeof(drweb_slen))) {
         close(sock);
         log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: unable to read 2 bytes from kavdaemon socket.");
+                  "malware acl condition: drweb: cannot read report size");
         return DEFER;
-      }
-
-      /* get errorcode from one nibble */
-      if (test_byte_order() == LITTLE_MY_ENDIAN) {
-        kav_rc = tmpbuf[0] & 0x0F;
-      }
-      else {
-        kav_rc = tmpbuf[1] & 0x0F;
       };
-
-      /* improper kavdaemon configuration */
-      if ( (kav_rc == 5) || (kav_rc == 6) ) {
+      drweb_slen = ntohl(drweb_slen);
+
+      /* read report body */
+      if ((bread = recv(sock, tmpbuf, drweb_slen, 0)) != drweb_slen) {
         close(sock);
         log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: please reconfigure kavdaemon to NOT disinfect or remove infected files.");
+                  "malware acl condition: drweb: cannot read report string");
         return DEFER;
       };
-
-      if (kav_rc == 1) {
-        close(sock);
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: kavdaemon reported 'scanning not completed' (code 1).");
-        return DEFER;
+      tmpbuf[drweb_slen] = '\0';
+
+      /* set up match regex, depends on retcode */
+      Ustrcpy(drweb_match_string, "infected\\swith\\s*(.+?)$");
+
+      drweb_re = pcre_compile(CS drweb_match_string,
+                              PCRE_COPT,
+                              (const char **)&rerror,
+                              &roffset,
+                              NULL);
+
+      /* try matcher on the line, grab substring */
+      result = pcre_exec(drweb_re, NULL, CS tmpbuf, Ustrlen(tmpbuf), 0, 0, ovector, 30);
+      if (result >= 2) {
+        pcre_copy_substring(CS tmpbuf, ovector, result, 1, CS pre_malware_nb, 255);
       };
-
-      if (kav_rc == 7) {
+      /* the first name we just copy to malware_name */
+      if (i==0)
+        Ustrcpy(CS malware_name_buffer, CS pre_malware_nb);
+      else {
+        /* concatenate each new virus name to previous */
+        int slen = Ustrlen(malware_name_buffer);
+        if (slen < (slen+Ustrlen(pre_malware_nb))) {
+          Ustrcat(malware_name_buffer, "/");
+          Ustrcat(malware_name_buffer, pre_malware_nb);
+        };
+      };
+    };
+  }
+  else {
+    /* no virus found */
+    malware_name = NULL;
+  };
+  close(sock);
+  return OK;
+}
+
+/* "kavdaemon" scanner type ------------------------------------------------ */
+static int scan_kavdaemon(uschar ** pscanner, int *psep) {
+  uschar *kav_options;
+  uschar kav_options_buffer[1024];
+  uschar kav_options_default[] = "/var/run/AvpCtl";
+  struct sockaddr_un server;
+  int sock;
+  time_t t;
+  uschar tmpbuf[1024];
+  uschar scanrequest[1024];
+  uschar kav_match_string[128];
+  int kav_rc;
+  unsigned long kav_reportlen, bread;
+  pcre *kav_re;
+  int roffset;
+  uschar *rerror;
+
+  if ((kav_options = string_nextinlist(pscanner, psep,
+                                       kav_options_buffer,
+                                       sizeof(kav_options_buffer))) == NULL) {
+    /* no options supplied, use default options */
+    kav_options = kav_options_default;
+  };
+
+  /* open the kavdaemon socket */
+  sock = socket(AF_UNIX, SOCK_STREAM, 0);
+  if (sock < 0) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: can't open UNIX socket.");
+    return DEFER;
+  };
+  server.sun_family = AF_UNIX;
+  Ustrcpy(server.sun_path, kav_options);
+  if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: unable to connect to kavdaemon UNIX socket (%s). errno=%d",
+              kav_options, errno);
+    return DEFER;
+  };
+
+  /* get current date and time, build scan request */
+  time(&t);
+  strftime(CS tmpbuf, sizeof(tmpbuf), "<0>%d %b %H:%M:%S:%%s/scan/%%s", localtime(&t));
+  snprintf(CS scanrequest, 1024, CS tmpbuf, spool_directory, message_id);
+
+  /* send scan request */
+  if (send(sock, scanrequest, Ustrlen(scanrequest)+1, 0) < 0) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: unable to write to kavdaemon UNIX socket (%s)",
+              kav_options);
+    return DEFER;
+  };
+
+  /* wait for result */
+  if ((bread = recv(sock, tmpbuf, 2, 0) != 2)) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: unable to read 2 bytes from kavdaemon socket.");
+    return DEFER;
+  };
+
+  /* get errorcode from one nibble */
+  if (test_byte_order() == LITTLE_MY_ENDIAN) {
+    kav_rc = tmpbuf[0] & 0x0F;
+  }
+  else {
+    kav_rc = tmpbuf[1] & 0x0F;
+  };
+
+  /* improper kavdaemon configuration */
+  if ((kav_rc == 5) || (kav_rc == 6)) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: please reconfigure kavdaemon to NOT disinfect or remove infected files.");
+    return DEFER;
+  };
+
+  if (kav_rc == 1) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: kavdaemon reported 'scanning not completed' (code 1).");
+    return DEFER;
+  };
+
+  if (kav_rc == 7) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: kavdaemon reported 'kavdaemon damaged' (code 7).");
+    return DEFER;
+  };
+
+  /* code 8 is not handled, since it is ambigous. It appears mostly on
+     bounces where part of a file has been cut off */
+
+  /* "virus found" return codes (2-4) */
+  if ((kav_rc > 1) && (kav_rc < 5)) {
+    int report_flag = 0;
+
+    /* setup default virus name */
+    Ustrcpy(malware_name_buffer, "unknown");
+    malware_name = malware_name_buffer;
+
+    if (test_byte_order() == LITTLE_MY_ENDIAN) {
+      report_flag = tmpbuf[1];
+    }
+    else {
+      report_flag = tmpbuf[0];
+    };
+
+    /* read the report, if available */
+    if (report_flag == 1) {
+      /* read report size */
+      if ((bread = recv(sock, &kav_reportlen, 4, 0)) != 4) {
         close(sock);
         log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: kavdaemon reported 'kavdaemon damaged' (code 7).");
+                  "malware acl condition: cannot read report size from kavdaemon");
         return DEFER;
       };
-
-      /* code 8 is not handled, since it is ambigous. It appears mostly on
-      bounces where part of a file has been cut off */
-
-      /* "virus found" return codes (2-4) */
-      if ((kav_rc > 1) && (kav_rc < 5)) {
-        int report_flag = 0;
-
-        /* setup default virus name */
-        Ustrcpy(malware_name_buffer,"unknown");
-        malware_name = malware_name_buffer;
-
-        if (test_byte_order() == LITTLE_MY_ENDIAN) {
-          report_flag = tmpbuf[1];
-        }
-        else {
-          report_flag = tmpbuf[0];
-        };
-
-        /* read the report, if available */
-        if( report_flag == 1 ) {
-          /* read report size */
-          if ((bread = recv(sock, &kav_reportlen, 4, 0)) != 4) {
-            close(sock);
-            log_write(0, LOG_MAIN|LOG_PANIC,
-                  "malware acl condition: cannot read report size from kavdaemon");
-            return DEFER;
+
+      /* it's possible that avp returns av_buffer[1] == 1 but the
+         reportsize is 0 (!?) */
+      if (kav_reportlen > 0) {
+        /* set up match regex, depends on retcode */
+        if (kav_rc == 3)
+          Ustrcpy(kav_match_string, "suspicion:\\s*(.+?)\\s*$");
+        else
+          Ustrcpy(kav_match_string, "infected:\\s*(.+?)\\s*$");
+
+        kav_re = pcre_compile(CS kav_match_string,
+                              PCRE_COPT,
+                              (const char **)&rerror,
+                              &roffset,
+                              NULL);
+
+        /* read report, linewise */
+        while (kav_reportlen > 0) {
+          int result = 0;
+          int ovector[30];
+
+          bread = 0;
+          while (recv(sock, &tmpbuf[bread], 1, 0) == 1) {
+            kav_reportlen--;
+            if ((tmpbuf[bread] == '\n') || (bread > 1021)) break;
+            bread++;
           };
-
-          /* it's possible that avp returns av_buffer[1] == 1 but the
-          reportsize is 0 (!?) */
-          if (kav_reportlen > 0) {
-            /* set up match regex, depends on retcode */
-            if( kav_rc == 3 )
-              Ustrcpy(kav_match_string, "suspicion:\\s*(.+?)\\s*$");
-            else
-              Ustrcpy(kav_match_string, "infected:\\s*(.+?)\\s*$");
-
-            kav_re = pcre_compile( CS kav_match_string,
-                                   PCRE_COPT,
-                                   (const char **)&rerror,
-                                   &roffset,
-                                   NULL );
-
-            /* read report, linewise */
-            while (kav_reportlen > 0) {
-              int result = 0;
-              int ovector[30];
-
-              bread = 0;
-              while ( recv(sock, &tmpbuf[bread], 1, 0) == 1 ) {
-                kav_reportlen--;
-                if ( (tmpbuf[bread] == '\n') || (bread > 1021) ) break;
-                bread++;
-              };
-              bread++;
-              tmpbuf[bread] = '\0';
-
-              /* try matcher on the line, grab substring */
-              result = pcre_exec(kav_re, NULL, CS tmpbuf, Ustrlen(tmpbuf), 0, 0, ovector, 30);
-              if (result >= 2) {
-                pcre_copy_substring(CS tmpbuf, ovector, result, 1, CS malware_name_buffer, 255);
-                break;
-              };
-            };
+          bread++;
+          tmpbuf[bread] = '\0';
+
+          /* try matcher on the line, grab substring */
+          result = pcre_exec(kav_re, NULL, CS tmpbuf, Ustrlen(tmpbuf), 0, 0, ovector, 30);
+          if (result >= 2) {
+            pcre_copy_substring(CS tmpbuf, ovector, result, 1, CS malware_name_buffer, 255);
+            break;
           };
         };
-      }
-      else {
-        /* no virus found */
-        malware_name = NULL;
       };
-
-      close(sock);
-      return OK;
+    };
+  }
+  else {
+    /* no virus found */
+    malware_name = NULL;
+  };
+
+  close(sock);
+  return OK;
 }
-
-    /* "cmdline" scanner type ------------------------------------------------ */
-static int scan_cmdline(uschar ** pscanner, int *psep)
-{
-      uschar *cmdline_scanner;
-      uschar cmdline_scanner_buffer[1024];
-      uschar *cmdline_trigger;
-      uschar cmdline_trigger_buffer[1024];
-      const pcre *cmdline_trigger_re;
-      uschar *cmdline_regex;
-      uschar cmdline_regex_buffer[1024];
-      const pcre *cmdline_regex_re;
-      uschar file_name[1024];
-      uschar commandline[1024];
-      void (*eximsigchld)(int);
-      void (*eximsigpipe)(int);
-      FILE *scanner_out = NULL;
-      FILE *scanner_record = NULL;
-      uschar linebuffer[32767];
-      int trigger = 0;
-      int result;
-      int ovector[30];
-      int roffset;
-      const uschar *rerror;
-
-      /* find scanner command line */
-      if ((cmdline_scanner = string_nextinlist(pscanner, psep,
-                                          cmdline_scanner_buffer,
-                                          sizeof(cmdline_scanner_buffer))) == NULL) {
-        /* no command line supplied */
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: missing commandline specification for cmdline scanner type.");
-        return DEFER;
-      };
-
-      /* find scanner output trigger */
-      if ((cmdline_trigger = string_nextinlist(pscanner, psep,
-                                          cmdline_trigger_buffer,
-                                          sizeof(cmdline_trigger_buffer))) == NULL) {
-        /* no trigger regex supplied */
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: missing trigger specification for cmdline scanner type.");
-        return DEFER;
-      };
-
-      /* precompile trigger regex */
-      cmdline_trigger_re = pcre_compile(CS cmdline_trigger, PCRE_COPT, (const char **)&rerror, &roffset, NULL);
-      if (cmdline_trigger_re == NULL) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-                 "malware acl condition: regular expression error in '%s': %s at offset %d", cmdline_trigger_re, rerror, roffset);
-        return DEFER;
-      };
-
-      /* find scanner name regex */
-      if ((cmdline_regex = string_nextinlist(pscanner, psep,
-                                             cmdline_regex_buffer,
-                                             sizeof(cmdline_regex_buffer))) == NULL) {
-        /* no name regex supplied */
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: missing virus name regex specification for cmdline scanner type.");
-        return DEFER;
-      };
-
-      /* precompile name regex */
-      cmdline_regex_re = pcre_compile(CS cmdline_regex, PCRE_COPT, (const char **)&rerror, &roffset, NULL);
-      if (cmdline_regex_re == NULL) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-                 "malware acl condition: regular expression error in '%s': %s at offset %d", cmdline_regex_re, rerror, roffset);
-        return DEFER;
-      };
-
-      /* prepare scanner call */
-      snprintf(CS file_name,1024,"%s/scan/%s", spool_directory, message_id);
-      snprintf(CS commandline,1024, CS cmdline_scanner,file_name);
-      /* redirect STDERR too */
-      Ustrcat(commandline," 2>&1");
-
-      /* store exims signal handlers */
-      eximsigchld = signal(SIGCHLD,SIG_DFL);
-      eximsigpipe = signal(SIGPIPE,SIG_DFL);
-
-      scanner_out = popen(CS commandline,"r");
-      if (scanner_out == NULL) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-                 "malware acl condition: calling cmdline scanner (%s) failed: %s.", commandline, strerror(errno));
-        signal(SIGCHLD,eximsigchld);
-        signal(SIGPIPE,eximsigpipe);
-        return DEFER;
-      };
-
-      snprintf(CS file_name,1024,"%s/scan/%s/%s_scanner_output", spool_directory, message_id, message_id);
-      scanner_record = fopen(CS file_name,"w");
-
-      if (scanner_record == NULL) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-                 "malware acl condition: opening scanner output file (%s) failed: %s.", file_name, strerror(errno));
-        pclose(scanner_out);
-        signal(SIGCHLD,eximsigchld);
-        signal(SIGPIPE,eximsigpipe);
-        return DEFER;
-      };
-
-      /* look for trigger while recording output */
-      while(fgets(CS linebuffer,32767,scanner_out) != NULL) {
-        if ( Ustrlen(linebuffer) > fwrite(linebuffer, 1, Ustrlen(linebuffer), scanner_record) ) {
-          /* short write */
-          log_write(0, LOG_MAIN|LOG_PANIC,
-                 "malware acl condition: short write on scanner output file (%s).", file_name);
-          pclose(scanner_out);
-          signal(SIGCHLD,eximsigchld);
-          signal(SIGPIPE,eximsigpipe);
-          return DEFER;
-        };
-        /* try trigger match */
-        if (!trigger && regex_match_and_setup(cmdline_trigger_re, linebuffer, 0, -1))
-          trigger = 1;
-      };
-
-      fclose(scanner_record);
+
+/* "cmdline" scanner type ------------------------------------------------ */
+static int scan_cmdline(uschar ** pscanner, int *psep) {
+  uschar *cmdline_scanner;
+  uschar cmdline_scanner_buffer[1024];
+  uschar *cmdline_trigger;
+  uschar cmdline_trigger_buffer[1024];
+  const pcre *cmdline_trigger_re;
+  uschar *cmdline_regex;
+  uschar cmdline_regex_buffer[1024];
+  const pcre *cmdline_regex_re;
+  uschar file_name[1024];
+  uschar commandline[1024];
+  void (*eximsigchld)(int);
+  void (*eximsigpipe)(int);
+  FILE *scanner_out = NULL;
+  FILE *scanner_record = NULL;
+  uschar linebuffer[32767];
+  int trigger = 0;
+  int result;
+  int ovector[30];
+  int roffset;
+  const uschar *rerror;
+
+  /* find scanner command line */
+  if ((cmdline_scanner = string_nextinlist(pscanner, psep,
+                                           cmdline_scanner_buffer,
+                                           sizeof(cmdline_scanner_buffer))) == NULL) {
+    /* no command line supplied */
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: missing commandline specification for cmdline scanner type.");
+    return DEFER;
+  };
+
+  /* find scanner output trigger */
+  if ((cmdline_trigger = string_nextinlist(pscanner, psep,
+                                           cmdline_trigger_buffer,
+                                           sizeof(cmdline_trigger_buffer))) == NULL) {
+    /* no trigger regex supplied */
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: missing trigger specification for cmdline scanner type.");
+    return DEFER;
+  };
+
+  /* precompile trigger regex */
+  cmdline_trigger_re = pcre_compile(CS cmdline_trigger,
+                                    PCRE_COPT,
+                                    (const char **)&rerror,
+                                    &roffset,
+                                    NULL);
+  if (cmdline_trigger_re == NULL) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: regular expression error in '%s': %s at offset %d",
+              cmdline_trigger_re, rerror, roffset);
+    return DEFER;
+  };
+
+  /* find scanner name regex */
+  if ((cmdline_regex = string_nextinlist(pscanner, psep,
+                                         cmdline_regex_buffer,
+                                         sizeof(cmdline_regex_buffer))) == NULL) {
+    /* no name regex supplied */
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: missing virus name regex specification for cmdline scanner type.");
+    return DEFER;
+  };
+
+  /* precompile name regex */
+  cmdline_regex_re = pcre_compile(CS cmdline_regex,
+                                  PCRE_COPT,
+                                  (const char **)&rerror,
+                                  &roffset, NULL);
+  if (cmdline_regex_re == NULL) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: regular expression error in '%s': %s at offset %d",
+              cmdline_regex_re, rerror, roffset);
+    return DEFER;
+  };
+
+  /* prepare scanner call */
+  snprintf(CS file_name, 1024, "%s/scan/%s", spool_directory, message_id);
+  snprintf(CS commandline, 1024, CS cmdline_scanner, file_name);
+  /* redirect STDERR too */
+  Ustrcat(commandline, " 2>&1");
+
+  /* store exims signal handlers */
+  eximsigchld = signal(SIGCHLD, SIG_DFL);
+  eximsigpipe = signal(SIGPIPE, SIG_DFL);
+
+  scanner_out = popen(CS commandline, "r");
+  if (scanner_out == NULL) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: calling cmdline scanner (%s) failed: %s.",
+              commandline, strerror(errno));
+    signal(SIGCHLD, eximsigchld);
+    signal(SIGPIPE, eximsigpipe);
+    return DEFER;
+  };
+
+  snprintf(CS file_name, 1024, "%s/scan/%s/%s_scanner_output",
+           spool_directory, message_id, message_id);
+  scanner_record = fopen(CS file_name, "w");
+
+  if (scanner_record == NULL) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: opening scanner output file (%s) failed: %s.",
+              file_name, strerror(errno));
+    pclose(scanner_out);
+    signal(SIGCHLD, eximsigchld);
+    signal(SIGPIPE, eximsigpipe);
+    return DEFER;
+  };
+
+  /* look for trigger while recording output */
+  while (fgets(CS linebuffer, 32767, scanner_out) != NULL) {
+    if (Ustrlen(linebuffer) > fwrite(linebuffer, 1, Ustrlen(linebuffer), scanner_record)) {
+      /* short write */
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: short write on scanner output file (%s).", file_name);
       pclose(scanner_out);
-      signal(SIGCHLD,eximsigchld);
-      signal(SIGPIPE,eximsigpipe);
-
-      if (trigger) {
-        /* setup default virus name */
-        Ustrcpy(malware_name_buffer,"unknown");
-        malware_name = malware_name_buffer;
-
-        /* re-open the scanner output file, look for name match */
-        scanner_record = fopen(CS file_name,"r");
-        while(fgets(CS linebuffer,32767,scanner_record) != NULL) {
-          /* try match */
-          result = pcre_exec(cmdline_regex_re, NULL, CS linebuffer, Ustrlen(linebuffer), 0, 0, ovector, 30);
-          if (result >= 2) {
-            pcre_copy_substring(CS linebuffer, ovector, result, 1, CS malware_name_buffer, 255);
-          };
-        };
-        fclose(scanner_record);
-      }
-      else {
-        /* no virus found */
-        malware_name = NULL;
+      signal(SIGCHLD, eximsigchld);
+      signal(SIGPIPE, eximsigpipe);
+      return DEFER;
+    };
+    /* try trigger match */
+    if (!trigger && regex_match_and_setup(cmdline_trigger_re, linebuffer, 0, -1))
+      trigger = 1;
+  };
+
+  fclose(scanner_record);
+  pclose(scanner_out);
+  signal(SIGCHLD, eximsigchld);
+  signal(SIGPIPE, eximsigpipe);
+
+  if (trigger) {
+    /* setup default virus name */
+    Ustrcpy(malware_name_buffer, "unknown");
+    malware_name = malware_name_buffer;
+
+    /* re-open the scanner output file, look for name match */
+    scanner_record = fopen(CS file_name, "r");
+    while (fgets(CS linebuffer, 32767, scanner_record) != NULL) {
+      /* try match */
+      result = pcre_exec(cmdline_regex_re, NULL, CS linebuffer,
+                         Ustrlen(linebuffer), 0, 0, ovector, 30);
+      if (result >= 2) {
+        pcre_copy_substring(CS linebuffer, ovector, result, 1, CS malware_name_buffer, 255);
       };
-      return OK;
+    };
+    fclose(scanner_record);
+  }
+  else {
+    /* no virus found */
+    malware_name = NULL;
+  };
+  return OK;
 }
-
-    /* "sophie" scanner type ------------------------------------------------- */
-static int scan_sophie(uschar ** pscanner, int *psep)
-{
-      uschar *sophie_options;
-      uschar sophie_options_buffer[1024];
-      uschar sophie_options_default[] = "/var/run/sophie";
-      int bread = 0;
-      struct sockaddr_un server;
-      int sock;
-      uschar file_name[1024];
-      uschar av_buffer[1024];
-
-      if ((sophie_options = string_nextinlist(pscanner, psep,
+
+/* "sophie" scanner type ------------------------------------------------- */
+static int scan_sophie(uschar ** pscanner, int *psep) {
+  uschar *sophie_options;
+  uschar sophie_options_buffer[1024];
+  uschar sophie_options_default[] = "/var/run/sophie";
+  int bread = 0;
+  struct sockaddr_un server;
+  int sock;
+  uschar file_name[1024];
+  uschar av_buffer[1024];
+
+  if ((sophie_options = string_nextinlist(pscanner, psep,
                                           sophie_options_buffer,
                                           sizeof(sophie_options_buffer))) == NULL) {
-        /* no options supplied, use default options */
-        sophie_options = sophie_options_default;
-      };
-
-      /* open the sophie socket */
-      sock = socket(AF_UNIX, SOCK_STREAM, 0);
-      if (sock < 0) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: can't open UNIX socket.");
-        return DEFER;
-      }
-      server.sun_family = AF_UNIX;
-      Ustrcpy(server.sun_path, sophie_options);
-      if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
-        close(sock);
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: unable to connect to sophie UNIX socket (%s). errno=%d", sophie_options, errno);
-        return DEFER;
-      }
-
-      /* pass the scan directory to sophie */
-      snprintf(CS file_name,1024,"%s/scan/%s", spool_directory, message_id);
-      if (write(sock, file_name, Ustrlen(file_name)) < 0) {
-        close(sock);
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: unable to write to sophie UNIX socket (%s)", sophie_options);
-        return DEFER;
-      };
-
-      write(sock, "\n", 1);
-
-      /* wait for result */
-      memset(av_buffer, 0, sizeof(av_buffer));
-      if ((!(bread = read(sock, av_buffer, sizeof(av_buffer))) > 0)) {
-        close(sock);
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: unable to read from sophie UNIX socket (%s)", sophie_options);
-        return DEFER;
-      };
-
-      close(sock);
-
-      /* infected ? */
-      if (av_buffer[0] == '1') {
-        if (Ustrchr(av_buffer, '\n')) *Ustrchr(av_buffer, '\n') = '\0';
-        Ustrcpy(malware_name_buffer,&av_buffer[2]);
-        malware_name = malware_name_buffer;
-      }
-      else if (!strncmp(CS av_buffer, "-1", 2)) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: malware acl condition: sophie reported error");
-        return DEFER;
-      }
-      else {
-        /* all ok, no virus */
-        malware_name = NULL;
-      };
-      return OK;
+    /* no options supplied, use default options */
+    sophie_options = sophie_options_default;
+  };
+
+  /* open the sophie socket */
+  sock = socket(AF_UNIX, SOCK_STREAM, 0);
+  if (sock < 0) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: can't open UNIX socket.");
+    return DEFER;
+  };
+  server.sun_family = AF_UNIX;
+  Ustrcpy(server.sun_path, sophie_options);
+  if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: unable to connect to sophie UNIX socket (%s). errno=%d",
+              sophie_options, errno);
+    return DEFER;
+  };
+
+  /* pass the scan directory to sophie */
+  snprintf(CS file_name, 1024, "%s/scan/%s", spool_directory, message_id);
+  if (write(sock, file_name, Ustrlen(file_name)) < 0) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: unable to write to sophie UNIX socket (%s)",
+              sophie_options);
+    return DEFER;
+  };
+
+  write(sock, "\n", 1);
+
+  /* wait for result */
+  memset(av_buffer, 0, sizeof(av_buffer));
+  if ((!(bread = read(sock, av_buffer, sizeof(av_buffer))) > 0)) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: unable to read from sophie UNIX socket (%s)",
+              sophie_options);
+    return DEFER;
+  };
+
+  close(sock);
+
+  /* infected ? */
+  if (av_buffer[0] == '1') {
+    if (Ustrchr(av_buffer, '\n')) *Ustrchr(av_buffer, '\n') = '\0';
+    Ustrcpy(malware_name_buffer, &av_buffer[2]);
+    malware_name = malware_name_buffer;
+  }
+  else if (!strncmp(CS av_buffer, "-1", 2)) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: malware acl condition: sophie reported error");
+    return DEFER;
+  }
+  else {
+    /* all ok, no virus */
+    malware_name = NULL;
+  };
+  return OK;
 }


-    /* "clamd" scanner type ------------------------------------------------- */
-    /* This code was contributed by David Saez <david@???> */
-static int scan_clamd(uschar ** pscanner, int *psep)
-{
-      uschar *clamd_options;
-      uschar clamd_options_buffer[1024];
-      uschar clamd_options_default[] = "/tmp/clamd";
-      uschar *p,*vname;
-      struct sockaddr_un server;
-      int sock,port,bread=0;
-      uschar file_name[1024];
-      uschar av_buffer[1024];
-      uschar hostname[256];
-      struct hostent *he;
-      struct in_addr in;
-
-      if ((clamd_options = string_nextinlist(pscanner, psep,
-                                             clamd_options_buffer,
-                                             sizeof(clamd_options_buffer))) == NULL) {
-        /* no options supplied, use default options */
-        clamd_options = clamd_options_default;
-      }
-
-      /* socket does not start with '/' -> network socket */
-      if (*clamd_options != '/') {
-
-        /* extract host and port part */
-        if( sscanf(CS clamd_options, "%s %u", hostname, &port) != 2 ) {
-          log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: clamd: invalid socket '%s'", clamd_options);
-          return DEFER;
-        };
-
-        /* Lookup the host */
-        if((he = gethostbyname(CS hostname)) == 0) {
-          log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: clamd: failed to lookup host '%s'", hostname);
-          return DEFER;
-        }
-
-        in = *(struct in_addr *) he->h_addr_list[0];
-
-        /* Open the ClamAV Socket */
-        if ( (sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
-          log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: clamd: unable to acquire socket (%s)",
-                    strerror(errno));
-          return DEFER;
-        }
-
-        if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
-          close(sock);
-          log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: clamd: connection to %s, port %u failed (%s)",
-                    inet_ntoa(in), port, strerror(errno));
-          return DEFER;
-        }
-      }
-      else {
-        /* open the local socket */
-        if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-          log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: clamd: unable to acquire socket (%s)",
-                    strerror(errno));
-          return DEFER;
-        }
-
-        server.sun_family = AF_UNIX;
-        Ustrcpy(server.sun_path, clamd_options);
-
-        if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
-          close(sock);
-          log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: clamd: unable to connect to UNIX socket %s (%s)",
-                    clamd_options, strerror(errno) );
-          return DEFER;
-        }
-      }
-
-      /* Pass the string to ClamAV (7 = "SCAN \n" + \0) */
-
-      snprintf(CS file_name,1024,"SCAN %s/scan/%s\n", spool_directory, message_id);
-
-      if (send(sock, file_name, Ustrlen(file_name), 0) < 0) {
-        close(sock);
-        log_write(0, LOG_MAIN|LOG_PANIC,"malware acl condition: clamd: unable to write to socket (%s)",
-                  strerror(errno));
-        return DEFER;
-      }
-
-      /*
-        We're done sending, close socket for writing.
-
-        One user reported that clamd 0.70 does not like this any more ...
-
-      */
-
-      /* shutdown(sock, SHUT_WR); */
-
-      /* Read the result */
-      memset(av_buffer, 0, sizeof(av_buffer));
-      bread = read(sock, av_buffer, sizeof(av_buffer));
+/* "clamd" scanner type ------------------------------------------------- */
+/* This code was contributed by David Saez <david@???> */
+static int scan_clamd(uschar ** pscanner, int *psep) {
+  uschar *clamd_options;
+  uschar clamd_options_buffer[1024];
+  uschar clamd_options_default[] = "/tmp/clamd";
+  uschar *p, *vname;
+  struct sockaddr_un server;
+  int sock, port, bread=0;
+  uschar file_name[1024];
+  uschar av_buffer[1024];
+  uschar hostname[256];
+  struct hostent *he;
+  struct in_addr in;
+
+  if ((clamd_options = string_nextinlist(pscanner, psep,
+                                         clamd_options_buffer,
+                                         sizeof(clamd_options_buffer))) == NULL) {
+    /* no options supplied, use default options */
+    clamd_options = clamd_options_default;
+  };
+
+  /* socket does not start with '/' -> network socket */
+  if (*clamd_options != '/') {
+
+    /* extract host and port part */
+    if (sscanf(CS clamd_options, "%s %u", hostname, &port) != 2) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: clamd: invalid socket '%s'", clamd_options);
+      return DEFER;
+    };
+
+    /* Lookup the host */
+    if ((he = gethostbyname(CS hostname)) == 0) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: clamd: failed to lookup host '%s'", hostname);
+      return DEFER;
+    };
+
+    in = *(struct in_addr *) he->h_addr_list[0];
+
+    /* Open the ClamAV Socket */
+    if ((sock = ip_socket(SOCK_STREAM, AF_INET)) < 0) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: clamd: unable to acquire socket (%s)",
+                strerror(errno));
+      return DEFER;
+    };
+
+    if (ip_connect(sock, AF_INET, (uschar*)inet_ntoa(in), port, 5) < 0) {
       close(sock);
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: clamd: connection to %s, port %u failed (%s)",
+                inet_ntoa(in), port, strerror(errno));
+      return DEFER;
+    };
+  }
+  else {
+    /* open the local socket */
+    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: clamd: unable to acquire socket (%s)",
+                strerror(errno));
+      return DEFER;
+    };


-      if (!(bread  > 0)) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-                  "malware acl condition: clamd: unable to read from socket (%s)",
-                  strerror(errno));
-        return DEFER;
-      }
-
-      if (bread == sizeof(av_buffer)) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-                  "malware acl condition: clamd: buffer too small");
-        return DEFER;
-      }
-
-      /* Check the result. ClamAV Returns
-         infected: -> "<filename>: <virusname> FOUND"
-         not-infected: -> "<filename>: OK"
-            error: -> "<filename>: <errcode> ERROR */
-
-      if (!(*av_buffer)) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-                  "malware acl condition: clamd: ClamAV returned null");
-        return DEFER;
-      }
-
-      /* colon in returned output? */
-      if((p = Ustrrchr(av_buffer,':')) == NULL) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-                  "malware acl condition: clamd: ClamAV returned malformed result: %s",
-                  av_buffer);
-        return DEFER;
-      }
-
-      /* strip filename strip CR at the end */
-      ++p;
-      while (*p == ' ') ++p;
-      vname = p;
-      p = vname + Ustrlen(vname) - 1;
-      if( *p == '\n' ) *p = '\0';
-
-      if ((p = Ustrstr(vname, "FOUND"))!=NULL) {
-           *p=0;
-           for (--p;p>vname && *p<=32;p--) *p=0;
-           for (;*vname==32;vname++);
-           Ustrcpy(malware_name_buffer,vname);
-           malware_name = malware_name_buffer;
-      }
-      else {
-           if (Ustrstr(vname, "ERROR")!=NULL) {
-              /* ClamAV reports ERROR
-              Find line start */
-              for (;*vname!='\n' && vname>av_buffer; vname--);
-              if (*vname=='\n') vname++;
-
-              log_write(0, LOG_MAIN|LOG_PANIC,
-                     "malware acl condition: clamd: ClamAV returned %s",vname);
-              return DEFER;
-           }
-           else {
-              /* Everything should be OK */
-              malware_name = NULL;
-           }
-      }
-    return OK;
-}
-
-    /* "mksd" scanner type --------------------------------------------------- */
-static int scan_mksd(uschar ** pscanner, int *psep)
-{
-      uschar *mksd_options;
-      char *mksd_options_end;
-      uschar mksd_options_buffer[32];
-      int mksd_maxproc = 1;  /* default, if no option supplied */
-      struct sockaddr_un server;
-      int sock;
-      int retval;
-
-      if ((mksd_options = string_nextinlist(pscanner, psep,
-                                            mksd_options_buffer,
-                                            sizeof(mksd_options_buffer))) != NULL) {
-        mksd_maxproc = (int) strtol(CS mksd_options, &mksd_options_end, 10);
-          if ((*mksd_options == '\0') || (*mksd_options_end != '\0') ||
-              (mksd_maxproc < 1) || (mksd_maxproc > 32)) {
-          log_write(0, LOG_MAIN|LOG_PANIC,
-                    "malware acl condition: mksd: invalid option '%s'", mksd_options);
-          return DEFER;
-        }
-      }
-
-      /* open the mksd socket */
-      sock = socket(AF_UNIX, SOCK_STREAM, 0);
-      if (sock < 0) {
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: can't open UNIX socket.");
-        return DEFER;
-      }
-      server.sun_family = AF_UNIX;
-      Ustrcpy(server.sun_path, "/var/run/mksd/socket");
-      if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
-        close(sock);
-        log_write(0, LOG_MAIN|LOG_PANIC,
-             "malware acl condition: unable to connect to mksd UNIX socket (/var/run/mksd/socket). errno=%d", errno);
-        return DEFER;
-      }
-
+    server.sun_family = AF_UNIX;
+    Ustrcpy(server.sun_path, clamd_options);
+
+    if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
+      close(sock);
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: clamd: unable to connect to UNIX socket %s (%s)",
+                clamd_options, strerror(errno));
+      return DEFER;
+    };
+  };
+
+  /* Pass the string to ClamAV (7 = "SCAN \n" + \0) */
+
+  snprintf(CS file_name, 1024, "SCAN %s/scan/%s\n", spool_directory, message_id);
+
+  if (send(sock, file_name, Ustrlen(file_name), 0) < 0) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: clamd: unable to write to socket (%s)",
+              strerror(errno));
+    return DEFER;
+  };
+
+  /*
+    We're done sending, close socket for writing.
+
+    One user reported that clamd 0.70 does not like this any more ...
+
+  */
+
+  /* shutdown(sock, SHUT_WR); */
+
+  /* Read the result */
+  memset(av_buffer, 0, sizeof(av_buffer));
+  bread = read(sock, av_buffer, sizeof(av_buffer));
+  close(sock);
+
+  if (!(bread  > 0)) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: clamd: unable to read from socket (%s)",
+              strerror(errno));
+    return DEFER;
+  };
+
+  if (bread == sizeof(av_buffer)) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: clamd: buffer too small");
+    return DEFER;
+  };
+
+  /* Check the result. ClamAV Returns
+     infected: -> "<filename>: <virusname> FOUND"
+     not-infected: -> "<filename>: OK"
+     error: -> "<filename>: <errcode> ERROR */
+
+  if (!(*av_buffer)) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: clamd: ClamAV returned null");
+    return DEFER;
+  };
+
+  /* colon in returned output? */
+  if ((p = Ustrrchr(av_buffer, ':')) == NULL) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: clamd: ClamAV returned malformed result: %s",
+              av_buffer);
+    return DEFER;
+  };
+
+  /* strip filename strip CR at the end */
+  ++p;
+  while (*p == ' ') ++p;
+  vname = p;
+  p = vname + Ustrlen(vname) - 1;
+  if (*p == '\n') *p = '\0';
+
+  if ((p = Ustrstr(vname, "FOUND"))!=NULL) {
+    *p=0;
+    for (--p;p>vname && *p<=32;p--) *p=0;
+    for (;*vname==32;vname++);
+    Ustrcpy(malware_name_buffer, vname);
+    malware_name = malware_name_buffer;
+  }
+  else {
+    if (Ustrstr(vname, "ERROR")!=NULL) {
+      /* ClamAV reports ERROR
+         Find line start */
+      for (;*vname!='\n' && vname>av_buffer; vname--);
+      if (*vname=='\n') vname++;
+
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: clamd: ClamAV returned %s", vname);
+      return DEFER;
+    }
+    else {
+      /* Everything should be OK */
       malware_name = NULL;
-
-      /* choose the appropriate scan routine */
-      retval = demime_ok ?
-               mksd_scan_unpacked(sock, mksd_maxproc) :
-               mksd_scan_packed(sock);
-
-      if (retval != OK)
-        return retval;
-
-    return OK;
+    };
+  };
+  return OK;
+}
+
+/* "mksd" scanner type --------------------------------------------------- */
+static int scan_mksd(uschar ** pscanner, int *psep) {
+  uschar *mksd_options;
+  char *mksd_options_end;
+  uschar mksd_options_buffer[32];
+  int mksd_maxproc = 1;  /* default, if no option supplied */
+  struct sockaddr_un server;
+  int sock;
+  int retval;
+
+  if ((mksd_options = string_nextinlist(pscanner, psep,
+                                        mksd_options_buffer,
+                                        sizeof(mksd_options_buffer))) != NULL) {
+    mksd_maxproc = (int) strtol(CS mksd_options, &mksd_options_end, 10);
+    if ((*mksd_options == '\0') || (*mksd_options_end != '\0') ||
+        (mksd_maxproc < 1) || (mksd_maxproc > 32)) {
+      log_write(0, LOG_MAIN|LOG_PANIC,
+                "malware acl condition: mksd: invalid option '%s'", mksd_options);
+      return DEFER;
+    };
+  };
+
+  /* open the mksd socket */
+  sock = socket(AF_UNIX, SOCK_STREAM, 0);
+  if (sock < 0) {
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: can't open UNIX socket.");
+    return DEFER;
+  };
+  server.sun_family = AF_UNIX;
+  Ustrcpy(server.sun_path, "/var/run/mksd/socket");
+  if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
+    close(sock);
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: unable to connect to mksd UNIX socket (/var/run/mksd/socket). errno=%d",
+              errno);
+    return DEFER;
+  };
+
+  malware_name = NULL;
+
+  /* choose the appropriate scan routine */
+  retval = demime_ok ?
+    mksd_scan_unpacked(sock, mksd_maxproc) :
+    mksd_scan_packed(sock);
+
+  if (retval != OK)
+    return retval;
+
+  return OK;
 }


/* ============= private routines for the "mksd" scanner type ============== */

#include <sys/uio.h>

-int mksd_writev (int sock, struct iovec *iov, int iovcnt)
-{
+int mksd_writev(int sock, struct iovec *iov, int iovcnt) {
   int i;
-
+
   for (;;) {
     do
-      i = writev (sock, iov, iovcnt);
+      i = writev(sock, iov, iovcnt);
     while ((i < 0) && (errno == EINTR));
     if (i <= 0) {
-      close (sock);
+      close(sock);
       log_write(0, LOG_MAIN|LOG_PANIC,
                 "malware acl condition: unable to write to mksd UNIX socket (/var/run/mksd/socket)");
       return -1;
-    }
-
+    };
+
     for (;;)
       if (i >= iov->iov_len) {
         if (--iovcnt == 0)
@@ -1075,103 +1097,99 @@
         iov->iov_len -= i;
         iov->iov_base = CS iov->iov_base + i;
         break;
-      }
-  }
+      };
+  };
 }


-int mksd_read_lines (int sock, uschar *av_buffer, int av_buffer_size)
-{
+int mksd_read_lines(int sock, uschar *av_buffer, int av_buffer_size) {
   int offset = 0;
   int i;
-
+
   do {
-    if ((i = recv (sock, av_buffer+offset, av_buffer_size-offset, 0)) <= 0) {
-      close (sock);
+    if ((i = recv(sock, av_buffer+offset, av_buffer_size-offset, 0)) <= 0) {
+      close(sock);
       log_write(0, LOG_MAIN|LOG_PANIC,
                 "malware acl condition: unable to read from mksd UNIX socket (/var/run/mksd/socket)");
       return -1;
-    }
-
+    };
+
     offset += i;
     /* offset == av_buffer_size -> buffer full */
     if (offset == av_buffer_size) {
-      close (sock);
+      close(sock);
       log_write(0, LOG_MAIN|LOG_PANIC,
                 "malware acl condition: malformed reply received from mksd");
       return -1;
-    }
+    };
   } while (av_buffer[offset-1] != '\n');
-
+
   av_buffer[offset] = '\0';
   return offset;
 }


-int mksd_parse_line (char *line)
-{
+int mksd_parse_line(char *line) {
   char *p;
-
+
   switch (*line) {
-    case 'O':
-      /* OK */
-      return OK;
-    case 'E':
-    case 'A':
-      /* ERR */
-      if ((p = strchr (line, '\n')) != NULL)
-        (*p) = '\0';
-      log_write(0, LOG_MAIN|LOG_PANIC,
-                "malware acl condition: mksd scanner failed: %s", line);
-      return DEFER;
-    default:
-      /* VIR */
-      if ((p = strchr (line, '\n')) != NULL) {
-        (*p) = '\0';
-        if (((p-line) > 5) && ((p-line) < sizeof (malware_name_buffer)) && (line[3] == ' '))
-          if (((p = strchr (line+4, ' ')) != NULL) && ((p-line) > 4)) {
-            (*p) = '\0';
-            Ustrcpy (malware_name_buffer, line+4);
-        malware_name = malware_name_buffer;
-            return OK;
-          }
-      }
-      log_write(0, LOG_MAIN|LOG_PANIC,
-                "malware acl condition: malformed reply received from mksd: %s", line);
-      return DEFER;
-  }
+  case 'O':
+    /* OK */
+    return OK;
+  case 'E':
+  case 'A':
+    /* ERR */
+    if ((p = strchr(line, '\n')) != NULL)
+      (*p) = '\0';
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: mksd scanner failed: %s", line);
+    return DEFER;
+  default:
+    /* VIR */
+    if ((p = strchr(line, '\n')) != NULL) {
+      (*p) = '\0';
+      if (((p-line) > 5) && ((p-line) < sizeof(malware_name_buffer)) && (line[3] == ' '))
+        if (((p = strchr(line+4, ' ')) != NULL) && ((p-line) > 4)) {
+          (*p) = '\0';
+          Ustrcpy(malware_name_buffer, line+4);
+          malware_name = malware_name_buffer;
+          return OK;
+        };
+    };
+    log_write(0, LOG_MAIN|LOG_PANIC,
+              "malware acl condition: malformed reply received from mksd: %s", line);
+    return DEFER;
+  };
 }


-int mksd_scan_packed (int sock)
-{
+int mksd_scan_packed(int sock) {
   struct iovec iov[7];
   char *cmd = "MSQ/scan/.eml\n";
   uschar av_buffer[1024];
-
+
   iov[0].iov_base = cmd;
   iov[0].iov_len = 3;
   iov[1].iov_base = CS spool_directory;
-  iov[1].iov_len = Ustrlen (spool_directory);
+  iov[1].iov_len = Ustrlen(spool_directory);
   iov[2].iov_base = cmd + 3;
   iov[2].iov_len = 6;
   iov[3].iov_base = iov[5].iov_base = CS message_id;
-  iov[3].iov_len = iov[5].iov_len = Ustrlen (message_id);
+  iov[3].iov_len = iov[5].iov_len = Ustrlen(message_id);
   iov[4].iov_base = cmd + 3;
   iov[4].iov_len = 1;
   iov[6].iov_base = cmd + 9;
   iov[6].iov_len = 5;
-
-  if (mksd_writev (sock, iov, 7) < 0)
+
+  if (mksd_writev(sock, iov, 7) < 0)
     return DEFER;
-
-  if (mksd_read_lines (sock, av_buffer, sizeof (av_buffer)) < 0)
+
+  if (mksd_read_lines(sock, av_buffer, sizeof(av_buffer)) < 0)
     return DEFER;
-
-  close (sock);
-
-  return mksd_parse_line (CS av_buffer);
+
+  close(sock);
+
+  return mksd_parse_line(CS av_buffer);
 }


-int mksd_scan_unpacked (int sock, int maxproc)
-{
+int mksd_scan_unpacked(int sock, int maxproc) {
   struct iovec iov[5];
   char *cmd = "\nSQ/";
   DIR *unpdir;
@@ -1182,80 +1200,80 @@
   uschar mbox_name[1024];
   uschar unpackdir[1024];
   uschar av_buffer[16384];
-
-  snprintf (CS mbox_name, sizeof (mbox_name), "%s.eml", CS message_id);
-  snprintf (CS unpackdir, sizeof (unpackdir), "%s/scan/%s", CS spool_directory, CS message_id);
-
-  if ((unpdir = opendir (CS unpackdir)) == NULL) {
-    close (sock);
+
+  snprintf(CS mbox_name, sizeof(mbox_name), "%s.eml", CS message_id);
+  snprintf(CS unpackdir, sizeof(unpackdir), "%s/scan/%s", CS spool_directory, CS message_id);
+
+  if ((unpdir = opendir(CS unpackdir)) == NULL) {
+    close(sock);
     log_write(0, LOG_MAIN|LOG_PANIC,
               "malware acl condition: unable to scan spool directory");
     return DEFER;
-  }
-
+  };
+
   iov[0].iov_base = cmd;
   iov[0].iov_len = 3;
   iov[1].iov_base = CS unpackdir;
-  iov[1].iov_len = Ustrlen (unpackdir);
+  iov[1].iov_len = Ustrlen(unpackdir);
   iov[2].iov_base = cmd + 3;
   iov[2].iov_len = 1;
   iov[4].iov_base = cmd;
   iov[4].iov_len = 1;
-
+
   /* main loop */
   while ((unpdir != NULL) || (pending > 0)) {
-
+
     /* write loop */
     while ((pending < maxproc) && (unpdir != NULL)) {
-      if ((entry = readdir (unpdir)) != NULL) {
-        if ((Ustrcmp (entry->d_name, ".") != 0) &&
-            (Ustrcmp (entry->d_name, "..") != 0) &&
-            (Ustrcmp (entry->d_name, mbox_name) != 0)) {
+      if ((entry = readdir(unpdir)) != NULL) {
+        if ((Ustrcmp(entry->d_name, ".") != 0) &&
+            (Ustrcmp(entry->d_name, "..") != 0) &&
+            (Ustrcmp(entry->d_name, mbox_name) != 0)) {
           iov[3].iov_base = entry->d_name;
-          iov[3].iov_len = strlen (entry->d_name);
-          if (mksd_writev (sock, iov, 5) < 0) {
-            closedir (unpdir);
+          iov[3].iov_len = strlen(entry->d_name);
+          if (mksd_writev(sock, iov, 5) < 0) {
+            closedir(unpdir);
             return DEFER;
-          }
+          };
           iov[0].iov_base = cmd + 1;
           iov[0].iov_len = 2;
           pending++;
-        }
+        };
       } else {
-        closedir (unpdir);
+        closedir(unpdir);
         unpdir = NULL;
-      }
-    }
-
+      };
+    };
+
     /* read and parse */
     if (pending > 0) {
-      if ((offset = mksd_read_lines (sock, av_buffer, sizeof (av_buffer))) < 0) {
+      if ((offset = mksd_read_lines(sock, av_buffer, sizeof(av_buffer))) < 0) {
         if (unpdir != NULL)
-          closedir (unpdir);
+          closedir(unpdir);
         return DEFER;
-      }
+      };
       line = av_buffer;
       do {
-        if (((i = mksd_parse_line (CS line)) != OK) || (malware_name != NULL)) {
-          close (sock);
+        if (((i = mksd_parse_line(CS line)) != OK) || (malware_name != NULL)) {
+          close(sock);
           if (unpdir != NULL)
-            closedir (unpdir);
+            closedir(unpdir);
           return i;
-        }
+        };
         pending--;
-        if ((line = Ustrchr (line, '\n')) == NULL) {
-          close (sock);
+        if ((line = Ustrchr(line, '\n')) == NULL) {
+          close(sock);
           if (unpdir != NULL)
-            closedir (unpdir);
+            closedir(unpdir);
           log_write(0, LOG_MAIN|LOG_PANIC,
                     "malware acl condition: unterminated line received from mksd");
           return DEFER;
-        }
+        };
       } while (++line != (av_buffer + offset));
       offset = 0;
-    }
-  }
-
-  close (sock);
+    };
+  };
+
+  close(sock);
   return OK;
 }



--
ilmari