diff options
author | Eric S. Raymond <esr@thyrsus.com> | 1996-10-24 20:41:57 +0000 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 1996-10-24 20:41:57 +0000 |
commit | a5c5ce437bce689c08dabdbcd1107f3d0175539d (patch) | |
tree | fa0e59dcd9d5aad39333910f0856e90aed4c0306 | |
parent | c3d362f9c8a1dea65918ec84e72de1555992adc0 (diff) | |
download | fetchmail-a5c5ce437bce689c08dabdbcd1107f3d0175539d.tar.gz fetchmail-a5c5ce437bce689c08dabdbcd1107f3d0175539d.tar.bz2 fetchmail-a5c5ce437bce689c08dabdbcd1107f3d0175539d.zip |
Support for multidrop mailboxes.
svn path=/trunk/; revision=374
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | README | 3 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | driver.c | 129 | ||||
-rw-r--r-- | fetchmail.c | 87 | ||||
-rw-r--r-- | fetchmail.h | 16 | ||||
-rw-r--r-- | fetchmail.man | 66 | ||||
-rw-r--r-- | rcfile_l.l | 3 | ||||
-rw-r--r-- | rcfile_y.y | 29 | ||||
-rw-r--r-- | uid.c | 65 |
10 files changed, 363 insertions, 44 deletions
@@ -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). @@ -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 @@ -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 @@ -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; } @@ -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(¤t.localnames, $1, NULL);} + | STRING MAP STRING + {save_id_pair(¤t.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 */ @@ -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; |