aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Andree <matthias.andree@gmx.de>2005-07-31 14:14:32 +0000
committerMatthias Andree <matthias.andree@gmx.de>2005-07-31 14:14:32 +0000
commitcc2cad965d93b5b4e4c39081cee0bafd04a0ff0e (patch)
tree3f3cc8565318007b4f3d61ce1e16f3a14f03b9c5
parentf194002467938d3f4d4cc6ff4dc4fe442d4aba11 (diff)
downloadfetchmail-cc2cad965d93b5b4e4c39081cee0bafd04a0ff0e.tar.gz
fetchmail-cc2cad965d93b5b4e4c39081cee0bafd04a0ff0e.tar.bz2
fetchmail-cc2cad965d93b5b4e4c39081cee0bafd04a0ff0e.zip
Get rid of alloca() in fetchmail.
svn path=/trunk/; revision=4209
-rw-r--r--COPYING2
-rw-r--r--NEWS1
-rw-r--r--alloca.c492
-rw-r--r--configure.ac8
-rw-r--r--driver.c32
-rw-r--r--fetchmail.h16
-rw-r--r--sink.c79
7 files changed, 66 insertions, 564 deletions
diff --git a/COPYING b/COPYING
index ab090041..ade57e94 100644
--- a/COPYING
+++ b/COPYING
@@ -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
diff --git a/NEWS b/NEWS
index 6a63410b..8167e798 100644
--- a/NEWS
+++ b/NEWS
@@ -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)
diff --git a/driver.c b/driver.c
index 9d624b81..5a2c8976 100644
--- a/driver.c
+++ b/driver.c
@@ -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 *);
diff --git a/sink.c b/sink.c
index 7aae42ac..62cc8fdd 100644
--- a/sink.c
+++ b/sink.c
@@ -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;
}
}
}