From 40f522c2e1eafed131184579bde7296799a5f442 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Thu, 5 Nov 1998 06:00:34 +0000 Subject: Context for bouncemail is encapsulated. svn path=/trunk/; revision=2171 --- driver.c | 129 ++++++++++++++++++++++++++++++------------------------------ fetchmail.h | 11 +++++- sink.c | 34 ++++++++-------- 3 files changed, 91 insertions(+), 83 deletions(-) diff --git a/driver.c b/driver.c index e3d18a50..9ef5446c 100644 --- a/driver.c +++ b/driver.c @@ -346,24 +346,25 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, struct addrblk **resent_to_chainptr = &resent_to_addrchain; char buf[MSGBUFSIZE+1]; - char return_path[HOSTLEN + USERNAMELEN + 4]; int from_offs, reply_to_offs, resent_from_offs; int app_from_offs, sender_offs, resent_sender_offs; int env_offs; - char *headers, *received_for, *rcv, *cp; + char *received_for, *rcv, *cp; int n, linelen, oldlen, ch, remaining, skipcount; - struct idlist *idp, *xmit_names; + struct idlist *idp; flag no_local_matches = FALSE; flag headers_ok, has_nuls; int olderrs, good_addresses, bad_addresses; + struct msgblk msg; sizeticker = 0; has_nuls = headers_ok = FALSE; - return_path[0] = '\0'; + msg.return_path[0] = '\0'; olderrs = ctl->errcount; /* read message headers */ - headers = received_for = NULL; + msg.reallen = reallen; + msg.headers = received_for = NULL; from_offs = reply_to_offs = resent_from_offs = app_from_offs = sender_offs = resent_sender_offs = env_offs = -1; oldlen = 0; @@ -383,7 +384,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, if ((n = SockRead(sock, buf, sizeof(buf)-1)) == -1) { set_timeout(0); free(line); - free(headers); + free(msg.headers); return(PS_SOCKET); } set_timeout(0); @@ -463,7 +464,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, #endif /* POP2_ENABLE */ if (num == 1 && !strncasecmp(line, "X-IMAP:", 7)) { free(line); - free(headers); + free(msg.headers); return(PS_RETAINED); } @@ -554,49 +555,49 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, */ if (!strncasecmp("Return-Path:", line, 12) && (cp = nxtaddr(line))) { - strcpy(return_path, cp); + strcpy(msg.return_path, cp); if (!ctl->mda) { free(line); continue; } } - if (!headers) + if (!msg.headers) { oldlen = strlen(line); - headers = xmalloc(oldlen + 1); - (void) strcpy(headers, line); + msg.headers = xmalloc(oldlen + 1); + (void) strcpy(msg.headers, line); free(line); - line = headers; + line = msg.headers; } else { int newlen; newlen = oldlen + strlen(line); - headers = (char *) realloc(headers, newlen + 1); - if (headers == NULL) { + msg.headers = (char *) realloc(msg.headers, newlen + 1); + if (msg.headers == NULL) { free(line); return(PS_IOERR); } - strcpy(headers + oldlen, line); + strcpy(msg.headers + oldlen, line); free(line); - line = headers + oldlen; + line = msg.headers + oldlen; oldlen = newlen; } if (!strncasecmp("From:", line, 5)) - from_offs = (line - headers); + from_offs = (line - msg.headers); else if (!strncasecmp("Reply-To:", line, 9)) - reply_to_offs = (line - headers); + reply_to_offs = (line - msg.headers); else if (!strncasecmp("Resent-From:", line, 12)) - resent_from_offs = (line - headers); + resent_from_offs = (line - msg.headers); else if (!strncasecmp("Apparently-From:", line, 16)) - app_from_offs = (line - headers); + app_from_offs = (line - msg.headers); else if (!strncasecmp("Sender:", line, 7)) - sender_offs = (line - headers); + sender_offs = (line - msg.headers); else if (!strncasecmp("Resent_Sender:", line, 14)) - resent_sender_offs = (line - headers); + resent_sender_offs = (line - msg.headers); else if (!strncasecmp("Message-Id:", buf, 11)) { @@ -623,7 +624,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, || !strncasecmp("Apparently-To:", line, 14)) { *to_chainptr = xmalloc(sizeof(struct addrblk)); - (*to_chainptr)->offset = (line - headers); + (*to_chainptr)->offset = (line - msg.headers); to_chainptr = &(*to_chainptr)->next; *to_chainptr = NULL; } @@ -633,7 +634,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, || !strncasecmp("Resent-Bcc:", line, 11)) { *resent_to_chainptr = xmalloc(sizeof(struct addrblk)); - (*resent_to_chainptr)->offset = (line - headers); + (*resent_to_chainptr)->offset = (line - msg.headers); resent_to_chainptr = &(*resent_to_chainptr)->next; *resent_to_chainptr = NULL; } @@ -649,7 +650,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, { if (skipcount++ != ctl->server.envskip) continue; - env_offs = (line - headers); + env_offs = (line - msg.headers); } } else if (!received_for && !strncasecmp("Received:", line, 9)) @@ -681,7 +682,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, * make either From or To address @-less, otherwise the reply_hack * logic will do bad things. */ - if (headers == (char *)NULL) + if (msg.headers == (char *)NULL) { #ifdef HAVE_SNPRINTF snprintf(buf, sizeof(buf), @@ -690,7 +691,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, #endif /* HAVE_SNPRINTF */ "From: FETCHMAIL-DAEMON\r\nTo: %s@%s\r\nSubject: Headerless mail from %s's mailbox on %s\r\n", user, fetchmailhost, ctl->remotename, ctl->server.truename); - headers = xstrdup(buf); + msg.headers = xstrdup(buf); } /* @@ -703,10 +704,10 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, * headers (RFC 2046). */ if (ctl->mimedecode) { - UnMimeHeader(headers); + UnMimeHeader(msg.headers); } /* Check for MIME headers indicating possible 8-bit data */ - ctl->mimemsg = MimeBodyType(headers, ctl->mimedecode); + ctl->mimemsg = MimeBodyType(msg.headers, ctl->mimedecode); /* * If there is a Return-Path address on the message, this was @@ -723,25 +724,25 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, * (ex: specified by "Sender:") which is much less annoying. This * is true for most mailing list packages. */ - if( !return_path[0] ){ + if( !msg.return_path[0] ){ char *ap = NULL; - if (resent_sender_offs >= 0 && (ap = nxtaddr(headers + resent_sender_offs))); - else if (sender_offs >= 0 && (ap = nxtaddr(headers + sender_offs))); - else if (resent_from_offs >= 0 && (ap = nxtaddr(headers + resent_from_offs))); - else if (from_offs >= 0 && (ap = nxtaddr(headers + from_offs))); - else if (reply_to_offs >= 0 && (ap = nxtaddr(headers + reply_to_offs))); - else if (app_from_offs >= 0 && (ap = nxtaddr(headers + app_from_offs))); - if (ap) strcpy( return_path, ap ); + if (resent_sender_offs >= 0 && (ap = nxtaddr(msg.headers + resent_sender_offs))); + else if (sender_offs >= 0 && (ap = nxtaddr(msg.headers + sender_offs))); + else if (resent_from_offs >= 0 && (ap = nxtaddr(msg.headers + resent_from_offs))); + else if (from_offs >= 0 && (ap = nxtaddr(msg.headers + from_offs))); + else if (reply_to_offs >= 0 && (ap = nxtaddr(msg.headers + reply_to_offs))); + else if (app_from_offs >= 0 && (ap = nxtaddr(msg.headers + app_from_offs))); + if (ap) strcpy( msg.return_path, ap ); } /* cons up a list of local recipients */ - xmit_names = (struct idlist *)NULL; + msg.xmit_names = (struct idlist *)NULL; accept_count = reject_count = 0; /* is this a multidrop box? */ if (MULTIDROP(ctl)) { if (env_offs > -1) /* We have the actual envelope addressee */ - find_server_names(headers + env_offs, ctl, &xmit_names); + find_server_names(msg.headers + env_offs, ctl, &msg.xmit_names); else if (received_for) /* * We have the Received for addressee. @@ -750,11 +751,11 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, * We use find_server_names() to let local * hostnames go through. */ - find_server_names(received_for, ctl, &xmit_names); + find_server_names(received_for, ctl, &msg.xmit_names); #ifdef SDPS_ENABLE else if (sdps_envto) { - find_server_names(sdps_envto, ctl, &xmit_names); + find_server_names(sdps_envto, ctl, &msg.xmit_names); free(sdps_envto); } #endif /* SDPS_ENABLE */ @@ -781,7 +782,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, } /* now look for remaining adresses */ while (to_addrchain) { - find_server_names(headers+to_addrchain->offset, ctl, &xmit_names); + find_server_names(msg.headers+to_addrchain->offset, ctl, &msg.xmit_names); nextptr = to_addrchain->next; free(to_addrchain); to_addrchain = nextptr; @@ -790,7 +791,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, if (!accept_count) { no_local_matches = TRUE; - save_str(&xmit_names, run.postmaster, XMIT_ACCEPT); + save_str(&msg.xmit_names, run.postmaster, XMIT_ACCEPT); if (outlevel >= O_DEBUG) error(0, 0, "no local matches, forwarding to %s", @@ -798,7 +799,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, } } else /* it's a single-drop box, use first localname */ - save_str(&xmit_names, ctl->localnames->id, XMIT_ACCEPT); + save_str(&msg.xmit_names, ctl->localnames->id, XMIT_ACCEPT); /* @@ -808,18 +809,18 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, { if (outlevel >= O_DEBUG) error(0,0, "forwarding and deletion suppressed due to DNS errors"); - free(headers); - free_str_list(&xmit_names); + free(msg.headers); + free_str_list(&msg.xmit_names); return(PS_TRANSIENT); } else { /* set up stuffline() so we can deliver the message body through it */ - if ((n = open_sink(ctl, return_path, xmit_names, reallen, + if ((n = open_sink(ctl, &msg, &good_addresses, &bad_addresses)) != PS_SUCCESS) { - free(headers); - free_str_list(&xmit_names); + free(msg.headers); + free_str_list(&msg.xmit_names); return(n); } } @@ -830,17 +831,17 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, * synthetic Received line is before the From header. Cope * with this... */ - if ((rcv = strstr(headers, "Received:")) == (char *)NULL) - rcv = headers; + if ((rcv = strstr(msg.headers, "Received:")) == (char *)NULL) + rcv = msg.headers; /* handle ">Received:" lines too */ - while (rcv > headers && rcv[-1] != '\n') + while (rcv > msg.headers && rcv[-1] != '\n') rcv--; - if (rcv > headers) + if (rcv > msg.headers) { char c = *rcv; *rcv = '\0'; - n = stuffline(ctl, headers); + n = stuffline(ctl, msg.headers); *rcv = c; } if (!run.invisible && n != -1) @@ -870,7 +871,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, } else if (good_addresses == 1) { - for (idp = xmit_names; idp; idp = idp->next) + for (idp = msg.xmit_names; idp; idp = idp->next) if (idp->val.status.mark == XMIT_ACCEPT) break; /* only report first address */ if (strchr(idp->id, '@')) @@ -891,14 +892,14 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, } if (n != -1) - n = stuffline(ctl, rcv); /* ship out rest of headers */ + n = stuffline(ctl, rcv); /* ship out rest of msg.headers */ if (n == -1) { - error(0, errno, "writing RFC822 headers"); + error(0, errno, "writing RFC822 msg.headers"); release_sink(ctl); - free(headers); - free_str_list(&xmit_names); + free(msg.headers); + free_str_list(&msg.xmit_names); return(PS_IOERR); } else if (!run.use_syslog && outlevel >= O_VERBOSE) @@ -918,7 +919,7 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, strcat(errhd, "no recipient addresses matched declared local names"); else { - for (idp = xmit_names; idp; idp = idp->next) + for (idp = msg.xmit_names; idp; idp = idp->next) if (idp->val.status.mark == XMIT_REJECT) break; sprintf(errhd+strlen(errhd), "recipient address %s didn't match any local name", idp->id); @@ -938,13 +939,13 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, strcat(errhd, "; "); strcat(errhd, "SMTP listener rejected local recipient addresses: "); errlen = strlen(errhd); - for (idp = xmit_names; idp; idp = idp->next) + for (idp = msg.xmit_names; idp; idp = idp->next) if (idp->val.status.mark == XMIT_ANTISPAM) errlen += strlen(idp->id) + 2; xalloca(errmsg, char *, errlen+3); (void) strcpy(errmsg, errhd); - for (idp = xmit_names; idp; idp = idp->next) + for (idp = msg.xmit_names; idp; idp = idp->next) if (idp->val.status.mark == XMIT_ANTISPAM) { strcat(errmsg, idp->id); @@ -967,8 +968,8 @@ static int readheaders(int sock, long fetchlen, long reallen, struct query *ctl, *cp++ = '\0'; stuffline(ctl, buf); - free(headers); - free_str_list(&xmit_names); + free(msg.headers); + free_str_list(&msg.xmit_names); return(headers_ok ? PS_SUCCESS : PS_TRUNCATED); } diff --git a/fetchmail.h b/fetchmail.h index c0550202..78551cd7 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -266,6 +266,15 @@ struct query struct query *next; /* next query control block in chain */ }; +struct msgblk /* message header parsed for open_sink() */ +{ + char *headers; /* raw message headers */ + struct idlist *xmit_names; /* addressees */ + char return_path[HOSTLEN + USERNAMELEN + 4]; + int reallen; +}; + + /* * Numeric option handling. Numeric option value of zero actually means * it's unspecified. Value less than zero is zero. @@ -361,7 +370,7 @@ extern int phase; /* sink.c: forwarding */ int stuffline(struct query *, char *); -int open_sink(struct query*, const char*, struct idlist*, long reallen, int*, int*); +int open_sink(struct query*, struct msgblk *, int*, int*); void release_sink(struct query *); int close_sink(struct query *, flag); int open_warning_by_mail(struct query *); diff --git a/sink.c b/sink.c index d802e493..133ea56b 100644 --- a/sink.c +++ b/sink.c @@ -249,10 +249,7 @@ static void sanitize(char *s) *cp = '_'; } -int open_sink(struct query *ctl, - const char *return_path, - struct idlist *xmit_names, - long reallen, +int open_sink(struct query *ctl, struct msgblk *msg, int *good_addresses, int *bad_addresses) /* set up sinkfp to be an input sink we can ship a message to */ { @@ -269,14 +266,14 @@ int open_sink(struct query *ctl, /* see the ap computation under the SMTP branch */ fprintf(sinkfp, - "MAIL FROM: %s", (return_path[0]) ? return_path : user); + "MAIL FROM: %s", (msg->return_path[0]) ? msg->return_path : user); if (ctl->pass8bits || (ctl->mimemsg & MSG_IS_8BIT)) fputs(" BODY=8BITMIME", sinkfp); else if (ctl->mimemsg & MSG_IS_7BIT) fputs(" BODY=7BIT", sinkfp); - fprintf(sinkfp, " SIZE=%ld\r\n", reallen); + fprintf(sinkfp, " SIZE=%ld\r\n", msg->reallen); /* * RFC 1123 requires that the domain name part of the @@ -288,7 +285,7 @@ int open_sink(struct query *ctl, ctl->destaddr = ctl->smtpaddress ? ctl->smtpaddress : "localhost"; *bad_addresses = 0; - for (idp = xmit_names; idp; idp = idp->next) + for (idp = msg->xmit_names; idp; idp = idp->next) if (idp->val.status.mark == XMIT_ACCEPT) { if (strchr(idp->id, '@')) @@ -315,7 +312,7 @@ int open_sink(struct query *ctl, ctl->destaddr = "localhost"; - for (idp = xmit_names; idp; idp = idp->next) + for (idp = msg->xmit_names; idp; idp = idp->next) if (idp->val.status.mark == XMIT_ACCEPT) (*good_addresses)++; @@ -330,7 +327,7 @@ int open_sink(struct query *ctl, * long lists of users and (re)implement %s. */ nameslen = 0; - for (idp = xmit_names; idp; idp = idp->next) + for (idp = msg->xmit_names; idp; idp = idp->next) if ((idp->val.status.mark == XMIT_ACCEPT)) nameslen += (strlen(idp->id) + 1); /* string + ' ' */ if ((*good_addresses == 0)) @@ -342,7 +339,7 @@ int open_sink(struct query *ctl, else { names[0] = '\0'; - for (idp = xmit_names; idp; idp = idp->next) + for (idp = msg->xmit_names; idp; idp = idp->next) if (idp->val.status.mark == XMIT_ACCEPT) { strcat(names, idp->id); @@ -358,7 +355,7 @@ int open_sink(struct query *ctl, /* get From address for %F */ if (strstr(before, "%F")) { - from = xstrdup(return_path); + from = xstrdup(msg->return_path); /* sanitize from in order to contain *only* harmless shell chars */ sanitize(from); @@ -478,8 +475,8 @@ int open_sink(struct query *ctl, strcpy(options, " BODY=7BIT"); } - if ((ctl->server.esmtp_options & ESMTP_SIZE) && reallen > 0) - sprintf(options + strlen(options), " SIZE=%ld", reallen); + if ((ctl->server.esmtp_options & ESMTP_SIZE) && msg->reallen > 0) + sprintf(options + strlen(options), " SIZE=%ld", msg->reallen); /* * Try to get the SMTP listener to take the Return-Path @@ -501,7 +498,7 @@ int open_sink(struct query *ctl, * None of these error conditions generates bouncemail. Comments * below explain for each case why this is so. */ - ap = (return_path[0]) ? return_path : user; + ap = (msg->return_path[0]) ? msg->return_path : user; if (SMTP_from(ctl->smtp_socket, ap, options) != SM_OK) { int smtperr = atoi(smtp_response); @@ -580,7 +577,7 @@ int open_sink(struct query *ctl, /* * Now list the recipient addressees */ - for (idp = xmit_names; idp; idp = idp->next) + for (idp = msg->xmit_names; idp; idp = idp->next) if (idp->val.status.mark == XMIT_ACCEPT) { if (strchr(idp->id, '@')) @@ -693,14 +690,15 @@ int open_warning_by_mail(struct query *ctl) /* set up output sink for a mailed warning to calling user */ { int good, bad; + static struct msgblk msg = {NULL, NULL, "FETCHMAIL-DAEMON", 0}; /* - * We give a null address list as arg 3 because we actually *want* - * this message to go to run.postmaster. The zero length arg 4 means + * We give a null address list as arg 4 because we actually *want* + * this message to go to run.postmaster. The zero length arg 5 means * we won't pass a SIZE option to ESMTP; the message length would * be more trouble than it's worth to compute. */ - return(open_sink(ctl, "FETCHMAIL-DAEMON", NULL, 0, &good, &bad)); + return(open_sink(ctl, &msg, &good, &bad)); } #if defined(HAVE_STDARG_H) -- cgit v1.2.3