X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/6023a6ad2ac0294879b14127f62795095da573b5..e498ab40197936833f696439e78c5cb08e5180cb:/src/src/transport.c diff --git a/src/src/transport.c b/src/src/transport.c index 78d9d517f..e1e6dcebf 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2014 */ +/* Copyright (c) University of Cambridge 1995 - 2016 */ /* See the file NOTICE for conditions of use and distribution. */ /* General functions concerned with transportation, and generic options for all @@ -66,7 +66,7 @@ optionlist optionlist_transports[] = { (void *)offsetof(transport_instance, driver_name) }, { "envelope_to_add", opt_bool|opt_public, (void *)(offsetof(transport_instance, envelope_to_add)) }, -#ifdef EXPERIMENTAL_EVENT +#ifndef DISABLE_EVENT { "event_action", opt_stringptr | opt_public, (void *)offsetof(transport_instance, event_action) }, #endif @@ -84,6 +84,8 @@ optionlist optionlist_transports[] = { (void *)offsetof(transport_instance, home_dir) }, { "initgroups", opt_bool|opt_public, (void *)offsetof(transport_instance, initgroups) }, + { "max_parallel", opt_stringptr|opt_public, + (void *)offsetof(transport_instance, max_parallel) }, { "message_size_limit", opt_stringptr|opt_public, (void *)offsetof(transport_instance, message_size_limit) }, { "rcpt_include_affixes", opt_bool|opt_public, @@ -653,7 +655,7 @@ for (h = header_list; h != NULL; h = h->next) if (h->type != htype_old) errno = ERRNO_CHHEADER_FAIL; return FALSE; } - len = Ustrlen(s); + len = s ? Ustrlen(s) : 0; if (strncmpic(h->text, s, len) != 0) continue; ss = h->text + len; while (*ss == ' ' || *ss == '\t') ss++; @@ -931,7 +933,8 @@ if ((options & topt_no_body) == 0) { nl_check_length = abs(nl_check_length); nl_partial_match = 0; - lseek(deliver_datafile, SPOOL_DATA_START_OFFSET, SEEK_SET); + if (lseek(deliver_datafile, SPOOL_DATA_START_OFFSET, SEEK_SET) < 0) + return FALSE; while ((len = read(deliver_datafile, deliver_in_buffer, DELIVER_IN_BUFFER_SIZE)) > 0) { @@ -1010,7 +1013,7 @@ dkim_transport_write_message(address_item *addr, int fd, int options, int dkim_fd; int save_errno = 0; BOOL rc; -uschar dkim_spool_name[256]; +uschar * dkim_spool_name; char sbuf[2048]; int sread = 0; int wwritten = 0; @@ -1024,8 +1027,8 @@ if (!(dkim_private_key && dkim_domain && dkim_selector)) check_string, escape_string, rewrite_rules, rewrite_existflags); -(void)string_format(dkim_spool_name, 256, "%s/input/%s/%s-%d-K", - spool_directory, message_subdir, message_id, (int)getpid()); +dkim_spool_name = spool_fname(US"input", message_subdir, message_id, + string_sprintf("-%d-K", (int)getpid())); if ((dkim_fd = Uopen(dkim_spool_name, O_RDWR|O_CREAT|O_TRUNC, SPOOL_MODE)) < 0) { @@ -1066,7 +1069,7 @@ if (dkim_private_key && dkim_domain && dkim_selector) uschar *dkim_strict_result = expand_string(dkim_strict); if (dkim_strict_result) if ( (strcmpic(dkim_strict,US"1") == 0) || - (strcmpic(dkim_strict,US"true") == 0) ) + (strcmpic(dkim_strict,US"true") == 0) ) { /* Set errno to something halfway meaningful */ save_errno = EACCES; @@ -1203,7 +1206,7 @@ transport_write_message(address_item *addr, int fd, int options, BOOL use_crlf; BOOL last_filter_was_NL = TRUE; int rc, len, yield, fd_read, fd_write, save_errno; -int pfd[2]; +int pfd[2] = {-1, -1}; pid_t filter_pid, write_pid; transport_filter_timed_out = FALSE; @@ -1211,7 +1214,10 @@ transport_filter_timed_out = FALSE; /* If there is no filter command set up, call the internal function that does the actual work, passing it the incoming fd, and return its result. */ -if (transport_filter_argv == NULL) +if ( !transport_filter_argv + || !*transport_filter_argv + || !**transport_filter_argv + ) return internal_transport_write_message(addr, fd, options, size_limit, add_headers, remove_headers, check_string, escape_string, rewrite_rules, rewrite_existflags); @@ -1643,20 +1649,13 @@ transport_check_waiting(const uschar *transport_name, const uschar *hostname, int local_message_max, uschar *new_message_id, BOOL *more, oicf oicf_func, void *oicf_data) { dbdata_wait *host_record; -int host_length, path_len; +int host_length; open_db dbblock; open_db *dbm_file; uschar buffer[256]; -msgq_t *msgq = NULL; -int msgq_count = 0; -int msgq_actual = 0; int i; -BOOL bFound = FALSE; -uschar spool_dir [PATH_MAX]; -uschar spool_file [PATH_MAX]; struct stat statbuf; -BOOL bContinuation = FALSE; *more = FALSE; @@ -1686,8 +1685,7 @@ if (dbm_file == NULL) return FALSE; /* See if there is a record for this host; if not, there's nothing to do. */ -host_record = dbfn_read(dbm_file, hostname); -if (host_record == NULL) +if (!(host_record = dbfn_read(dbm_file, hostname))) { dbfn_close(dbm_file); DEBUG(D_transport) debug_printf("no messages waiting for %s\n", hostname); @@ -1714,12 +1712,16 @@ emptied, delete it and continue with any continuation records that may exist. but the 1 off will remain without it. This code now allows me to SKIP over a message I do not want to send out on this run. */ -sprintf(CS spool_dir, "%s/input/", spool_directory); - host_length = host_record->count * MESSAGE_ID_LENGTH; while (1) { + msgq_t *msgq; + int msgq_count = 0; + int msgq_actual = 0; + BOOL bFound = FALSE; + BOOL bContinuation = FALSE; + /* create an array to read entire message queue into memory for processing */ msgq = (msgq_t*) malloc(sizeof(msgq_t) * host_record->count); @@ -1746,17 +1748,15 @@ while (1) /* now find the next acceptable message_id */ - bFound = FALSE; - for (i = msgq_count - 1; i >= 0; --i) if (msgq[i].bKeep) { - if (split_spool_directory) - sprintf(CS spool_file, "%s%c/%s-D", - spool_dir, new_message_id[5], msgq[i].message_id); - else - sprintf(CS spool_file, "%s%s-D", spool_dir, msgq[i].message_id); + uschar subdir[2]; + + subdir[0] = split_spool_directory ? msgq[i].message_id[5] : 0; + subdir[1] = 0; - if (Ustat(spool_file, &statbuf) != 0) + if (Ustat(spool_fname(US"input", subdir, msgq[i].message_id, US"-D"), + &statbuf) != 0) msgq[i].bKeep = FALSE; else if (!oicf_func || oicf_func(msgq[i].message_id, oicf_data)) { @@ -1773,8 +1773,7 @@ while (1) msgq_actual++; /* reassemble the host record, based on removed message ids, from in - * memory queue. - */ + memory queue */ if (msgq_actual <= 0) { @@ -1801,8 +1800,6 @@ while (1) /* Jeremy: check for a continuation record, this code I do not know how to test but the code should work */ - bContinuation = FALSE; - while (host_length <= 0) { int i; @@ -1833,8 +1830,11 @@ test but the code should work */ bContinuation = TRUE; } - if (bFound) + if (bFound) /* Usual exit from main loop */ + { + free (msgq); break; + } /* If host_length <= 0 we have emptied a record and not found a good message, and there are no continuation records. Otherwise there is a continuation @@ -1853,20 +1853,13 @@ test but the code should work */ if (!bContinuation) { - Ustrcpy (new_message_id, message_id); + Ustrcpy(new_message_id, message_id); dbfn_close(dbm_file); return FALSE; } - } /* we need to process a continuation record */ -/* clean up in memory queue */ -if (msgq) - { - free (msgq); - msgq = NULL; - msgq_count = 0; - msgq_actual = 0; - } + free(msgq); + } /* we need to process a continuation record */ /* Control gets here when an existing message has been encountered; its id is in new_message_id, and host_length is the revised length of the @@ -1875,19 +1868,8 @@ record if required, close the database, and return TRUE. */ if (host_length > 0) { - uschar msg [MESSAGE_ID_LENGTH + 1]; - int i; - host_record->count = host_length/MESSAGE_ID_LENGTH; - /* rebuild the host_record->text */ - - for (i = 0; i < host_record->count; ++i) - { - Ustrncpy(msg, host_record->text + (i*MESSAGE_ID_LENGTH), MESSAGE_ID_LENGTH); - msg[MESSAGE_ID_LENGTH] = 0; - } - dbfn_write(dbm_file, hostname, host_record, (int)sizeof(dbdata_wait) + host_length); *more = TRUE; } @@ -1941,7 +1923,6 @@ if ((pid = fork()) == 0) argv = CUSS child_exec_exim(CEE_RETURN_ARGV, TRUE, &i, FALSE, 0); - /* Call with the dsn flag */ if (smtp_use_dsn) argv[i++] = US"-MCD"; if (smtp_authenticated) argv[i++] = US"-MCA";