aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>1997-05-15 20:12:53 +0000
committerEric S. Raymond <esr@thyrsus.com>1997-05-15 20:12:53 +0000
commitdea547a71036ae3445a5a612f6afd00b76ed721a (patch)
tree21526ebcd03d92a894cdb61b36d33ae56b8c5684
parent3dd9a93bd23e0ad36e52ffd79efe2dcbdaf85272 (diff)
downloadfetchmail-dea547a71036ae3445a5a612f6afd00b76ed721a.tar.gz
fetchmail-dea547a71036ae3445a5a612f6afd00b76ed721a.tar.bz2
fetchmail-dea547a71036ae3445a5a612f6afd00b76ed721a.zip
Add multiple-folder support.
svn path=/trunk/; revision=1012
-rw-r--r--NEWS4
-rw-r--r--driver.c323
-rw-r--r--etrn.c2
-rw-r--r--fetchmail.c15
-rw-r--r--fetchmail.h2
-rw-r--r--fetchmail.man26
-rw-r--r--imap.c9
-rw-r--r--options.c23
-rw-r--r--pop2.c26
-rw-r--r--pop3.c7
-rw-r--r--rcfile_l.l11
-rw-r--r--rcfile_y.y11
-rw-r--r--sample.rcfile4
-rw-r--r--uid.c4
14 files changed, 264 insertions, 203 deletions
diff --git a/NEWS b/NEWS
index 4685c5a3..98cd44db 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,8 @@ every user entry in a multi-user poll declaration.
re-code this so --limit is still operative with --fetchall on, but you
can turn off the size limit with --limit 0.
+* Use the libmd functions for md5 under Free BSD? (Low priority.)
+
Release Notes:
------------------------------------------------------------------------------
@@ -26,6 +28,8 @@ pl 3.9.5 ():
* Add an error notification when an incoming message has embedded NULs.
* Throw out >From lines in headers to prevent getting hosed by upstream
sendmails with the 'E' option on.
+* Enable forcecr to work on the \r\n header terminator line.
+* Multiple-folder support for POP2 and IMAP.
pl 3.9.4 (Wed May 14 12:27:22 EDT 1997):
* Fixed a compilation glitch for systems like SunOS & others without atexit(3).
diff --git a/driver.c b/driver.c
index 0cdbeceb..66a70024 100644
--- a/driver.c
+++ b/driver.c
@@ -1248,8 +1248,9 @@ const struct method *proto; /* protocol method table */
{
char buf [POPBUFSIZE+1];
int *msgsizes, len, num, count, new, deletions = 0;
- int sock, port;
-
+ int sock, port, fetches;
+ struct idlist *idp;
+
/* execute pre-initialization command, if any */
if (ctl->preconnect && (ok = system(ctl->preconnect)))
{
@@ -1381,190 +1382,194 @@ const struct method *proto; /* protocol method table */
set_timeout(ctl->server.timeout);
}
- /* compute number of messages and number of new messages waiting */
- ok = (protocol->getrange)(sock, ctl, &count, &new);
- if (ok != 0)
- goto cleanUp;
- set_timeout(ctl->server.timeout);
+ ctl->errcount = fetches = 0;
- /* show user how many messages we downloaded */
- if (ctl->mailbox)
- (void) sprintf(buf, "%s@%s:%s",
- ctl->remotename, realname, ctl->mailbox);
- else
- (void) sprintf(buf, "%s@%s", ctl->remotename, realname);
- if (outlevel > O_SILENT)
- if (count == -1) /* only used for ETRN */
- error(0, 0, "Polling %s", buf);
- else if (count == 0)
- error(0, 0, "No mail at %s", buf);
- else
- {
- if (new != -1 && (count - new) > 0)
- error(0, 0, "%d message%s (%d seen) at %s.",
- count, count > 1 ? "s" : "", count-new, buf);
- else
- error(0, 0, "%d message%s at %s.",
- count, count > 1 ? "s" : "", buf);
- }
-
- /* we may need to get sizes in order to check message limits */
- msgsizes = (int *)NULL;
- if (!ctl->fetchall && proto->getsizes && ctl->limit)
+ /* now iterate over each folder selected */
+ for (idp = ctl->mailboxes; idp; idp = idp->next)
{
- msgsizes = (int *)alloca(sizeof(int) * count);
-
- ok = (proto->getsizes)(sock, count, msgsizes);
+ if (outlevel >= O_VERBOSE)
+ if (idp->next)
+ error(0, 0, "selecting folder %s");
+ else
+ error(0, 0, "selecting default folder");
+
+ /* compute number of messages and number of new messages waiting */
+ ok = (protocol->getrange)(sock, ctl, idp->id, &count, &new);
if (ok != 0)
goto cleanUp;
set_timeout(ctl->server.timeout);
- }
- if (check_only)
- {
- if (new == -1 || ctl->fetchall)
- new = count;
- ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
- goto cleanUp;
- }
- else if (count > 0)
- {
- int force_retrieval, fetches;
+ /* show user how many messages we downloaded */
+ if (idp->id)
+ (void) sprintf(buf, "%s@%s:%s",
+ ctl->remotename, realname, idp->id);
+ else
+ (void) sprintf(buf, "%s@%s", ctl->remotename, realname);
+ if (outlevel > O_SILENT)
+ if (count == -1) /* only used for ETRN */
+ error(0, 0, "Polling %s", buf);
+ else if (count == 0)
+ error(0, 0, "No mail at %s", buf);
+ else
+ {
+ if (new != -1 && (count - new) > 0)
+ error(0, 0, "%d message%s (%d seen) at %s.",
+ count, count > 1 ? "s" : "", count-new, buf);
+ else
+ error(0, 0, "%d message%s at %s.",
+ count, count > 1 ? "s" : "", buf);
+ }
- /*
- * What forces this code is that in POP3 and IMAP2BIS you can't
- * fetch a message without having it marked `seen'. In IMAP4,
- * on the other hand, you can (peek_capable is set to convey
- * this).
- *
- * The result of being unable to peek is that if there's
- * any kind of transient error (DNS lookup failure, or
- * sendmail refusing delivery due to process-table limits)
- * the message will be marked "seen" on the server without
- * having been delivered. This is not a big problem if
- * fetchmail is running in foreground, because the user
- * will see a "skipped" message when it next runs and get
- * clued in.
- *
- * But in daemon mode this leads to the message being silently
- * ignored forever. This is not acceptable.
- *
- * We compensate for this by checking the error count from the
- * previous pass and forcing all messages to be considered new
- * if it's nonzero.
- */
- force_retrieval = !peek_capable && (ctl->errcount > 0);
+ /* we may need to get sizes in order to check message limits */
+ msgsizes = (int *)NULL;
+ if (!ctl->fetchall && proto->getsizes && ctl->limit)
+ {
+ msgsizes = (int *)alloca(sizeof(int) * count);
- ctl->errcount = fetches = 0;
+ ok = (proto->getsizes)(sock, count, msgsizes);
+ if (ok != 0)
+ goto cleanUp;
+ set_timeout(ctl->server.timeout);
+ }
- /* read, forward, and delete messages */
- for (num = 1; num <= count; num++)
+ if (check_only)
{
- int toolarge = msgsizes && (msgsizes[num-1] > ctl->limit);
- int fetch_it = ctl->fetchall ||
- (!toolarge && (force_retrieval || !(protocol->is_old && (protocol->is_old)(sock,ctl,num))));
- int suppress_delete = FALSE;
+ if (new == -1 || ctl->fetchall)
+ new = count;
+ ok = ((new > 0) ? PS_SUCCESS : PS_NOMAIL);
+ goto cleanUp;
+ }
+ else if (count > 0)
+ {
+ int force_retrieval;
- /* we may want to reject this message if it's old */
- if (!fetch_it)
- {
- if (outlevel > O_SILENT)
- {
- error_build("skipping message %d", num);
- if (toolarge)
- error_build(" (oversized, %d bytes)", msgsizes[num-1]);
- }
- }
- else
+ /*
+ * What forces this code is that in POP3 and IMAP2BIS you can't
+ * fetch a message without having it marked `seen'. In IMAP4,
+ * on the other hand, you can (peek_capable is set to convey
+ * this).
+ *
+ * The result of being unable to peek is that if there's
+ * any kind of transient error (DNS lookup failure, or
+ * sendmail refusing delivery due to process-table limits)
+ * the message will be marked "seen" on the server without
+ * having been delivered. This is not a big problem if
+ * fetchmail is running in foreground, because the user
+ * will see a "skipped" message when it next runs and get
+ * clued in.
+ *
+ * But in daemon mode this leads to the message being silently
+ * ignored forever. This is not acceptable.
+ *
+ * We compensate for this by checking the error count from the
+ * previous pass and forcing all messages to be considered new
+ * if it's nonzero.
+ */
+ force_retrieval = !peek_capable && (ctl->errcount > 0);
+
+ /* read, forward, and delete messages */
+ for (num = 1; num <= count; num++)
{
- /* request a message */
- ok = (protocol->fetch)(sock, ctl, num, &len);
- if (ok != 0)
- goto cleanUp;
- set_timeout(ctl->server.timeout);
+ int toolarge = msgsizes && (msgsizes[num-1] > ctl->limit);
+ int fetch_it = ctl->fetchall ||
+ (!toolarge && (force_retrieval || !(protocol->is_old && (protocol->is_old)(sock,ctl,num))));
+ int suppress_delete = FALSE;
- if (outlevel > O_SILENT)
+ /* we may want to reject this message if it's old */
+ if (!fetch_it)
{
- error_build("reading message %d", num);
- if (len > 0)
- error_build(" (%d bytes)", len);
- if (outlevel == O_VERBOSE)
- error_complete(0, 0, "");
- else
- error_build(" ");
+ if (outlevel > O_SILENT)
+ {
+ error_build("skipping message %d", num);
+ if (toolarge)
+ error_build(" (oversized, %d bytes)", msgsizes[num-1]);
+ }
}
-
- /* read the message and ship it to the output sink */
- ok = gen_readmsg(sock,
- len,
- protocol->delimited,
- ctl,
- realname);
- if (ok == PS_TRANSIENT)
- suppress_delete = TRUE;
- else if (ok)
- goto cleanUp;
- set_timeout(ctl->server.timeout);
-
- /* tell the server we got it OK and resynchronize */
- if (protocol->trail)
+ else
{
- ok = (protocol->trail)(sock, ctl, num);
+ /* request a message */
+ ok = (protocol->fetch)(sock, ctl, num, &len);
if (ok != 0)
goto cleanUp;
set_timeout(ctl->server.timeout);
+
+ if (outlevel > O_SILENT)
+ {
+ error_build("reading message %d", num);
+ if (len > 0)
+ error_build(" (%d bytes)", len);
+ if (outlevel == O_VERBOSE)
+ error_complete(0, 0, "");
+ else
+ error_build(" ");
+ }
+
+ /* read the message and ship it to the output sink */
+ ok = gen_readmsg(sock,
+ len,
+ protocol->delimited,
+ ctl,
+ realname);
+ if (ok == PS_TRANSIENT)
+ suppress_delete = TRUE;
+ else if (ok)
+ goto cleanUp;
+ set_timeout(ctl->server.timeout);
+
+ /* tell the server we got it OK and resynchronize */
+ if (protocol->trail)
+ {
+ ok = (protocol->trail)(sock, ctl, num);
+ if (ok != 0)
+ goto cleanUp;
+ set_timeout(ctl->server.timeout);
+ }
+
+ fetches++;
}
- fetches++;
- }
+ /*
+ * At this point in flow of control, either we've bombed
+ * on a protocol error or had delivery refused by the SMTP
+ * server (unlikely -- I've never seen it) or we've seen
+ * `accepted for delivery' and the message is shipped.
+ * It's safe to mark the message seen and delete it on the
+ * server now.
+ */
- /*
- * At this point in flow of control, either we've bombed
- * on a protocol error or had delivery refused by the SMTP
- * server (unlikely -- I've never seen it) or we've seen
- * `accepted for delivery' and the message is shipped.
- * It's safe to mark the message seen and delete it on the
- * server now.
- */
+ /* maybe we delete this message now? */
+ if (protocol->delete
+ && !suppress_delete
+ && (fetch_it ? !ctl->keep : ctl->flush))
+ {
+ deletions++;
+ if (outlevel > O_SILENT)
+ error_complete(0, 0, " flushed");
+ ok = (protocol->delete)(sock, ctl, num);
+ if (ok != 0)
+ goto cleanUp;
+ set_timeout(ctl->server.timeout);
+ delete_str(&ctl->newsaved, num);
+ }
+ else if (outlevel > O_SILENT)
+ error_complete(0, 0, " not flushed");
- /* maybe we delete this message now? */
- if (protocol->delete
- && !suppress_delete
- && (fetch_it ? !ctl->keep : ctl->flush))
- {
- deletions++;
- if (outlevel > O_SILENT)
- error_complete(0, 0, " flushed");
- ok = (protocol->delete)(sock, ctl, num);
- if (ok != 0)
- goto cleanUp;
- set_timeout(ctl->server.timeout);
- delete_str(&ctl->newsaved, num);
+ /* perhaps this as many as we're ready to handle */
+ if (ctl->fetchlimit && ctl->fetchlimit <= fetches)
+ goto no_error;
}
- else if (outlevel > O_SILENT)
- error_complete(0, 0, " not flushed");
-
- /* perhaps this as many as we're ready to handle */
- if (ctl->fetchlimit && ctl->fetchlimit <= fetches)
- break;
}
-
- ok = gen_transact(sock, protocol->exit_cmd);
- if (ok == 0)
- ok = (fetches > 0) ? PS_SUCCESS : PS_NOMAIL;
- set_timeout(0);
- close(sock);
- goto closeUp;
- }
- else {
- ok = gen_transact(sock, protocol->exit_cmd);
- if (ok == 0)
- ok = PS_NOMAIL;
- set_timeout(0);
- close(sock);
- goto closeUp;
}
+ no_error:
+ set_timeout(ctl->server.timeout);
+ ok = gen_transact(sock, protocol->exit_cmd);
+ if (ok == 0)
+ ok = (fetches > 0) ? PS_SUCCESS : PS_NOMAIL;
+ set_timeout(0);
+ close(sock);
+ goto closeUp;
+
cleanUp:
set_timeout(ctl->server.timeout);
if (ok != 0 && ok != PS_SOCKET)
diff --git a/etrn.c b/etrn.c
index c931d2cc..12ee2f20 100644
--- a/etrn.c
+++ b/etrn.c
@@ -117,7 +117,7 @@ int doETRN (struct query *ctl)
fprintf(stderr, "Option --flush is not supported with ETRN\n");
return(PS_SYNTAX);
}
- if (ctl->mailbox) {
+ if (ctl->mailboxes) {
fprintf(stderr, "Option --remote is not supported with ETRN\n");
return(PS_SYNTAX);
}
diff --git a/fetchmail.c b/fetchmail.c
index fbc16d9a..3bea5ab4 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -650,6 +650,10 @@ static int load_params(int argc, char **argv, int optind)
if (ctl->server.envelope == (char *)NULL)
ctl->server.envelope = "X-Envelope-To:";
+ /* if no folders were specified, set up the null one as default */
+ if (!ctl->mailboxes)
+ save_str(&ctl->mailboxes, -1, (char *)NULL);
+
/* sanity checks */
if (ctl->server.port < 0)
{
@@ -849,6 +853,17 @@ void dump_params (struct query *ctl)
putchar('\n');
}
+ if (!ctl->mailboxes->id)
+ printf(" Default mailbox selected.\n");
+ else
+ {
+ struct idlist *idp;
+
+ printf(" Selected mailboxes are:");
+ for (idp = ctl->mailboxes; idp; idp = idp->next)
+ printf(" %s", idp->id);
+ printf("\n");
+ }
printf(" %s messages will be retrieved (--all %s).\n",
ctl->fetchall ? "All" : "Only new",
ctl->fetchall ? "on" : "off");
diff --git a/fetchmail.h b/fetchmail.h
index a50659e5..879112db 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -102,7 +102,7 @@ struct query
int wildcard; /* should unmatched names be passed through */
char *remotename;
char *password;
- char *mailbox;
+ struct idlist *mailboxes;
struct idlist *smtphunt;
char *smtphost;
char *mda;
diff --git a/fetchmail.man b/fetchmail.man
index e274a79c..6f27538e 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -164,18 +164,19 @@ The option permits you to specify a TCP/IP port to connect on.
This option will seldom be necessary as all the supported protocols have
well-established default port numbers.
.TP
-.B \-r folder, --remote folder
-Causes a specified non-default mail folder on the mailserver to be retrieved.
-The syntax of the folder name is server dependent, as is the default
-behavior when no folder is specified. This option is not available
-under POP3 or ETRN.
+.B \-r folder, --folder folder
+Causes a specified non-default mail folder on the mailserver (or
+comma-separated list of folders) to be retrieved. The syntax of the
+folder name is server-dependent. This option is not available under
+POP3 or ETRN.
.SS Delivery Control Options
.TP
.B \-S host, --smtphost host
-Specify a hunt list of hosts to forward mail to.
-In ETRN mode, set the host that the mailserver is asked to ship mail to.
-Hosts are tried in list order; the first one that is up becomes the
-forwarding or ETRN target for the current run.
+Specify a hunt list of hosts to forward mail to (one or more
+hostnames, comma-separated). In ETRN mode, set the host that the
+mailserver is asked to ship mail to. Hosts are tried in list order;
+the first one that is up becomes the forwarding or ETRN target for the
+current run.
.TP
.B \-m, \--mda
You can force mail to be passed to an MDA directly (rather than
@@ -610,7 +611,7 @@ Legal user options are
is
to
password (or pass)
- remotefolder (or remote)
+ folder
smtphost (or smtp)
mda
preconnect
@@ -634,7 +635,10 @@ Legal user options are
fetchlimit
syslog
.PP
-All options correspond to the obvious command-line arguments except
+The 'remotefolder' and 'smtphost' options can take a space- or
+comma-separated list of names following them.
+.PP
+All options correspond to the obvious command-line arguments, except
the following: `aka', `is', `to', `dns'/`no dns', `password',
\&`preconnect', `localdomains', `stripcr'/`no stripcr' ,
\&`forcecr'/`no forcecr' and `no received'.
diff --git a/imap.c b/imap.c
index 938c5f0a..035942f7 100644
--- a/imap.c
+++ b/imap.c
@@ -117,16 +117,17 @@ int imap_getauth(int sock, struct query *ctl, char *buf)
return(PS_SUCCESS);
}
-static int imap_getrange(int sock, struct query *ctl, int*countp, int*newp)
+static int imap_getrange(int sock,
+ struct query *ctl,
+ const char *folder,
+ int *countp, int *newp)
/* get range of messages to be fetched */
{
int ok;
/* find out how many messages are waiting */
recent = unseen = 0;
- ok = gen_transact(sock,
- "SELECT %s",
- ctl->mailbox ? ctl->mailbox : "INBOX");
+ ok = gen_transact(sock, "SELECT %s", folder ? folder : "INBOX");
if (ok != 0)
{
error(0, 0, "mailbox selection failed");
diff --git a/options.c b/options.c
index 2a5f91c8..fcc5fddf 100644
--- a/options.c
+++ b/options.c
@@ -41,7 +41,7 @@
#define LA_FLUSH 23
#define LA_NOREWRITE 24
#define LA_LIMIT 25
-#define LA_REMOTEFILE 26
+#define LA_FOLDER 26
#define LA_SMTPHOST 27
#define LA_BATCHLIMIT 28
#define LA_FETCHLIMIT 29
@@ -83,7 +83,7 @@ static struct option longoptions[] = {
{"norewrite", no_argument, (int *) 0, LA_NOREWRITE },
{"limit", required_argument, (int *) 0, LA_LIMIT },
- {"remote", required_argument, (int *) 0, LA_REMOTEFILE },
+ {"folder", required_argument, (int *) 0, LA_FOLDER },
{"smtphost", required_argument, (int *) 0, LA_SMTPHOST },
{"batchlimit",required_argument, (int *) 0, LA_BATCHLIMIT },
{"fetchlimit",required_argument, (int *) 0, LA_FETCHLIMIT },
@@ -117,6 +117,7 @@ struct query *ctl; /* option record to be initialized */
int ocount = 0; /* count of destinations specified */
int errflag = 0; /* TRUE when a syntax error is detected */
int option_index;
+ char buf[BUFSIZ], *cp;
cmd_daemon = -1;
@@ -254,12 +255,22 @@ struct query *ctl; /* option record to be initialized */
ctl->limit = atoi(optarg);
break;
case 'r':
- case LA_REMOTEFILE:
- ctl->mailbox = xstrdup(optarg);
+ case LA_FOLDER:
+ strcpy(buf, optarg);
+ cp = strtok(buf, ",");
+ do {
+ save_str(&ctl->mailboxes, -1, optarg);
+ } while
+ ((cp = strtok((char *)NULL, ",")));
break;
case 'S':
case LA_SMTPHOST:
- save_str(&ctl->smtphunt, -1, optarg);
+ strcpy(buf, optarg);
+ cp = strtok(buf, ",");
+ do {
+ save_str(&ctl->smtphunt, -1, optarg);
+ } while
+ ((cp = strtok((char *)NULL, ",")));
ocount++;
break;
case 'b':
@@ -343,7 +354,7 @@ struct query *ctl; /* option record to be initialized */
fputs(" -S, --smtphost set SMTP forwarding host\n", stderr);
fputs(" -b, --batchlimit set batch limit for SMTP connections\n", stderr);
fputs(" -B, --fetchlimit set fetch limit for server connections\n", stderr);
- fputs(" -r, --remote specify remote folder name\n", stderr);
+ fputs(" -r, --folder specify remote folder name\n", stderr);
return(-1);
}
diff --git a/pop2.c b/pop2.c
index 88140a3d..1f04a4ce 100644
--- a/pop2.c
+++ b/pop2.c
@@ -58,26 +58,32 @@ int pop2_getauth(int sock, struct query *ctl, char *buf)
ctl->remotename, ctl->password));
}
-static int pop2_getrange(int sock, struct query *ctl, int*countp, int*newp)
+static int pop2_getrange(int sock, struct query *ctl, const char *folder, int*countp, int*newp)
/* get range of messages to be fetched */
{
- /*
- * We should have picked up a count of messages in the user's
- * default inbox from the pop2_getauth() response.
- */
- if (pound_arg == -1)
- return(PS_ERROR);
-
/* maybe the user wanted a non-default folder */
- if (ctl->mailbox)
+ if (folder)
{
- int ok = gen_transact(sock, "FOLD %s", ctl->mailbox);
+ int ok = gen_transact(sock, "FOLD %s", folder);
if (ok != 0)
return(ok);
if (pound_arg == -1)
return(PS_ERROR);
}
+ else
+ /*
+ * We should have picked up a count of messages in the user's
+ * default inbox from the pop2_getauth() response.
+ *
+ * Note: this logic only works because there is no way to select
+ * both the unnamed folder and named folders within a single
+ * fetchmail run. If that assumption ever becomes invalid, the
+ * pop2_getauth code will have to stash the pound response away
+ * explicitly in case it gets stepped on.
+ */
+ if (pound_arg == -1)
+ return(PS_ERROR);
*countp = pound_arg;
*newp = -1;
diff --git a/pop3.c b/pop3.c
index cc3a82d2..a6443835 100644
--- a/pop3.c
+++ b/pop3.c
@@ -125,7 +125,10 @@ int pop3_getauth(int sock, struct query *ctl, char *greeting)
return(0);
}
-static int pop3_getrange(int sock, struct query *ctl, int*countp, int*newp)
+static int pop3_getrange(int sock,
+ struct query *ctl,
+ const char *folder,
+ int *countp, int *newp)
/* get range of messages to be fetched */
{
int ok;
@@ -279,7 +282,7 @@ const static struct method pop3 =
int doPOP3 (struct query *ctl)
/* retrieve messages using POP3 */
{
- if (ctl->mailbox) {
+ if (ctl->mailboxes->id) {
fprintf(stderr,"Option --remote is not supported with POP3\n");
return(PS_SYNTAX);
}
diff --git a/rcfile_l.l b/rcfile_l.l
index 4fa4185e..d52d6389 100644
--- a/rcfile_l.l
+++ b/rcfile_l.l
@@ -41,7 +41,7 @@ envelope { return ENVELOPE; }
user(name)? { return USERNAME; }
pass(word)? { return PASSWORD; }
-remote(folder)? { return FOLDER; }
+folder(s) { return FOLDER; }
smtp(host)? { return SMTPHOST; }
mda { return MDA; }
pre(connect) { return PRECONNECT; }
@@ -55,7 +55,7 @@ to { return TO; }
= { return MAP; }
"*" { return WILDCARD; }
-no/[kfrsdu ] { return NO;}
+no/[kfrsdu ].* { return NO;}
keep { return KEEP; }
flush { return FLUSH; }
@@ -83,6 +83,11 @@ options {/* EMPTY */}
(etrn)|(ETRN) { yylval.proto = P_ETRN; return PROTO; }
(kpop)|(KPOP) { return KPOP; }
+remote(folder)? {
+ fprintf(stderr,
+ "fetchmail: `remote' keyword is gone, use `folder'\n");
+ }
+
(#.*)?\\?\n { prc_lineno++; } /* newline is ignored */
@@ -106,3 +111,5 @@ options {/* EMPTY */}
[ \t\r]+ ; /* whitespace */
+
+
diff --git a/rcfile_y.y b/rcfile_y.y
index c5da848a..c2f121a5 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -193,6 +193,10 @@ mapping : STRING
{save_str_pair(&current.localnames, $1, $3);}
;
+folder_list : STRING {save_str(&current.mailboxes,-1,$1);}
+ | folder_list STRING {save_str(&current.mailboxes,-1,$2);}
+ ;
+
smtphunt : STRING {save_str(&current.smtphunt, -1, $1);}
| smtphunt STRING {save_str(&current.smtphunt, -1, $2);}
;
@@ -204,7 +208,7 @@ user_option : TO localnames HERE
| IS STRING THERE {current.remotename = xstrdup($2);}
| PASSWORD STRING {current.password = xstrdup($2);}
- | FOLDER STRING {current.mailbox = xstrdup($2);}
+ | FOLDER folder_list
| SMTPHOST smtphunt
| MDA STRING {current.mda = xstrdup($2);}
| PRECONNECT STRING {current.preconnect = xstrdup($2);}
@@ -397,7 +401,8 @@ static void record_current(void)
FLAG_FORCE(remotename);
FLAG_FORCE(password);
- FLAG_FORCE(mailbox);
+ if (cmd_opts.mailboxes)
+ save_str(&current.mailboxes, -1, cmd_opts.mailboxes->id);
if (cmd_opts.smtphunt)
save_str(&current.smtphunt, -1, cmd_opts.smtphunt->id);
FLAG_FORCE(mda);
@@ -423,6 +428,7 @@ void optmerge(struct query *h2, struct query *h1)
{
append_str_list(&h2->server.localdomains, &h1->server.localdomains);
append_str_list(&h2->localnames, &h1->localnames);
+ append_str_list(&h2->mailboxes, &h1->mailboxes);
append_str_list(&h2->smtphunt, &h1->smtphunt);
#define FLAG_MERGE(fld) if (!h2->fld) h2->fld = h1->fld
@@ -442,7 +448,6 @@ void optmerge(struct query *h2, struct query *h1)
FLAG_MERGE(remotename);
FLAG_MERGE(password);
- FLAG_MERGE(mailbox);
FLAG_MERGE(mda);
FLAG_MERGE(preconnect);
diff --git a/sample.rcfile b/sample.rcfile
index 209242f6..e0edc8d7 100644
--- a/sample.rcfile
+++ b/sample.rcfile
@@ -34,9 +34,9 @@
#
# username (or user) -- must be followed by a name
# is -- must be followed by one or more names
-# remotefolder (or remote) -- must be followed by a filename
+# folder -- must be followed by remote folder names
# password (or pass) -- must be followed by a password string
-# smtphost (or smtp) -- must be followed by a host name
+# smtphost (or smtp) -- must be followed by host names
# mda -- must be followed by an MDA command string
# preconnect (or pre) -- must be followed by an initialization command
#
diff --git a/uid.c b/uid.c
index e6fa1b26..c531915a 100644
--- a/uid.c
+++ b/uid.c
@@ -112,7 +112,7 @@ struct idlist *save_str(struct idlist **idl, int num, const char *str)
*end = (struct idlist *)xmalloc(sizeof(struct idlist));
(*end)->val.num = num;
- (*end)->id = xstrdup(str);
+ (*end)->id = str ? xstrdup(str) : (char *)NULL;
(*end)->next = NULL;
return(*end);
@@ -140,7 +140,7 @@ void save_str_pair(struct idlist **idl, const char *str1, const char *str2)
continue;
*end = (struct idlist *)xmalloc(sizeof(struct idlist));
- (*end)->id = xstrdup(str1);
+ (*end)->id = str1 ? xstrdup(str1) : (char *)NULL;
if (str2)
(*end)->val.id2 = xstrdup(str2);
else