summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/auto-aux/gethostbyaddr.c54
-rw-r--r--config/auto-aux/gethostbyname.c41
-rwxr-xr-xconfig/auto-aux/trycompile7
-rw-r--r--config/s-templ.h12
-rwxr-xr-xconfigure18
-rw-r--r--otherlibs/unix/gethost.c110
6 files changed, 229 insertions, 13 deletions
diff --git a/config/auto-aux/gethostbyaddr.c b/config/auto-aux/gethostbyaddr.c
new file mode 100644
index 000000000..5a10598ee
--- /dev/null
+++ b/config/auto-aux/gethostbyaddr.c
@@ -0,0 +1,54 @@
+/***********************************************************************/
+/* */
+/* Objective Caml */
+/* */
+/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
+/* */
+/* Copyright 2002 Institut National de Recherche en Informatique et */
+/* en Automatique. All rights reserved. This file is distributed */
+/* under the terms of the GNU Library General Public License, with */
+/* the special exception on linking described in file ../../LICENSE. */
+/* */
+/***********************************************************************/
+
+/* $Id$ */
+
+#include <sys/types.h>
+#include <netdb.h>
+
+int main(int argc, char ** argv)
+{
+#if NUM_ARGS == 7
+ char * address;
+ int length;
+ int type;
+ struct hostent h;
+ char buffer[10];
+ int buflen;
+ int h_errnop;
+ struct hostent * hp;
+ hp = gethostbyaddr_r(address, length, type, &h,
+ buffer, buflen, &h_errnop);
+#elif NUM_ARGS == 8
+ char * address;
+ int length;
+ int type;
+ struct hostent h;
+ char buffer[10];
+ int buflen;
+ int h_errnop;
+ struct hostent * hp;
+ int rc;
+ rc = gethostbyaddr_r(address, length, type, &h,
+ buffer, buflen, &hp, &h_errnop);
+#elif NUM_ARGS == 5
+ char * address;
+ int length;
+ int type;
+ struct hostent h;
+ struct hostent_data hdata;
+ int rc;
+ rc = gethostbyaddr_r(address, length, type, &h, &hdata);
+#endif
+ return 0;
+}
diff --git a/config/auto-aux/gethostbyname.c b/config/auto-aux/gethostbyname.c
new file mode 100644
index 000000000..fa475b16d
--- /dev/null
+++ b/config/auto-aux/gethostbyname.c
@@ -0,0 +1,41 @@
+/***********************************************************************/
+/* */
+/* Objective Caml */
+/* */
+/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
+/* */
+/* Copyright 2002 Institut National de Recherche en Informatique et */
+/* en Automatique. All rights reserved. This file is distributed */
+/* under the terms of the GNU Library General Public License, with */
+/* the special exception on linking described in file ../../LICENSE. */
+/* */
+/***********************************************************************/
+
+/* $Id$ */
+
+#include <sys/types.h>
+#include <netdb.h>
+
+int main(int argc, char ** argv)
+{
+#if NUM_ARGS == 5
+ struct hostent *hp;
+ struct hostent h;
+ char buffer[10];
+ int h_errno;
+ hp = gethostbyname_r("www.caml.org", &h, buffer, 10, &h_errno);
+#elif NUM_ARGS == 6
+ struct hostent *hp;
+ struct hostent h;
+ char buffer[10];
+ int h_errno;
+ int rc;
+ rc = gethostbyname_r("www.caml.org", &h, buffer, 10, &hp, &h_errno);
+#elif NUM_ARGS == 3
+ struct hostent h;
+ struct hostent_data hdata;
+ int rc;
+ rc = gethostbyname_r("www.caml.org", &h, &hdata);
+#endif
+ return 0;
+}
diff --git a/config/auto-aux/trycompile b/config/auto-aux/trycompile
new file mode 100755
index 000000000..797a1c386
--- /dev/null
+++ b/config/auto-aux/trycompile
@@ -0,0 +1,7 @@
+#!/bin/sh
+if test "$verbose" = yes; then
+echo "trycompile: $cc -o tst $* $cclibs" >&2
+$cc -o tst $* $cclibs || exit 100
+else
+$cc -o tst $* $cclibs 2> /dev/null || exit 100
+fi
diff --git a/config/s-templ.h b/config/s-templ.h
index d5a914289..9904b4759 100644
--- a/config/s-templ.h
+++ b/config/s-templ.h
@@ -191,3 +191,15 @@
/* Define HAS_MMAP if you have the include file <sys/mman.h> and the
functions mmap() and munmap(). */
+
+#define HAS_GETHOSTBYNAME_R 6
+
+/* Define HAS_GETHOSTBYNAME_R if gethostbyname_r() is available.
+ The value of this symbol is the number of arguments of
+ gethostbyname_r(): either 3, 5 or 6 depending on prototype. */
+
+#define HAS_GETHOSTBYADDR_R 8
+
+/* Define HAS_GETHOSTBYADDR_R if gethostbyname_r() is available.
+ The value of this symbol is the number of arguments of
+ gethostbyaddr_r(): either 5, 7 or 8 depending on prototype. */
diff --git a/configure b/configure
index 2472a7e57..788a5bb50 100755
--- a/configure
+++ b/configure
@@ -910,6 +910,24 @@ if sh ./hasgot -i sys/types.h -i sys/mman.h && sh ./hasgot mmap munmap; then
echo "#define HAS_MMAP" >> s.h
fi
+nargs=none
+for i in 5 6 3; do
+ if sh ./trycompile -DNUM_ARGS=${i} gethostbyname.c; then nargs=$i; break; fi
+done
+if test $nargs != "none"; then
+ echo "gethostbyname_r() found (with ${nargs} arguments)."
+ echo "#define HAS_GETHOSTBYNAME_R $nargs" >> s.h
+fi
+
+nargs=none
+for i in 7 8 5; do
+ if sh ./trycompile -DNUM_ARGS=${i} gethostbyaddr.c; then nargs=$i; break; fi
+done
+if test $nargs != "none"; then
+ echo "gethostbyaddr_r() found (with ${nargs} arguments)."
+ echo "#define HAS_GETHOSTBYADDR_R $nargs" >> s.h
+fi
+
# Determine if the debugger is supported
if test "$has_sockets" = "yes"; then
diff --git a/otherlibs/unix/gethost.c b/otherlibs/unix/gethost.c
index 2f3da9485..c1584ea6c 100644
--- a/otherlibs/unix/gethost.c
+++ b/otherlibs/unix/gethost.c
@@ -25,9 +25,17 @@
#include "socketaddr.h"
#ifndef _WIN32
+#include <sys/types.h>
#include <netdb.h>
#endif
+#define NETDB_BUFFER_SIZE 10000
+
+#ifdef _WIN32
+#define GETHOSTBYADDR_IS_REENTRANT
+#define GETHOSTBYNAME_IS_REENTRANT
+#endif
+
static int entry_h_length;
extern int socket_domain_table[];
@@ -67,27 +75,103 @@ static value alloc_host_entry(struct hostent *entry)
CAMLprim value unix_gethostbyaddr(value a)
{
- uint32 adr;
- struct hostent * entry;
- adr = GET_INET_ADDR(a);
+ uint32 adr = GET_INET_ADDR(a);
+ struct hostent * hp;
+#if HAS_GETHOSTBYADDR_R == 7
+ struct hostent h;
+ char buffer[NETDB_BUFFER_SIZE];
+ int h_errnop;
+ enter_blocking_section();
+ hp = gethostbyaddr_r((char *) &adr, 4, AF_INET,
+ &h, buffer, sizeof(buffer), &h_errnop);
+ leave_blocking_section();
+#elif HAS_GETHOSTBYADDR_R == 8
+ struct hostent h;
+ char buffer[NETDB_BUFFER_SIZE];
+ int h_errnop, rc;
+ enter_blocking_section();
+ rc = gethostbyaddr_r((char *) &adr, 4, AF_INET,
+ &h, buffer, sizeof(buffer), &hp, &h_errnop);
+ leave_blocking_section();
+ if (rc != 0) hp = NULL;
+#elif HAS_GETHOSTBYADDR_R == 5
+ struct hostent h;
+ struct hostent_data hdata;
+ int rc;
+ enter_blocking_section();
+ rc = gethostbyaddr_r((char *) &adr, 4, AF_INET, &h, &hdata);
+ leave_blocking_section();
+ hp = rc == 0 ? &h : NULL;
+#else
+#ifdef GETHOSTBYADDR_IS_REENTRANT
enter_blocking_section();
- entry = gethostbyaddr((char *) &adr, 4, AF_INET);
+#endif
+ hp = gethostbyaddr((char *) &adr, 4, AF_INET);
+#ifdef GETHOSTBYADDR_IS_REENTRANT
leave_blocking_section();
- if (entry == (struct hostent *) NULL) raise_not_found();
- return alloc_host_entry(entry);
+#endif
+#endif
+ if (hp == (struct hostent *) NULL) raise_not_found();
+ return alloc_host_entry(hp);
}
CAMLprim value unix_gethostbyname(value name)
{
- char hostname[256];
- struct hostent * entry;
- strncpy(hostname, String_val(name), sizeof(hostname) - 1);
- hostname[sizeof(hostname) - 1] = 0;
+ struct hostent * hp;
+ char * hostname;
+
+#if HAS_GETHOSTBYNAME_R != 0 || GETHOSTBYNAME_IS_REENTRANT
+ hostname = stat_alloc(string_length(name) + 1);
+ strcpy(hostname, String_val(name));
+#else
+ hostname = String_val(name);
+#endif
+
+#if HAS_GETHOSTBYNAME_R == 5
+ {
+ struct hostent h;
+ char buffer[NETDB_BUFFER_SIZE];
+ int h_errno;
+ enter_blocking_section();
+ hp = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &h_errno);
+ leave_blocking_section();
+ }
+#elif HAS_GETHOSTBYNAME_R == 6
+ {
+ struct hostent h;
+ char buffer[NETDB_BUFFER_SIZE];
+ int h_errno, rc;
+ enter_blocking_section();
+ rc = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &hp, &h_errno);
+ leave_blocking_section();
+ if (rc != 0) hp = NULL;
+ }
+#elif HAS_GETHOSTBYNAME_R == 3
+ {
+ struct hostent h;
+ struct hostent_data hdata;
+ int rc;
+ enter_blocking_section();
+ rc = gethostbyname_r(hostname, &h, &hdata);
+ leave_blocking_section();
+ hp = rc == 0 ? &h : NULL;
+ }
+#else
+#ifdef GETHOSTBYNAME_IS_REENTRANT
enter_blocking_section();
- entry = gethostbyname(hostname);
+#endif
+ hp = gethostbyname(hostname);
+#ifdef GETHOSTBYNAME_IS_REENTRANT
leave_blocking_section();
- if (entry == (struct hostent *) NULL) raise_not_found();
- return alloc_host_entry(entry);
+#endif
+#endif
+
+#if HAS_GETHOSTBYNAME_R != 0 || GETHOSTBYNAME_IS_REENTRANT
+ stat_free(hostname);
+#endif
+
+ if (hp == (struct hostent *) NULL) raise_not_found();
+ return alloc_host_entry(hp);
}
#else