US"CONFIGURE\tTIMEOUT\t0\n",
US"CONFIGURE\tMAXARCH\t5\n",
US"CONFIGURE\tMIME\t1\n" };
+ time_t tmo;
malware_name = NULL;
DEBUG(D_acl) debug_printf("Malware scan: issuing %s scan [%s]\n",
scanner_name, scanner_options);
-
+ tmo = time(NULL) + MALWARE_TIMEOUT;
/* pass options */
memset(av_buffer, 0, sizeof(av_buffer));
for (i=0; i != nelements(cmdopt); i++) {
/* todo also SUSPICION\t */
fs_inf = m_pcre_compile(US"\\S{0,5}INFECTED\\t[^\\t]*\\t([^\\t]+)\\t\\S*$", &errstr);
- /* read report, linewise */
- do {
- i = 0;
- memset(av_buffer, 0, sizeof(av_buffer));
- do {
- if ((bread= ip_recv(sock, &av_buffer[i], 1, MALWARE_TIMEOUT)) < 0)
+ /* read report, linewise. Apply a timeout as the Fsecure daemon
+ sometimes wants an answer to "PING" but they won't tell us what */
+ {
+ uschar * p = av_buffer;
+ uschar * q;
+
+ for (;;)
+ {
+ int t = tmo - time(NULL);
+
+ errno = ETIME;
+ i = av_buffer+sizeof(av_buffer)-p;
+ if ( t <= 0
+ || (bread= ip_recv(sock, p, i-1, t)) < 0
+ )
return m_errlog_defer_3(scanent,
string_sprintf("unable to read result (%s)", strerror(errno)),
sock);
- } while (++i < sizeof(av_buffer)-1 && av_buffer[i-1] != '\n');
- av_buffer[i-1] = '\0';
- /* Really search for virus again? */
- if (malware_name == NULL)
- /* try matcher on the line, grab substring */
- malware_name = m_pcre_exec(fs_inf, av_buffer);
+ for (p[bread] = '\0'; q = strchr(p, '\n'); p = q+1)
+ {
+ *q = '\0';
+
+ /* Really search for virus again? */
+ if (!malware_name)
+ /* try matcher on the line, grab substring */
+ malware_name = m_pcre_exec(fs_inf, p);
+
+ if (Ustrstr(p, "OK\tScan ok."))
+ goto fsec_found;
+ }
+
+ /* copy down the trailing partial line then read another chunk */
+ i = av_buffer+sizeof(av_buffer)-p;
+ memmove(av_buffer, p, i);
+ p = av_buffer+i;
+ }
}
- while (Ustrstr(av_buffer, "OK\tScan ok.") == NULL);
+
+ fsec_found:
break;
} /* fsecure */