+ uschar scan_filename[1024];
+ BOOL fits;
+
+ fits = string_format(scan_filename, sizeof(scan_filename),
+ CS"%s/scan/%s/%s.eml", spool_directory, message_id, message_id);
+ if (!fits)
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "malware filename does not fit in buffer [malware()]");
+ return DEFER;
+ }
+
+ return malware_internal(listptr, scan_filename, FALSE);
+}
+
+
+/*************************************************
+* Scan a file for malware *
+*************************************************/
+
+/* This is a test wrapper for scanning an email, which is not used in
+normal processing. Scan any file, using the Exim scanning interface.
+This function tampers with various global variables so is unsafe to use
+in any other context.
+
+Arguments:
+ eml_filename a file holding the message to be scanned
+
+Returns: Exim message processing code (OK, FAIL, DEFER, ...)
+ where true means malware was found (condition applies)
+*/
+int malware_in_file(uschar *eml_filename) {
+ uschar *scan_options[2];
+ uschar message_id_buf[64];
+ int ret;
+
+ scan_options[0] = "*";
+ scan_options[1] = NULL;
+
+ /* spool_mbox() assumes various parameters exist, when creating
+ the relevant directory and the email within */
+ (void) string_format(message_id_buf, sizeof(message_id_buf),
+ US"dummy-%d", pseudo_random_number(INT_MAX));
+ message_id = message_id_buf;
+ sender_address = "malware-sender@example.net";
+ return_path = "";
+ recipients_list = NULL;
+ receive_add_recipient("malware-victim@example.net", -1);
+ enable_dollar_recipients = TRUE;
+
+ ret = malware_internal(scan_options, eml_filename, TRUE);
+
+ strncpy(spooled_message_id, message_id, sizeof(spooled_message_id));
+ spool_mbox_ok = 1;
+ /* don't set no_mbox_unspool; at present, there's no way for it to become
+ set, but if that changes, then it should apply to these tests too */
+ unspool_mbox();
+
+ return ret;
+}
+
+
+/*************************************************
+* Scan content for malware *
+*************************************************/
+
+/* This is an internal interface for scanning an email; the normal interface
+is via malware(), or there's malware_in_file() used for testing/debugging.
+
+Arguments:
+ listptr the list of options to the "malware = ..." ACL condition
+ eml_filename the file holding the email to be scanned
+ faking whether or not we're faking this up for the -bmalware test
+
+Returns: Exim message processing code (OK, FAIL, DEFER, ...)
+ where true means malware was found (condition applies)
+*/
+static int malware_internal(uschar **listptr, uschar *eml_filename, BOOL faking) {