X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Ftransport.c;h=b8a4636b60818fe2cc4220d5ff8de4ebb7ab2cec;hb=cf0812d57c63b531e2e73187508c7ae99156043c;hp=88d925e39904fd2c98a71345e397f0648ae24fde;hpb=2d14f39731e88a6d6bb9f1b5c56f497eb12198c4;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/transport.c b/src/src/transport.c index 88d925e39..b8a4636b6 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -108,10 +108,23 @@ optionlist optionlist_transports[] = { (void *)offsetof(transport_instance, uid) } }; -int optionlist_transports_size = - sizeof(optionlist_transports)/sizeof(optionlist); +int optionlist_transports_size = nelem(optionlist_transports); +void +readconf_options_transports(void) +{ +struct transport_info * ti; + +readconf_options_from_list(optionlist_transports, nelem(optionlist_transports), US"TRANSPORTS", NULL); + +for (ti = transports_available; ti->driver_name[0]; ti++) + { + macro_create(string_sprintf("_DRIVER_TRANSPORT_%T", ti->driver_name), US"y", FALSE, TRUE); + readconf_options_from_list(ti->options, (unsigned)*ti->options_count, US"TRANSPORT", ti->driver_name); + } +} + /************************************************* * Initialize transport list * *************************************************/ @@ -139,14 +152,11 @@ readconf_driver_init(US"transport", /* Now scan the configured transports and check inconsistencies. A shadow transport is permitted only for local transports. */ -for (t = transports; t != NULL; t = t->next) +for (t = transports; t; t = t->next) { - if (!t->info->local) - { - if (t->shadow != NULL) - log_write(0, LOG_PANIC_DIE|LOG_CONFIG, - "shadow transport not allowed on non-local transport %s", t->name); - } + if (!t->info->local && t->shadow) + log_write(0, LOG_PANIC_DIE|LOG_CONFIG, + "shadow transport not allowed on non-local transport %s", t->name); if (t->body_only && t->headers_only) log_write(0, LOG_PANIC_DIE|LOG_CONFIG, @@ -418,15 +428,22 @@ for (ptr = start; ptr < end; ptr++) if ((len = chunk_ptr - deliver_out_buffer) > mlen) { + DEBUG(D_transport) debug_printf("flushing headers buffer\n"); + /* If CHUNKING, prefix with BDAT (size) NON-LAST. Also, reap responses from previous SMTP commands. */ if (tctx && tctx->options & topt_use_bdat && tctx->chunk_cb) - if (tctx->chunk_cb(fd, tctx, (unsigned)len, tc_reap_prev|tc_reap_one) != OK) + { + if ( tctx->chunk_cb(fd, tctx, (unsigned)len, 0) != OK + || !transport_write_block(fd, deliver_out_buffer, len) + || tctx->chunk_cb(fd, tctx, 0, tc_reap_prev) != OK + ) + return FALSE; + } + else + if (!transport_write_block(fd, deliver_out_buffer, len)) return FALSE; - - if (!transport_write_block(fd, deliver_out_buffer, len)) - return FALSE; chunk_ptr = deliver_out_buffer; } @@ -607,7 +624,7 @@ return write_chunk(fd, tctx, pp->address, Ustrlen(pp->address)); -/* Add/remove/rewwrite headers, and send them plus the empty-line sparator. +/* Add/remove/rewrite headers, and send them plus the empty-line separator. Globals: header_list @@ -616,13 +633,8 @@ Arguments: addr (chain of) addresses (for extra headers), or NULL; only the first address is used fd file descriptor to write the message to + tctx transport context sendfn function for output (transport or verify) - wck_flags - use_crlf turn NL into CR LF - use_bdat callback before chunk flush - rewrite_rules chain of header rewriting rules - rewrite_existflags flags for the rewriting rules - chunk_cb transport callback function for data-chunk commands Returns: TRUE on success; FALSE on failure. */ @@ -896,7 +908,7 @@ if (!(tctx->options & topt_no_headers)) /* Pick up from all the addresses. The plist and dlist variables are anchors for lists of addresses already handled; they have to be defined at - this level becuase write_env_to() calls itself recursively. */ + this level because write_env_to() calls itself recursively. */ for (p = tctx->addr; p; p = p->next) if (!write_env_to(p, &plist, &dlist, &first, fd, tctx)) @@ -927,11 +939,11 @@ if (!(tctx->options & topt_no_headers)) return FALSE; } -/* When doing RFC3030 CHUNKING output, work out how much data will be in the -last BDAT, consisting of the current write_chunk() output buffer fill +/* When doing RFC3030 CHUNKING output, work out how much data would be in a +last-BDAT, consisting of the current write_chunk() output buffer fill (optimally, all of the headers - but it does not matter if we already had to flush that buffer with non-last BDAT prependix) plus the amount of body data -(as expanded for CRLF lines). Then create and write the BDAT, and ensure +(as expanded for CRLF lines). Then create and write BDAT(s), and ensure that further use of write_chunk() will not prepend BDATs. The first BDAT written will also first flush any outstanding MAIL and RCPT commands which were buffered thans to PIPELINING. @@ -942,7 +954,7 @@ suboptimal. */ if (tctx->options & topt_use_bdat) { off_t fsize; - int hsize, size; + int hsize, size = 0; if ((hsize = chunk_ptr - deliver_out_buffer) < 0) hsize = 0; @@ -965,6 +977,8 @@ if (tctx->options & topt_use_bdat) if (size > DELIVER_OUT_BUFFER_SIZE && hsize > 0) { + DEBUG(D_transport) + debug_printf("sending small initial BDAT; hsize=%d\n", hsize); if ( tctx->chunk_cb(fd, tctx, hsize, 0) != OK || !transport_write_block(fd, deliver_out_buffer, hsize) || tctx->chunk_cb(fd, tctx, 0, tc_reap_prev) != OK @@ -1077,7 +1091,8 @@ if ((dkim_fd = Uopen(dkim_spool_name, O_RDWR|O_CREAT|O_TRUNC, SPOOL_MODE)) < 0) goto CLEANUP; } -/* Call original function to write the -K file; does the CRLF expansion */ +/* Call original function to write the -K file; does the CRLF expansion +(but, in the CHUNKING case, not dot-stuffing and dot-termination). */ options = tctx->options; tctx->options &= ~topt_use_bdat; @@ -1092,14 +1107,9 @@ if (!rc) } /* Rewind file and feed it to the goats^W DKIM lib */ +dkim->dot_stuffed = !!(options & topt_end_dot); lseek(dkim_fd, 0, SEEK_SET); -dkim_signature = dkim_exim_sign(dkim_fd, - dkim->dkim_private_key, - dkim->dkim_domain, - dkim->dkim_selector, - dkim->dkim_canon, - dkim->dkim_sign_headers); -if (dkim_signature) +if ((dkim_signature = dkim_exim_sign(dkim_fd, dkim))) siglen = Ustrlen(dkim_signature); else if (dkim->dkim_strict) { @@ -1175,17 +1185,17 @@ else /* Send file down the original fd */ while((sread = read(dkim_fd, deliver_out_buffer, DELIVER_OUT_BUFFER_SIZE)) >0) { - char *p = deliver_out_buffer; + uschar * p = deliver_out_buffer; /* write the chunk */ while (sread) { #ifdef SUPPORT_TLS wwritten = tls_out.active == out_fd - ? tls_write(FALSE, US p, sread) - : write(out_fd, p, sread); + ? tls_write(FALSE, p, sread) + : write(out_fd, CS p, sread); #else - wwritten = write(out_fd, p, sread); + wwritten = write(out_fd, CS p, sread); #endif if (wwritten == -1) goto err; @@ -1228,6 +1238,7 @@ set up a filtering process, fork another process to call the internal function to write to the filter, and in this process just suck from the filter and write down the given fd. At the end, tidy up the pipes and the processes. +XXX Arguments: as for internal_transport_write_message() above Returns: TRUE on success; FALSE (with errno) for any failure @@ -1237,7 +1248,6 @@ Returns: TRUE on success; FALSE (with errno) for any failure BOOL transport_write_message(int fd, transport_ctx * tctx, int size_limit) { -unsigned wck_flags; BOOL last_filter_was_NL = TRUE; int rc, len, yield, fd_read, fd_write, save_errno; int pfd[2] = {-1, -1}; @@ -1261,7 +1271,6 @@ if ( !transport_filter_argv before being written to the incoming fd. First set up the special processing to be done during the copying. */ -wck_flags = tctx->options & topt_use_crlf; nl_partial_match = -1; if (tctx->check_string && tctx->escape_string) @@ -1285,10 +1294,13 @@ save_errno = 0; yield = FALSE; write_pid = (pid_t)(-1); -(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); -filter_pid = child_open(USS transport_filter_argv, NULL, 077, - &fd_write, &fd_read, FALSE); -(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC); + { + int bits = fcntl(fd, F_GETFD); + (void)fcntl(fd, F_SETFD, bits | FD_CLOEXEC); + filter_pid = child_open(USS transport_filter_argv, NULL, 077, + &fd_write, &fd_read, FALSE); + (void)fcntl(fd, F_SETFD, bits & ~FD_CLOEXEC); + } if (filter_pid < 0) goto TIDY_UP; /* errno set */ DEBUG(D_transport) @@ -1427,14 +1439,19 @@ if (write_pid > 0) { rc = child_close(write_pid, 30); if (yield) - { if (rc == 0) { BOOL ok; - int dummy = read(pfd[pipe_read], (void *)&ok, sizeof(BOOL)); - if (!ok) + if (read(pfd[pipe_read], (void *)&ok, sizeof(BOOL)) != sizeof(BOOL)) + { + DEBUG(D_transport) + debug_printf("pipe read from writing process: %s\n", strerror(errno)); + save_errno = ERRNO_FILTER_FAIL; + yield = FALSE; + } + else if (!ok) { - dummy = read(pfd[pipe_read], (void *)&save_errno, sizeof(int)); + int dummy = read(pfd[pipe_read], (void *)&save_errno, sizeof(int)); dummy = read(pfd[pipe_read], (void *)&(tctx->addr->more_errno), sizeof(int)); yield = FALSE; } @@ -1446,7 +1463,6 @@ if (write_pid > 0) tctx->addr->more_errno = rc; DEBUG(D_transport) debug_printf("writing process returned %d\n", rc); } - } } (void)close(pfd[pipe_read]); @@ -1760,7 +1776,7 @@ while (1) /* create an array to read entire message queue into memory for processing */ - msgq = (msgq_t*) malloc(sizeof(msgq_t) * host_record->count); + msgq = store_malloc(sizeof(msgq_t) * host_record->count); msgq_count = host_record->count; msgq_actual = msgq_count; @@ -1868,7 +1884,7 @@ test but the code should work */ if (bFound) /* Usual exit from main loop */ { - free (msgq); + store_free (msgq); break; } @@ -1894,7 +1910,7 @@ test but the code should work */ return FALSE; } - free(msgq); + store_free(msgq); } /* we need to process a continuation record */ /* Control gets here when an existing message has been encountered; its @@ -2256,7 +2272,7 @@ if (expand_arguments) */ if (address_pipe_argcount > 1) memmove( - /* current position + additonal args */ + /* current position + additional args */ argv + i + address_pipe_argcount, /* current position + 1 (for the (uschar *)0 at the end) */ argv + i + 1,