aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Andree <matthias.andree@gmx.de>2006-08-14 01:28:47 +0000
committerMatthias Andree <matthias.andree@gmx.de>2006-08-14 01:28:47 +0000
commitdf4a264f6a4bf53592f9e273462a8861ea7e6a6d (patch)
tree7fc180164f8bc204cea413b098a9068dbdc2c792
parentc625d7a00b024fe5de26d16b6420abebb1db705c (diff)
downloadfetchmail-df4a264f6a4bf53592f9e273462a8861ea7e6a6d.tar.gz
fetchmail-df4a264f6a4bf53592f9e273462a8861ea7e6a6d.tar.bz2
fetchmail-df4a264f6a4bf53592f9e273462a8861ea7e6a6d.zip
Wrap getaddrinfo() and block SIGALRM where needed.
Also wrap freeaddrinfo() without added functionality. svn path=/branches/BRANCH_6-3/; revision=4895
-rw-r--r--Makefile.am2
-rw-r--r--NEWS5
-rw-r--r--checkalias.c14
-rw-r--r--configure.ac20
-rw-r--r--driver.c8
-rw-r--r--env.c4
-rw-r--r--fetchmail.h3
-rw-r--r--fm_getaddrinfo.c40
-rw-r--r--servport.c6
-rw-r--r--socket.c4
10 files changed, 83 insertions, 23 deletions
diff --git a/Makefile.am b/Makefile.am
index c866488c..db06fee0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,7 +39,7 @@ libfm_a_SOURCES= xmalloc.c base64.c rfc822.c report.c rfc2047e.c \
servport.c ntlm.h smbbyteorder.h smbdes.h smbmd4.h \
smbencrypt.h smbdes.c smbencrypt.c smbmd4.c smbutil.c \
libesmtp/gethostbyname.h libesmtp/gethostbyname.c \
- smbtypes.h
+ smbtypes.h fm_getaddrinfo.c
libfm_a_LIBADD= $(EXTRAOBJ)
libfm_a_DEPENDENCIES= $(EXTRAOBJ)
LDADD = libfm.a @LIBINTL@ $(LIBOBJS)
diff --git a/NEWS b/NEWS
index 6d8f922a..48d6fc40 100644
--- a/NEWS
+++ b/NEWS
@@ -98,8 +98,9 @@ fetchmail 6.3.5 (not yet released):
with new polls, and SIGHUP would be ignored for root users. SIGHUP now matches
documented behavior. SIGUSR1 has always been a wakeup signal for both root
(undocumented) and non-root users. See also the deprecation warning above.
-* Track getaddrinfo() results to properly free them after timeouts,
- reported by Uli Zappe. This MIGHT fix Debian Bug#294547 and Bug#377135.
+* Track getaddrinfo() results to properly free them after timeouts and make sure
+ that getaddrinfo() isn't interrupted by a timeout (which breaks on MacOS X),
+ reported by Uli Zappe. This should fix Debian Bug#294547 and Bug#377135.
* --logfile is now handled more carefully, errors opening the logfile are
now reported to the TTY where fetchmail was started from.
* fetchmail now complains and aborts when it cannot properly daemonize itself.
diff --git a/checkalias.c b/checkalias.c
index 1f0495b9..80356ed2 100644
--- a/checkalias.c
+++ b/checkalias.c
@@ -36,7 +36,7 @@ static int getaddresses(struct addrinfo **result, const char *name)
hints.ai_socktype=SOCK_STREAM;
hints.ai_protocol=PF_UNSPEC;
hints.ai_family=AF_UNSPEC;
- return getaddrinfo(name, NULL, &hints, result);
+ return fm_getaddrinfo(name, NULL, &hints, result);
}
/* XXX FIXME: doesn't detect if an IPv6-mapped IPv4 address
@@ -77,9 +77,9 @@ static int is_ip_alias(const char *name1,const char *name2)
found:
if (res2)
- freeaddrinfo(res2);
+ fm_freeaddrinfo(res2);
if (res1)
- freeaddrinfo(res1);
+ fm_freeaddrinfo(res1);
return rc;
}
@@ -160,16 +160,16 @@ int is_host_alias(const char *name, struct query *ctl, struct addrinfo **res)
hints.ai_socktype=SOCK_STREAM;
hints.ai_flags=AI_CANONNAME;
- e = getaddrinfo(name, NULL, &hints, res);
+ e = fm_getaddrinfo(name, NULL, &hints, res);
if (e == 0)
{
int rr = (strcasecmp(ctl->server.truename, (*res)->ai_canonname) == 0);
- freeaddrinfo(*res); *res = NULL;
+ fm_freeaddrinfo(*res); *res = NULL;
if (rr)
goto match;
- else if (ctl->server.checkalias && 0 == getaddrinfo(ctl->server.truename, NULL, &hints, &res_st))
+ else if (ctl->server.checkalias && 0 == fm_getaddrinfo(ctl->server.truename, NULL, &hints, &res_st))
{
- freeaddrinfo(res_st);
+ fm_freeaddrinfo(res_st);
if (outlevel >= O_DEBUG)
report(stdout, GT_("Checking if %s is really the same node as %s\n"),ctl->server.truename,name);
if (is_ip_alias(ctl->server.truename,name) == TRUE)
diff --git a/configure.ac b/configure.ac
index 03d0b33c..e5012850 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@ dnl
dnl Process this file with autoconf to produce a configure script.
dnl
-AC_INIT([fetchmail],[6.3.5-beta1],[fetchmail-users@lists.berlios.de])
+AC_INIT([fetchmail],[6.3.5-beta2],[fetchmail-users@lists.berlios.de])
AC_CONFIG_SRCDIR([fetchmail.h])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_LIBOBJ_DIR([.])
@@ -138,7 +138,7 @@ AC_SUBST(EXTRAOBJ)
AC_CHECK_FUNCS(tcsetattr stty setsid geteuid seteuid dnl
strerror syslog snprintf vprintf vsnprintf vsyslog dnl
- atexit inet_aton strftime setrlimit socketpair sigprocmask dnl
+ atexit inet_aton strftime setrlimit socketpair dnl
sigaction strdup setlocale)
AC_CHECK_DECLS(strerror)
@@ -428,6 +428,22 @@ AC_CHECK_FUNCS(getnameinfo inet_ntop)
AM_CONDITIONAL(NEED_GETADDRINFO, test "$ac_cv_search_getaddrinfo" != "none required")
AM_CONDITIONAL(NEED_GETNAMEINFO, test "$ac_cv_func_getnameinfo" != yes)
+dnl Check if getaddrinfo is async-signal-safe - most implementations aren't
+if test "$ac_cv_search_getaddrinfo" = "none required" ; then
+ AC_MSG_CHECKING(if your getaddrinfo is async-signal-safe)
+ gai_ts=no
+ dnl we have getaddrinfo() - check if the OS is known to have a async-signal-safe implementation
+ case $target_os in
+ linux*) gai_ts=yes ;;
+ freebsd5.5|freebsd6*|freebsd7*) gai_ts=yes ;;
+ solaris2.8|solaris2.9|solaris2.10) gai_ts=yes ;;
+ esac
+ AC_MSG_RESULT($gai_ts)
+ if test $gai_ts = yes ; then
+ AC_DEFINE(GETADDRINFO_ASYNCSAFE, 1, [define to 1 if you know your getaddrinfo function is async-signal-safe])
+ fi
+fi
+
# This version of the Kerberos 4 and 5 options addresses the follwing issues:
#
# * Build correctly under Heimdal kerberos if it is compiled with db2 and
diff --git a/driver.c b/driver.c
index ae4b7e69..d3c8c970 100644
--- a/driver.c
+++ b/driver.c
@@ -862,11 +862,11 @@ static int do_session(
sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
if (ai0) {
- freeaddrinfo(ai0); ai0 = NULL;
+ fm_freeaddrinfo(ai0); ai0 = NULL;
}
if (ai1) {
- freeaddrinfo(ai1); ai1 = NULL;
+ fm_freeaddrinfo(ai1); ai1 = NULL;
}
if (js == THROW_TIMEOUT)
@@ -998,7 +998,7 @@ static int do_session(
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_CANONNAME;
- error = getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
+ error = fm_getaddrinfo(ctl->server.queryname, NULL, &hints, &res);
if (error)
{
report(stderr,
@@ -1024,7 +1024,7 @@ static int do_session(
ctl->server.trueaddr = (struct sockaddr *)xmalloc(res->ai_addrlen);
ctl->server.trueaddr_len = res->ai_addrlen;
memcpy(ctl->server.trueaddr, res->ai_addr, res->ai_addrlen);
- freeaddrinfo(res);
+ fm_freeaddrinfo(res);
}
}
}
diff --git a/env.c b/env.c
index 85c992c0..9b9e608c 100644
--- a/env.c
+++ b/env.c
@@ -161,7 +161,7 @@ char *host_fqdn(int required)
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags=AI_CANONNAME;
- e = getaddrinfo(tmpbuf, NULL, &hints, &res);
+ e = fm_getaddrinfo(tmpbuf, NULL, &hints, &res);
if (e) {
/* exit with error message */
fprintf(stderr,
@@ -177,7 +177,7 @@ char *host_fqdn(int required)
}
result = xstrdup(res->ai_canonname);
- freeaddrinfo(res);
+ fm_freeaddrinfo(res);
}
else
result = xstrdup(tmpbuf);
diff --git a/fetchmail.h b/fetchmail.h
index 7c63e22a..cfe6a634 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -759,5 +759,8 @@ int servport(const char *service);
# define NI_DGRAM 16
#endif
+int fm_getaddrinfo(const char *node, const char *serv, const struct addrinfo *hints, struct addrinfo **res);
+void fm_freeaddrinfo(struct addrinfo *ai);
+
#endif
/* fetchmail.h ends here */
diff --git a/fm_getaddrinfo.c b/fm_getaddrinfo.c
new file mode 100644
index 00000000..97cec65c
--- /dev/null
+++ b/fm_getaddrinfo.c
@@ -0,0 +1,40 @@
+#include "config.h"
+#include "fetchmail.h"
+#include "i18n.h"
+
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+
+/** This is a getaddrinfo() replacement that blocks SIGALRM,
+ * to avoid issues with non-reentrant getaddrinfo() implementations
+ * after SIGALRM timeouts, for instance on MacOS X or NetBSD. */
+int fm_getaddrinfo(const char *node, const char *serv, const struct addrinfo *hints, struct addrinfo **res)
+{
+ int rc;
+
+#ifndef GETADDRINFO_ASYNCSAFE
+ sigset_t ss, os;
+
+ sigemptyset(&ss);
+ sigaddset(&ss, SIGALRM);
+
+ if (sigprocmask(SIG_BLOCK, &ss, &os))
+ report(stderr, GT_("Cannot modify signal mask: %s"), strerror(errno));
+#endif
+
+ rc = getaddrinfo(node, serv, hints, res);
+
+#ifndef GETADDRINFO_ASYNCSAFE
+ if (sigprocmask(SIG_SETMASK, &os, NULL))
+ report(stderr, GT_("Cannot modify signal mask: %s"), strerror(errno));
+#endif
+
+ return rc;
+}
+
+/** this is a debugging freeaddrinfo() wrapper. */
+void fm_freeaddrinfo(struct addrinfo *ai)
+{
+ freeaddrinfo(ai);
+}
diff --git a/servport.c b/servport.c
index 2849f7c2..0a12c640 100644
--- a/servport.c
+++ b/servport.c
@@ -48,7 +48,7 @@ int servport(const char *service) {
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
- e = getaddrinfo(NULL, service, &hints, &res);
+ e = fm_getaddrinfo(NULL, service, &hints, &res);
if (e) {
report(stderr, GT_("getaddrinfo(NULL, \"%s\") error: %s\n"),
service, gai_strerror(e));
@@ -64,10 +64,10 @@ int servport(const char *service) {
break;
#endif
default:
- freeaddrinfo(res);
+ fm_freeaddrinfo(res);
goto err;
}
- freeaddrinfo(res);
+ fm_freeaddrinfo(res);
}
} else {
if (u == 0 || u > 65535)
diff --git a/socket.c b/socket.c
index 080f1888..52e9f1cf 100644
--- a/socket.c
+++ b/socket.c
@@ -277,7 +277,7 @@ int SockOpen(const char *host, const char *service,
memset(&req, 0, sizeof(struct addrinfo));
req.ai_socktype = SOCK_STREAM;
- i = getaddrinfo(host, service, &req, ai0);
+ i = fm_getaddrinfo(host, service, &req, ai0);
if (i) {
report(stderr, GT_("getaddrinfo(\"%s\",\"%s\") error: %s\n"),
host, service, gai_strerror(i));
@@ -340,7 +340,7 @@ int SockOpen(const char *host, const char *service,
break;
}
- freeaddrinfo(*ai0);
+ fm_freeaddrinfo(*ai0);
*ai0 = NULL;
if (i == -1)