Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Aug 2002 13:14:49 +0300
From:      Maxim Sobolev <sobomax@FreeBSD.org>
To:        hackers@FreeBSD.org, audit@FreeBSD.org, Alexander Litvin <archer@whichever.org>, Andriy Gapon <agapon@excite.com>
Subject:   Thread-safe resolver [patches for review]
Message-ID:  <3D578A99.F0821712@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------051496A982500B2DDF1E4FCD
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 7bit

Folks,

Attched please find two patches based on bin/29581 PR to make FreeBSD
resolver thread-safe. They represent two approaches to reach this goal
- the first is to introduce reentrant versions of the standard
gethostbyXXX(3) APIs, similar to ones existing in other unices, and
the second one is to make gethostbyXXX(3) returning data placed into
per-thread storage when linked with libc_r. I like the latter approach
more, since it doesn't introduce new non-standard APIs.

I would like to hear any comments and suggestions on the proposed
patches, as well as to opinions about which path to chose.

Thanks!

-Maxim
--------------051496A982500B2DDF1E4FCD
Content-Type: text/plain; charset=koi8-r;
 name="resolv_r-1.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="resolv_r-1.diff"

Index: src/include/netdb.h
===================================================================
RCS file: /home/ncvs/src/include/netdb.h,v
retrieving revision 1.24
diff -d -u -r1.24 netdb.h
--- src/include/netdb.h	26 Jun 2002 08:18:42 -0000	1.24
+++ src/include/netdb.h	10 Aug 2002 10:03:43 -0000
@@ -82,7 +82,10 @@
 #define	_PATH_PROTOCOLS	"/etc/protocols"
 #define	_PATH_SERVICES	"/etc/services"
 
-extern int h_errno;
+__BEGIN_DECLS
+int * __h_errno_accessor(void);
+__END_DECLS
+#define h_errno (* __h_errno_accessor())
 
 /*
  * Structures returned by network data base library.  All addresses are
@@ -240,6 +243,15 @@
 char		*gai_strerror(int);
 void		setnetgrent(const char *);
 void		setservent(int);
+
+int		gethostbyaddr_r(const char *, int, int, struct hostent *,
+				 char *, int, int *);
+int		gethostbyname_r(const char *, struct hostent *,
+				 char *, int, int *);
+int		gethostbyname2_r(const char *, int, struct hostent *,
+				  char *, int, int *);
+struct hostent	*gethostent_r(struct hostent *, char *, int);
+
 
 /*
  * PRIVATE functions specific to the FreeBSD implementation
Index: src/include/resolv.h
===================================================================
RCS file: /home/ncvs/src/include/resolv.h,v
retrieving revision 1.21
diff -d -u -r1.21 resolv.h
--- src/include/resolv.h	23 Mar 2002 17:24:53 -0000	1.21
+++ src/include/resolv.h	10 Aug 2002 10:03:43 -0000
@@ -90,11 +90,16 @@
 #define	MAXDFLSRCH		3	/* # default domain levels to try */
 #define	MAXDNSRCH		6	/* max # domains in search path */
 #define	LOCALDOMAINPARTS	2	/* min levels in name that is "local" */
+#define	MAXALIASES		35	/* max # of aliases to return */
+#define	MAXADDRS		35	/* max # of addresses to return */
 
 #define	RES_TIMEOUT		5	/* min. seconds between retries */
 #define	MAXRESOLVSORT		10	/* number of net to sort on */
 #define	RES_MAXNDOTS		15	/* should reflect bit field size */
 
+#define	CAST_ALIGN(ptr, type) \
+		(char*)(type)ptr < (char*)ptr ? ((type)ptr) + 1 : (type)ptr
+
 struct __res_state {
 	int	retrans;	 	/* retransmition time interval */
 	int	retry;			/* number of times to retransmit */
@@ -198,10 +203,6 @@
 	char *	humanname;	/* Its fun name, like "mail exchanger" */
 };
 
-extern struct __res_state _res;
-/* for INET6 */
-extern struct __res_state_ext _res_ext;
-
 extern const struct res_sym __p_class_syms[];
 extern const struct res_sym __p_type_syms[];
 
@@ -224,6 +225,7 @@
 #define	fp_query	__fp_query
 #define	fp_nquery	__fp_nquery
 #define	hostalias	__hostalias
+#define	hostalias_r	__hostalias_r
 #define	putlong		__putlong
 #define	putshort	__putshort
 #define	p_class		__p_class
@@ -273,6 +275,7 @@
 void		fp_query(const u_char *, FILE *);
 void		fp_nquery(const u_char *, int, FILE *);
 const char *	hostalias(const char *);
+const char *	hostalias_r(const char *, char *, int);
 void		putlong(u_int32_t, u_char *);
 void		putshort(u_int16_t, u_char *);
 const char *	p_class(int);
@@ -315,5 +318,30 @@
 void		res_freeupdrec(ns_updrec *);
 #endif
 __END_DECLS
+
+struct __res_data {
+	int h_errno_res;
+	int s;		/* socket used for communications */
+	int connected : 1;	/* is the socket connected */
+	int vc : 1;		/* is the socket a virtual circuit? */
+	int af;		/* address family of socket */
+	res_send_qhook Qhook;
+	res_send_rhook Rhook;
+	FILE* hostf;
+	int stayopen;
+	struct __res_state *res;
+	struct __res_state_ext *res_ext;
+};
+
+__BEGIN_DECLS
+u_int16_t _getshort(const u_char *);
+u_int32_t _getlong(const u_char *);
+struct __res_data * __res_data_accessor(void);
+struct __res_state * __res_accessor(void);
+__END_DECLS
+#define _res_data (* __res_data_accessor())
+#define _res (* __res_accessor())
+/* for INET6 */
+#define _res_ext (* (__res_data_accessor()->res_ext))
 
 #endif /* !_RESOLV_H_ */
Index: src/lib/libc/net/getaddrinfo.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/getaddrinfo.c,v
retrieving revision 1.28
diff -d -u -r1.28 getaddrinfo.c
--- src/lib/libc/net/getaddrinfo.c	2 Aug 2002 11:58:48 -0000	1.28
+++ src/lib/libc/net/getaddrinfo.c	10 Aug 2002 10:03:49 -0000
@@ -1673,7 +1673,6 @@
 /* resolver logic */
 
 extern const char *__hostalias(const char *);
-extern int h_errno;
 
 /*
  * Formulate a normal query, send, and await answer.
Index: src/lib/libc/net/gethostbydns.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/gethostbydns.c,v
retrieving revision 1.36
diff -d -u -r1.36 gethostbydns.c
--- src/lib/libc/net/gethostbydns.c	26 Jun 2002 14:18:36 -0000	1.36
+++ src/lib/libc/net/gethostbydns.c	10 Aug 2002 10:03:49 -0000
@@ -68,6 +68,7 @@
 #include <arpa/nameser.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <netdb.h>
@@ -82,18 +83,11 @@
 
 #define SPRINTF(x) ((size_t)sprintf x)
 
-#define	MAXALIASES	35
-#define	MAXADDRS	35
-
 static const char AskedForGot[] =
 		"gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
 
-static char *h_addr_ptrs[MAXADDRS + 1];
-
-static struct hostent host;
-static char *host_aliases[MAXALIASES];
-static char hostbuf[8*1024];
-static u_char host_addr[16];	/* IPv4 or IPv6 */
+static char hostbuf_s[8*1024];
+static u_char host_addr_s[16];	/* IPv4 or IPv6 */
 
 #ifdef RESOLVSORT
 static void addrsort(char **, int);
@@ -119,7 +113,6 @@
     char ac;
 } align;
 
-extern int h_errno;
 int _dns_ttl_;
 
 #ifdef DEBUG
@@ -157,11 +150,14 @@
 	} while (0)
 
 static struct hostent *
-gethostanswer(answer, anslen, qname, qtype)
+gethostanswer(answer, anslen, qname, qtype, host, hostbuf, hostbuflen)
 	const querybuf *answer;
 	int anslen;
 	const char *qname;
 	int qtype;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
 {
 	const HEADER *hp;
 	const u_char *cp;
@@ -176,7 +172,7 @@
 	int (*name_ok)(const char *);
 
 	tname = qname;
-	host.h_name = NULL;
+	host->h_name = NULL;
 	eom = answer->buf + anslen;
 	switch (qtype) {
 	case T_A:
@@ -197,7 +193,7 @@
 	ancount = ntohs(hp->ancount);
 	qdcount = ntohs(hp->qdcount);
 	bp = hostbuf;
-	ep = hostbuf + sizeof hostbuf;
+	ep = hostbuf + hostbuflen;
 	cp = answer->buf;
 	BOUNDED_INCR(HFIXEDSZ);
 	if (qdcount != 1) {
@@ -220,17 +216,15 @@
 			h_errno = NO_RECOVERY;
 			return (NULL);
 		}
-		host.h_name = bp;
+		host->h_name = bp;
 		bp += n;
 		/* The qname can be abbreviated, but h_name is now absolute. */
-		qname = host.h_name;
+		qname = host->h_name;
 	}
-	ap = host_aliases;
+	ap = host->h_aliases;
 	*ap = NULL;
-	host.h_aliases = host_aliases;
-	hap = h_addr_ptrs;
+	hap = host->h_addr_list;
 	*hap = NULL;
-	host.h_addr_list = h_addr_ptrs;
 	haveanswer = 0;
 	had_error = 0;
 	_dns_ttl_ = -1;
@@ -259,7 +253,7 @@
 			continue;		/* XXX - had_error++ ? */
 		}
 		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
-			if (ap >= &host_aliases[MAXALIASES-1])
+			if (ap >= &host->h_aliases[MAXALIASES-1])
 				continue;
 			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
 			if ((n < 0) || !(*name_ok)(tbuf)) {
@@ -286,7 +280,7 @@
 				continue;
 			}
 			strcpy(bp, tbuf);
-			host.h_name = bp;
+			host->h_name = bp;
 			bp += n;
 			continue;
 		}
@@ -341,8 +335,8 @@
 				return (NULL);
 			}
 			if (!haveanswer)
-				host.h_name = bp;
-			else if (ap < &host_aliases[MAXALIASES-1])
+				host->h_name = bp;
+			else if (ap < &host->h_aliases[MAXALIASES-1])
 				*ap++ = bp;
 			else
 				n = -1;
@@ -356,7 +350,7 @@
 			}
 			break;
 #else
-			host.h_name = bp;
+			host->h_name = bp;
 			if (_res.options & RES_USE_INET6) {
 				n = strlen(bp) + 1;	/* for the \0 */
 				if (n >= MAXHOSTNAMELEN) {
@@ -364,27 +358,27 @@
 					break;
 				}
 				bp += n;
-				_map_v4v6_hostent(&host, &bp, &ep);
+				_map_v4v6_hostent(host, &bp, &ep);
 			}
 			h_errno = NETDB_SUCCESS;
-			return (&host);
+			return (host);
 #endif
 		case T_A:
 		case T_AAAA:
-			if (strcasecmp(host.h_name, bp) != 0) {
+			if (strcasecmp(host->h_name, bp) != 0) {
 				syslog(LOG_NOTICE|LOG_AUTH,
-				       AskedForGot, host.h_name, bp);
+				       AskedForGot, host->h_name, bp);
 				cp += n;
 				continue;	/* XXX - had_error++ ? */
 			}
-			if (n != host.h_length) {
+			if (n != host->h_length) {
 				cp += n;
 				continue;
 			}
 			if (!haveanswer) {
 				int nn;
 
-				host.h_name = bp;
+				host->h_name = bp;
 				nn = strlen(bp) + 1;	/* for the \0 */
 				bp += nn;
 			}
@@ -396,7 +390,7 @@
 				had_error++;
 				continue;
 			}
-			if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+			if (hap >= &host->h_addr_list[MAXADDRS-1]) {
 				if (!toobig++)
 					dprintf("Too many addresses (%d)\n",
 						MAXADDRS);
@@ -430,62 +424,82 @@
 		 * address in that case, not some random one
 		 */
 		if (_res.nsort && haveanswer > 1 && qtype == T_A)
-			addrsort(h_addr_ptrs, haveanswer);
+			addrsort(host->h_addr_list, haveanswer);
 # endif /*RESOLVSORT*/
-		if (!host.h_name) {
+		if (!host->h_name) {
 			n = strlen(qname) + 1;	/* for the \0 */
 			if (n > ep - bp || n >= MAXHOSTNAMELEN)
 				goto no_recovery;
 			strcpy(bp, qname);
-			host.h_name = bp;
+			host->h_name = bp;
 			bp += n;
 		}
 		if (_res.options & RES_USE_INET6)
-			_map_v4v6_hostent(&host, &bp, &ep);
+			_map_v4v6_hostent(host, &bp, &ep);
 		h_errno = NETDB_SUCCESS;
-		return (&host);
+		return (host);
 	}
  no_recovery:
 	h_errno = NO_RECOVERY;
 	return (NULL);
 }
 
-struct hostent *
-__dns_getanswer(answer, anslen, qname, qtype)
-	const char *answer;
-	int anslen;
-	const char *qname;
-	int qtype;
-{
-	switch(qtype) {
-	case T_AAAA:
-		host.h_addrtype = AF_INET6;
-		host.h_length = IN6ADDRSZ;
-		break;
-	case T_A:
-	default:
-		host.h_addrtype = AF_INET;
-		host.h_length = INADDRSZ;
-		break;
-	}
-
-	return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
-}
-
 int
 _dns_gethostbyname(void *rval, void *cb_data, va_list ap)
 {
 	const char *name;
 	int af;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
+	u_char *host_addr;
 	querybuf buf;
 	const char *cp;
 	char *bp, *ep;
 	int n, size, type, len;
+	char abuf[MAXDNAME];
 
 	name = va_arg(ap, const char *);
 	af = va_arg(ap, int);
+	host = va_arg(ap, struct hostent *);
+	hostbuf = va_arg(ap, char *);
+	hostbuflen = va_arg(ap, int);
 	*(struct hostent **)rval = NULL;
 
+	if(hostbuflen != 0 && hostbuf != NULL) {
+		host->h_aliases = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+		host->h_addr_list = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_addr_list + sizeof(char *[MAXADDRS + 1]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+		host_addr = hostbuf;
+		bp = (char *)host_addr + sizeof(u_char[16]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < MAXDNAME+1) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+	} else {
+		hostbuf = hostbuf_s;
+		hostbuflen = sizeof hostbuf_s;
+		host_addr = host_addr_s;
+	}
+
 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
 		h_errno = NETDB_INTERNAL;
 		return NS_UNAVAIL;
@@ -506,15 +520,15 @@
 		return NS_UNAVAIL;
 	}
 
-	host.h_addrtype = af;
-	host.h_length = size;
+	host->h_addrtype = af;
+	host->h_length = size;
 
 	/*
 	 * if there aren't any dots, it could be a user-level alias.
 	 * this is also done in res_query() since we are not the only
 	 * function that looks up host names.
 	 */
-	if (!strchr(name, '.') && (cp = __hostalias(name)))
+	if (!strchr(name, '.') && (cp = __hostalias_r(name, abuf, sizeof abuf)))
 		name = cp;
 
 	/*
@@ -538,17 +552,15 @@
 				strncpy(hostbuf, name, MAXDNAME);
 				hostbuf[MAXDNAME] = '\0';
 				bp = hostbuf + MAXDNAME;
-				ep = hostbuf + sizeof hostbuf;
-				host.h_name = hostbuf;
-				host.h_aliases = host_aliases;
-				host_aliases[0] = NULL;
-				h_addr_ptrs[0] = (char *)host_addr;
-				h_addr_ptrs[1] = NULL;
-				host.h_addr_list = h_addr_ptrs;
+				ep = hostbuf + hostbuflen;
+				host->h_name = hostbuf;
+				host->h_aliases[0] = NULL;
+				host->h_addr_list[0] = (char *)host_addr;
+				host->h_addr_list[1] = NULL;
 				if (_res.options & RES_USE_INET6)
-					_map_v4v6_hostent(&host, &bp, &ep);
+					_map_v4v6_hostent(host, &bp, &ep);
 				h_errno = NETDB_SUCCESS;
-				*(struct hostent **)rval = &host;
+				*(struct hostent **)rval = host;
 				return NS_SUCCESS;
 			}
 			if (!isdigit((unsigned char)*cp) && *cp != '.')
@@ -572,15 +584,13 @@
 				strncpy(hostbuf, name, MAXDNAME);
 				hostbuf[MAXDNAME] = '\0';
 				bp = hostbuf + MAXDNAME;
-				len = sizeof hostbuf - MAXDNAME;
-				host.h_name = hostbuf;
-				host.h_aliases = host_aliases;
-				host_aliases[0] = NULL;
-				h_addr_ptrs[0] = (char *)host_addr;
-				h_addr_ptrs[1] = NULL;
-				host.h_addr_list = h_addr_ptrs;
+				len = hostbuflen - MAXDNAME;
+				host->h_name = hostbuf;
+				host->h_aliases[0] = NULL;
+				host->h_addr_list[0] = (char *)host_addr;
+				host->h_addr_list[1] = NULL;
 				h_errno = NETDB_SUCCESS;
-				*(struct hostent **)rval = &host;
+				*(struct hostent **)rval = host;
 				return NS_SUCCESS;
 			}
 			if (!isxdigit((unsigned char)*cp) && *cp != ':' && *cp != '.')
@@ -591,7 +601,8 @@
 		dprintf("res_search failed (%d)\n", n);
 		return NS_UNAVAIL;
 	}
-	*(struct hostent **)rval = gethostanswer(&buf, n, name, type);
+	*(struct hostent **)rval = gethostanswer(&buf, n, name, type,
+	    host, hostbuf, hostbuflen);
 	return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;
 }
 
@@ -600,6 +611,10 @@
 {
 	const char *addr;	/* XXX should have been def'd as u_char! */
 	int len, af;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
+	char *bp;
 	const u_char *uaddr;
 	static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
 	static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
@@ -607,6 +622,7 @@
 	querybuf buf;
 	struct hostent *hp;
 	char qbuf[MAXDNAME+1], *qp;
+	u_char *host_addr;
 #ifdef SUNSECURITY
 	struct hostent *rhp;
 	char **haddr;
@@ -618,9 +634,45 @@
 	uaddr = (const u_char *)addr;
 	len = va_arg(ap, int);
 	af = va_arg(ap, int);
-	
+	host = va_arg(ap, struct hostent *);
+	hostbuf = va_arg(ap, char*);
+	hostbuflen = va_arg(ap, int);
 	*(struct hostent **)rval = NULL;
 	
+	if(hostbuflen != 0 && hostbuf != NULL) {
+		host->h_aliases = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+		host->h_addr_list = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_addr_list + sizeof(char *[MAXADDRS + 1]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+		host_addr = hostbuf;
+		bp = (char *)host_addr + sizeof(u_char[16]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < MAXDNAME+1) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+	} else {
+		hostbuf = hostbuf_s;
+		hostbuflen = sizeof hostbuf_s;
+		host_addr = host_addr_s;
+	}
+
 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
 		h_errno = NETDB_INTERNAL;
 		return NS_UNAVAIL;
@@ -680,7 +732,7 @@
 		dprintf("static buffer is too small (%d)\n", n);
 		return NS_UNAVAIL;
 	}
-	if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR)))
+	if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR, host, hostbuf, hostbuflen)))
 		return NS_NOTFOUND;   /* h_errno was set by gethostanswer() */
 #ifdef SUNSECURITY
 	if (af == AF_INET) {
@@ -717,8 +769,8 @@
 	hp->h_addrtype = af;
 	hp->h_length = len;
 	bcopy(addr, host_addr, len);
-	h_addr_ptrs[0] = (char *)host_addr;
-	h_addr_ptrs[1] = NULL;
+	host->h_addr_list[0] = (char *)host_addr;
+	host->h_addr_list[1] = NULL;
 	if (af == AF_INET && (_res.options & RES_USE_INET6)) {
 		_map_v4v6_address((char*)host_addr, (char*)host_addr);
 		hp->h_addrtype = AF_INET6;
Index: src/lib/libc/net/gethostbyht.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/gethostbyht.c,v
retrieving revision 1.16
diff -d -u -r1.16 gethostbyht.c
--- src/lib/libc/net/gethostbyht.c	22 Mar 2002 21:52:29 -0000	1.16
+++ src/lib/libc/net/gethostbyht.c	10 Aug 2002 10:03:52 -0000
@@ -62,6 +62,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <errno.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
@@ -70,49 +71,53 @@
 #include <arpa/nameser.h>	/* XXX */
 #include <resolv.h>		/* XXX */
 
-#define	MAXALIASES	35
-
-static struct hostent host;
-static char *host_aliases[MAXALIASES];
-static char hostbuf[BUFSIZ+1];
-static FILE *hostf = NULL;
-static u_int32_t host_addr[4];	/* IPv4 or IPv6 */
 static char *h_addr_ptrs[2];
-static int stayopen = 0;
+static char *host_aliases[MAXALIASES];
+static struct hostent host_s = { NULL, host_aliases, 0, 0, h_addr_ptrs };
+
+static char hostbuf_s[BUFSIZ+1];
+static u_int32_t host_addr_s[4];	/* IPv4 or IPv6 */
 
 void
 _sethosthtent(f)
 	int f;
 {
-	if (!hostf)
-		hostf = fopen(_PATH_HOSTS, "r" );
+	if (!_res_data.hostf)
+		_res_data.hostf = fopen(_PATH_HOSTS, "r" );
 	else
-		rewind(hostf);
-	stayopen = f;
+		rewind(_res_data.hostf);
+	_res_data.stayopen = f;
 }
 
 void
 _endhosthtent()
 {
-	if (hostf && !stayopen) {
-		(void) fclose(hostf);
-		hostf = NULL;
+	if (_res_data.hostf && !_res_data.stayopen) {
+		(void) fclose(_res_data.hostf);
+		_res_data.hostf = NULL;
 	}
 }
 
 struct hostent *
 gethostent()
 {
+
+	return (gethostent_r(&host_s, hostbuf_s, sizeof hostbuf_s));
+}
+
+struct hostent *
+gethostent_r(struct hostent *host, char *hostbuf, int hostbuflen)
+{
 	char *p;
 	char *cp, **q;
 	int af, len;
 
-	if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
+	if (!_res_data.hostf && !(_res_data.hostf = fopen(_PATH_HOSTS, "r" ))) {
 		h_errno = NETDB_INTERNAL;
 		return (NULL);
 	}
  again:
-	if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
+	if (!(p = fgets(hostbuf, hostbuflen, _res_data.hostf))) {
 		h_errno = HOST_NOT_FOUND;
 		return (NULL);
 	}
@@ -124,12 +129,12 @@
 	if (!(cp = strpbrk(p, " \t")))
 		goto again;
 	*cp++ = '\0';
-	if (inet_pton(AF_INET6, p, host_addr) > 0) {
+	if (inet_pton(AF_INET6, p, host->h_addr_list[0]) > 0) {
 		af = AF_INET6;
 		len = IN6ADDRSZ;
-	} else if (inet_pton(AF_INET, p, host_addr) > 0) {
+	} else if (inet_pton(AF_INET, p, host->h_addr_list[0]) > 0) {
 		if (_res.options & RES_USE_INET6) {
-			_map_v4v6_address((char*)host_addr, (char*)host_addr);
+			_map_v4v6_address(host->h_addr_list[0], host->h_addr_list[0]);
 			af = AF_INET6;
 			len = IN6ADDRSZ;
 		} else {
@@ -139,15 +144,12 @@
 	} else {
 		goto again;
 	}
-	h_addr_ptrs[0] = (char *)host_addr;
-	h_addr_ptrs[1] = NULL;
-	host.h_addr_list = h_addr_ptrs;
-	host.h_length = len;
-	host.h_addrtype = af;
+	host->h_length = len;
+	host->h_addrtype = af;
 	while (*cp == ' ' || *cp == '\t')
 		cp++;
-	host.h_name = cp;
-	q = host.h_aliases = host_aliases;
+	host->h_name = cp;
+	q = host->h_aliases;
 	if ((cp = strpbrk(cp, " \t")) != NULL)
 		*cp++ = '\0';
 	while (cp && *cp) {
@@ -155,14 +157,14 @@
 			cp++;
 			continue;
 		}
-		if (q < &host_aliases[MAXALIASES - 1])
+		if (q < &host->h_aliases[MAXALIASES - 1])
 			*q++ = cp;
 		if ((cp = strpbrk(cp, " \t")) != NULL)
 			*cp++ = '\0';
 	}
 	*q = NULL;
 	h_errno = NETDB_SUCCESS;
-	return (&host);
+	return (host);
 }
 
 int
@@ -170,14 +172,58 @@
 {
 	const char *name;
 	int af;
+	struct hostent *host;
+	char *hostbuf, *bp;
+	int hostbuflen;
+	u_int32_t *host_addr;
 	struct hostent *p;
 	char **cp;
 
 	name = va_arg(ap, const char *);
 	af = va_arg(ap, int);
+	host = va_arg(ap, struct hostent *);
+	hostbuf = va_arg(ap, char*);
+	hostbuflen = va_arg(ap, int);
 	
+	if(hostbuflen != 0 && hostbuf != NULL) {
+		host->h_aliases = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+		host->h_addr_list = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_addr_list + sizeof(char *[2]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+		host_addr = CAST_ALIGN(hostbuf, u_int32_t *);
+		bp = (char *)host_addr + sizeof(u_int32_t[4]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < BUFSIZ+1) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+	} else {
+		hostbuf = hostbuf_s;
+		hostbuflen = sizeof hostbuf_s;
+		host_addr = host_addr_s;
+	}
+
+	host->h_addr_list[0] = (char *)host_addr;
+	host->h_addr_list[1] = NULL;
+
 	sethostent(0);
-	while ((p = gethostent()) != NULL) {
+	while ((p = gethostent_r(host, hostbuf, hostbuflen)) != NULL) {
 		if (p->h_addrtype != af)
 			continue;
 		if (strcasecmp(p->h_name, name) == 0)
@@ -198,14 +244,58 @@
 {
 	const char *addr;
 	int len, af;
+	struct hostent *host;
+	char *hostbuf, *bp;
+	int hostbuflen;
+	u_int32_t *host_addr;
 	struct hostent *p;
 
 	addr = va_arg(ap, const char *);
 	len = va_arg(ap, int);
 	af = va_arg(ap, int);
+	host = va_arg(ap, struct hostent *);
+	hostbuf = va_arg(ap, char*);
+	hostbuflen = va_arg(ap, int);
+	
+	if(hostbuflen != 0 && hostbuf != NULL) {
+		host->h_aliases = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+		host->h_addr_list = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_addr_list + sizeof(char *[2]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+		host_addr = CAST_ALIGN(hostbuf, u_int32_t *);
+		bp = (char *)host_addr + sizeof(u_int32_t[4]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < BUFSIZ+1) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NS_UNAVAIL);
+		}
+	} else {
+		hostbuf = hostbuf_s;
+		hostbuflen = sizeof hostbuf_s;
+		host_addr = host_addr_s;
+	}
+
+	host->h_addr_list[0] = (char *)host_addr;
+	host->h_addr_list[1] = NULL;
 
 	sethostent(0);
-	while ((p = gethostent()) != NULL)
+	while ((p = gethostent_r(host, hostbuf, hostbuflen)) != NULL)
 		if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
 			break;
 	endhostent();
Index: src/lib/libc/net/gethostbynis.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/gethostbynis.c,v
retrieving revision 1.15
diff -d -u -r1.15 gethostbynis.c
--- src/lib/libc/net/gethostbynis.c	22 Mar 2002 21:52:29 -0000	1.15
+++ src/lib/libc/net/gethostbynis.c	10 Aug 2002 10:03:52 -0000
@@ -44,29 +44,63 @@
 #include <rpcsvc/yp_prot.h>
 #include <rpcsvc/ypclnt.h>
 #endif
-
-#define	MAXALIASES	35
-#define	MAXADDRS	35
-
-extern int h_errno;
+#include <resolv.h>
 
 #ifdef YP
+static char hostbuf_s[8*1024];
+static u_char host_addr_s[16];
+
+static char *h_addr_ptrs[2];
 static char *host_aliases[MAXALIASES];
-static char hostaddr[MAXADDRS];
-static char *host_addrs[2];
+static struct hostent host_s = { NULL, host_aliases, 0, 0, h_addr_ptrs };
 
 static struct hostent *
-_gethostbynis(name, map, af)
+_gethostbynis(name, map, af, host, hostbuf, hostbuflen)
 	const char *name;
 	char *map;
 	int af;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
 {
-	char *cp, **q;
+	char *bp, *cp, **q;
 	char *result;
 	int resultlen,size;
-	static struct hostent h;
 	static char *domain = (char *)NULL;
-	static char ypbuf[YPMAXRECORD + 2];
+
+	if(hostbuflen != 0 && hostbuf != NULL) {
+		host->h_aliases = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NULL);
+		}
+		host->h_addr_list = CAST_ALIGN(hostbuf, char **);
+		bp = (char *)host->h_addr_list + sizeof(char *[2]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NULL);
+		}
+		host->h_addr_list[0] = hostbuf;
+		bp = (char *)host->h_addr_list[0] + sizeof(u_char[16]);
+		hostbuflen -= (bp - hostbuf);
+		hostbuf = bp;
+		if(hostbuflen < 0) {
+			h_errno = NO_RECOVERY;
+			errno = ERANGE;
+			return (NULL);
+		}
+	} else {
+		hostbuf = hostbuf_s;
+		hostbuflen = sizeof hostbuf_s;
+		host->h_addr_list[0] = host_addr_s;
+	}
 
 	switch(af) {
 	case AF_INET:
@@ -90,27 +124,29 @@
 		h_errno = HOST_NOT_FOUND;
 		return ((struct hostent *)NULL);
 	}
-
-	/* avoid potential memory leak */
-	bcopy((char *)result, (char *)&ypbuf, resultlen);
-	ypbuf[resultlen] = '\0';
+	if (resultlen > hostbuflen) {
+		h_errno = NO_RECOVERY;
+		errno = ERANGE;
+		return (NULL);
+	}
+	result[resultlen] = '\0';
+	bcopy((char *)result, hostbuf, resultlen);
 	free(result);
-	result = (char *)&ypbuf;
+	result = hostbuf;
 
 	if ((cp = index(result, '\n')))
 		*cp = '\0';
 
 	cp = strpbrk(result, " \t");
 	*cp++ = '\0';
-	h.h_addr_list = host_addrs;
-	h.h_addr = hostaddr;
-	*((u_long *)h.h_addr) = inet_addr(result);
-	h.h_length = size;
-	h.h_addrtype = AF_INET;
+	*((u_long *)host->h_addr_list[0]) = inet_addr(result);
+	host->h_addr_list[1] = NULL;
+	host->h_length = size;
+	host->h_addrtype = AF_INET;
 	while (*cp == ' ' || *cp == '\t')
 		cp++;
-	h.h_name = cp;
-	q = h.h_aliases = host_aliases;
+	host->h_name = cp;
+	q = host->h_aliases;
 	cp = strpbrk(cp, " \t");
 	if (cp != NULL)
 		*cp++ = '\0';
@@ -119,14 +155,14 @@
 			cp++;
 			continue;
 		}
-		if (q < &host_aliases[MAXALIASES - 1])
+		if (q < &host->h_aliases[MAXALIASES - 1])
 			*q++ = cp;
 		cp = strpbrk(cp, " \t");
 		if (cp != NULL)
 			*cp++ = '\0';
 	}
 	*q = NULL;
-	return (&h);
+	return (host);
 }
 #endif /* YP */
 
@@ -135,7 +171,7 @@
 _gethostbynisname(const char *name, int af)
 {
 #ifdef YP
-	return _gethostbynis(name, "hosts.byname", af);
+	return _gethostbynis(name, "hosts.byname", af, &host_s, NULL, 0);
 #else
 	return NULL;
 #endif
@@ -146,7 +182,7 @@
 {
 #ifdef YP
 	return _gethostbynis(inet_ntoa(*(struct in_addr *)addr), 
-			     "hosts.byaddr", af);
+			     "hosts.byaddr", af, &host_s, NULL, 0);
 #else
 	return NULL;
 #endif
@@ -159,11 +195,18 @@
 #ifdef YP
 	const char *name;
 	int af;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
 
 	name = va_arg(ap, const char *);
 	af = va_arg(ap, int);
+	host = va_arg(ap, struct hostent *);
+	hostbuf = va_arg(ap, char *);
+	hostbuflen = va_arg(ap, int);
 
-	*(struct hostent **)rval = _gethostbynis(name, "hosts.byname", af);
+	*(struct hostent **)rval = _gethostbynis(name, "hosts.byname", af,
+	    host, hostbuf, hostbuflen);
 	return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;
 #else
 	return NS_UNAVAIL;
@@ -177,12 +220,19 @@
 	const char *addr;
 	int len;
 	int af;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
 
 	addr = va_arg(ap, const char *);
 	len = va_arg(ap, int);
 	af = va_arg(ap, int);
-	
-	*(struct hostent **)rval =_gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af);
+	host = va_arg(ap, struct hostent *);
+	hostbuf = va_arg(ap, char *);
+	hostbuflen = va_arg(ap, int);
+
+	*(struct hostent **)rval =_gethostbynis(inet_ntoa(*(struct in_addr *)addr),
+	    "hosts.byaddr", af, host, hostbuf, hostbuflen);
 	return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;
 #else
 	return NS_UNAVAIL;
Index: src/lib/libc/net/gethostnamadr.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/gethostnamadr.c,v
retrieving revision 1.20
diff -d -u -r1.20 gethostnamadr.c
--- src/lib/libc/net/gethostnamadr.c	22 Mar 2002 21:52:29 -0000	1.20
+++ src/lib/libc/net/gethostnamadr.c	10 Aug 2002 10:03:52 -0000
@@ -31,6 +31,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <errno.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
@@ -46,6 +47,10 @@
 extern int _dns_gethostbyaddr(void *, void *, va_list);
 extern int _nis_gethostbyaddr(void *, void *, va_list);
 
+static char *h_addr_ptrs[MAXADDRS + 1];
+static char *host_aliases[MAXALIASES];
+static struct hostent host_s = { NULL, host_aliases, 0, 0, h_addr_ptrs };
+
 /* Host lookup order if nsswitch.conf is broken or nonexistant */
 static const ns_src default_src[] = { 
 	{ NSSRC_FILES, NS_SUCCESS },
@@ -53,25 +58,38 @@
 	{ 0 }
 };
 
-struct hostent *
-gethostbyname(const char *name)
+int
+gethostbyname_r(const char *name, struct hostent *resp,
+	char *buffer, int buflen, int *h_errnop)
 {
-	struct hostent *hp;
+	int rval;
 
 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
-		h_errno = NETDB_INTERNAL;
-		return (NULL);
+		*h_errnop = NO_RECOVERY;
+		return (NETDB_INTERNAL);
 	}
 	if (_res.options & RES_USE_INET6) {		/* XXX */
-		hp = gethostbyname2(name, AF_INET6);	/* XXX */
-		if (hp)					/* XXX */
-			return (hp);			/* XXX */
+		rval = gethostbyname2_r(name, AF_INET6, resp,
+		    buffer, buflen, h_errnop);		/* XXX */
+		if (rval == 0)				/* XXX */
+			return (0);			/* XXX */
 	}						/* XXX */
-	return (gethostbyname2(name, AF_INET));
+	return (gethostbyname2_r(name, AF_INET, resp,
+		buffer, buflen, h_errnop));
 }
 
 struct hostent *
-gethostbyname2(const char *name, int type)
+gethostbyname(const char *name)
+{
+	int rval;
+
+	rval = gethostbyname_r(name, &host_s, NULL, 0, &h_errno);
+	return (rval == 0 ? &host_s : NULL);
+}
+
+int
+gethostbyname2_r(const char *name, int type, struct hostent *resp,
+	char *buffer, int buflen, int *h_errnop)
 {
 	struct hostent *hp = 0;
 	int rval;
@@ -82,18 +100,29 @@
 		NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */
 		{ 0 }
 	};       
-	
+
 	rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname",
-			  default_src, name, type);
+			  default_src, name, type, resp, buffer, buflen);
 
+	*h_errnop = h_errno;
 	if (rval != NS_SUCCESS)
-		return NULL;
+		return ((errno == 0) ? -1 : errno);	/* Be paranoid */
 	else
-		return hp;
+		return (0);
 }
 
 struct hostent *
-gethostbyaddr(const char *addr, int len, int type)
+gethostbyname2(const char *name, int type)
+{
+	int rval;
+
+	rval = gethostbyname2_r(name, type, &host_s, NULL, 0, &h_errno);
+	return (rval == 0 ? &host_s : NULL);
+}
+
+int
+gethostbyaddr_r(const char *addr, int len, int type, struct hostent *resp,
+	char *buffer, int buflen, int *h_errnop)
 {
 	struct hostent *hp = 0;
 	int rval;
@@ -106,37 +135,28 @@
 	};       
 
 	rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
-			  default_src, addr, len, type);
+			  default_src, addr, len, type, resp, buffer, buflen);
 
+	*h_errnop = h_errno;
 	if (rval != NS_SUCCESS)
-		return NULL;
+		return ((errno == 0) ? -1 : errno);	/* Be paranoid */
 	else
-		return hp;
+		return (0);
 }
 
-struct hostent_data;
-
-/*
- * Temporary function (not thread safe)
- */
-int gethostbyaddr_r(const char *addr, int len, int type,
-	struct hostent *result, struct hostent_data *buffer)
+struct hostent *
+gethostbyaddr(const char *addr, int len, int type)
 {
-	struct hostent *hp;
-	int ret;
-	if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
-		ret = -1;
-	} else {
-		memcpy(result, hp, sizeof(struct hostent));
-		ret = 0;
-	}
-	return(ret);
+	int rval;
+
+	rval = gethostbyaddr_r(addr, len, type, NULL, NULL, 0, &h_errno);
+	return (rval == 0 ? &host_s : NULL);
 }
 
 void
-sethostent(stayopen)
-	int stayopen;
+sethostent(int stayopen)
 {
+
 	_sethosthtent(stayopen);
 	_sethostdnsent(stayopen);
 }
@@ -144,6 +164,7 @@
 void
 endhostent()
 {
+
 	_endhosthtent();
 	_endhostdnsent();
 }
Index: src/lib/libc/net/getnetbydns.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/getnetbydns.c,v
retrieving revision 1.21
diff -d -u -r1.21 getnetbydns.c
--- src/lib/libc/net/getnetbydns.c	26 Jun 2002 14:18:36 -0000	1.21
+++ src/lib/libc/net/getnetbydns.c	10 Aug 2002 10:03:52 -0000
@@ -82,11 +82,8 @@
 
 #include "res_config.h"
 
-extern int h_errno;
-
 #define BYADDR 0
 #define BYNAME 1
-#define	MAXALIASES	35
 
 #if PACKETSZ > 1024
 #define	MAXPACKET	PACKETSZ
Index: src/lib/libc/net/getnetbyht.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/getnetbyht.c,v
retrieving revision 1.10
diff -d -u -r1.10 getnetbyht.c
--- src/lib/libc/net/getnetbyht.c	22 Mar 2002 21:52:29 -0000	1.10
+++ src/lib/libc/net/getnetbyht.c	10 Aug 2002 10:03:52 -0000
@@ -58,8 +58,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <nsswitch.h>
-
-#define	MAXALIASES	35
+#include <resolv.h>
 
 static FILE *netf;
 static char line[BUFSIZ+1];
Index: src/lib/libc/net/getnetbynis.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/getnetbynis.c,v
retrieving revision 1.15
diff -d -u -r1.15 getnetbynis.c
--- src/lib/libc/net/getnetbynis.c	22 Mar 2002 21:52:29 -0000	1.15
+++ src/lib/libc/net/getnetbynis.c	10 Aug 2002 10:03:52 -0000
@@ -44,9 +44,7 @@
 #include <rpcsvc/yp_prot.h>
 #include <rpcsvc/ypclnt.h>
 #endif
-
-#define	MAXALIASES	35
-#define	MAXADDRS	35
+#include <resolv.h>
 
 #ifdef YP
 static char *host_aliases[MAXALIASES];
Index: src/lib/libc/net/herror.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/herror.c,v
retrieving revision 1.11
diff -d -u -r1.11 herror.c
--- src/lib/libc/net/herror.c	22 Mar 2002 21:52:29 -0000	1.11
+++ src/lib/libc/net/herror.c	10 Aug 2002 10:03:52 -0000
@@ -71,8 +71,6 @@
 };
 int	h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
 
-int	h_errno;
-
 /*
  * herror --
  *	print the error indicated by the h_errno value.
@@ -110,3 +108,19 @@
 		return (h_errlist[err]);
 	return ("Unknown resolver error");
 }
+
+#undef h_errno
+int	h_errno;
+
+/*
+ * Declare a weak reference in case the application is not linked
+ * with libpthread.
+ */
+__weak_reference(__h_errno_accessor_unthreaded, __h_errno_accessor);
+
+int *
+__h_errno_accessor_unthreaded()
+{
+	return &h_errno;
+}
+
Index: src/lib/libc/net/res_init.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/res_init.c,v
retrieving revision 1.29
diff -d -u -r1.29 res_init.c
--- src/lib/libc/net/res_init.c	22 Mar 2002 21:52:30 -0000	1.29
+++ src/lib/libc/net/res_init.c	10 Aug 2002 10:03:55 -0000
@@ -104,17 +104,6 @@
 # define isascii(c) (!(c & 0200))
 #endif
 
-/*
- * Resolver state default settings.
- */
-
-struct __res_state _res
-# if defined(__BIND_RES_TEXT)
-	= { RES_TIMEOUT, }	/* Motorola, et al. */
-# endif
-	;
-
-struct __res_state_ext _res_ext;
 
 /*
  * Set up default settings.  If the configuration file exist, the values
@@ -154,6 +143,9 @@
 #ifndef RFC1535
 	int dots;
 #endif
+	
+	if(&_res_data==NULL)
+		return -1;
 
 	/*
 	 * These three fields used to be statically initialized.  This made
@@ -582,3 +574,43 @@
  */
 #undef res_init
 __weak_reference(__res_init, res_init);
+
+/*
+ * Resolver state default settings.
+ */
+
+#undef _res
+#undef _res_ext
+#undef _res_data
+
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+	= { RES_TIMEOUT, }	/* Motorola, et al. */
+# endif
+	;
+
+struct __res_state_ext _res_ext;
+
+struct __res_data _res_data = { 0, -1, 0, 0, 0, NULL, NULL, NULL, 0, &_res,
+    &_res_ext };
+
+/*
+ * Declare a weak reference in case the application is not linked
+ * with libpthread.
+ */
+__weak_reference(__res_data_accessor_unthreaded, __res_data_accessor);
+__weak_reference(__res_accessor_unthreaded, __res_accessor);
+
+struct __res_data *
+__res_data_accessor_unthreaded()
+{
+
+	return &_res_data;
+}
+
+struct __res_state *
+__res_accessor_unthreaded()
+{
+
+	return _res_data.res;
+}
Index: src/lib/libc/net/res_query.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/res_query.c,v
retrieving revision 1.23
diff -d -u -r1.23 res_query.c
--- src/lib/libc/net/res_query.c	7 Jul 2002 11:28:28 -0000	1.23
+++ src/lib/libc/net/res_query.c	10 Aug 2002 10:03:55 -0000
@@ -87,6 +87,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "res_config.h"
 
@@ -374,11 +375,20 @@
 hostalias(name)
 	const char *name;
 {
+	static char abuf[MAXDNAME];
+	return (hostalias_r(name, abuf, sizeof abuf));
+}
+
+const char *
+hostalias_r(name, abuf, len)
+	const char *name;
+	char *abuf;
+	int len;
+{
 	char *cp1, *cp2;
 	FILE *fp;
 	char *file;
 	char buf[BUFSIZ];
-	static char abuf[MAXDNAME];
 
 	if (_res.options & RES_NOALIASES)
 		return (NULL);
@@ -402,8 +412,8 @@
 				break;
 			for (cp2 = cp1 + 1; *cp2 && !isspace((unsigned char)*cp2); ++cp2)
 				;
-			abuf[sizeof(abuf) - 1] = *cp2 = '\0';
-			strncpy(abuf, cp1, sizeof(abuf) - 1);
+			abuf[len - 1] = *cp2 = '\0';
+			strncpy(abuf, cp1, len - 1);
 			fclose(fp);
 			return (abuf);
 		}
Index: src/lib/libc/net/res_send.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/res_send.c,v
retrieving revision 1.45
diff -d -u -r1.45 res_send.c
--- src/lib/libc/net/res_send.c	1 Apr 2002 16:09:45 -0000	1.45
+++ src/lib/libc/net/res_send.c	10 Aug 2002 10:03:56 -0000
@@ -102,13 +102,6 @@
 
 #include "res_config.h"
 
-static int s = -1;		/* socket used for communications */
-static int connected = 0;	/* is the socket connected */
-static int vc = 0;		/* is the socket a virtual circuit? */
-static int af = 0;		/* address family of socket */
-static res_send_qhook Qhook = NULL;
-static res_send_rhook Rhook = NULL;
-
 
 #define CAN_RECONNECT 1
 
@@ -170,7 +163,7 @@
 	res_send_qhook hook;
 {
 
-	Qhook = hook;
+	_res_data.Qhook = hook;
 }
 
 void
@@ -178,7 +171,7 @@
 	res_send_rhook hook;
 {
 
-	Rhook = hook;
+	_res_data.Rhook = hook;
 }
 
 static struct sockaddr * get_nsaddr(size_t);
@@ -406,13 +399,13 @@
 			goto next_ns;
 		}
 
-		if (Qhook) {
+		if (_res_data.Qhook) {
 			int done = 0, loops = 0;
 
 			do {
 				res_sendhookact act;
 
-				act = (*Qhook)((struct sockaddr_in **)&nsap,
+				act = (*_res_data.Qhook)((struct sockaddr_in **)&nsap,
 					       &buf, &buflen,
 					       ans, anssiz, &resplen);
 				switch (act) {
@@ -457,14 +450,14 @@
 			 */
 			try = _res.retry;
 			truncated = 0;
-			if (s < 0 || !vc || hp->opcode == ns_o_update ||
-			    af != nsap->sa_family) {
-				if (s >= 0)
+			if (_res_data.s < 0 || !_res_data.vc || hp->opcode == ns_o_update ||
+			    _res_data.af != nsap->sa_family) {
+				if (_res_data.s >= 0)
 					res_close();
 
-				af = nsap->sa_family;
-				s = _socket(af, SOCK_STREAM, 0);
-				if (s < 0) {
+				_res_data.af = nsap->sa_family;
+				_res_data.s = _socket(_res_data.af, SOCK_STREAM, 0);
+				if (_res_data.s < 0) {
 					terrno = errno;
 					Perror(stderr, "socket(vc)", errno);
 					badns |= (1 << ns);
@@ -472,7 +465,7 @@
 					goto next_ns;
 				}
 				errno = 0;
-				if (_connect(s, nsap, salen) < 0) {
+				if (_connect(_res_data.s, nsap, salen) < 0) {
 					terrno = errno;
 					Aerror(stderr, "connect/vc",
 					       errno, nsap);
@@ -480,7 +473,7 @@
 					res_close();
 					goto next_ns;
 				}
-				vc = 1;
+				_res_data.vc = 1;
 			}
 			/*
 			 * Send length & message
@@ -490,7 +483,7 @@
 			iov[0].iov_len = INT16SZ;
 			iov[1].iov_base = (caddr_t)buf;
 			iov[1].iov_len = buflen;
-			if (_writev(s, iov, 2) != (INT16SZ + buflen)) {
+			if (_writev(_res_data.s, iov, 2) != (INT16SZ + buflen)) {
 				terrno = errno;
 				Perror(stderr, "write failed", errno);
 				badns |= (1 << ns);
@@ -503,7 +496,7 @@
 read_len:
 			cp = ans;
 			len = INT16SZ;
-			while ((n = _read(s, (char *)cp, (int)len)) > 0) {
+			while ((n = _read(_res_data.s, (char *)cp, (int)len)) > 0) {
 				cp += n;
 				if ((len -= n) <= 0)
 					break;
@@ -551,7 +544,7 @@
 			}
 			cp = ans;
 			while (len != 0 &&
-			       (n = _read(s, (char *)cp, (int)len)) > 0) {
+			       (n = _read(_res_data.s, (char *)cp, (int)len)) > 0) {
 				cp += n;
 				len -= n;
 			}
@@ -574,7 +567,7 @@
 					n = (len > sizeof(junk)
 					     ? sizeof(junk)
 					     : len);
-					if ((n = _read(s, junk, n)) > 0)
+					if ((n = _read(_res_data.s, junk, n)) > 0)
 						len -= n;
 					else
 						break;
@@ -604,12 +597,13 @@
 			struct sockaddr_storage from;
 			int fromlen;
 
-			if (s < 0 || vc || af != nsap->sa_family) {
-				if (vc)
+			if (_res_data.s < 0 || _res_data.vc ||
+				_res_data.af != nsap->sa_family) {
+				if (_res_data.vc)
 					res_close();
-				af = nsap->sa_family;
-				s = _socket(af, SOCK_DGRAM, 0);
-				if (s < 0) {
+				_res_data.af = nsap->sa_family;
+				_res_data.s = _socket(_res_data.af, SOCK_DGRAM, 0);
+				if (_res_data.s < 0) {
 #ifndef CAN_RECONNECT
  bad_dg_sock:
 #endif
@@ -619,7 +613,7 @@
 					res_close();
 					goto next_ns;
 				}
-				connected = 0;
+				_res_data.connected = 0;
 			}
 #ifndef CANNOT_CONNECT_DGRAM
 			/*
@@ -650,8 +644,8 @@
 				 * Connect only if we are sure we won't
 				 * receive a response from another server.
 				 */
-				if (!connected) {
-					if (_connect(s, nsap, salen) < 0) {
+				if (!_res_data.connected) {
+					if (_connect(_res_data.s, nsap, salen) < 0) {
 						Aerror(stderr,
 						       "connect(dg)",
 						       errno, nsap);
@@ -659,9 +653,9 @@
 						res_close();
 						goto next_ns;
 					}
-					connected = 1;
+					_res_data.connected = 1;
 				}
-				if (send(s, (char*)buf, buflen, 0) != buflen) {
+				if (send(_res_data.s, (char*)buf, buflen, 0) != buflen) {
 					Perror(stderr, "send", errno);
 					badns |= (1 << ns);
 					res_close();
@@ -672,7 +666,7 @@
 				 * Disconnect if we want to listen
 				 * for responses from more than one server.
 				 */
-				if (connected) {
+				if (_res_data.connected) {
 #ifdef CAN_RECONNECT
 					/* XXX: any errornous address */
 					struct sockaddr_in no_addr;
@@ -680,24 +674,24 @@
 					no_addr.sin_family = AF_INET;
 					no_addr.sin_addr.s_addr = INADDR_ANY;
 					no_addr.sin_port = 0;
-					(void) _connect(s,
+					(void) _connect(_res_data.s,
 						       (struct sockaddr *)
 						        &no_addr,
 						       sizeof no_addr);
 #else
-					int s1 = _socket(af, SOCK_DGRAM,0);
+					int s1 = _socket(_res_data.af, SOCK_DGRAM,0);
 					if (s1 < 0)
 						goto bad_dg_sock;
-					(void)_dup2(s1, s);
+					(void)_dup2(s1, _res_data.s);
 					(void)_close(s1);
 					Dprint(_res.options & RES_DEBUG,
 						(stdout, ";; new DG socket\n"))
 #endif /* CAN_RECONNECT */
-					connected = 0;
+					_res_data.connected = 0;
 					errno = 0;
 				}
 #endif /* !CANNOT_CONNECT_DGRAM */
-				if (_sendto(s, (char*)buf, buflen, 0,
+				if (_sendto(_res_data.s, (char*)buf, buflen, 0,
 					   nsap, salen) != buflen) {
 					Aerror(stderr, "sendto", errno, nsap);
 					badns |= (1 << ns);
@@ -722,13 +716,13 @@
 			(void) gettimeofday(&ctv, NULL);
 			timeradd(&timeout, &ctv, &timeout);
     wait:
-			if (s < 0) {
+			if (_res_data.s < 0) {
 				Perror(stderr, "s out-of-bounds", EMFILE);
 				res_close();
 				goto next_ns;
 			}
 
-			EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0,0,0);
+			EV_SET(&kv, _res_data.s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0,0,0);
 
 			n = _kevent(kq, &kv, 1, &kv, 1, &ts);
 			if (n < 0) {
@@ -757,7 +751,7 @@
 			}
 			errno = 0;
 			fromlen = sizeof(from);
-			resplen = _recvfrom(s, (char*)ans, anssiz, 0,
+			resplen = _recvfrom(_res_data.s, (char*)ans, anssiz, 0,
 					   (struct sockaddr *)&from, &fromlen);
 			if (resplen <= 0) {
 				Perror(stderr, "recvfrom", errno);
@@ -862,13 +856,13 @@
 		    !(_res.options & RES_STAYOPEN)) {
 			res_close();
 		}
-		if (Rhook) {
+		if (_res_data.Rhook) {
 			int done = 0, loops = 0;
 
 			do {
 				res_sendhookact act;
 
-				act = (*Rhook)((struct sockaddr_in *)nsap,
+				act = (*_res_data.Rhook)((struct sockaddr_in *)nsap,
 					       buf, buflen,
 					       ans, anssiz, &resplen);
 				switch (act) {
@@ -920,12 +914,12 @@
 void
 res_close()
 {
-	if (s >= 0) {
-		(void)_close(s);
-		s = -1;
-		connected = 0;
-		vc = 0;
-		af = 0;
+	if (_res_data.s >= 0) {
+		(void)_close(_res_data.s);
+		_res_data.s = -1;
+		_res_data.connected = 0;
+		_res_data.vc = 0;
+		_res_data.af = 0;
 	}
 }
 
Index: src/lib/libc_r/sys/Makefile.inc
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/sys/Makefile.inc,v
retrieving revision 1.10
diff -d -u -r1.10 Makefile.inc
--- src/lib/libc_r/sys/Makefile.inc	28 Aug 1999 00:03:13 -0000	1.10
+++ src/lib/libc_r/sys/Makefile.inc	10 Aug 2002 10:03:56 -0000
@@ -2,5 +2,5 @@
 
 .PATH:	 ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH}
 
-SRCS+=	uthread_error.c _atomic_lock.S
+SRCS+=	uthread_error.c uthread_resolv.c _atomic_lock.S
 
Index: src/lib/libc_r/sys/uthread_resolv.c
===================================================================
RCS file: src/lib/libc_r/sys/uthread_resolv.c
diff -N src/lib/libc_r/sys/uthread_resolv.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/lib/libc_r/sys/uthread_resolv.c	10 Aug 2002 10:03:56 -0000
@@ -0,0 +1,151 @@
+/*-
+ * Copyright (c) 2001 Alexandr Litvin <archer@whichever.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+#undef h_errno
+#undef _res
+#undef _res_ext
+#undef _res_data
+
+extern	int h_errno;
+extern  struct __res_data _res_data;
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+static pthread_key_t key;
+
+
+static void
+__res_data_destroy(void *p)
+{
+	struct __res_data *_res_datap = (struct __res_data *)p;
+
+	if(_res_datap->res)
+		free(_res_datap->res);
+	if(_res_datap->res_ext)
+		free(_res_datap->res_ext);
+	if(_res_datap->s >= 0)
+		close(_res_datap->s);
+	if(_res_datap->hostf)
+		fclose(_res_datap->hostf);
+	free(_res_datap);
+}
+
+static void
+__res_data_init()
+{
+
+	pthread_key_create(&key, __res_data_destroy);
+}
+
+struct __res_data *
+__res_data_accessor()
+{
+	struct __res_data *_res_datap;
+
+	if (_thread_run == _thread_initial) {
+		_res_datap = &_res_data;
+	} else {
+		pthread_once(&once, __res_data_init);
+		_res_datap = (struct __res_data *)pthread_getspecific(key);
+		if(_res_datap==NULL) {
+			_res_datap = malloc(sizeof(struct __res_data));
+			if(_res_datap==NULL)
+				return (NULL);
+			bzero(_res_datap, sizeof(struct __res_data));
+			_res_datap->res = malloc(sizeof(struct __res_state));
+			if(_res_datap->res == NULL) {
+				free(_res_datap);
+				return (NULL);
+			}
+			bzero(_res_datap->res, sizeof(struct __res_state));
+			_res_datap->res_ext =
+			    malloc(sizeof(struct __res_state_ext));
+			if(_res_datap->res_ext == NULL) {
+				free(_res_datap->res);
+				free(_res_datap);
+				return (NULL);
+			}
+			bzero(_res_datap->res_ext,
+			    sizeof(struct __res_state_ext));
+			_res_datap->s = -1;
+			pthread_setspecific(key, _res_datap);
+		}
+	}
+	return (_res_datap);
+}
+
+static struct __res_state dummy_res;
+static int dummy_h_errno;
+
+struct __res_state *
+__res_accessor()
+{
+	struct __res_state *resp;
+	struct __res_data *_res_datap;
+
+	if (_thread_run == _thread_initial) {
+		resp = _res_data.res;
+	} else {
+		_res_datap = __res_data_accessor();
+		if(_res_datap) {
+			resp = _res_datap->res;
+		} else {
+			dummy_res.options = RES_DEFAULT;
+			resp = &dummy_res;
+		}
+	}
+	return (resp);
+}
+
+int *
+__h_errno_accessor()
+{
+	int *h_errnop;
+	struct __res_data *_res_datap;
+
+	if (_thread_run == _thread_initial) {
+		h_errnop = &h_errno;
+	} else {
+		_res_datap = __res_data_accessor();
+		if(_res_datap) {
+			h_errnop = &_res_datap->h_errno_res;
+		} else {
+			dummy_h_errno = NETDB_INTERNAL;
+			h_errnop = &dummy_h_errno;
+		}
+	}
+	return (h_errnop);
+}


--------------051496A982500B2DDF1E4FCD
Content-Type: text/plain; charset=koi8-r;
 name="resolv_r-2.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="resolv_r-2.diff"

Index: src/include/netdb.h
===================================================================
RCS file: /home/ncvs/src/include/netdb.h,v
retrieving revision 1.24
diff -d -u -r1.24 netdb.h
--- src/include/netdb.h	26 Jun 2002 08:18:42 -0000	1.24
+++ src/include/netdb.h	12 Aug 2002 09:48:11 -0000
@@ -82,7 +82,10 @@
 #define	_PATH_PROTOCOLS	"/etc/protocols"
 #define	_PATH_SERVICES	"/etc/services"
 
-extern int h_errno;
+__BEGIN_DECLS
+int * __h_errno_accessor(void);
+__END_DECLS
+#define h_errno (* __h_errno_accessor())
 
 /*
  * Structures returned by network data base library.  All addresses are
Index: src/include/resolv.h
===================================================================
RCS file: /home/ncvs/src/include/resolv.h,v
retrieving revision 1.21
diff -d -u -r1.21 resolv.h
--- src/include/resolv.h	23 Mar 2002 17:24:53 -0000	1.21
+++ src/include/resolv.h	12 Aug 2002 09:48:11 -0000
@@ -62,6 +62,7 @@
 #include <sys/cdefs.h>
 #include <sys/socket.h>
 #include <stdio.h>
+#include <netdb.h>
 
 /*
  * Revision information.  This is the release date in YYYYMMDD format.
@@ -90,6 +91,8 @@
 #define	MAXDFLSRCH		3	/* # default domain levels to try */
 #define	MAXDNSRCH		6	/* max # domains in search path */
 #define	LOCALDOMAINPARTS	2	/* min levels in name that is "local" */
+#define	MAXALIASES		35	/* max # of aliases to return */
+#define	MAXADDRS		35	/* max # of addresses to return */
 
 #define	RES_TIMEOUT		5	/* min. seconds between retries */
 #define	MAXRESOLVSORT		10	/* number of net to sort on */
@@ -198,10 +201,6 @@
 	char *	humanname;	/* Its fun name, like "mail exchanger" */
 };
 
-extern struct __res_state _res;
-/* for INET6 */
-extern struct __res_state_ext _res_ext;
-
 extern const struct res_sym __p_class_syms[];
 extern const struct res_sym __p_type_syms[];
 
@@ -224,6 +223,7 @@
 #define	fp_query	__fp_query
 #define	fp_nquery	__fp_nquery
 #define	hostalias	__hostalias
+#define	hostalias_r	__hostalias_r
 #define	putlong		__putlong
 #define	putshort	__putshort
 #define	p_class		__p_class
@@ -273,6 +273,7 @@
 void		fp_query(const u_char *, FILE *);
 void		fp_nquery(const u_char *, int, FILE *);
 const char *	hostalias(const char *);
+const char *	hostalias_r(const char *, char *, int);
 void		putlong(u_int32_t, u_char *);
 void		putshort(u_int16_t, u_char *);
 const char *	p_class(int);
@@ -315,5 +316,35 @@
 void		res_freeupdrec(ns_updrec *);
 #endif
 __END_DECLS
+
+struct __res_data {
+	int h_errno_res;
+	int s;		/* socket used for communications */
+	int connected : 1;	/* is the socket connected */
+	int vc : 1;		/* is the socket a virtual circuit? */
+	int af;		/* address family of socket */
+	res_send_qhook Qhook;
+	res_send_rhook Rhook;
+	FILE* hostf;
+	int stayopen;
+	struct hostent host;
+	char *hostbuf;
+	int hostbuflen;
+	u_char *host_addr;
+	int host_addrlen;
+	struct __res_state *res;
+	struct __res_state_ext *res_ext;
+};
+
+__BEGIN_DECLS
+u_int16_t _getshort(const u_char *);
+u_int32_t _getlong(const u_char *);
+struct __res_data * __res_data_accessor(void);
+struct __res_state * __res_accessor(void);
+__END_DECLS
+#define _res_data (* __res_data_accessor())
+#define _res (* __res_accessor())
+/* for INET6 */
+#define _res_ext (* (__res_data_accessor()->res_ext))
 
 #endif /* !_RESOLV_H_ */
Index: src/lib/libc/net/getaddrinfo.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/getaddrinfo.c,v
retrieving revision 1.28
diff -d -u -r1.28 getaddrinfo.c
--- src/lib/libc/net/getaddrinfo.c	2 Aug 2002 11:58:48 -0000	1.28
+++ src/lib/libc/net/getaddrinfo.c	12 Aug 2002 09:48:17 -0000
@@ -1673,7 +1673,6 @@
 /* resolver logic */
 
 extern const char *__hostalias(const char *);
-extern int h_errno;
 
 /*
  * Formulate a normal query, send, and await answer.
Index: src/lib/libc/net/gethostbydns.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/gethostbydns.c,v
retrieving revision 1.36
diff -d -u -r1.36 gethostbydns.c
--- src/lib/libc/net/gethostbydns.c	26 Jun 2002 14:18:36 -0000	1.36
+++ src/lib/libc/net/gethostbydns.c	12 Aug 2002 09:48:17 -0000
@@ -68,6 +68,7 @@
 #include <arpa/nameser.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <netdb.h>
@@ -82,19 +83,9 @@
 
 #define SPRINTF(x) ((size_t)sprintf x)
 
-#define	MAXALIASES	35
-#define	MAXADDRS	35
-
 static const char AskedForGot[] =
 		"gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
 
-static char *h_addr_ptrs[MAXADDRS + 1];
-
-static struct hostent host;
-static char *host_aliases[MAXALIASES];
-static char hostbuf[8*1024];
-static u_char host_addr[16];	/* IPv4 or IPv6 */
-
 #ifdef RESOLVSORT
 static void addrsort(char **, int);
 #endif
@@ -119,7 +110,6 @@
     char ac;
 } align;
 
-extern int h_errno;
 int _dns_ttl_;
 
 #ifdef DEBUG
@@ -157,11 +147,14 @@
 	} while (0)
 
 static struct hostent *
-gethostanswer(answer, anslen, qname, qtype)
+gethostanswer(answer, anslen, qname, qtype, host, hostbuf, hostbuflen)
 	const querybuf *answer;
 	int anslen;
 	const char *qname;
 	int qtype;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
 {
 	const HEADER *hp;
 	const u_char *cp;
@@ -176,7 +169,7 @@
 	int (*name_ok)(const char *);
 
 	tname = qname;
-	host.h_name = NULL;
+	host->h_name = NULL;
 	eom = answer->buf + anslen;
 	switch (qtype) {
 	case T_A:
@@ -197,7 +190,7 @@
 	ancount = ntohs(hp->ancount);
 	qdcount = ntohs(hp->qdcount);
 	bp = hostbuf;
-	ep = hostbuf + sizeof hostbuf;
+	ep = hostbuf + hostbuflen;
 	cp = answer->buf;
 	BOUNDED_INCR(HFIXEDSZ);
 	if (qdcount != 1) {
@@ -220,17 +213,15 @@
 			h_errno = NO_RECOVERY;
 			return (NULL);
 		}
-		host.h_name = bp;
+		host->h_name = bp;
 		bp += n;
 		/* The qname can be abbreviated, but h_name is now absolute. */
-		qname = host.h_name;
+		qname = host->h_name;
 	}
-	ap = host_aliases;
+	ap = host->h_aliases;
 	*ap = NULL;
-	host.h_aliases = host_aliases;
-	hap = h_addr_ptrs;
+	hap = host->h_addr_list;
 	*hap = NULL;
-	host.h_addr_list = h_addr_ptrs;
 	haveanswer = 0;
 	had_error = 0;
 	_dns_ttl_ = -1;
@@ -259,7 +250,7 @@
 			continue;		/* XXX - had_error++ ? */
 		}
 		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
-			if (ap >= &host_aliases[MAXALIASES-1])
+			if (ap >= &host->h_aliases[MAXALIASES-1])
 				continue;
 			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
 			if ((n < 0) || !(*name_ok)(tbuf)) {
@@ -286,7 +277,7 @@
 				continue;
 			}
 			strcpy(bp, tbuf);
-			host.h_name = bp;
+			host->h_name = bp;
 			bp += n;
 			continue;
 		}
@@ -341,8 +332,8 @@
 				return (NULL);
 			}
 			if (!haveanswer)
-				host.h_name = bp;
-			else if (ap < &host_aliases[MAXALIASES-1])
+				host->h_name = bp;
+			else if (ap < &host->h_aliases[MAXALIASES-1])
 				*ap++ = bp;
 			else
 				n = -1;
@@ -356,7 +347,7 @@
 			}
 			break;
 #else
-			host.h_name = bp;
+			host->h_name = bp;
 			if (_res.options & RES_USE_INET6) {
 				n = strlen(bp) + 1;	/* for the \0 */
 				if (n >= MAXHOSTNAMELEN) {
@@ -364,27 +355,27 @@
 					break;
 				}
 				bp += n;
-				_map_v4v6_hostent(&host, &bp, &ep);
+				_map_v4v6_hostent(host, &bp, &ep);
 			}
 			h_errno = NETDB_SUCCESS;
-			return (&host);
+			return (host);
 #endif
 		case T_A:
 		case T_AAAA:
-			if (strcasecmp(host.h_name, bp) != 0) {
+			if (strcasecmp(host->h_name, bp) != 0) {
 				syslog(LOG_NOTICE|LOG_AUTH,
-				       AskedForGot, host.h_name, bp);
+				       AskedForGot, host->h_name, bp);
 				cp += n;
 				continue;	/* XXX - had_error++ ? */
 			}
-			if (n != host.h_length) {
+			if (n != host->h_length) {
 				cp += n;
 				continue;
 			}
 			if (!haveanswer) {
 				int nn;
 
-				host.h_name = bp;
+				host->h_name = bp;
 				nn = strlen(bp) + 1;	/* for the \0 */
 				bp += nn;
 			}
@@ -396,7 +387,7 @@
 				had_error++;
 				continue;
 			}
-			if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+			if (hap >= &host->h_addr_list[MAXADDRS-1]) {
 				if (!toobig++)
 					dprintf("Too many addresses (%d)\n",
 						MAXADDRS);
@@ -430,57 +421,40 @@
 		 * address in that case, not some random one
 		 */
 		if (_res.nsort && haveanswer > 1 && qtype == T_A)
-			addrsort(h_addr_ptrs, haveanswer);
+			addrsort(host->h_addr_list, haveanswer);
 # endif /*RESOLVSORT*/
-		if (!host.h_name) {
+		if (!host->h_name) {
 			n = strlen(qname) + 1;	/* for the \0 */
 			if (n > ep - bp || n >= MAXHOSTNAMELEN)
 				goto no_recovery;
 			strcpy(bp, qname);
-			host.h_name = bp;
+			host->h_name = bp;
 			bp += n;
 		}
 		if (_res.options & RES_USE_INET6)
-			_map_v4v6_hostent(&host, &bp, &ep);
+			_map_v4v6_hostent(host, &bp, &ep);
 		h_errno = NETDB_SUCCESS;
-		return (&host);
+		return (host);
 	}
  no_recovery:
 	h_errno = NO_RECOVERY;
 	return (NULL);
 }
 
-struct hostent *
-__dns_getanswer(answer, anslen, qname, qtype)
-	const char *answer;
-	int anslen;
-	const char *qname;
-	int qtype;
-{
-	switch(qtype) {
-	case T_AAAA:
-		host.h_addrtype = AF_INET6;
-		host.h_length = IN6ADDRSZ;
-		break;
-	case T_A:
-	default:
-		host.h_addrtype = AF_INET;
-		host.h_length = INADDRSZ;
-		break;
-	}
-
-	return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
-}
-
 int
 _dns_gethostbyname(void *rval, void *cb_data, va_list ap)
 {
 	const char *name;
 	int af;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
+	u_char *host_addr;
 	querybuf buf;
 	const char *cp;
 	char *bp, *ep;
 	int n, size, type, len;
+	char abuf[MAXDNAME];
 
 	name = va_arg(ap, const char *);
 	af = va_arg(ap, int);
@@ -491,6 +465,11 @@
 		return NS_UNAVAIL;
 	}
 
+	host = &_res_data.host;
+	hostbuf = _res_data.hostbuf;
+	hostbuflen = _res_data.hostbuflen;
+	host_addr = _res_data.host_addr;
+
 	switch (af) {
 	case AF_INET:
 		size = INADDRSZ;
@@ -506,15 +485,15 @@
 		return NS_UNAVAIL;
 	}
 
-	host.h_addrtype = af;
-	host.h_length = size;
+	host->h_addrtype = af;
+	host->h_length = size;
 
 	/*
 	 * if there aren't any dots, it could be a user-level alias.
 	 * this is also done in res_query() since we are not the only
 	 * function that looks up host names.
 	 */
-	if (!strchr(name, '.') && (cp = __hostalias(name)))
+	if (!strchr(name, '.') && (cp = __hostalias_r(name, abuf, sizeof abuf)))
 		name = cp;
 
 	/*
@@ -538,17 +517,15 @@
 				strncpy(hostbuf, name, MAXDNAME);
 				hostbuf[MAXDNAME] = '\0';
 				bp = hostbuf + MAXDNAME;
-				ep = hostbuf + sizeof hostbuf;
-				host.h_name = hostbuf;
-				host.h_aliases = host_aliases;
-				host_aliases[0] = NULL;
-				h_addr_ptrs[0] = (char *)host_addr;
-				h_addr_ptrs[1] = NULL;
-				host.h_addr_list = h_addr_ptrs;
+				ep = hostbuf + hostbuflen;
+				host->h_name = hostbuf;
+				host->h_aliases[0] = NULL;
+				host->h_addr_list[0] = (char *)host_addr;
+				host->h_addr_list[1] = NULL;
 				if (_res.options & RES_USE_INET6)
-					_map_v4v6_hostent(&host, &bp, &ep);
+					_map_v4v6_hostent(host, &bp, &ep);
 				h_errno = NETDB_SUCCESS;
-				*(struct hostent **)rval = &host;
+				*(struct hostent **)rval = host;
 				return NS_SUCCESS;
 			}
 			if (!isdigit((unsigned char)*cp) && *cp != '.')
@@ -572,15 +549,13 @@
 				strncpy(hostbuf, name, MAXDNAME);
 				hostbuf[MAXDNAME] = '\0';
 				bp = hostbuf + MAXDNAME;
-				len = sizeof hostbuf - MAXDNAME;
-				host.h_name = hostbuf;
-				host.h_aliases = host_aliases;
-				host_aliases[0] = NULL;
-				h_addr_ptrs[0] = (char *)host_addr;
-				h_addr_ptrs[1] = NULL;
-				host.h_addr_list = h_addr_ptrs;
+				len = hostbuflen - MAXDNAME;
+				host->h_name = hostbuf;
+				host->h_aliases[0] = NULL;
+				host->h_addr_list[0] = (char *)host_addr;
+				host->h_addr_list[1] = NULL;
 				h_errno = NETDB_SUCCESS;
-				*(struct hostent **)rval = &host;
+				*(struct hostent **)rval = host;
 				return NS_SUCCESS;
 			}
 			if (!isxdigit((unsigned char)*cp) && *cp != ':' && *cp != '.')
@@ -591,7 +566,8 @@
 		dprintf("res_search failed (%d)\n", n);
 		return NS_UNAVAIL;
 	}
-	*(struct hostent **)rval = gethostanswer(&buf, n, name, type);
+	*(struct hostent **)rval = gethostanswer(&buf, n, name, type,
+	    host, hostbuf, hostbuflen);
 	return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;
 }
 
@@ -600,6 +576,9 @@
 {
 	const char *addr;	/* XXX should have been def'd as u_char! */
 	int len, af;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
 	const u_char *uaddr;
 	static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
 	static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
@@ -607,6 +586,7 @@
 	querybuf buf;
 	struct hostent *hp;
 	char qbuf[MAXDNAME+1], *qp;
+	u_char *host_addr;
 #ifdef SUNSECURITY
 	struct hostent *rhp;
 	char **haddr;
@@ -618,13 +598,19 @@
 	uaddr = (const u_char *)addr;
 	len = va_arg(ap, int);
 	af = va_arg(ap, int);
-	
+
 	*(struct hostent **)rval = NULL;
 	
 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
 		h_errno = NETDB_INTERNAL;
 		return NS_UNAVAIL;
 	}
+
+	host = &_res_data.host;
+	hostbuf = _res_data.hostbuf;
+	hostbuflen = _res_data.hostbuflen;
+	host_addr = _res_data.host_addr;
+
 	if (af == AF_INET6 && len == IN6ADDRSZ &&
 	    (!bcmp(uaddr, mapped, sizeof mapped) ||
 	     !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
@@ -680,7 +666,8 @@
 		dprintf("static buffer is too small (%d)\n", n);
 		return NS_UNAVAIL;
 	}
-	if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR)))
+	if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR, host, hostbuf,
+	    hostbuflen)))
 		return NS_NOTFOUND;   /* h_errno was set by gethostanswer() */
 #ifdef SUNSECURITY
 	if (af == AF_INET) {
@@ -717,8 +704,8 @@
 	hp->h_addrtype = af;
 	hp->h_length = len;
 	bcopy(addr, host_addr, len);
-	h_addr_ptrs[0] = (char *)host_addr;
-	h_addr_ptrs[1] = NULL;
+	host->h_addr_list[0] = (char *)host_addr;
+	host->h_addr_list[1] = NULL;
 	if (af == AF_INET && (_res.options & RES_USE_INET6)) {
 		_map_v4v6_address((char*)host_addr, (char*)host_addr);
 		hp->h_addrtype = AF_INET6;
Index: src/lib/libc/net/gethostbyht.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/gethostbyht.c,v
retrieving revision 1.16
diff -d -u -r1.16 gethostbyht.c
--- src/lib/libc/net/gethostbyht.c	22 Mar 2002 21:52:29 -0000	1.16
+++ src/lib/libc/net/gethostbyht.c	12 Aug 2002 09:48:20 -0000
@@ -62,6 +62,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <errno.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
@@ -70,33 +71,35 @@
 #include <arpa/nameser.h>	/* XXX */
 #include <resolv.h>		/* XXX */
 
-#define	MAXALIASES	35
-
-static struct hostent host;
-static char *host_aliases[MAXALIASES];
-static char hostbuf[BUFSIZ+1];
-static FILE *hostf = NULL;
-static u_int32_t host_addr[4];	/* IPv4 or IPv6 */
-static char *h_addr_ptrs[2];
-static int stayopen = 0;
-
 void
 _sethosthtent(f)
 	int f;
 {
-	if (!hostf)
-		hostf = fopen(_PATH_HOSTS, "r" );
+
+	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+		h_errno = NETDB_INTERNAL;
+		return;
+	}
+
+	if (!_res_data.hostf)
+		_res_data.hostf = fopen(_PATH_HOSTS, "r" );
 	else
-		rewind(hostf);
-	stayopen = f;
+		rewind(_res_data.hostf);
+	_res_data.stayopen = f;
 }
 
 void
 _endhosthtent()
 {
-	if (hostf && !stayopen) {
-		(void) fclose(hostf);
-		hostf = NULL;
+
+	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+		h_errno = NETDB_INTERNAL;
+		return;
+	}
+
+	if (_res_data.hostf && !_res_data.stayopen) {
+		(void) fclose(_res_data.hostf);
+		_res_data.hostf = NULL;
 	}
 }
 
@@ -106,13 +109,27 @@
 	char *p;
 	char *cp, **q;
 	int af, len;
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
 
-	if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
+	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+		h_errno = NETDB_INTERNAL;
+		return NULL;
+	}
+
+	host = &_res_data.host;
+	hostbuf = _res_data.hostbuf;
+	hostbuflen = _res_data.hostbuflen;
+	host->h_addr_list[0] = _res_data.host_addr;
+	host->h_addr_list[1] = NULL;
+
+	if (!_res_data.hostf && !(_res_data.hostf = fopen(_PATH_HOSTS, "r" ))) {
 		h_errno = NETDB_INTERNAL;
 		return (NULL);
 	}
  again:
-	if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
+	if (!(p = fgets(hostbuf, hostbuflen, _res_data.hostf))) {
 		h_errno = HOST_NOT_FOUND;
 		return (NULL);
 	}
@@ -124,12 +141,12 @@
 	if (!(cp = strpbrk(p, " \t")))
 		goto again;
 	*cp++ = '\0';
-	if (inet_pton(AF_INET6, p, host_addr) > 0) {
+	if (inet_pton(AF_INET6, p, host->h_addr_list[0]) > 0) {
 		af = AF_INET6;
 		len = IN6ADDRSZ;
-	} else if (inet_pton(AF_INET, p, host_addr) > 0) {
+	} else if (inet_pton(AF_INET, p, host->h_addr_list[0]) > 0) {
 		if (_res.options & RES_USE_INET6) {
-			_map_v4v6_address((char*)host_addr, (char*)host_addr);
+			_map_v4v6_address(host->h_addr_list[0], host->h_addr_list[0]);
 			af = AF_INET6;
 			len = IN6ADDRSZ;
 		} else {
@@ -139,15 +156,12 @@
 	} else {
 		goto again;
 	}
-	h_addr_ptrs[0] = (char *)host_addr;
-	h_addr_ptrs[1] = NULL;
-	host.h_addr_list = h_addr_ptrs;
-	host.h_length = len;
-	host.h_addrtype = af;
+	host->h_length = len;
+	host->h_addrtype = af;
 	while (*cp == ' ' || *cp == '\t')
 		cp++;
-	host.h_name = cp;
-	q = host.h_aliases = host_aliases;
+	host->h_name = cp;
+	q = host->h_aliases;
 	if ((cp = strpbrk(cp, " \t")) != NULL)
 		*cp++ = '\0';
 	while (cp && *cp) {
@@ -155,14 +169,14 @@
 			cp++;
 			continue;
 		}
-		if (q < &host_aliases[MAXALIASES - 1])
+		if (q < &host->h_aliases[MAXALIASES - 1])
 			*q++ = cp;
 		if ((cp = strpbrk(cp, " \t")) != NULL)
 			*cp++ = '\0';
 	}
 	*q = NULL;
 	h_errno = NETDB_SUCCESS;
-	return (&host);
+	return (host);
 }
 
 int
@@ -175,7 +189,7 @@
 
 	name = va_arg(ap, const char *);
 	af = va_arg(ap, int);
-	
+
 	sethostent(0);
 	while ((p = gethostent()) != NULL) {
 		if (p->h_addrtype != af)
Index: src/lib/libc/net/gethostbynis.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/gethostbynis.c,v
retrieving revision 1.15
diff -d -u -r1.15 gethostbynis.c
--- src/lib/libc/net/gethostbynis.c	22 Mar 2002 21:52:29 -0000	1.15
+++ src/lib/libc/net/gethostbynis.c	12 Aug 2002 09:48:20 -0000
@@ -44,16 +44,9 @@
 #include <rpcsvc/yp_prot.h>
 #include <rpcsvc/ypclnt.h>
 #endif
-
-#define	MAXALIASES	35
-#define	MAXADDRS	35
-
-extern int h_errno;
+#include <resolv.h>
 
 #ifdef YP
-static char *host_aliases[MAXALIASES];
-static char hostaddr[MAXADDRS];
-static char *host_addrs[2];
 
 static struct hostent *
 _gethostbynis(name, map, af)
@@ -64,9 +57,20 @@
 	char *cp, **q;
 	char *result;
 	int resultlen,size;
-	static struct hostent h;
 	static char *domain = (char *)NULL;
-	static char ypbuf[YPMAXRECORD + 2];
+	struct hostent *host;
+	char *hostbuf;
+	int hostbuflen;
+
+	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+		h_errno = NETDB_INTERNAL;
+		return NULL;
+	}
+
+	host = &_res_data.host;
+	hostbuf = _res_data.hostbuf;
+	hostbuflen = _res_data.hostbuflen;
+	host->h_addr_list[0] = _res_data.host_addr;
 
 	switch(af) {
 	case AF_INET:
@@ -90,27 +94,29 @@
 		h_errno = HOST_NOT_FOUND;
 		return ((struct hostent *)NULL);
 	}
-
-	/* avoid potential memory leak */
-	bcopy((char *)result, (char *)&ypbuf, resultlen);
-	ypbuf[resultlen] = '\0';
+	if (resultlen > hostbuflen) {
+		h_errno = NETDB_INTERNAL;
+		errno = ERANGE;
+		return (NULL);
+	}
+	result[resultlen] = '\0';
+	bcopy((char *)result, hostbuf, resultlen);
 	free(result);
-	result = (char *)&ypbuf;
+	result = hostbuf;
 
 	if ((cp = index(result, '\n')))
 		*cp = '\0';
 
 	cp = strpbrk(result, " \t");
 	*cp++ = '\0';
-	h.h_addr_list = host_addrs;
-	h.h_addr = hostaddr;
-	*((u_long *)h.h_addr) = inet_addr(result);
-	h.h_length = size;
-	h.h_addrtype = AF_INET;
+	*((u_long *)host->h_addr_list[0]) = inet_addr(result);
+	host->h_addr_list[1] = NULL;
+	host->h_length = size;
+	host->h_addrtype = AF_INET;
 	while (*cp == ' ' || *cp == '\t')
 		cp++;
-	h.h_name = cp;
-	q = h.h_aliases = host_aliases;
+	host->h_name = cp;
+	q = host->h_aliases;
 	cp = strpbrk(cp, " \t");
 	if (cp != NULL)
 		*cp++ = '\0';
@@ -119,14 +125,14 @@
 			cp++;
 			continue;
 		}
-		if (q < &host_aliases[MAXALIASES - 1])
+		if (q < &host->h_aliases[MAXALIASES - 1])
 			*q++ = cp;
 		cp = strpbrk(cp, " \t");
 		if (cp != NULL)
 			*cp++ = '\0';
 	}
 	*q = NULL;
-	return (&h);
+	return (host);
 }
 #endif /* YP */
 
@@ -163,6 +169,11 @@
 	name = va_arg(ap, const char *);
 	af = va_arg(ap, int);
 
+	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+		h_errno = NETDB_INTERNAL;
+		return NS_UNAVAIL;
+	}
+
 	*(struct hostent **)rval = _gethostbynis(name, "hosts.byname", af);
 	return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;
 #else
@@ -181,8 +192,14 @@
 	addr = va_arg(ap, const char *);
 	len = va_arg(ap, int);
 	af = va_arg(ap, int);
-	
-	*(struct hostent **)rval =_gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af);
+
+	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+		h_errno = NETDB_INTERNAL;
+		return NS_UNAVAIL;
+	}
+
+	*(struct hostent **)rval = _gethostbynis(
+	    inet_ntoa(*(struct in_addr *)addr), "hosts.byaddr", af);
 	return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND;
 #else
 	return NS_UNAVAIL;
Index: src/lib/libc/net/gethostnamadr.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/gethostnamadr.c,v
retrieving revision 1.20
diff -d -u -r1.20 gethostnamadr.c
--- src/lib/libc/net/gethostnamadr.c	22 Mar 2002 21:52:29 -0000	1.20
+++ src/lib/libc/net/gethostnamadr.c	12 Aug 2002 09:48:20 -0000
@@ -31,6 +31,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <errno.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
@@ -82,7 +83,7 @@
 		NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */
 		{ 0 }
 	};       
-	
+
 	rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname",
 			  default_src, name, type);
 
@@ -114,29 +115,10 @@
 		return hp;
 }
 
-struct hostent_data;
-
-/*
- * Temporary function (not thread safe)
- */
-int gethostbyaddr_r(const char *addr, int len, int type,
-	struct hostent *result, struct hostent_data *buffer)
-{
-	struct hostent *hp;
-	int ret;
-	if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
-		ret = -1;
-	} else {
-		memcpy(result, hp, sizeof(struct hostent));
-		ret = 0;
-	}
-	return(ret);
-}
-
 void
-sethostent(stayopen)
-	int stayopen;
+sethostent(int stayopen)
 {
+
 	_sethosthtent(stayopen);
 	_sethostdnsent(stayopen);
 }
@@ -144,6 +126,7 @@
 void
 endhostent()
 {
+
 	_endhosthtent();
 	_endhostdnsent();
 }
Index: src/lib/libc/net/getnetbydns.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/getnetbydns.c,v
retrieving revision 1.21
diff -d -u -r1.21 getnetbydns.c
--- src/lib/libc/net/getnetbydns.c	26 Jun 2002 14:18:36 -0000	1.21
+++ src/lib/libc/net/getnetbydns.c	12 Aug 2002 09:48:20 -0000
@@ -82,11 +82,8 @@
 
 #include "res_config.h"
 
-extern int h_errno;
-
 #define BYADDR 0
 #define BYNAME 1
-#define	MAXALIASES	35
 
 #if PACKETSZ > 1024
 #define	MAXPACKET	PACKETSZ
Index: src/lib/libc/net/getnetbyht.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/getnetbyht.c,v
retrieving revision 1.10
diff -d -u -r1.10 getnetbyht.c
--- src/lib/libc/net/getnetbyht.c	22 Mar 2002 21:52:29 -0000	1.10
+++ src/lib/libc/net/getnetbyht.c	12 Aug 2002 09:48:20 -0000
@@ -58,8 +58,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <nsswitch.h>
-
-#define	MAXALIASES	35
+#include <resolv.h>
 
 static FILE *netf;
 static char line[BUFSIZ+1];
Index: src/lib/libc/net/getnetbynis.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/getnetbynis.c,v
retrieving revision 1.15
diff -d -u -r1.15 getnetbynis.c
--- src/lib/libc/net/getnetbynis.c	22 Mar 2002 21:52:29 -0000	1.15
+++ src/lib/libc/net/getnetbynis.c	12 Aug 2002 09:48:20 -0000
@@ -44,9 +44,7 @@
 #include <rpcsvc/yp_prot.h>
 #include <rpcsvc/ypclnt.h>
 #endif
-
-#define	MAXALIASES	35
-#define	MAXADDRS	35
+#include <resolv.h>
 
 #ifdef YP
 static char *host_aliases[MAXALIASES];
Index: src/lib/libc/net/herror.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/herror.c,v
retrieving revision 1.11
diff -d -u -r1.11 herror.c
--- src/lib/libc/net/herror.c	22 Mar 2002 21:52:29 -0000	1.11
+++ src/lib/libc/net/herror.c	12 Aug 2002 09:48:20 -0000
@@ -71,8 +71,6 @@
 };
 int	h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
 
-int	h_errno;
-
 /*
  * herror --
  *	print the error indicated by the h_errno value.
@@ -104,9 +102,26 @@
 hstrerror(err)
 	int err;
 {
+
 	if (err < 0)
 		return ("Resolver internal error");
 	else if (err < h_nerr)
 		return (h_errlist[err]);
 	return ("Unknown resolver error");
+}
+
+#undef h_errno
+int	h_errno;
+
+/*
+ * Declare a weak reference in case the application is not linked
+ * with libpthread.
+ */
+__weak_reference(__h_errno_accessor_unthreaded, __h_errno_accessor);
+
+int *
+__h_errno_accessor_unthreaded()
+{
+
+	return &h_errno;
 }
Index: src/lib/libc/net/res_init.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/res_init.c,v
retrieving revision 1.29
diff -d -u -r1.29 res_init.c
--- src/lib/libc/net/res_init.c	22 Mar 2002 21:52:30 -0000	1.29
+++ src/lib/libc/net/res_init.c	12 Aug 2002 09:48:22 -0000
@@ -83,12 +83,12 @@
 #include <arpa/inet.h>
 #include <arpa/nameser.h>
 #include <ctype.h>
-#include <resolv.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <netdb.h>
+#include <resolv.h>
 
 #include "res_config.h"
 
@@ -104,17 +104,6 @@
 # define isascii(c) (!(c & 0200))
 #endif
 
-/*
- * Resolver state default settings.
- */
-
-struct __res_state _res
-# if defined(__BIND_RES_TEXT)
-	= { RES_TIMEOUT, }	/* Motorola, et al. */
-# endif
-	;
-
-struct __res_state_ext _res_ext;
 
 /*
  * Set up default settings.  If the configuration file exist, the values
@@ -154,6 +143,10 @@
 #ifndef RFC1535
 	int dots;
 #endif
+	
+	/* Ensure that _res_data is inited in the threaded case */
+	if(&_res_data == NULL)
+		return -1;
 
 	/*
 	 * These three fields used to be statically initialized.  This made
@@ -582,3 +575,49 @@
  */
 #undef res_init
 __weak_reference(__res_init, res_init);
+
+/*
+ * Resolver state default settings.
+ */
+
+#undef _res
+#undef _res_ext
+#undef _res_data
+
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+	= { RES_TIMEOUT, }	/* Motorola, et al. */
+# endif
+	;
+
+struct __res_state_ext _res_ext;
+
+static char *host_aliases[MAXALIASES];
+static char *h_addr_ptrs[MAXADDRS + 1];
+static char hostbuf[8*1024];
+static u_char host_addr[16];
+
+struct __res_data _res_data = { 0, -1, 0, 0, 0, NULL, NULL, NULL, 0,
+    { NULL, host_aliases, 0, 0, h_addr_ptrs }, hostbuf, sizeof hostbuf,
+    host_addr, sizeof host_addr, &_res, &_res_ext };
+
+/*
+ * Declare a weak reference in case the application is not linked
+ * with libpthread.
+ */
+__weak_reference(__res_data_accessor_unthreaded, __res_data_accessor);
+__weak_reference(__res_accessor_unthreaded, __res_accessor);
+
+struct __res_data *
+__res_data_accessor_unthreaded()
+{
+
+	return &_res_data;
+}
+
+struct __res_state *
+__res_accessor_unthreaded()
+{
+
+	return _res_data.res;
+}
Index: src/lib/libc/net/res_query.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/res_query.c,v
retrieving revision 1.23
diff -d -u -r1.23 res_query.c
--- src/lib/libc/net/res_query.c	7 Jul 2002 11:28:28 -0000	1.23
+++ src/lib/libc/net/res_query.c	12 Aug 2002 09:48:22 -0000
@@ -87,6 +87,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "res_config.h"
 
@@ -374,11 +375,21 @@
 hostalias(name)
 	const char *name;
 {
+	static char abuf[MAXDNAME];
+
+	return (hostalias_r(name, abuf, sizeof abuf));
+}
+
+const char *
+hostalias_r(name, abuf, len)
+	const char *name;
+	char *abuf;
+	int len;
+{
 	char *cp1, *cp2;
 	FILE *fp;
 	char *file;
 	char buf[BUFSIZ];
-	static char abuf[MAXDNAME];
 
 	if (_res.options & RES_NOALIASES)
 		return (NULL);
@@ -402,8 +413,8 @@
 				break;
 			for (cp2 = cp1 + 1; *cp2 && !isspace((unsigned char)*cp2); ++cp2)
 				;
-			abuf[sizeof(abuf) - 1] = *cp2 = '\0';
-			strncpy(abuf, cp1, sizeof(abuf) - 1);
+			abuf[len - 1] = *cp2 = '\0';
+			strncpy(abuf, cp1, len - 1);
 			fclose(fp);
 			return (abuf);
 		}
Index: src/lib/libc/net/res_send.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/net/res_send.c,v
retrieving revision 1.45
diff -d -u -r1.45 res_send.c
--- src/lib/libc/net/res_send.c	1 Apr 2002 16:09:45 -0000	1.45
+++ src/lib/libc/net/res_send.c	12 Aug 2002 09:48:23 -0000
@@ -102,13 +102,6 @@
 
 #include "res_config.h"
 
-static int s = -1;		/* socket used for communications */
-static int connected = 0;	/* is the socket connected */
-static int vc = 0;		/* is the socket a virtual circuit? */
-static int af = 0;		/* address family of socket */
-static res_send_qhook Qhook = NULL;
-static res_send_rhook Rhook = NULL;
-
 
 #define CAN_RECONNECT 1
 
@@ -170,7 +163,7 @@
 	res_send_qhook hook;
 {
 
-	Qhook = hook;
+	_res_data.Qhook = hook;
 }
 
 void
@@ -178,7 +171,7 @@
 	res_send_rhook hook;
 {
 
-	Rhook = hook;
+	_res_data.Rhook = hook;
 }
 
 static struct sockaddr * get_nsaddr(size_t);
@@ -406,13 +399,13 @@
 			goto next_ns;
 		}
 
-		if (Qhook) {
+		if (_res_data.Qhook) {
 			int done = 0, loops = 0;
 
 			do {
 				res_sendhookact act;
 
-				act = (*Qhook)((struct sockaddr_in **)&nsap,
+				act = (*_res_data.Qhook)((struct sockaddr_in **)&nsap,
 					       &buf, &buflen,
 					       ans, anssiz, &resplen);
 				switch (act) {
@@ -457,14 +450,16 @@
 			 */
 			try = _res.retry;
 			truncated = 0;
-			if (s < 0 || !vc || hp->opcode == ns_o_update ||
-			    af != nsap->sa_family) {
-				if (s >= 0)
+			if (_res_data.s < 0 || !_res_data.vc ||
+			    hp->opcode == ns_o_update ||
+			    _res_data.af != nsap->sa_family) {
+				if (_res_data.s >= 0)
 					res_close();
 
-				af = nsap->sa_family;
-				s = _socket(af, SOCK_STREAM, 0);
-				if (s < 0) {
+				_res_data.af = nsap->sa_family;
+				_res_data.s = _socket(_res_data.af, SOCK_STREAM,
+				    0);
+				if (_res_data.s < 0) {
 					terrno = errno;
 					Perror(stderr, "socket(vc)", errno);
 					badns |= (1 << ns);
@@ -472,7 +467,7 @@
 					goto next_ns;
 				}
 				errno = 0;
-				if (_connect(s, nsap, salen) < 0) {
+				if (_connect(_res_data.s, nsap, salen) < 0) {
 					terrno = errno;
 					Aerror(stderr, "connect/vc",
 					       errno, nsap);
@@ -480,7 +475,7 @@
 					res_close();
 					goto next_ns;
 				}
-				vc = 1;
+				_res_data.vc = 1;
 			}
 			/*
 			 * Send length & message
@@ -490,7 +485,7 @@
 			iov[0].iov_len = INT16SZ;
 			iov[1].iov_base = (caddr_t)buf;
 			iov[1].iov_len = buflen;
-			if (_writev(s, iov, 2) != (INT16SZ + buflen)) {
+			if (_writev(_res_data.s, iov, 2) != (INT16SZ + buflen)) {
 				terrno = errno;
 				Perror(stderr, "write failed", errno);
 				badns |= (1 << ns);
@@ -503,7 +498,7 @@
 read_len:
 			cp = ans;
 			len = INT16SZ;
-			while ((n = _read(s, (char *)cp, (int)len)) > 0) {
+			while ((n = _read(_res_data.s, (char *)cp, (int)len)) > 0) {
 				cp += n;
 				if ((len -= n) <= 0)
 					break;
@@ -551,7 +546,7 @@
 			}
 			cp = ans;
 			while (len != 0 &&
-			       (n = _read(s, (char *)cp, (int)len)) > 0) {
+			       (n = _read(_res_data.s, (char *)cp, (int)len)) > 0) {
 				cp += n;
 				len -= n;
 			}
@@ -574,7 +569,7 @@
 					n = (len > sizeof(junk)
 					     ? sizeof(junk)
 					     : len);
-					if ((n = _read(s, junk, n)) > 0)
+					if ((n = _read(_res_data.s, junk, n)) > 0)
 						len -= n;
 					else
 						break;
@@ -604,12 +599,14 @@
 			struct sockaddr_storage from;
 			int fromlen;
 
-			if (s < 0 || vc || af != nsap->sa_family) {
-				if (vc)
+			if (_res_data.s < 0 || _res_data.vc ||
+				_res_data.af != nsap->sa_family) {
+				if (_res_data.vc)
 					res_close();
-				af = nsap->sa_family;
-				s = _socket(af, SOCK_DGRAM, 0);
-				if (s < 0) {
+				_res_data.af = nsap->sa_family;
+				_res_data.s = _socket(_res_data.af, SOCK_DGRAM,
+				    0);
+				if (_res_data.s < 0) {
 #ifndef CAN_RECONNECT
  bad_dg_sock:
 #endif
@@ -619,7 +616,7 @@
 					res_close();
 					goto next_ns;
 				}
-				connected = 0;
+				_res_data.connected = 0;
 			}
 #ifndef CANNOT_CONNECT_DGRAM
 			/*
@@ -650,8 +647,9 @@
 				 * Connect only if we are sure we won't
 				 * receive a response from another server.
 				 */
-				if (!connected) {
-					if (_connect(s, nsap, salen) < 0) {
+				if (!_res_data.connected) {
+					if (_connect(_res_data.s, nsap, salen) <
+					    0) {
 						Aerror(stderr,
 						       "connect(dg)",
 						       errno, nsap);
@@ -659,9 +657,10 @@
 						res_close();
 						goto next_ns;
 					}
-					connected = 1;
+					_res_data.connected = 1;
 				}
-				if (send(s, (char*)buf, buflen, 0) != buflen) {
+				if (send(_res_data.s, (char*)buf, buflen, 0) !=
+				    buflen) {
 					Perror(stderr, "send", errno);
 					badns |= (1 << ns);
 					res_close();
@@ -672,7 +671,7 @@
 				 * Disconnect if we want to listen
 				 * for responses from more than one server.
 				 */
-				if (connected) {
+				if (_res_data.connected) {
 #ifdef CAN_RECONNECT
 					/* XXX: any errornous address */
 					struct sockaddr_in no_addr;
@@ -680,24 +679,25 @@
 					no_addr.sin_family = AF_INET;
 					no_addr.sin_addr.s_addr = INADDR_ANY;
 					no_addr.sin_port = 0;
-					(void) _connect(s,
+					(void) _connect(_res_data.s,
 						       (struct sockaddr *)
 						        &no_addr,
 						       sizeof no_addr);
 #else
-					int s1 = _socket(af, SOCK_DGRAM,0);
+					int s1 = _socket(_res_data.af,
+					    SOCK_DGRAM,0);
 					if (s1 < 0)
 						goto bad_dg_sock;
-					(void)_dup2(s1, s);
+					(void)_dup2(s1, _res_data.s);
 					(void)_close(s1);
 					Dprint(_res.options & RES_DEBUG,
 						(stdout, ";; new DG socket\n"))
 #endif /* CAN_RECONNECT */
-					connected = 0;
+					_res_data.connected = 0;
 					errno = 0;
 				}
 #endif /* !CANNOT_CONNECT_DGRAM */
-				if (_sendto(s, (char*)buf, buflen, 0,
+				if (_sendto(_res_data.s, (char*)buf, buflen, 0,
 					   nsap, salen) != buflen) {
 					Aerror(stderr, "sendto", errno, nsap);
 					badns |= (1 << ns);
@@ -722,13 +722,14 @@
 			(void) gettimeofday(&ctv, NULL);
 			timeradd(&timeout, &ctv, &timeout);
     wait:
-			if (s < 0) {
+			if (_res_data.s < 0) {
 				Perror(stderr, "s out-of-bounds", EMFILE);
 				res_close();
 				goto next_ns;
 			}
 
-			EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0,0,0);
+			EV_SET(&kv, _res_data.s, EVFILT_READ,
+			    EV_ADD | EV_ONESHOT, 0,0,0);
 
 			n = _kevent(kq, &kv, 1, &kv, 1, &ts);
 			if (n < 0) {
@@ -757,7 +758,7 @@
 			}
 			errno = 0;
 			fromlen = sizeof(from);
-			resplen = _recvfrom(s, (char*)ans, anssiz, 0,
+			resplen = _recvfrom(_res_data.s, (char*)ans, anssiz, 0,
 					   (struct sockaddr *)&from, &fromlen);
 			if (resplen <= 0) {
 				Perror(stderr, "recvfrom", errno);
@@ -862,15 +863,15 @@
 		    !(_res.options & RES_STAYOPEN)) {
 			res_close();
 		}
-		if (Rhook) {
+		if (_res_data.Rhook) {
 			int done = 0, loops = 0;
 
 			do {
 				res_sendhookact act;
 
-				act = (*Rhook)((struct sockaddr_in *)nsap,
-					       buf, buflen,
-					       ans, anssiz, &resplen);
+				act = (*_res_data.Rhook)(
+				    (struct sockaddr_in *)nsap, buf, buflen,
+				    ans, anssiz, &resplen);
 				switch (act) {
 				case res_goahead:
 				case res_done:
@@ -920,12 +921,12 @@
 void
 res_close()
 {
-	if (s >= 0) {
-		(void)_close(s);
-		s = -1;
-		connected = 0;
-		vc = 0;
-		af = 0;
+	if (_res_data.s >= 0) {
+		(void)_close(_res_data.s);
+		_res_data.s = -1;
+		_res_data.connected = 0;
+		_res_data.vc = 0;
+		_res_data.af = 0;
 	}
 }
 
Index: src/lib/libc_r/sys/Makefile.inc
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/sys/Makefile.inc,v
retrieving revision 1.10
diff -d -u -r1.10 Makefile.inc
--- src/lib/libc_r/sys/Makefile.inc	28 Aug 1999 00:03:13 -0000	1.10
+++ src/lib/libc_r/sys/Makefile.inc	12 Aug 2002 09:48:23 -0000
@@ -2,5 +2,5 @@
 
 .PATH:	 ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH}
 
-SRCS+=	uthread_error.c _atomic_lock.S
+SRCS+=	uthread_error.c uthread_resolv.c _atomic_lock.S
 
Index: src/lib/libc_r/sys/uthread_resolv.c
===================================================================
RCS file: src/lib/libc_r/sys/uthread_resolv.c
diff -N src/lib/libc_r/sys/uthread_resolv.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/lib/libc_r/sys/uthread_resolv.c	12 Aug 2002 09:48:23 -0000
@@ -0,0 +1,186 @@
+/*-
+ * Copyright (c) 2001 Alexandr Litvin <archer@whichever.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+#undef h_errno
+#undef _res
+#undef _res_ext
+#undef _res_data
+
+extern	int h_errno;
+extern  struct __res_data _res_data;
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+static pthread_key_t key;
+
+
+static void
+__res_data_destroy(void *p)
+{
+	struct __res_data *_res_datap = (struct __res_data *)p;
+
+	if(_res_datap->res)
+		free(_res_datap->res);
+	if(_res_datap->res_ext)
+		free(_res_datap->res_ext);
+	if (_res_datap->host.h_aliases)
+		free(_res_datap->host.h_aliases);
+	if (_res_datap->host.h_addr_list)
+		free(_res_datap->host.h_addr_list);
+	if (_res_datap->hostbuf)
+		free(_res_datap->hostbuf);
+	if (_res_datap->host_addr)
+		free(_res_datap->host_addr);
+	if(_res_datap->s >= 0)
+		close(_res_datap->s);
+	if(_res_datap->hostf)
+		fclose(_res_datap->hostf);
+	free(_res_datap);
+}
+
+static void
+__res_data_init()
+{
+
+	pthread_key_create(&key, __res_data_destroy);
+}
+
+struct __res_data *
+__res_data_accessor()
+{
+	struct __res_data *_res_datap;
+
+	if (_thread_run == _thread_initial) {
+		_res_datap = &_res_data;
+	} else {
+		pthread_once(&once, __res_data_init);
+		_res_datap = (struct __res_data *)pthread_getspecific(key);
+		if(_res_datap==NULL) {
+			_res_datap = malloc(sizeof(struct __res_data));
+			if(_res_datap==NULL)
+				return (NULL);
+			bzero(_res_datap, sizeof(struct __res_data));
+			_res_datap->res = malloc(sizeof(struct __res_state));
+			if(_res_datap->res == NULL)
+				goto e1;
+			bzero(_res_datap->res, sizeof(struct __res_state));
+			_res_datap->res_ext =
+			    malloc(sizeof(struct __res_state_ext));
+			if(_res_datap->res_ext == NULL)
+				goto e2;
+			bzero(_res_datap->res_ext,
+			    sizeof(struct __res_state_ext));
+			_res_datap->s = -1;
+			_res_datap->host.h_name = NULL;
+			_res_datap->host.h_aliases =
+			    malloc(sizeof(char *[MAXALIASES]));
+			if (_res_datap->host.h_aliases == NULL)
+				goto e3;
+			_res_datap->host.h_addrtype = 0;
+			_res_datap->host.h_length = 0;
+			_res_datap->host.h_addr_list =
+			    malloc(sizeof(char *[MAXADDRS + 1]));
+			if (_res_datap->host.h_addr_list == NULL)
+				goto e4;
+			_res_datap->hostbuflen = sizeof(*_res_datap->hostbuf) *
+			    8 * 1024;
+			_res_datap->hostbuf = malloc(_res_datap->hostbuflen);
+			if (_res_datap->hostbuf == NULL)
+				goto e5;
+			_res_datap->host_addrlen =
+			    sizeof(*_res_datap->host_addr) * 16;
+			_res_datap->host_addr =
+			    malloc(_res_datap->host_addrlen);
+			if (_res_datap->host_addr == NULL)
+				goto e6;
+			pthread_setspecific(key, _res_datap);
+		}
+	}
+	return (_res_datap);
+
+e6:	free(_res_datap->hostbuf);
+e5:	free(_res_datap->host.h_addr_list);
+e4:	free(_res_datap->host.h_aliases);
+e3:	free(_res_datap->res_ext);
+e2:	free(_res_datap->res);
+e1:	free(_res_datap);
+	return (NULL);
+}
+
+static struct __res_state dummy_res;
+static int dummy_h_errno;
+
+struct __res_state *
+__res_accessor()
+{
+	struct __res_state *resp;
+	struct __res_data *_res_datap;
+
+	if (_thread_run == _thread_initial) {
+		resp = _res_data.res;
+	} else {
+		_res_datap = __res_data_accessor();
+		if(_res_datap) {
+			resp = _res_datap->res;
+		} else {
+			dummy_res.options = RES_DEFAULT;
+			resp = &dummy_res;
+		}
+	}
+	return (resp);
+}
+
+int *
+__h_errno_accessor()
+{
+	int *h_errnop;
+	struct __res_data *_res_datap;
+
+	if (_thread_run == _thread_initial) {
+		h_errnop = &h_errno;
+	} else {
+		_res_datap = __res_data_accessor();
+		if(_res_datap) {
+			h_errnop = &_res_datap->h_errno_res;
+		} else {
+			dummy_h_errno = NETDB_INTERNAL;
+			h_errnop = &dummy_h_errno;
+		}
+	}
+	return (h_errnop);
+}


--------------051496A982500B2DDF1E4FCD--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3D578A99.F0821712>