Re: Exiscan Patch - multiple spamd servers and/or virus scanners

[email protected] (Dagfinn Ilmari Mannsåker)
Newsgroups gmane.mail.exim.user,gmane.mail.exim.exiscan.user
Organization Program-, Informasjons- og Nettverksteknologisk Gruppe, UiO
Message-ID <[email protected]>
[email protected] (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 <[email protected]> */
-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 <[email protected]> */
+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


--

## List details at http://www.exim.org/mailman/listinfo/exim-users Exim details at http://www.exim.org/ ##
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.