diff options
-rw-r--r-- | COPYING | 2 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | alloca.c | 492 | ||||
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | driver.c | 32 | ||||
-rw-r--r-- | fetchmail.h | 16 | ||||
-rw-r--r-- | sink.c | 79 |
7 files changed, 66 insertions, 564 deletions
@@ -6,7 +6,7 @@ is under GPL version 2. Tridge has granted a specific exemption for his GPL-licensed code to be linked with non-GPL-compliant code in fetchmail. The relevant files are smb*.[ch] and ntlm.h. -The following files are public-domain: acconfig.h, alloca.c, md5c.c, md5.h. +The following files are public-domain: acconfig.h, md5c.c, md5.h. The following file is under a variant of the InnerNet Version 2 license (with the advertising clause removed for GPL compatibility) supplied @@ -161,6 +161,7 @@ OTHER CHANGES: 2. didn't match IP aliases versus MX hosts. Matthias Andree * gettext has been removed from the fetchmail package. Install GNU gettext 0.14 separately for NLS (i18n). Matthias Andree +* Got rid of alloca() in fetchmail proper. Matthias Andree fetchmail-6.2.5 (Wed Oct 15 18:39:22 EDT 2003), 23079 lines: diff --git a/alloca.c b/alloca.c deleted file mode 100644 index ec432dfc..00000000 --- a/alloca.c +++ /dev/null @@ -1,492 +0,0 @@ -/* alloca.c -- allocate automatically reclaimed memory - (Mostly) portable public-domain implementation -- D A Gwyn - - This implementation of the PWB library alloca function, - which is used to allocate space off the run-time stack so - that it is automatically reclaimed upon procedure exit, - was inspired by discussions with J. Q. Johnson of Cornell. - J.Otto Tennant <jot@cray.com> contributed the Cray support. - - There are some preprocessor constants that can - be defined when compiling for your specific system, for - improved efficiency; however, the defaults should be okay. - - The general concept of this implementation is to keep - track of all alloca-allocated blocks, and reclaim any - that are found to be deeper in the stack than the current - invocation. This heuristic does not reclaim storage as - soon as it becomes invalid, but it will do so eventually. - - As a special case, alloca(0) reclaims storage without - allocating any. It is a good idea to use alloca(0) in - your main control loop, etc. to force garbage collection. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef emacs -#include "blockinput.h" -#endif - -/* If compiling with GCC 2, this file's not needed. */ -#if !defined (__GNUC__) || __GNUC__ < 2 - -/* If someone has defined alloca as a macro, - there must be some other way alloca is supposed to work. */ -#ifndef alloca - -#ifdef emacs -#ifdef static -/* actually, only want this if static is defined as "" - -- this is for usg, in which emacs must undefine static - in order to make unexec workable - */ -#ifndef STACK_DIRECTION -you -lose --- must know STACK_DIRECTION at compile-time -#endif /* STACK_DIRECTION undefined */ -#endif /* static */ -#endif /* emacs */ - -/* If your stack is a linked list of frames, you have to - provide an "address metric" ADDRESS_FUNCTION macro. */ - -#if defined (CRAY) && defined (CRAY_STACKSEG_END) -long i00afunc (); -#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) -#else -#define ADDRESS_FUNCTION(arg) &(arg) -#endif - -#if __STDC__ -typedef void *pointer; -#else -typedef char *pointer; -#endif - -#define NULL 0 - -/* Different portions of Emacs need to call different versions of - malloc. The Emacs executable needs alloca to call xmalloc, because - ordinary malloc isn't protected from input signals. On the other - hand, the utilities in lib-src need alloca to call malloc; some of - them are very simple, and don't have an xmalloc routine. - - Non-Emacs programs expect this to call use xmalloc. - - Callers below should use malloc. */ - -#ifndef emacs -#define malloc xmalloc -#endif -extern pointer malloc (); - -/* Define STACK_DIRECTION if you know the direction of stack - growth for your system; otherwise it will be automatically - deduced at run-time. - - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ - -#ifndef STACK_DIRECTION -#define STACK_DIRECTION 0 /* Direction unknown. */ -#endif - -#if STACK_DIRECTION != 0 - -#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ - -#else /* STACK_DIRECTION == 0; need run-time code. */ - -static int stack_dir; /* 1 or -1 once known. */ -#define STACK_DIR stack_dir - -static void -find_stack_direction () -{ - static char *addr = NULL; /* Address of first `dummy', once known. */ - auto char dummy; /* To get stack address. */ - - if (addr == NULL) - { /* Initial entry. */ - addr = ADDRESS_FUNCTION (dummy); - - find_stack_direction (); /* Recurse once. */ - } - else - { - /* Second entry. */ - if (ADDRESS_FUNCTION (dummy) > addr) - stack_dir = 1; /* Stack grew upward. */ - else - stack_dir = -1; /* Stack grew downward. */ - } -} - -#endif /* STACK_DIRECTION == 0 */ - -/* An "alloca header" is used to: - (a) chain together all alloca'ed blocks; - (b) keep track of stack depth. - - It is very important that sizeof(header) agree with malloc - alignment chunk size. The following default should work okay. */ - -#ifndef ALIGN_SIZE -#define ALIGN_SIZE sizeof(double) -#endif - -typedef union hdr -{ - char align[ALIGN_SIZE]; /* To force sizeof(header). */ - struct - { - union hdr *next; /* For chaining headers. */ - char *deep; /* For stack depth measure. */ - } h; -} header; - -static header *last_alloca_header = NULL; /* -> last alloca header. */ - -/* Return a pointer to at least SIZE bytes of storage, - which will be automatically reclaimed upon exit from - the procedure that called alloca. Originally, this space - was supposed to be taken from the current stack frame of the - caller, but that method cannot be made to work for some - implementations of C, for example under Gould's UTX/32. */ - -pointer -alloca (size) - unsigned size; -{ - auto char probe; /* Probes stack depth: */ - register char *depth = ADDRESS_FUNCTION (probe); - -#if STACK_DIRECTION == 0 - if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction (); -#endif - - /* Reclaim garbage, defined as all alloca'd storage that - was allocated from deeper in the stack than currently. */ - - { - register header *hp; /* Traverses linked list. */ - -#ifdef emacs - BLOCK_INPUT; -#endif - - for (hp = last_alloca_header; hp != NULL;) - if ((STACK_DIR > 0 && hp->h.deep > depth) - || (STACK_DIR < 0 && hp->h.deep < depth)) - { - register header *np = hp->h.next; - - free ((pointer) hp); /* Collect garbage. */ - - hp = np; /* -> next header. */ - } - else - break; /* Rest are not deeper. */ - - last_alloca_header = hp; /* -> last valid storage. */ - -#ifdef emacs - UNBLOCK_INPUT; -#endif - } - - if (size == 0) - return NULL; /* No allocation required. */ - - /* Allocate combined header + user data storage. */ - - { - register pointer new = malloc (sizeof (header) + size); - /* Address of header. */ - - ((header *) new)->h.next = last_alloca_header; - ((header *) new)->h.deep = depth; - - last_alloca_header = (header *) new; - - /* User storage begins just after header. */ - - return (pointer) ((char *) new + sizeof (header)); - } -} - -#if defined (CRAY) && defined (CRAY_STACKSEG_END) - -#ifdef DEBUG_I00AFUNC -#include <stdio.h> -#endif - -#ifndef CRAY_STACK -#define CRAY_STACK -#ifndef CRAY2 -/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ -struct stack_control_header - { - long shgrow:32; /* Number of times stack has grown. */ - long shaseg:32; /* Size of increments to stack. */ - long shhwm:32; /* High water mark of stack. */ - long shsize:32; /* Current size of stack (all segments). */ - }; - -/* The stack segment linkage control information occurs at - the high-address end of a stack segment. (The stack - grows from low addresses to high addresses.) The initial - part of the stack segment linkage control information is - 0200 (octal) words. This provides for register storage - for the routine which overflows the stack. */ - -struct stack_segment_linkage - { - long ss[0200]; /* 0200 overflow words. */ - long sssize:32; /* Number of words in this segment. */ - long ssbase:32; /* Offset to stack base. */ - long:32; - long sspseg:32; /* Offset to linkage control of previous - segment of stack. */ - long:32; - long sstcpt:32; /* Pointer to task common address block. */ - long sscsnm; /* Private control structure number for - microtasking. */ - long ssusr1; /* Reserved for user. */ - long ssusr2; /* Reserved for user. */ - long sstpid; /* Process ID for pid based multi-tasking. */ - long ssgvup; /* Pointer to multitasking thread giveup. */ - long sscray[7]; /* Reserved for Cray Research. */ - long ssa0; - long ssa1; - long ssa2; - long ssa3; - long ssa4; - long ssa5; - long ssa6; - long ssa7; - long sss0; - long sss1; - long sss2; - long sss3; - long sss4; - long sss5; - long sss6; - long sss7; - }; - -#else /* CRAY2 */ -/* The following structure defines the vector of words - returned by the STKSTAT library routine. */ -struct stk_stat - { - long now; /* Current total stack size. */ - long maxc; /* Amount of contiguous space which would - be required to satisfy the maximum - stack demand to date. */ - long high_water; /* Stack high-water mark. */ - long overflows; /* Number of stack overflow ($STKOFEN) calls. */ - long hits; /* Number of internal buffer hits. */ - long extends; /* Number of block extensions. */ - long stko_mallocs; /* Block allocations by $STKOFEN. */ - long underflows; /* Number of stack underflow calls ($STKRETN). */ - long stko_free; /* Number of deallocations by $STKRETN. */ - long stkm_free; /* Number of deallocations by $STKMRET. */ - long segments; /* Current number of stack segments. */ - long maxs; /* Maximum number of stack segments so far. */ - long pad_size; /* Stack pad size. */ - long current_address; /* Current stack segment address. */ - long current_size; /* Current stack segment size. This - number is actually corrupted by STKSTAT to - include the fifteen word trailer area. */ - long initial_address; /* Address of initial segment. */ - long initial_size; /* Size of initial segment. */ - }; - -/* The following structure describes the data structure which trails - any stack segment. I think that the description in 'asdef' is - out of date. I only describe the parts that I am sure about. */ - -struct stk_trailer - { - long this_address; /* Address of this block. */ - long this_size; /* Size of this block (does not include - this trailer). */ - long unknown2; - long unknown3; - long link; /* Address of trailer block of previous - segment. */ - long unknown5; - long unknown6; - long unknown7; - long unknown8; - long unknown9; - long unknown10; - long unknown11; - long unknown12; - long unknown13; - long unknown14; - }; - -#endif /* CRAY2 */ -#endif /* not CRAY_STACK */ - -#ifdef CRAY2 -/* Determine a "stack measure" for an arbitrary ADDRESS. - I doubt that "lint" will like this much. */ - -static long -i00afunc (long *address) -{ - struct stk_stat status; - struct stk_trailer *trailer; - long *block, size; - long result = 0; - - /* We want to iterate through all of the segments. The first - step is to get the stack status structure. We could do this - more quickly and more directly, perhaps, by referencing the - $LM00 common block, but I know that this works. */ - - STKSTAT (&status); - - /* Set up the iteration. */ - - trailer = (struct stk_trailer *) (status.current_address - + status.current_size - - 15); - - /* There must be at least one stack segment. Therefore it is - a fatal error if "trailer" is null. */ - - if (trailer == 0) - abort (); - - /* Discard segments that do not contain our argument address. */ - - while (trailer != 0) - { - block = (long *) trailer->this_address; - size = trailer->this_size; - if (block == 0 || size == 0) - abort (); - trailer = (struct stk_trailer *) trailer->link; - if ((block <= address) && (address < (block + size))) - break; - } - - /* Set the result to the offset in this segment and add the sizes - of all predecessor segments. */ - - result = address - block; - - if (trailer == 0) - { - return result; - } - - do - { - if (trailer->this_size <= 0) - abort (); - result += trailer->this_size; - trailer = (struct stk_trailer *) trailer->link; - } - while (trailer != 0); - - /* We are done. Note that if you present a bogus address (one - not in any segment), you will get a different number back, formed - from subtracting the address of the first block. This is probably - not what you want. */ - - return (result); -} - -#else /* not CRAY2 */ -/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. - Determine the number of the cell within the stack, - given the address of the cell. The purpose of this - routine is to linearize, in some sense, stack addresses - for alloca. */ - -static long -i00afunc (long address) -{ - long stkl = 0; - - long size, pseg, this_segment, stack; - long result = 0; - - struct stack_segment_linkage *ssptr; - - /* Register B67 contains the address of the end of the - current stack segment. If you (as a subprogram) store - your registers on the stack and find that you are past - the contents of B67, you have overflowed the segment. - - B67 also points to the stack segment linkage control - area, which is what we are really interested in. */ - - stkl = CRAY_STACKSEG_END (); - ssptr = (struct stack_segment_linkage *) stkl; - - /* If one subtracts 'size' from the end of the segment, - one has the address of the first word of the segment. - - If this is not the first segment, 'pseg' will be - nonzero. */ - - pseg = ssptr->sspseg; - size = ssptr->sssize; - - this_segment = stkl - size; - - /* It is possible that calling this routine itself caused - a stack overflow. Discard stack segments which do not - contain the target address. */ - - while (!(this_segment <= address && address <= stkl)) - { -#ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); -#endif - if (pseg == 0) - break; - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - this_segment = stkl - size; - } - - result = address - this_segment; - - /* If you subtract pseg from the current end of the stack, - you get the address of the previous stack segment's end. - This seems a little convoluted to me, but I'll bet you save - a cycle somewhere. */ - - while (pseg != 0) - { -#ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o\n", pseg, size); -#endif - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - result += size; - } - return (result); -} - -#endif /* not CRAY2 */ -#endif /* CRAY */ - -#endif /* no alloca */ -#endif /* not GCC version 2 */ diff --git a/configure.ac b/configure.ac index ace8bad7..f6bde8b7 100644 --- a/configure.ac +++ b/configure.ac @@ -28,7 +28,7 @@ AC_TYPE_SIZE_T AC_TYPE_PID_T AC_TYPE_SIGNAL AC_CHECK_HEADERS([unistd.h termios.h termio.h sgtty.h stdarg.h \ - alloca.h sys/itimer.h fcntl.h sys/fcntl.h memory.h sys/wait.h \ + sys/itimer.h fcntl.h sys/fcntl.h memory.h sys/wait.h \ arpa/inet.h arpa/nameser.h netinet/in.h net/socket.h \ sys/select.h sys/socket.h sys/time.h langinfo.h]) AC_CHECK_HEADERS([resolv.h],,,[ @@ -47,8 +47,6 @@ AM_PROG_LEX AC_PROG_MAKE_SET AC_PROG_YACC -AC_FUNC_ALLOCA - # Check for LynxOS special case: -lbsd needed (at least on 2.3.0) and -s # not working. if test `uname` = "LynxOS" @@ -113,10 +111,6 @@ AC_CHECK_FUNC(getopt_long, [], EXTRAOBJ="$EXTRAOBJ getopt.\$(OBJEXT) getopt1.\$(OBJEXT)"]) AC_FUNC_VPRINTF -if test -n "$ALLOCA" -then - EXTRAOBJ="$EXTRAOBJ alloca.\$(OBJEXT)" -fi AC_SUBST(EXTRAOBJ) @@ -174,7 +174,7 @@ char *principal; } } - xalloca(ticket, KTEXT, sizeof (KTEXT_ST)); + ticket = xmalloc(sizeof (KTEXT_ST)); rem = (krb_sendauth (0L, socket, ticket, prin ? prin : "pop", inst ? inst : canonical, @@ -186,6 +186,7 @@ char *principal; ((struct sockaddr_in *) 0), ((struct sockaddr_in *) 0), "KPOPV0.1")); + free(ticket); if (prin_copy) { free(prin_copy); @@ -418,7 +419,7 @@ static void mark_oversized(struct query *ctl, int num, int size) } static int fetch_messages(int mailserver_socket, struct query *ctl, - int count, int *msgsizes, int maxfetch, + int count, int **msgsizes, int maxfetch, int *fetches, int *dispatches, int *deletions) /* fetch messages in lockstep mode */ { @@ -439,7 +440,8 @@ static int fetch_messages(int mailserver_socket, struct query *ctl, } /* Time to allocate memory to store the sizes */ - xalloca(msgsizes, int *, sizeof(int) * fetchsizelimit); + xfree(*msgsizes); + *msgsizes = xmalloc(sizeof(int) * fetchsizelimit); } /* @@ -521,16 +523,17 @@ static int fetch_messages(int mailserver_socket, struct query *ctl, if (lastnum > count) lastnum = count; for (i = 0; i < fetchsizelimit; i++) - msgsizes[i] = 0; + (*msgsizes)[i] = 0; stage = STAGE_GETSIZES; - err = (ctl->server.base_protocol->getpartialsizes)(mailserver_socket, num, lastnum, msgsizes); - if (err != 0) + err = (ctl->server.base_protocol->getpartialsizes)(mailserver_socket, num, lastnum, *msgsizes); + if (err != 0) { return err; + } stage = oldstage; } - msgsize = msgsizes ? msgsizes[num-firstnum] : 0; + msgsize = *msgsizes ? (*msgsizes)[num-firstnum] : 0; /* check if the message is oversized */ if (NUM_NONZERO(ctl->limit) && (msgsize > ctl->limit)) @@ -1458,7 +1461,7 @@ is restored.")); if (proto->getsizes && !(proto->getpartialsizes && NUM_NONZERO(ctl->fetchsizelimit))) { - xalloca(msgsizes, int *, sizeof(int) * count); + msgsizes = xmalloc(sizeof(int) * count); for (i = 0; i < count; i++) msgsizes[i] = 0; @@ -1480,7 +1483,7 @@ is restored.")); /* fetch in lockstep mode */ err = fetch_messages(mailserver_socket, ctl, - count, msgsizes, + count, &msgsizes, maxfetch, &fetches, &dispatches, &deletions); if (err) @@ -1538,7 +1541,8 @@ is restored.")); } } - msg = (const char *)NULL; /* sacrifice to -Wall */ + /* no report on PS_MAXFETCH or PS_UNDEFINED or PS_AUTHFAIL */ + msg = NULL; switch (err) { case PS_SOCKET: @@ -1569,11 +1573,7 @@ is restored.")); report(stderr, GT_("undefined error\n")); break; } - /* no report on PS_MAXFETCH or PS_UNDEFINED or PS_AUTHFAIL */ - if (err==PS_SOCKET || err==PS_SYNTAX - || err==PS_IOERR || err==PS_ERROR || err==PS_PROTOCOL - || err==PS_LOCKBUSY || err==PS_SMTP || err==PS_DNS) - { + if (msg) { char *stem; if (phase == FORWARDING_WAIT || phase == LISTENER_WAIT) @@ -1584,6 +1584,8 @@ is restored.")); } closeUp: + xfree(msgsizes); + /* execute wrapup command, if any */ if (ctl->postconnect && (err = system(ctl->postconnect))) { diff --git a/fetchmail.h b/fetchmail.h index 89d8e608..eede713a 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -605,22 +605,6 @@ XMALLOCTYPE *xmalloc(size_t); XMALLOCTYPE *xrealloc(/*@null@*/ XMALLOCTYPE *, size_t); #define xfree(p) { if (p) { free(p); } (p) = 0; } char *xstrdup(const char *); -#if defined(HAVE_ALLOCA_H) -#include <alloca.h> -#else -#ifdef _AIX -#pragma alloca -#endif -#endif -#define xalloca(ptr, t, n) if (!(ptr = (t) alloca(n)))\ - {report(stderr, GT_("alloca failed")); exit(PS_UNDEFINED);} -#if 0 -/* - * This is a hack to help xgettext which cannot find strings in - * macro definitions like the one for xalloca above. - */ -static char *dummy = gettext_noop("alloca failed"); -#endif /* protocol driver and methods */ int doPOP2 (struct query *); @@ -131,8 +131,7 @@ int smtp_open(struct query *ctl) if(ctl->smtphost[0]=='/') ctl->listener = LMTP_MODE; - xalloca(parsed_host, char *, strlen(idp->id) + 1); - strcpy(parsed_host, idp->id); + parsed_host = xstrdup(idp->id); if ((cp = strrchr(parsed_host, '/'))) { @@ -157,6 +156,7 @@ int smtp_open(struct query *ctl) { set_timeout(0); phase = oldphase; + xfree(parsed_host); return(ctl->smtp_socket); /* success */ } @@ -245,6 +245,7 @@ int smtp_open(struct query *ctl) if (outlevel >= O_DEBUG && ctl->smtp_socket != -1) report(stdout, GT_("forwarding to %s\n"), ctl->smtphost); + xfree(parsed_host); return(ctl->smtp_socket); } @@ -452,8 +453,7 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg) struct idlist *walk; int found = 0; - xalloca(responses[0], char *, strlen(smtp_response)+1); - strcpy(responses[0], smtp_response); + responses[0] = xstrdup(smtp_response); #ifdef __UNUSED__ /* @@ -505,15 +505,16 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg) * */ if (run.spambounce) - { - char rejmsg[160]; - snprintf(rejmsg, sizeof(rejmsg), - "spam filter or virus scanner rejected message because:\r\n" - "%s\r\n", responses[0]); - - send_bouncemail(ctl, msg, XMIT_ACCEPT, - rejmsg, 1, responses); - } + { + char rejmsg[160]; + snprintf(rejmsg, sizeof(rejmsg), + "spam filter or virus scanner rejected message because:\r\n" + "%s\r\n", responses[0]); + + send_bouncemail(ctl, msg, XMIT_ACCEPT, + rejmsg, 1, responses); + } + free(responses[0]); return(PS_REFUSED); } @@ -539,6 +540,7 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg) send_bouncemail(ctl, msg, XMIT_ACCEPT, "This message was too large (SMTP error 552).\r\n", 1, responses); + free(responses[0]); return(PS_REFUSED); case 553: /* invalid sending domain */ @@ -555,6 +557,7 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg) "Invalid address in MAIL FROM (SMTP error 553).\r\n", 1, responses); #endif /* __DONT_FEED_THE_SPAMMERS__ */ + free(responses[0]); return(PS_REFUSED); default: @@ -564,6 +567,7 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg) send_bouncemail(ctl, msg, XMIT_ACCEPT, "General SMTP/ESMTP error.\r\n", 1, responses); + free(responses[0]); return(PS_REFUSED); } /* @@ -583,6 +587,7 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg) * these are not actual failures, we're very likely to be * able to recover on the next cycle. */ + free(responses[0]); return(PS_TRANSIENT); } } @@ -818,7 +823,7 @@ static int is_dottedquad(const char *hostname) } static int open_smtp_sink(struct query *ctl, struct msgblk *msg, - int *good_addresses, int *bad_addresses) + int *good_addresses, int *bad_addresses /* this must be signed, to prevent endless loop in from_addresses */) /* open an SMTP stream */ { const char *ap; @@ -933,7 +938,7 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg, for (idp = msg->recipients; idp; idp = idp->next) total_addresses++; #ifdef EXPLICIT_BOUNCE_ON_BAD_ADDRESS - xalloca(from_responses, char **, sizeof(char *) * total_addresses); + from_responses = xmalloc(sizeof(char *) * total_addresses); #endif /* EXPLICIT_BOUNCE_ON_BAD_ADDRESS */ for (idp = msg->recipients; idp; idp = idp->next) if (idp->val.status.mark == XMIT_ACCEPT) @@ -943,6 +948,12 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg, if ((smtp_err = SMTP_rcpt(ctl->smtp_socket, address)) == SM_UNRECOVERABLE) { smtp_close(ctl, 0); +transient: +#ifdef EXPLICIT_BOUNCE_ON_BAD_ADDRESS + while (*bad_addresses) + free(from_responses[*--bad_addresses]); + free(from_responses); +#endif /* EXPLICIT_BOUNCE_ON_BAD_ADDRESS */ return(PS_TRANSIENT); } if (smtp_err == SM_OK) @@ -957,9 +968,7 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg, case PS_SUCCESS: #ifdef EXPLICIT_BOUNCE_ON_BAD_ADDRESS - xalloca(from_responses[*bad_addresses], - char *, - strlen(smtp_response)+1); + from_responses[*bad_addresses] = xstrdup(smtp_response); strcpy(from_responses[*bad_addresses], smtp_response); #endif /* EXPLICIT_BOUNCE_ON_BAD_ADDRESS */ @@ -987,7 +996,7 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg, * we return exactly that. */ SMTP_rset(ctl->smtp_socket); /* required by RFC1870 */ - return(PS_TRANSIENT); + goto transient; } #ifdef EXPLICIT_BOUNCE_ON_BAD_ADDRESS /* @@ -998,6 +1007,9 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg, send_bouncemail(ctl, msg, XMIT_RCPTBAD, "Some addresses were rejected by the MDA fetchmail forwards to.\r\n", *bad_addresses, from_responses); + while (*bad_addresses) + free(from_responses[*--bad_addresses]); + free(from_responses); #endif /* EXPLICIT_BOUNCE_ON_BAD_ADDRESS */ /* @@ -1418,32 +1430,27 @@ int close_sink(struct query *ctl, struct msgblk *msg, flag forward) } else { - int i, errors; + int i, errors, rc = FALSE; char **responses; /* eat the RFC2033-required responses, saving errors */ - xalloca(responses, char **, sizeof(char *) * lmtp_responses); + responses = xmalloc(sizeof(char *) * lmtp_responses); for (errors = i = 0; i < lmtp_responses; i++) { if ((smtp_err = SMTP_ok(ctl->smtp_socket)) == SM_UNRECOVERABLE) { smtp_close(ctl, 0); - return(FALSE); + goto unrecov; } - if (smtp_err == SM_OK) - responses[i] = (char *)NULL; - else + if (smtp_err != SM_OK) { - xalloca(responses[errors], - char *, - strlen(smtp_response)+1); - strcpy(responses[errors], smtp_response); + responses[errors] = xstrdup(smtp_response); errors++; } } if (errors == 0) - return(TRUE); /* all deliveries succeeded */ + rc = TRUE; /* all deliveries succeeded */ else /* * One or more deliveries failed. @@ -1453,9 +1460,15 @@ int close_sink(struct query *ctl, struct msgblk *msg, flag forward) * message from the server so it won't be * re-forwarded on subsequent poll cycles. */ - return(send_bouncemail(ctl, msg, XMIT_ACCEPT, - "LMTP partial delivery failure.\r\n", - errors, responses)); + rc = send_bouncemail(ctl, msg, XMIT_ACCEPT, + "LMTP partial delivery failure.\r\n", + errors, responses); + +unrecov: + for (i = 0; i < errors; i++) + free(responses[i]); + free(responses); + return rc; } } } |