aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>1996-10-25 19:57:22 +0000
committerEric S. Raymond <esr@thyrsus.com>1996-10-25 19:57:22 +0000
commit15ad60aad2f4671e2381b065dc0121d20d0ee3e8 (patch)
tree74f41195e395e80c7799416fa9fbfd9916605129
parentf7bd2799faf6fa398a43be8715d9c0df314b6393 (diff)
downloadfetchmail-15ad60aad2f4671e2381b065dc0121d20d0ee3e8.tar.gz
fetchmail-15ad60aad2f4671e2381b065dc0121d20d0ee3e8.tar.bz2
fetchmail-15ad60aad2f4671e2381b065dc0121d20d0ee3e8.zip
MDAs should be able to handle multidrop mailboxes now too.
svn path=/trunk/; revision=382
-rw-r--r--driver.c154
-rw-r--r--fetchmail.c14
-rw-r--r--fetchmail.h6
3 files changed, 101 insertions, 73 deletions
diff --git a/driver.c b/driver.c
index d008443d..58c37a6a 100644
--- a/driver.c
+++ b/driver.c
@@ -417,8 +417,7 @@ struct hostrec *queryctl; /* query control record */
char fromBuf[MSGBUFSIZE+1];
char *bufp, *headers, *unixfrom, *fromhdr, *tohdr, *cchdr, *bcchdr;
int n, oldlen;
- int inheaders;
- int lines,sizeticker;
+ int inheaders,lines,sizeticker;
/* This keeps the retrieved message count for display purposes */
static int msgnum = 0;
@@ -506,53 +505,89 @@ struct hostrec *queryctl; /* query control record */
goto skipwrite;
}
- else if (headers)
+ else if (headers) /* OK, we're at end of headers now */
{
char *cp;
+ struct idlist *idp, *xmit_names;
- if (!queryctl->mda[0])
+ /* cons up a list of local recipients */
+ xmit_names = (struct idlist *)NULL;
+#ifdef HAVE_GETHOSTBYNAME
+ /* is this a multidrop box? */
+ if (queryctl->localnames != (struct idlist *)NULL
+ && queryctl->localnames->next != (struct idlist *)NULL)
+ {
+ /* compute the local address list */
+ find_server_names(tohdr, queryctl, &xmit_names);
+ find_server_names(cchdr, queryctl, &xmit_names);
+ find_server_names(bcchdr, queryctl, &xmit_names);
+
+ /* if nothing supplied localnames, default appropriately */
+ if (!xmit_names)
+ save_uid(&xmit_names, -1, dfltuser);
+ }
+ else /* it's a single-drop box, use first localname */
+#endif /* HAVE_GETHOSTBYNAME */
+ {
+ if (queryctl->localnames)
+ save_uid(&xmit_names, -1, queryctl->localnames->id);
+ else
+ save_uid(&xmit_names, -1, dfltuser);
+ }
+
+ /* time to address the message */
+ if (queryctl->mda[0]) /* we have a declared MDA */
+ {
+ int i, nlocals = 0;
+ char **sargv, **sp;
+
+ /*
+ * We go through this in order to be able to handle very
+ * long lists of users.
+ */
+ for (idp = xmit_names; idp; idp = idp->next)
+ nlocals++;
+ sp = sargv = (char **)alloca(queryctl->mda_argcount + nlocals);
+ for (i = 0; i < queryctl->mda_argcount; i++)
+ *sp++ = queryctl->mda_argv[i];
+ for (idp = xmit_names; idp; idp = idp->next)
+ *sp++ = idp->id;
+ *sp = (char *)NULL;
+
+#ifdef HAVE_SETEUID
+ /*
+ * Arrange to run with user's permissions if we're root.
+ * This will initialize the ownership of any files the
+ * MDA creates properly. (The seteuid call is available
+ * under all BSDs and Linux)
+ */
+ seteuid(queryctl->uid);
+#endif /* HAVE_SETEUID */
+
+ mboxfd = openmailpipe(sargv);
+
+#ifdef HAVE_SETEUID
+ /* this will fail quietly if we didn't start as root */
+ seteuid(0);
+#endif /* HAVE_SETEUID */
+
+ if (mboxfd < 0)
+ return(PS_IOERR);
+ }
+ else
{
if (SMTP_from(mboxfd, nxtaddr(fromhdr)) != SM_OK)
return(PS_SMTP);
-#ifdef HAVE_GETHOSTBYNAME
- /* is this a multidrop box? */
- if (queryctl->localnames != (struct idlist *)NULL
- && queryctl->localnames->next != (struct idlist *)NULL)
- {
- struct idlist *idp, *xmit_names;
-
- /* compute the local address list */
- xmit_names = (struct idlist *)NULL;
- find_server_names(tohdr, queryctl, &xmit_names);
- find_server_names(cchdr, queryctl, &xmit_names);
- find_server_names(bcchdr, queryctl, &xmit_names);
-
- /* if nothing supplied localnames, default appropriately */
- if (!xmit_names)
- save_uid(&xmit_names, -1, dfltuser);
-
- for (idp = xmit_names; idp; idp = idp->next)
- if (SMTP_rcpt(mboxfd, idp->id) != SM_OK)
- return(PS_SMTP);
- free_uid_list(&xmit_names);
- }
- else /* it's a single-drop box, use first localname */
-#endif /* HAVE_GETHOSTBYNAME */
- {
- if (queryctl->localnames)
- cp = queryctl->localnames->id;
- else
- cp = dfltuser;
-
- if (SMTP_rcpt(mboxfd, cp) != SM_OK)
+ for (idp = xmit_names; idp; idp = idp->next)
+ if (SMTP_rcpt(mboxfd, idp->id) != SM_OK)
return(PS_SMTP);
- }
SMTP_data(mboxfd);
if (outlevel == O_VERBOSE)
fputs("SMTP> ", stderr);
}
+ free_uid_list(&xmit_names);
/* change continuation markers back to regular newlines */
for (cp = headers; cp < headers + oldlen; cp++)
@@ -614,10 +649,20 @@ struct hostrec *queryctl; /* query control record */
if (alarmed)
return (0);
- /* write message terminator */
- if (!queryctl->mda[0])
+
+ if (queryctl->mda[0])
+ {
+ /* close the delivery pipe, we'll reopen before next message */
+ if (closemailpipe(mboxfd))
+ return(PS_IOERR);
+ }
+ else
+ {
+ /* write message terminator */
if (SMTP_eom(mboxfd) != SM_OK)
return(PS_SMTP);
+ }
+
return(0);
}
@@ -821,27 +866,13 @@ struct method *proto; /* protocol method table */
fputc(' ', stderr);
}
- /* open the delivery pipe now if we're using an MDA */
- if (queryctl->mda[0])
- {
-#ifdef HAVE_SETEUID
- /*
- * Arrange to run with user's permissions if we're root.
- * This will initialize the ownership of any files the
- * MDA creates properly. (The seteuid call is available
- * under all BSDs and Linux)
- */
- seteuid(queryctl->uid);
-#endif /* HAVE_SETEUID */
- mboxfd = openmailpipe(queryctl);
-#ifdef HAVE_SETEUID
- /* this will fail quietly if we didn't start as root */
- seteuid(0);
-#endif /* HAVE_SETEUID */
-
- if (mboxfd < 0)
- goto cleanUp;
- }
+ /*
+ * If we're forwarding via SMTP, mboxfd is initialized
+ * at this point (it was set at start of retrieval).
+ * If we're using an MDA it's not set -- gen_readmsg()
+ * may have to parse message headers to know what
+ * delivery addresses should be passed to the MDA
+ */
/* read the message and ship it to the output sink */
ok = gen_readmsg(socket, mboxfd,
@@ -849,11 +880,6 @@ struct method *proto; /* protocol method table */
protocol->delimited,
queryctl);
- /* close the delivery pipe, we'll reopen before next message */
- if (queryctl->mda[0])
- if ((ok = closemailpipe(mboxfd)) != 0 || alarmed)
- goto cleanUp;
-
/* tell the server we got it OK and resynchronize */
if (protocol->trail)
(protocol->trail)(socket, queryctl, num);
diff --git a/fetchmail.c b/fetchmail.c
index bbef5002..c585bd03 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -228,20 +228,20 @@ char **argv;
/* expand MDA commands */
if (!check_only && hostp->mda[0])
{
- int argi;
char *argp;
/* punch nulls into the delimiting whitespace in the args */
- for (argp = hostp->mdabuf, argi = 1; *argp != '\0'; argi++)
+ hostp->mda_argcount = 0;
+ for (argp = hostp->mdabuf, hostp->mda_argcount = 1; *argp != '\0'; hostp->mda_argcount++)
{
- hostp->mda_argv[argi] = argp;
+ hostp->mda_argv[hostp->mda_argcount] = argp;
while (!(*argp == '\0' || isspace(*argp)))
argp++;
if (*argp != '\0')
*(argp++) = '\0';
}
- hostp->mda_argv[argi] = (char *)NULL;
+ hostp->mda_argv[hostp->mda_argcount] = (char *)NULL;
hostp->mda_argv[0] = hostp->mda_argv[1];
if ((argp = strrchr(hostp->mda_argv[1], '/')) != (char *)NULL)
@@ -658,9 +658,9 @@ struct hostrec *queryctl; /* query parameter block */
}
}
-int openmailpipe (queryctl)
+int openmailpipe (argv)
/* open a one-way pipe to a mail delivery agent */
-struct hostrec *queryctl; /* query control block */
+char *argv[];
{
int pipefd [2];
int childpid;
@@ -683,7 +683,7 @@ struct hostrec *queryctl; /* query control block */
exit(1);
}
- execv(queryctl->mda_argv[0], queryctl->mda_argv + 1);
+ execv(argv[0], argv + 1);
/* if we got here, an error occurred */
perror("fetchmail: openmailpipe: exec");
diff --git a/fetchmail.h b/fetchmail.h
index baaa6f88..3bfd5811 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -53,6 +53,7 @@
#define O_VERBOSE 2 /* excessive */
#define SIZETICKER 1024 /* print 1 dot per this many bytes */
+#define MDA_MAXARGS 32 /* max arguments per MDA call */
struct idlist
{
@@ -81,7 +82,8 @@ struct hostrec
int timeout;
/* MDA arguments */
- char *mda_argv[32];
+ int mda_argcount;
+ char *mda_argv[MDA_MAXARGS];
char mdabuf[MDALEN+1];
/* control flags */
@@ -179,7 +181,7 @@ struct hostrec *hostalloc(struct hostrec *);
int parsecmdline (int, char **, struct hostrec *);
void optmerge(struct hostrec *, struct hostrec *);
char *MD5Digest (char *);
-int openmailpipe (struct hostrec *);
+int openmailpipe (char **);
int daemonize(const char *, void (*)(int));
void escapes(const char *, char *);