Mailing List Archive

[patch] LMTP over a unix socket
I developed this with Cyrus admins in mind--Cyrus 2.1 lmtpd listens on a
unix socket (or a TCP socket, but that's a little heavier)--but it may
well be useful for other systems too. My patch will allow a transport like
the following:

lmtpsock:
driver = lmtp
socket = /var/lib/cyrus/socket/lmtp

It alters the lmtp transport to require either a "command" or a "socket".
Philip will look at it when he has time; perhaps any minor deities on the
list can spot any horrible errors to save him some time :)

The patch doesn't apply cleanly to Exim 3: it could be back-ported, but
otoh that might be no less effort than running convert4r4..

diff -ur exim-4.10.pristine/src/transports/lmtp.c exim-4.10.rogered/src/transports/lmtp.c
--- exim-4.10.pristine/src/transports/lmtp.c Mon Jul 22 09:59:51 2002
+++ exim-4.10.rogered/src/transports/lmtp.c Fri Jul 26 11:26:48 2002
@@ -8,6 +8,7 @@

#include "../exim.h"
#include "lmtp.h"
+#include <sys/un.h>

#define PENDING_OK 256

@@ -26,6 +27,8 @@
(void *)offsetof(transport_instance, batch_max) },
{ "command", opt_stringptr,
(void *)offsetof(lmtp_transport_options_block, cmd) },
+ { "socket", opt_stringptr,
+ (void *)offsetof(lmtp_transport_options_block, skt) },
{ "timeout", opt_time,
(void *)offsetof(lmtp_transport_options_block, timeout) }
};
@@ -40,6 +43,7 @@

lmtp_transport_options_block lmtp_transport_option_defaults = {
NULL, /* cmd */
+ NULL, /* skt */
5*60, /* timeout */
0 /* options */
};
@@ -60,11 +64,11 @@
lmtp_transport_options_block *ob =
(lmtp_transport_options_block *)(tblock->options_block);

-/* The command field must be set */
+/* Either the command field or the socket field must be set */

-if (ob->cmd == NULL)
+if ((ob->cmd == NULL) && (ob->skt == NULL))
log_write(0, LOG_PANIC_DIE|LOG_CONFIG,
- "command must be set for the %s transport", tblock->name);
+ "command or socket must be set for the %s transport", tblock->name);

/* If a fixed uid field is set, then a gid field must also be set. */

@@ -451,6 +455,8 @@
address_item *addr;
uschar buffer[256];
uschar **argv;
+struct sockaddr_un sun;
+int addrlen;

DEBUG(D_transport) debug_printf("%s transport entered\n", tblock->name);

@@ -459,9 +465,35 @@
fails, copy the error information into the second and subsequent addresses. */

sprintf(CS buffer, "%.50s transport", tblock->name);
-if (!transport_set_up_command(&argv, ob->cmd, TRUE, PANIC, addrlist, buffer,
- NULL))
- return FALSE;
+if (ob->cmd != NULL)
+ {
+ DEBUG(D_transport) debug_printf("using command %s\n", ob->cmd);
+ if (!transport_set_up_command(&argv, ob->cmd, TRUE, PANIC, addrlist,
+ buffer, NULL))
+ return FALSE;
+ }
+else
+ {
+ DEBUG(D_transport) debug_printf("using socket %s\n", ob->skt);
+
+ if ((fd_in = fd_out = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
+ {
+ addrlist->message = string_sprintf(
+ "Failed to set up socket %s for %s transport: %s",
+ sun.sun_path, tblock->name, strerror(errno));
+ return FALSE;
+ }
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, ob->skt, 108);
+ addrlen = sizeof(sun);
+ if(connect(fd_out, (struct sockaddr *) &sun, addrlen) == -1)
+ {
+ addrlist->message = string_sprintf(
+ "Failed to connect to socket %s for %s transport: %s",
+ sun.sun_path, tblock->name, strerror(errno));
+ return FALSE;
+ }
+ }

/* If the -N option is set, can't do any more. Presume all has gone well. */

@@ -479,8 +511,8 @@
change. Request that the new process be a process group leader, so we
can kill it and all its children on an error. */

-if ((pid = child_open(argv, NULL, 0, NULL, NULL, &fd_in, &fd_out,
- NULL, TRUE)) < 0)
+if ((ob->cmd != NULL) && ((pid = child_open(argv, NULL, 0, NULL, NULL,
+ &fd_in, &fd_out, NULL, TRUE)) < 0))
{
addrlist->message = string_sprintf(
"Failed to create child process for %s transport: %s", tblock->name,
diff -ur exim-4.10.pristine/src/transports/lmtp.h exim-4.10.rogered/src/transports/lmtp.h
--- exim-4.10.pristine/src/transports/lmtp.h Mon Jul 22 09:59:51 2002
+++ exim-4.10.rogered/src/transports/lmtp.h Fri Jul 26 10:32:28 2002
@@ -9,6 +9,7 @@

typedef struct {
uschar *cmd;
+ uschar *skt;
int timeout;
int options;
} lmtp_transport_options_block;