+int
+spam(const uschar **listptr)
+{
+int sep = 0;
+const uschar *list = *listptr;
+uschar *user_name;
+uschar user_name_buffer[128];
+unsigned long mbox_size;
+FILE *mbox_file;
+int spamd_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;
+struct sockaddr_un server;
+#ifndef NO_POLL_H
+struct pollfd pollfd;
+#else /* Patch posted by Erik ? for OS X */
+struct timeval select_tv; /* and applied by PH */
+fd_set select_fd;
+#endif
+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,
+ user_name_buffer,
+ sizeof(user_name_buffer))) == NULL)
+ {
+ /* no username given, this means no scanning should be done */
+ return FAIL;
+ }
+
+/* if username is "0" or "false", do not scan */
+if ( (Ustrcmp(user_name,"0") == 0) ||
+ (strcmpic(user_name,US"false") == 0) )
+ return FAIL;
+
+/* if there is an additional option, check if it is "true" */
+if (strcmpic(list,US"true") == 0)
+ /* in that case, always return true later */
+ override = 1;
+
+/* expand spamd_address if needed */
+if (*spamd_address == '$')
+ {
+ spamd_address_work = expand_string(spamd_address);
+ if (spamd_address_work == NULL)
+ {
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "%s spamd_address starts with $, but expansion failed: %s",
+ loglabel, expand_string_message);
+ return DEFER;
+ }
+ }
+else
+ spamd_address_work = spamd_address;
+
+HDEBUG(D_acl) debug_printf("spamd: addrlist '%s'\n", spamd_address_work);
+
+/* check if previous spamd_address was expanded and has changed. dump cached results if so */
+if ( spam_ok
+ && prev_spamd_address_work != NULL
+ && Ustrcmp(prev_spamd_address_work, spamd_address_work) != 0
+ )
+ spam_ok = 0;
+
+/* if we scanned for this username last time, just return */
+if (spam_ok && Ustrcmp(prev_user_name, user_name) == 0)
+ return override ? OK : spam_rc;
+
+/* make sure the eml mbox file is spooled up */
+mbox_file = spool_mbox(&mbox_size, NULL);
+
+if (mbox_file == NULL)
+ {
+ /* error while spooling */
+ log_write(0, LOG_MAIN|LOG_PANIC,
+ "%s error while creating mbox spool file", loglabel);
+ return DEFER;
+ }
+
+start = time(NULL);
+
+ {
+ int num_servers = 0;
+ int current_server;
+ uschar *address;
+ const uschar *spamd_address_list_ptr = spamd_address_work;
+ spamd_address_container * spamd_address_vector[32];
+
+ /* Check how many spamd servers we have
+ and register their addresses */
+ while ((address = string_nextinlist(&spamd_address_list_ptr, &sep,
+ NULL, 0)) != NULL)
+ {
+ const uschar * sublist;
+ int sublist_sep = -(int)' '; /* default space-sep */
+ unsigned args;
+ uschar * s;
+
+ HDEBUG(D_acl) debug_printf("spamd: addr entry '%s'\n", address);
+ sd = (spamd_address_container *)store_get(sizeof(spamd_address_container));
+
+ for (sublist = address, args = 0, spamd_param_init(sd);
+ s = string_nextinlist(&sublist, &sublist_sep, NULL, 0);
+ args++
+ )
+ {
+ HDEBUG(D_acl) debug_printf("spamd: addr parm '%s'\n", s);
+ switch (args)