(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 *
*************************************************/
/* 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,
-/* 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
/* 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))
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;
if (size > DELIVER_OUT_BUFFER_SIZE && hsize > 0)
{
DEBUG(D_transport)
- debug_printf("sending small initial BDAT; hssize=%d\n", hsize);
+ 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
BOOL
dkim_transport_write_message(int out_fd, transport_ctx * tctx,
- struct ob_dkim * dkim)
+ struct ob_dkim * dkim, const uschar ** err)
{
int dkim_fd;
int save_errno = 0;
BOOL rc;
uschar * dkim_spool_name;
-int sread = 0;
-int wwritten = 0;
-uschar *dkim_signature = NULL;
-int siglen = 0;
+uschar * dkim_signature = NULL;
+int sread = 0, wwritten = 0, siglen = 0, options;
off_t k_file_size;
-int options;
+const uschar * errstr;
/* If we can't sign, just call the original function. */
/* Can't create spool file. Ugh. */
rc = FALSE;
save_errno = errno;
+ *err = string_sprintf("dkim spoolfile create: %s", strerror(errno));
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;
}
/* 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, &errstr)))
siglen = Ustrlen(dkim_signature);
else if (dkim->dkim_strict)
{
save_errno = EACCES;
log_write(0, LOG_MAIN, "DKIM: message could not be signed,"
" and dkim_strict is set. Deferring message delivery.");
+ *err = errstr;
rc = FALSE;
goto CLEANUP;
}
/* 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;
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};
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)
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)
{
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;
}
tctx->addr->more_errno = rc;
DEBUG(D_transport) debug_printf("writing process returned %d\n", rc);
}
- }
}
(void)close(pfd[pipe_read]);
/* 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;
if (bFound) /* Usual exit from main loop */
{
- free (msgq);
+ store_free (msgq);
break;
}
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
*/
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,