- /* send our request */
- if (send(spamd_sock, spamd_buffer, Ustrlen(spamd_buffer), 0) < 0) {
- close(spamd_sock);
- log_write(0, LOG_MAIN|LOG_PANIC,
- "spam acl condition: spamd send failed: %s", strerror(errno));
- fclose(mbox_file);
- close(spamd_sock);
- return DEFER;
- };
-
- /* now send the file */
- do {
- j = fread(spamd_buffer,1,sizeof(spamd_buffer),mbox_file);
- if (j > 0) {
- i = send(spamd_sock,spamd_buffer,j,0);
- if (i != j) {
- log_write(0, LOG_MAIN|LOG_PANIC,
- "spam acl condition: error/short send to spamd");
- close(spamd_sock);
- fclose(mbox_file);
- return DEFER;
- };
- };
+if (Ustrncmp(param, "tmo=", 4) == 0)
+ {
+ int sec = readconf_readtime((s = param+4), '\0', FALSE);
+ name = US"timeout";
+ if (sec < 0)
+ goto badval;
+ spamd->timeout = sec;
+ return 0;
+ }
+
+if (Ustrncmp(param, "retry=", 6) == 0)
+ {
+ int sec = readconf_readtime((s = param+6), '\0', FALSE);
+ name = US"retry";
+ if (sec < 0)
+ goto badval;
+ spamd->retry = sec;
+ return 0;
+ }
+
+log_write(0, LOG_MAIN, "%s warning - invalid spamd parameter: '%s'",
+ loglabel, param);
+return -1; /* syntax error */
+
+badval:
+ log_write(0, LOG_MAIN,
+ "%s warning - invalid spamd %s value: '%s'", loglabel, name, s);
+ return -1; /* syntax error */
+}
+
+
+static int
+spamd_get_server(spamd_address_container ** spamds, int num_servers)
+{
+unsigned int i;
+spamd_address_container * sd;
+long weights;
+unsigned pri;
+
+/* speedup, if we have only 1 server */
+if (num_servers == 1)
+ return (spamds[0]->is_failed ? -1 : 0);
+
+/* scan for highest pri */
+for (pri = 0, i = 0; i < num_servers; i++)
+ {
+ sd = spamds[i];
+ if (!sd->is_failed && sd->priority > pri) pri = sd->priority;
+ }
+
+/* get sum of weights */
+for (weights = 0, i = 0; i < num_servers; i++)
+ {
+ sd = spamds[i];
+ if (!sd->is_failed && sd->priority == pri) weights += sd->weight;
+ }
+if (weights == 0) /* all servers failed */
+ return -1;
+
+for (long rnd = random_number(weights), i = 0; i < num_servers; i++)
+ {
+ sd = spamds[i];
+ if (!sd->is_failed && sd->priority == pri)
+ if ((rnd -= sd->weight) < 0)
+ return i;
+ }
+
+log_write(0, LOG_MAIN|LOG_PANIC,
+ "%s unknown error (memory/cpu corruption?)", loglabel);
+return -1;
+}
+
+
+int
+spam(const uschar **listptr)
+{
+int sep = 0;
+const uschar *list = *listptr;
+uschar *user_name;
+unsigned long mbox_size;
+FILE *mbox_file;
+client_conn_ctx spamd_cctx = {.sock = -1};
+uschar spamd_buffer[32600];
+int i, j, offset, result;
+uschar spamd_version[8];
+uschar spamd_short_result[8];
+uschar spamd_score_char;
+double spamd_threshold, spamd_score, spamd_reject_score;
+int spamd_report_offset;
+uschar *p,*q;
+int override = 0;
+time_t start;
+size_t read, wrote;
+uschar *spamd_address_work;
+spamd_address_container * sd;
+
+/* stop compiler warning */
+result = 0;
+
+/* find the username from the option list */
+if (!(user_name = string_nextinlist(&list, &sep, NULL, 0)))
+ {
+ /* no username given, this means no scanning should be done */
+ return FAIL;