aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>1996-10-24 20:41:57 +0000
committerEric S. Raymond <esr@thyrsus.com>1996-10-24 20:41:57 +0000
commita5c5ce437bce689c08dabdbcd1107f3d0175539d (patch)
treefa0e59dcd9d5aad39333910f0856e90aed4c0306
parentc3d362f9c8a1dea65918ec84e72de1555992adc0 (diff)
downloadfetchmail-a5c5ce437bce689c08dabdbcd1107f3d0175539d.tar.gz
fetchmail-a5c5ce437bce689c08dabdbcd1107f3d0175539d.tar.bz2
fetchmail-a5c5ce437bce689c08dabdbcd1107f3d0175539d.zip
Support for multidrop mailboxes.
svn path=/trunk/; revision=374
-rw-r--r--NEWS7
-rw-r--r--README3
-rw-r--r--configure.in2
-rw-r--r--driver.c129
-rw-r--r--fetchmail.c87
-rw-r--r--fetchmail.h16
-rw-r--r--fetchmail.man66
-rw-r--r--rcfile_l.l3
-rw-r--r--rcfile_y.y29
-rw-r--r--uid.c65
10 files changed, 363 insertions, 44 deletions
diff --git a/NEWS b/NEWS
index 0148fd23..9d19d43b 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,13 @@ fetchmail-1.9 (Mon Oct 21 13:42:07 EDT 1996):
features --
+* It is now possible to specify multiple local recipients by giving a list
+ of names following "to" or "is". Each local recipient is checked for in the
+ To:, Cc: and Bcc: headers of each message; if a match is found, the message
+ is sent to that local recipient. This makes it possible to do mailing
+ lists and multidrop mailboxes. See the man page for details (and note
+ the caveat in the BUGS AND KNOWN PROBLEMS section).
+
* The first message from a query now includes the number of old messages
when this can be determined (that is not under POP2).
diff --git a/README b/README
index 35ee9746..d7f8fc3d 100644
--- a/README
+++ b/README
@@ -51,6 +51,9 @@ with **.
** Timeout if server connection is dropped.
+ ** Support for retrieving and forwarding from multi-drop mailboxes
+ that is guaranteed not to cause mail loops.
+
* Easy control via command line or free-format run control file.
* Daemon mode -- fetchmail can be run in background to poll
diff --git a/configure.in b/configure.in
index 736068cd..2c5f573d 100644
--- a/configure.in
+++ b/configure.in
@@ -61,7 +61,7 @@ dnl All AC_CHECK_FUNCs must precede the following AC_SUBSTs
AC_SUBST(EXTRASRC)
AC_SUBST(EXTRAOBJ)
-AC_CHECK_FUNCS(tcsetattr stty setsid seteuid rresvport)
+AC_CHECK_FUNCS(tcsetattr stty setsid seteuid gethostbyname)
dnl AC_FUNC_SETVBUF_REVERSED
diff --git a/driver.c b/driver.c
index 7d2e281a..3d38b8d9 100644
--- a/driver.c
+++ b/driver.c
@@ -20,6 +20,10 @@
#include <sys/time.h>
#include <signal.h>
+#ifdef HAVE_GETHOSTBYNAME
+#include <netdb.h>
+#endif /* HAVE_GETHOSTBYNAME */
+
#ifdef KERBEROS_V4
#include <krb.h>
#include <des.h>
@@ -295,6 +299,86 @@ char *hdr; /* header line to be parsed, NUL to continue in previous hdr */
return(NULL);
}
+#ifdef HAVE_GETHOSTBYNAME
+static int is_host_alias(name, host, canonical)
+/* determine whether name is a DNS alias of either following hostname */
+const char *name, *host, *canonical;
+{
+ struct hostent *he;
+
+ /*
+
+ * The first two checks are optimizations that will catch a good
+ * many cases. First, check against the hostname the user specified.
+ * Odds are good this will either be the mailserver's FQDN or a
+ * suffix of it with the mailserver's domain's default host name
+ * omitted. Next, check against the mailserver's FQDN, in case
+ * it's not the same as the declared hostname.
+ *
+ * Either of these on a mail address is definitive. Only if the
+ * name doesn't match either is it time to call the bind library.
+ * If this happens odds are good we're looking at an MX name.
+ */
+ if (strcmp(name, host) == 0)
+ return(1);
+ else if (strcmp(name, canonical) == 0)
+ return(1);
+ else if ((he = gethostbyname(name)) == (struct hostent *)NULL)
+ {
+ /*
+ * We treat lookup failure as a negative on the theory that
+ * the mailserver's DNS server is `nearby' and should be able
+ * to respond quickly and reliably. Ergo if we get failure,
+ * the name isn't a mailserver alias.
+ */
+ if (outlevel == O_VERBOSE)
+ fprintf(stderr, "fetchmail: DNS lookup of %s failed\n", name);
+ return(FALSE);
+ }
+ else
+ return(strcmp(name, he->h_name) == 0);
+}
+
+void find_server_names(hdr, queryctl, xmit_names)
+/* parse names out of a RFC822 header into an ID list */
+const char *hdr; /* RFC822 header in question */
+struct hostrec *queryctl; /* list of permissible aliases */
+struct idlist **xmit_names; /* list of recipient names parsed out */
+{
+ if (hdr == (char *)NULL)
+ return;
+ else
+ {
+ char *cp = nxtaddr(hdr), *lname;
+
+ do {
+ char *atsign = strchr(cp, '@');
+
+ if (atsign)
+ if (queryctl->norewrite)
+ continue;
+ else
+ {
+ if (!is_host_alias(atsign+1,
+ queryctl->servername,
+ queryctl->canonical_name))
+ continue;
+ atsign[0] = '\0';
+ }
+ if ((lname = idpair_find(&queryctl->localnames, cp))!=(char *)NULL)
+ {
+ if (outlevel == O_VERBOSE)
+ fprintf(stderr,
+ "fetchmail: mapped %s to local %s\n",
+ cp, lname);
+ save_uid(xmit_names, -1, lname);
+ }
+ } while
+ ((cp = nxtaddr((char *)NULL)) != (char *)NULL);
+ }
+}
+#endif /* HAVE_GETHOSTBYNAME */
+
static int gen_readmsg (socket, mboxfd, len, delimited, queryctl)
/* read message content and ship to SMTP or MDA */
int socket; /* to which the server is connected */
@@ -398,14 +482,47 @@ struct hostrec *queryctl; /* query control record */
}
else if (headers)
{
- char *cp;
+ char *cp;
if (!queryctl->mda[0])
{
if (SMTP_from(mboxfd, nxtaddr(fromhdr)) != SM_OK)
return(PS_SMTP);
- if (SMTP_rcpt(mboxfd, queryctl->localname) != 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)
+ return(PS_SMTP);
+ }
+
SMTP_data(mboxfd);
if (outlevel == O_VERBOSE)
fputs("SMTP> ", stderr);
@@ -618,9 +735,8 @@ struct method *proto; /* protocol method table */
/* show user how many messages we downloaded */
if (outlevel > O_SILENT && outlevel < O_VERBOSE)
if (count == 0)
- fprintf(stderr, "No mail for %s from %s@%s\n",
+ fprintf(stderr, "No mail from %s@%s\n",
queryctl->remotename,
- queryctl->localname,
queryctl->servername);
else
{
@@ -628,9 +744,8 @@ struct method *proto; /* protocol method table */
if (new != -1 && (count - new) > 0)
fprintf(stderr, " (%d seen)", count-new);
fprintf(stderr,
- " from %s for %s@%s.\n",
+ " from %s@%s.\n",
queryctl->remotename,
- queryctl->localname,
queryctl->servername);
}
diff --git a/fetchmail.c b/fetchmail.c
index 3e5a991d..bbef5002 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -26,10 +26,14 @@
#include <sys/stat.h>
#include <fcntl.h>
+#ifdef HAVE_GETHOSTBYNAME
+#include <netdb.h>
+#endif /* HAVE_GETHOSTBYNAME */
+
#include "fetchmail.h"
#include "getopt.h"
-#define DROPDEAD 6 /* maximum bad socjet opens */
+#define DROPDEAD 6 /* maximum bad socket opens */
#ifdef HAVE_PROTOTYPES
/* prototypes for internal functions */
@@ -52,6 +56,7 @@ int check_only; /* if --probe was set */
char *rcfile; /* path name of rc file */
char *idfile; /* UID list file */
int versioninfo; /* emit only version info */
+char *dfltuser; /* invoking user */
static void termhook();
static char *lockfile;
@@ -166,26 +171,51 @@ char **argv;
if (strcmp(hostp->servername, "defaults") == 0)
exit(PS_SYNTAX);
+ /* figure out who the default recipient should be */
+ if (getuid() == 0)
+ dfltuser = hostp->remotename;
+ else
+ dfltuser = user;
+
/* merge in wired defaults, do sanity checks and prepare internal fields */
for (hostp = hostlist; hostp; hostp = hostp->next)
if (hostp->active && !(implicitmode && hostp->skip))
{
+#ifdef HAVE_GETHOSTBYNAME
+ struct hostent *namerec;
+#endif /* HAVE_GETHOSTBYNAME */
+
/* merge in defaults */
optmerge(hostp, &def_opts);
- /* if rc file didn't supply a localname, default appropriately */
- if (!hostp->localname[0])
- if (getuid() == 0)
- strcpy(hostp->localname, hostp->remotename);
- else
- strcpy(hostp->localname, user);
-
/* check that delivery is going to a real local user */
if ((pw = getpwnam(user)) == (struct passwd *)NULL)
exit(PS_SYNTAX); /* has to be from bad rc file */
else
hostp->uid = pw->pw_uid;
+#ifdef HAVE_GETHOSTBYNAME
+ /* compute the canonical name of the host */
+ namerec = gethostbyname(hostp->servername);
+ if (namerec == (struct hostent *)NULL)
+ {
+ fprintf(stderr,
+ "fetchmail: can't get canonical name of host %s\n",
+ hostp->servername);
+ exit(PS_SYNTAX);
+ }
+ else
+ hostp->canonical_name = xstrdup((char *)namerec->h_name);
+#else
+ /* can't handle multidrop mailboxes unless we can do DNS lookups */
+ if (hostp->localnames && hostp->localnames->next)
+ {
+ fputs("fetchmail: can't handle multidrop mailboxes without DNS\n",
+ stderr);
+ exit(PS_SYNTAX);
+ }
+#endif /* HAVE_GETHOSTBYNAME */
+
/* sanity checks */
if (hostp->port < 0)
{
@@ -201,10 +231,7 @@ char **argv;
int argi;
char *argp;
- /* expand the %s escape if any before parsing */
- sprintf(hostp->mdabuf, hostp->mda, hostp->localname);
-
- /* now punch nulls into the delimiting whitespace in the args */
+ /* punch nulls into the delimiting whitespace in the args */
for (argp = hostp->mdabuf, argi = 1; *argp != '\0'; argi++)
{
hostp->mda_argv[argi] = argp;
@@ -398,6 +425,11 @@ char **argv;
*/
lossage = 0;
do {
+
+#ifdef HAVE_GETHOSTBYNAME
+ sethostent(TRUE); /* use TCP/IP for mailserver queries */
+#endif /* HAVE_GETHOSTBYNAME */
+
for (hostp = hostlist; hostp; hostp = hostp->next)
{
if (hostp->active && !(implicitmode && hostp->skip))
@@ -433,6 +465,10 @@ char **argv;
}
}
+#ifdef HAVE_GETHOSTBYNAME
+ endhostent(); /* release TCP/IP connection to nameserver */
+#endif /* HAVE_GETHOSTBYNAME */
+
if (sleep(poll_interval))
(void) fputs("fetchmail: awakened by SIGHUP\n", stderr);
} while
@@ -523,12 +559,14 @@ int dump_params (queryctl)
/* display query parameters in English */
struct hostrec *queryctl; /* query parameter block */
{
- printf("Options for %s retrieving from %s:\n",
- hostp->localname, visbuf(hostp->servername));
+ printf("Options for retrieving from %s@%s:\n",
+ hostp->remotename, visbuf(hostp->servername));
+#ifdef HAVE_GETHOSTBYNAME
+ printf(" Canonical DNS name of server is %s.\n", hostp->canonical_name);
+#endif /* HAVE_GETHOSTBYNAME */
if (queryctl->skip || outlevel == O_VERBOSE)
printf(" This host will%s be queried when no host is specified.\n",
queryctl->skip ? " not" : "");
- printf(" Username = '%s'.\n", visbuf(queryctl->remotename));
if (queryctl->password[0] == '\0')
printf(" Password will be prompted for.\n");
else if (outlevel == O_VERBOSE)
@@ -583,6 +621,25 @@ struct hostrec *queryctl; /* query parameter block */
else
printf(" Messages will be SMTP-forwarded to '%s'.\n",
visbuf(queryctl->smtphost));
+ if (!queryctl->localnames)
+ printf(" No localnames declared for this host.\n");
+ else
+ {
+ struct idlist *idp;
+ int count = 0;
+
+ for (idp = hostp->localnames; idp; idp = idp->next)
+ ++count;
+
+ printf(" %d local names recognized.\n", count);
+ if (outlevel == O_VERBOSE)
+ for (idp = hostp->localnames; idp; idp = idp->next)
+ if (idp->val.id2)
+ fprintf(stderr, "\t%s -> %s\n", idp->id, idp->val.id2);
+ else
+ fprintf(stderr, "\t%s\n", idp->id);
+ }
+
if (queryctl->protocol > P_POP2)
if (!queryctl->oldsaved)
printf(" No UIDs saved from this host.\n");
diff --git a/fetchmail.h b/fetchmail.h
index c5ef2496..baaa6f88 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -56,8 +56,12 @@
struct idlist
{
- int num;
char *id;
+ union
+ {
+ int num;
+ char *id2;
+ } val;
struct idlist *next;
};
@@ -65,12 +69,12 @@ struct hostrec
{
/* per-host data */
char servername [HOSTLEN+1];
- char localname [USERNAMELEN+1];
char remotename [USERNAMELEN+1];
char password [PASSWORDLEN+1];
char mailbox [FOLDERLEN];
char smtphost[HOSTLEN+1];
char mda [MDALEN+1];
+ struct idlist *localnames;
int protocol;
int port;
int authenticate;
@@ -95,6 +99,9 @@ struct hostrec
struct hostrec *next; /* next host in chain */
unsigned int uid; /* UID of user to deliver to */
char digest [DIGESTLEN];
+#ifdef HAVE_GETHOSTBYNAME
+ char *canonical_name; /* DNS canonical name of server host */
+#endif /* HAVE_GETHOSTBYNAME */
};
struct method
@@ -135,6 +142,7 @@ extern char *rcfile; /* path name of rc file */
extern char *idfile; /* path name of UID file */
extern int linelimit; /* limit # lines retrieved per site */
extern int versioninfo; /* emit only version info */
+extern char *dfltuser; /* invoking user */
#ifdef HAVE_PROTOTYPES
@@ -157,9 +165,13 @@ int doIMAP (struct hostrec *);
void initialize_saved_lists(struct hostrec *, char *);
void save_uid(struct idlist **, int, char *);
void free_uid_list(struct idlist **);
+void save_id_pair(struct idlist **, char *, char *);
+void free_idpair_list(struct idlist **);
int delete_uid(struct idlist **, int);
int uid_in_list(struct idlist **, char *);
char *uid_find(struct idlist **, int);
+char *idpair_find(struct idlist **, char *);
+void append_uid_list(struct idlist **, struct idlist **);
void update_uid_lists(struct hostrec *);
void write_saved_lists(struct hostrec *, char *);
diff --git a/fetchmail.man b/fetchmail.man
index b2165186..5cab1cf5 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -408,19 +408,32 @@ Legal user options are
norewrite
.PP
All options correspond to the obvious command-line arguments except
-four: \fBis\fR, \fBto\fR, \fBpassword\fR and \fBskip\fR.
+five: \fBis\fR, \fBto\fR, \fBpassword\fR, and \fBskip\fR.
.PP
-The \fBis\fR or \fIto\fR keywords associate a following local
-username with the mailserver user name in the entry. They are intended
-to be used in configurations where \fIfetchmail\fR runs as root and
-retrieves mail for multiple local users. If no \fBis\fR or \fIto\fR
-clause is present, the default local username is the calling user,
-unless the calling user is root in which case it is the remote user
-name of the current entry.
+The \fBis\fR or \fIto\fR keywords associate the following local (client)
+name(s) (or server-name to client-name mappings separated by =) with
+the mailserver user name in the entry.
+.PP
+A single local name can be used to support redirecting your mail when
+your username on the client machine is different from your name on the
+mailserver. When there is only a single local name, mail is forwarded
+to that username regardless of the message's To, Cc, and Bcc headers.
+.PP
+When there is more than one local name (or name mapping) the
+\fIfetchmail\fR code does look at the To, Cc, and Bcc headers of
+retrieved mail. When a declared mailserver username is recognized, its
+local mapping is added to the list of local recipients. If
+\fIfetchmail\fR cannot recognize any mailserver usernames, the default
+recipient is the calling user, unless the calling user is root in
+which case it is the remote user name of the current entry.
.PP
The \fBpassword\fR option requires a string argument, which is the password
to be used with the entry's server.
.PP
+The \fBaliases\fR option declares names that are recognized as OK for
+local delivery. Your local name is automatically one of these; the
+aliases directive can be used to declare others.
+.PP
The \fBskip\fR option tells
.I fetchmail
not to query this host unless it is explicitly named on the command
@@ -552,6 +565,21 @@ to be specifying multiple users per server unless running it as root
pop-provider.net, which is probably not what you want).
In any case, we strongly recommend always having an explicit
\fBuser\fR clause when specifying multiple users for server.
+.PP
+Here's what a simple retrieval configuration for a multi-drop mailbox
+looks like:
+
+.nf
+ server pop.provider.net:
+ user maildrop with pass secret1 to golux hurkle=happy snark here
+.fi
+
+This says that the mailbox of account `maildrop' on the server is a
+multi-drop box, and that messages in it should be parsed for the
+server user names `golux', `hurkle', and `snark'. It further
+specifies that `golux' and `snark' have the same name on the
+client as on the server, but mail for server user `hurkle' should be
+delivered to client user `happy'.
.SH EXIT CODES
To facilitate the use of
.I fetchmail
@@ -598,6 +626,19 @@ When
.I fetchmail
queries more than one host, the returned status is that of the last
host queried.
+.SH NOTE
+Multiple local names can be used to support forwarding from a
+"multi-drop" mailbox accumulating mail on the server for several
+client-machine users. Local names can also be used to administer a
+mailing list from the client side of a \fIfetchmail\fR collection.
+Suppose your name is `esr', and you maintain a mailing list called
+(say) "fetchmail-friends", and you want to keep the alias list on your
+client machine. On your server, you can alias fetchmail-friends to
+esr; then, in your \fI.fetchmailrc\fR, declare `to esr
+fetchmail-friends here'. Then, when mail including that alias in any
+of its recpient lines line gets fetched, the alias will be appended to
+the list of recipients your SMTP listener sees. Therefore it will
+undergo alias expansion locally.
.SH AUTHORS
.I fetchmail
was originated (under the name `popclient') by Carl Harris at Virginia
@@ -642,6 +683,15 @@ to the mailserver. This creates a risk that name/password pairs
might be snaffled with a packet sniffer or more sophisticated
monitoring software.
.PP
+Retrieval and forwarding from multi-drop server mailboxes is only as
+reliable as your mail server host's DNS service. Each host
+address part in each message of a multi-drop mailbox is checked
+with
+.BR gethostbyname (2)
+to see if it's an alias of the mail server. If it is, but the
+lookup fails due to network congestion or a crashed server, forwarding
+will not get done correctly.
+.PP
Under Linux, if fetchmail is run in daemon mode with the network
inaccessible, each poll leaves a socket allocated but in CLOSE state
(this is visible in netstat(1)'s output). For some reason, these
diff --git a/rcfile_l.l b/rcfile_l.l
index 5ef8722d..701edd57 100644
--- a/rcfile_l.l
+++ b/rcfile_l.l
@@ -13,6 +13,8 @@
int prc_lineno = 1;
%}
+%o 4000
+
%%
defaults { return DEFAULTS; }
@@ -32,6 +34,7 @@ is { return IS; }
here { return HERE; }
there { return THERE; }
to { return TO; }
+= { return MAP; }
keep { yylval.flag = FLAG_TRUE; return KEEP; }
flush { yylval.flag = FLAG_TRUE; return FLUSH; }
diff --git a/rcfile_y.y b/rcfile_y.y
index 5f9be831..6582a31c 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -31,7 +31,7 @@ static int prc_errflag;
}
%token DEFAULTS SERVER PROTOCOL AUTHENTICATE TIMEOUT KPOP KERBEROS
-%token USERNAME PASSWORD FOLDER SMTPHOST MDA IS HERE THERE TO
+%token USERNAME PASSWORD FOLDER SMTPHOST MDA IS HERE THERE TO MAP
%token <proto> PROTO
%token <sval> STRING
%token <number> NUMBER
@@ -91,7 +91,7 @@ explicitdef : userdef user0opts
;
userdef : USERNAME STRING {strcpy(current.remotename, $2);}
- | USERNAME STRING HERE {strcpy(current.localname, $2);}
+ | USERNAME mapping_list HERE
| USERNAME STRING THERE {strcpy(current.remotename, $2);}
;
@@ -103,10 +103,20 @@ user1opts : user_option
| user1opts user_option
;
-user_option : TO STRING {strcpy(current.localname, $2);}
- | TO STRING HERE {strcpy(current.localname, $2);}
- | IS STRING {strcpy(current.localname, $2);}
- | IS STRING HERE {strcpy(current.localname, $2);}
+mapping_list : mapping
+ | mapping_list mapping
+ ;
+
+mapping : STRING
+ {save_id_pair(&current.localnames, $1, NULL);}
+ | STRING MAP STRING
+ {save_id_pair(&current.localnames, $1, $3);}
+ ;
+
+user_option : TO mapping_list HERE
+ | TO mapping_list
+ | IS mapping_list HERE
+ | IS mapping_list
| IS STRING THERE {strcpy(current.remotename, $2);}
| PASSWORD STRING {strcpy(current.password, $2);}
| FOLDER STRING {strcpy(current.mailbox, $2);}
@@ -256,7 +266,6 @@ int prc_register()
{
#define STR_FORCE(fld, len) if (cmd_opts.fld[0]) \
strcpy(current.fld, cmd_opts.fld)
- STR_FORCE(localname, USERNAMELEN);
STR_FORCE(remotename, USERNAMELEN);
STR_FORCE(password, PASSWORDLEN);
STR_FORCE(mailbox, FOLDERLEN);
@@ -284,8 +293,11 @@ void optmerge(h2, h1)
struct hostrec *h1;
struct hostrec *h2;
{
+ struct idlist *idp;
+
+ append_uid_list(&h2->localnames, &h1->localnames);
+
#define STR_MERGE(fld, len) if (*(h2->fld) == '\0') strcpy(h2->fld, h1->fld)
- STR_MERGE(localname, USERNAMELEN);
STR_MERGE(remotename, USERNAMELEN);
STR_MERGE(password, PASSWORDLEN);
STR_MERGE(mailbox, FOLDERLEN);
@@ -304,6 +316,7 @@ struct hostrec *h2;
FLAG_MERGE(authenticate);
FLAG_MERGE(timeout);
#undef FLAG_MERGE
+
}
/* easier to do this than cope with variations in where the library lives */
diff --git a/uid.c b/uid.c
index ad043af6..8ad4215f 100644
--- a/uid.c
+++ b/uid.c
@@ -110,7 +110,7 @@ char *str;
struct idlist *new;
new = (struct idlist *)xmalloc(sizeof(struct idlist));
- new->num = num;
+ new->val.num = num;
new->id = xstrdup(str);
new->next = *idl;
*idl = new;
@@ -129,6 +129,39 @@ struct idlist **idl;
*idl = (struct idlist *)NULL;
}
+void save_id_pair(idl, str1, str2)
+/* save an ID pair on the given list */
+struct idlist **idl;
+char *str1, *str2;
+{
+ struct idlist *new;
+
+ new = (struct idlist *)xmalloc(sizeof(struct idlist));
+ new->id = xstrdup(str1);
+ if (str2)
+ new->val.id2 = xstrdup(str2);
+ else
+ new->val.id2 = (char *)NULL;
+ new->next = *idl;
+ *idl = new;
+}
+
+#ifdef __UNUSED__
+void free_idpair_list(idl)
+/* free the given ID pair list */
+struct idlist **idl;
+{
+ if (*idl == (struct idlist *)NULL)
+ return;
+
+ free_idpair_list(&(*idl)->next);
+ free ((*idl)->id);
+ free ((*idl)->val.id2);
+ free(*idl);
+ *idl = (struct idlist *)NULL;
+}
+#endif
+
int uid_in_list(idl, str)
/* is a given ID in the given list? */
struct idlist **idl;
@@ -149,12 +182,25 @@ int number;
{
if (*idl == (struct idlist *) 0)
return((char *) 0);
- else if (number == (*idl)->num)
+ else if (number == (*idl)->val.num)
return((*idl)->id);
else
return(uid_find(&(*idl)->next, number));
}
+char *idpair_find(idl, id)
+/* return the id of the given number in the given list. */
+struct idlist **idl;
+char *id;
+{
+ if (*idl == (struct idlist *) 0)
+ return((char *) 0);
+ else if (strcmp(id, (*idl)->id))
+ return((*idl)->val.id2 ? (*idl)->val.id2 : (*idl)->id);
+ else
+ return(idpair_find(&(*idl)->next, id));
+}
+
int delete_uid(idl, num)
/* delete given message from given list */
struct idlist **idl;
@@ -162,7 +208,7 @@ int num;
{
if (*idl == (struct idlist *)NULL)
return(0);
- else if ((*idl)->num == num)
+ else if ((*idl)->val.num == num)
{
struct idlist *next = (*idl)->next;
@@ -176,6 +222,19 @@ int num;
return(0);
}
+void append_uid_list(idl, nidl)
+/* append nidl to idl (does not copy *) */
+struct idlist **idl;
+struct idlist **nidl;
+{
+ if ((*idl) == (struct idlist *)NULL)
+ *idl = *nidl;
+ else if ((*idl)->next == (struct idlist *)NULL)
+ (*idl)->next = *nidl;
+ else
+ append_uid_list(&(*idl)->next, nidl);
+}
+
void update_uid_lists(hostp)
/* perform end-of-query actions on UID lists */
struct hostrec *hostp;