Index: w3m/Makefile.in
diff -u w3m/Makefile.in:1.7 w3m/Makefile.in:1.6.2.5
--- w3m/Makefile.in:1.7	Sun Mar 28 01:23:44 2004
+++ w3m/Makefile.in	Sun Mar 28 02:38:01 2004
@@ -44,8 +44,9 @@
         -DLOCALEDIR=\"$(localedir)\"
 LDFLAGS = @LDFLAGS@
 LIBS = -L. -lindep @LIBINTL@ @LIBS@
-W3M_LIBS = @W3M_LIBS@
+W3M_LIBS = @W3M_LIBS@ -Lresolv -lw3mresolv
 WCTARGET = @WCTARGET@
+RESTARGET = resolv/libw3mresolv.a
 NLSTARGET = @NLSTARGET@
 
 MAKE_ARGS = PERL='$(PERL)' MKDIR='$(MKDIR)' INSTALL='$(INSTALL)' \
@@ -119,12 +120,12 @@
 
 DEFUNS=$(top_srcdir)/main.c $(top_srcdir)/menu.c
 SCRIPTSUBDIRS= scripts
-SUBDIRS = $(SCRIPTSUBDIRS) w3mimg libwc po
+SUBDIRS = $(SCRIPTSUBDIRS) w3mimg libwc resolv po
 .PHONY: $(SUBDIRS)
 
 all: $(TARGETS) all-scripts $(NLSTARGET)
 
-$(TARGET): $(ALLOBJS) $(ALIB) $(WCTARGET)
+$(TARGET): $(ALLOBJS) $(ALIB) $(WCTARGET) $(RESTARGET)
 	$(CC) $(CFLAGS) -o $(TARGET) $(ALLOBJS) $(LDFLAGS) $(LIBS) $(W3M_LIBS)
 
 $(ALIB): $(ALIBOBJS)
@@ -199,6 +200,9 @@
 w3mimg/w3mimg.a:
 	(cd w3mimg && $(MAKE) CC="$(CC0)" CFLAGS="$(CFLAGS)")
 
+resolv/libw3mresolv.a:
+	(cd resolv && $(MAKE) CC='$(CC0)' TOP_CFLAGS='$(CFLAGS)')
+ 
 po:
 	(cd $@ && $(MAKE))
 
@@ -280,7 +284,7 @@
 	-$(RM) -f *.o *.a $(TARGETS) mktable$(EXT)
 	-$(RM) -f funcname.tab
 	-$(RM) -f funcname.c funcname1.h funcname2.h tagtable.c functable.c
-	-for dir in w3mimg libwc; \
+	-for dir in w3mimg libwc resolv; \
 	do \
 		(cd $$dir && $(MAKE) clean RM="$(RM)"); \
 	done
Index: w3m/acinclude.m4
diff -u w3m/acinclude.m4:1.6 w3m/acinclude.m4:1.5.2.2
--- w3m/acinclude.m4:1.6	Sun Mar 28 01:23:44 2004
+++ w3m/acinclude.m4	Sun Mar 28 02:38:01 2004
@@ -741,7 +741,8 @@
 # AC_W3M_IPv6
 # ----------------------------------------------------------------
 AC_DEFUN([AC_W3M_IPv6],
-[AC_MSG_CHECKING(if IPv6 support is enabled)
+[AC_SUBST(EXTRA_RESOLV_OBJS)
+AC_MSG_CHECKING(if IPv6 support is enabled)
 AC_ARG_ENABLE(ipv6,
  [  --disable-ipv6		disable IPv6],,
  [enable_ipv6="yes"])
@@ -798,6 +799,10 @@
  if test x"$enable_ipv6" = xyes; then
     AC_DEFINE(INET6)
  fi
+fi
+if test x"$enable_ipv6" != xyes; then
+  EXTRA_RESOLV_OBJS='$(INET4_OBJS)'
+  AC_DEFINE(EXTRA_RESOLV_OBJS, "$EXTRA_RESOLV_OBJS")
 fi])
 #
 # ----------------------------------------------------------------
Index: w3m/config.h.in
diff -u w3m/config.h.in:1.8 w3m/config.h.in:1.7.2.2
--- w3m/config.h.in:1.8	Sun Mar 28 02:20:06 2004
+++ w3m/config.h.in	Sun Mar 28 02:38:01 2004
@@ -143,6 +143,11 @@
 #undef HAVE_CHDIR
 #undef HAVE_SETPGRP
 #undef HAVE_SETLOCALE
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+#undef HAVE_SOCKLEN_T
+#undef HAVE_IN_ADDR_T
+#undef HAVE_IN_PORT_T
+#undef HAVE_U_INT32_T
 
 #undef SETPGRP_VOID
 #ifdef SETPGRP_VOID
Index: w3m/configure.in
diff -u w3m/configure.in:1.9 w3m/configure.in:1.7.2.3
--- w3m/configure.in:1.9	Sun Mar 28 02:42:08 2004
+++ w3m/configure.in	Sun Mar 28 02:38:01 2004
@@ -148,6 +148,15 @@
 AC_FUNC_STRFTIME
 AC_FUNC_WAIT3
 AC_FUNC_SETPGRP
+AC_CHECK_MEMBERS([struct sockaddr.sa_len],,,[dnl
+#include <sys/types.h>
+#include <sys/socket.h>
+])
+AC_CHECK_TYPES([socklen_t,in_addr_t,in_port_t,u_int32_t],,,[dnl
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+])
 AC_W3M_SYS_ERRLIST
 AC_W3M_SIGSETJMP
 AC_W3M_SIGNAL
@@ -173,6 +182,7 @@
 scripts/w3mman/w3mman2html.cgi \
 libwc/Makefile \
 w3mimg/Makefile w3mimg/fb/Makefile w3mimg/x11/Makefile \
+resolv/Makefile \
 w3mhelp-w3m_en.html w3mhelp-w3m_ja.html \
 w3mhelp-lynx_en.html w3mhelp-lynx_ja.html])
 
Index: w3m/etc.c
diff -u w3m/etc.c:1.15 w3m/etc.c:1.15.2.3
--- w3m/etc.c:1.15	Tue Mar 23 04:47:20 2004
+++ w3m/etc.c	Sat Mar 27 22:29:06 2004
@@ -1932,19 +1932,20 @@
 }
 
 #ifdef USE_COOKIE
-#ifdef INET6
-#include <sys/socket.h>
-#endif				/* INET6 */
-#include <netdb.h>
+#include "resolv/w3mresolv.h"
+static MySignalHandler
+KeyAbort(SIGNAL_ARG)
+{
+    w3m_cancel_resolv();
+    SIGNAL_RETURN;
+}
+
 char *
 FQDN(char *host)
 {
     char *p;
-#ifndef INET6
-    struct hostent *entry;
-#else				/* INET6 */
     int *af;
-#endif				/* INET6 */
+    MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
 
     if (host == NULL)
 	return NULL;
@@ -1957,23 +1958,26 @@
     if (*p == '.')
 	return host;
 
-#ifndef INET6
-    if (!(entry = gethostbyname(host)))
-	return NULL;
+    /*
+     * I don't change terminal settings because FQDN() is invoked in
+     * both contexts where TRAP_ON and where TRAP_OFF.
+     */
+    if (TrapSignal)
+	prevtrap = mySignal(SIGINT, KeyAbort);
 
-    return allocStr(entry->h_name, -1);
-#else				/* INET6 */
     for (af = ai_family_order_table[DNS_order];; af++) {
 	int error;
-	struct addrinfo hints;
-	struct addrinfo *res, *res0;
+	struct w3m_addrinfo hints;
+	struct w3m_addrinfo *res, *res0;
 	char *namebuf;
 
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_family = *af;
 	hints.ai_socktype = SOCK_STREAM;
-	error = getaddrinfo(host, NULL, &hints, &res0);
-	if (error) {
+	error = w3m_getaddrinfo_intr(host, NULL, &hints, &res0, NULL);
+	if (error == W3M_RESOLV_CANCELED) {
+	    break;
+	} else if (error == W3M_RESOLV_FAILED) {
 	    if (*af == PF_UNSPEC) {
 		/* all done */
 		break;
@@ -1984,19 +1988,22 @@
 	for (res = res0; res != NULL; res = res->ai_next) {
 	    if (res->ai_canonname) {
 		/* found */
-		namebuf = strdup(res->ai_canonname);
-		freeaddrinfo(res0);
+		namebuf = allocStr(res->ai_canonname, -1);
+		w3m_freeaddrinfo(res0);
+		if (TrapSignal)
+		    mySignal(SIGINT, prevtrap);
 		return namebuf;
 	    }
 	}
-	freeaddrinfo(res0);
+	w3m_freeaddrinfo(res0);
 	if (*af == PF_UNSPEC) {
 	    break;
 	}
     }
     /* all failed */
+    if (TrapSignal)
+	mySignal(SIGINT, prevtrap);
     return NULL;
-#endif				/* INET6 */
 }
 
 #endif				/* USE_COOKIE */
@@ -2007,7 +2014,7 @@
 
     sigemptyset(&new_action.sa_mask);
     new_action.sa_handler = action;
-    if (signal_number == SIGALRM) {
+    if (signal_number == SIGALRM || signal_number == SIGINT) {
 #ifdef	SA_INTERRUPT
 	new_action.sa_flags = SA_INTERRUPT;
 #else
Index: w3m/fm.h
diff -u w3m/fm.h:1.21 w3m/fm.h:1.20.2.3
--- w3m/fm.h:1.21	Sun Mar 28 02:20:06 2004
+++ w3m/fm.h	Sun Mar 28 02:38:01 2004
@@ -22,6 +22,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <assert.h>
 #include "config.h"
 #include "history.h"
 
@@ -839,7 +840,10 @@
 #define DNS_ORDER_INET6_ONLY 6
 global int DNS_order init(DNS_ORDER_UNSPEC);
 extern int ai_family_order_table[7][3];	/* XXX */
-#endif				/* INET6 */
+#else				/* !INET6 */
+#define DNS_order 0
+extern int ai_family_order_table[1][3];	/* XXX */
+#endif				/* !INET6 */
 global TextList *NO_proxy_domains;
 global char NoCache init(FALSE);
 global char use_proxy init(TRUE);
Index: w3m/ftp.c
diff -u w3m/ftp.c:1.1.1.8 w3m/ftp.c:1.1.1.8.2.1
--- w3m/ftp.c:1.1.1.8	Sat Nov  1 21:02:54 2003
+++ w3m/ftp.c	Sat Mar 27 10:39:35 2004
@@ -9,6 +9,7 @@
 #include "fm.h"
 #include "html.h"
 #include "myctype.h"
+#include "resolv/w3mresolv.h"
 
 #ifdef DEBUG
 #include <malloc.h>
@@ -42,6 +43,13 @@
     SIGNAL_RETURN;
 }
 
+static MySignalHandler
+KeyAbortResolv(SIGNAL_ARG)
+{
+    w3m_cancel_resolv();
+    SIGNAL_RETURN;
+}
+
 static Str
 ftp_command(FTP ftp, char *cmd, char *arg, int *status)
 {
@@ -121,21 +129,46 @@
 	size_t n = strlen(ftp->pass);
 
 	if (n > 0 && ftp->pass[n - 1] == '@') {
+#ifdef INET6
+	    struct sockaddr_storage sockname;
+#else
 	    struct sockaddr_in sockname;
+#endif
 	    int socknamelen = sizeof(sockname);
 
 	    if (!getsockname(sock, (struct sockaddr *)&sockname, &socknamelen)) {
-		struct hostent *sockent;
-		Str tmp = Strnew_charp(ftp->pass);
-
-		if ((sockent = gethostbyaddr((char *)&sockname.sin_addr,
-					     sizeof(sockname.sin_addr),
-					     sockname.sin_family)))
-		    Strcat_charp(tmp, sockent->h_name);
-		else
-		    Strcat_m_charp(tmp, "[", inet_ntoa(sockname.sin_addr),
-				   "]", NULL);
+		MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
+		char hostbuf[W3M_NI_MAXHOST];
+		int r;
 
+		Str tmp = Strnew_charp(ftp->pass);
+		if (TrapSignal) {
+		    prevtrap = mySignal(SIGINT, KeyAbortResolv);
+		    if (fmInitialized)
+			term_cbreak();
+		}
+		r = w3m_getnameinfo_intr(
+			(struct sockaddr *)&sockname, socknamelen,
+			hostbuf, sizeof hostbuf, NULL, 0,
+			W3M_NI_NAMEREQD, NULL);
+		if (TrapSignal) {
+		    if (fmInitialized)
+			term_raw();
+		    if (prevtrap)
+			mySignal(SIGINT, prevtrap);
+		}
+
+		if (r == W3M_RESOLV_OK) {
+		    Strcat_charp(tmp, hostbuf);
+		} else if (r == W3M_RESOLV_FAILED) {
+		    if (w3m_getnameinfo(
+				(struct sockaddr *)&sockname, socknamelen,
+				hostbuf, sizeof hostbuf, NULL, 0,
+				W3M_NI_NUMERICHOST) == 0)
+			Strcat_m_charp(tmp, "[", hostbuf, "]", NULL);
+		    else
+			Strcat_charp(tmp, "unknown");
+		}
 		ftp->pass = tmp->ptr;
 	    }
 	}
Index: w3m/url.c
diff -u w3m/url.c:1.18 w3m/url.c:1.16.2.5
--- w3m/url.c:1.18	Sun Mar 28 02:27:26 2004
+++ w3m/url.c	Sun Mar 28 02:38:01 2004
@@ -1,5 +1,6 @@
 /* $Id: url.c,v 1.87 2003/12/08 16:17:21 ukai Exp $ */
 #include "fm.h"
+#include "resolv/w3mresolv.h"
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -43,10 +44,12 @@
     {PF_UNSPEC, PF_UNSPEC, PF_UNSPEC},  /* 5: --- */
     {PF_INET6, PF_UNSPEC, PF_UNSPEC},   /* 6:inet6 */
 };
+#else				/* !INET6 */
+int ai_family_order_table[1][3] = {
+    {PF_UNSPEC, PF_UNSPEC, PF_UNSPEC},
+};
 #endif				/* INET6 */
 
-static JMP_BUF AbortLoading;
-
 /* XXX: note html.h SCM_ */
 static int
  DefaultPort[] = {
@@ -234,7 +237,7 @@
 static MySignalHandler
 KeyAbort(SIGNAL_ARG)
 {
-    LONGJMP(AbortLoading, 1);
+    w3m_cancel_resolv();
     SIGNAL_RETURN;
 }
 
@@ -441,67 +444,68 @@
 openSocket(char *const hostname,
 	   char *remoteport_name, unsigned short remoteport_num)
 {
-    volatile int sock = -1;
-#ifdef INET6
+    int sock = -1;
+    int reason;
     int *af;
-    struct addrinfo hints, *res0, *res;
+    struct w3m_addrinfo hints, *res0 = NULL, *res;
     int error;
     char *hname;
-#else				/* not INET6 */
-    struct sockaddr_in hostaddr;
-    struct hostent *entry;
-    struct protoent *proto;
-    unsigned short s_port;
-    int a1, a2, a3, a4;
-    unsigned long adr;
-#endif				/* not INET6 */
     MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
 
+    assert(hostname);
     if (fmInitialized) {
 	/* FIXME: gettextize? */
 	message(Sprintf("Opening socket...")->ptr, 0, 0);
 	refresh();
     }
-    if (SETJMP(AbortLoading) != 0) {
-#ifdef SOCK_DEBUG
-	sock_log("openSocket() failed. reason: user abort\n");
-#endif
-	if (sock >= 0)
-	    close(sock);
-	goto error;
-    }
-    TRAP_ON;
-    if (hostname == NULL) {
-#ifdef SOCK_DEBUG
-	sock_log("openSocket() failed. reason: Bad hostname \"%s\"\n",
-		 hostname);
-#endif
-	goto error;
-    }
 
+    hname = hostname;
 #ifdef INET6
     /* rfc2732 compliance */
-    hname = hostname;
-    if (hname != NULL && hname[0] == '[' && hname[strlen(hname) - 1] == ']') {
+    if (hname[0] == '[' && hname[strlen(hname) - 1] == ']') {
 	hname = allocStr(hostname + 1, -1);
 	hname[strlen(hname) - 1] = '\0';
-	if (strspn(hname, "0123456789abcdefABCDEF:.") != strlen(hname))
-	    goto error;
+	if (strspn(hname, "0123456789abcdefABCDEF:.") != strlen(hname)) {
+#ifdef SOCK_DEBUG
+	    sock_log("openSocket() failed. reason: Bad hostname \"%s\"\n",
+		     hostname);
+#endif
+	    return -1;
+	}
     }
+#endif
+
+    TRAP_ON;
     for (af = ai_family_order_table[DNS_order];; af++) {
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_family = *af;
 	hints.ai_socktype = SOCK_STREAM;
 	if (remoteport_num != 0) {
 	    Str portbuf = Sprintf("%d", remoteport_num);
-	    error = getaddrinfo(hname, portbuf->ptr, &hints, &res0);
+	    error = w3m_getaddrinfo_intr(
+		    hname, portbuf->ptr, &hints, &res0, &reason);
+#ifdef SOCK_DEBUG
+	    if (error)
+		sock_log("openSocket: w3m_getaddrinfo_intr() failed. reason: %s\n",
+			 w3m_gai_strerror(reason));
+#endif
+	    if (error == W3M_RESOLV_CANCELED)
+		goto canceled;
 	}
 	else {
 	    error = -1;
 	}
 	if (error && remoteport_name && remoteport_name[0] != '\0') {
 	    /* try default port */
-	    error = getaddrinfo(hname, remoteport_name, &hints, &res0);
+	    error = w3m_getaddrinfo_intr(
+		    hname, remoteport_name, &hints, &res0, &reason);
+#ifdef SOCK_DEBUG
+	    if (error)
+		sock_log("openSocket: w3m_getaddrinfo_intr() failed. reason: %s\n",
+			 w3m_gai_strerror(reason));
+#endif
+	    if (error == W3M_RESOLV_CANCELED)
+		goto canceled;
 	}
 	if (error) {
 	    if (*af == PF_UNSPEC) {
@@ -510,117 +514,58 @@
 	    /* try next ai family */
 	    continue;
 	}
-	sock = -1;
 	for (res = res0; res; res = res->ai_next) {
 	    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 	    if (sock < 0) {
+		int saved_errno = errno;
+#ifdef SOCK_DEBUG
+		sock_log("openSocket: socket() failed. reason: %s\n",
+			strerror(saved_errno));
+#endif
+		if (saved_errno == EINTR)
+		    goto canceled;
 		continue;
 	    }
 	    if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
+		int saved_errno = errno;
 		close(sock);
 		sock = -1;
+#ifdef SOCK_DEBUG
+		sock_log("openSocket: connect() failed. reason: %s\n",
+			strerror(saved_errno));
+#endif
+		if (saved_errno == EINTR)
+		    goto canceled;
 		continue;
 	    }
 	    break;
 	}
+	w3m_freeaddrinfo(res0);
+	res0 = NULL;
 	if (sock < 0) {
-	    freeaddrinfo(res0);
 	    if (*af == PF_UNSPEC) {
 		goto error;
 	    }
 	    /* try next ai family */
 	    continue;
 	}
-	freeaddrinfo(res0);
 	break;
     }
-#else				/* not INET6 */
-    s_port = htons(remoteport_num);
-    bzero((char *)&hostaddr, sizeof(struct sockaddr_in));
-    if ((proto = getprotobyname("tcp")) == NULL) {
-	/* protocol number of TCP is 6 */
-	proto = New(struct protoent);
-	proto->p_proto = 6;
-    }
-    if ((sock = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0) {
-#ifdef SOCK_DEBUG
-	sock_log("openSocket: socket() failed. reason: %s\n", strerror(errno));
-#endif
-	goto error;
-    }
-    regexCompile("^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$", 0);
-    if (regexMatch(hostname, -1, 1)) {
-	sscanf(hostname, "%d.%d.%d.%d", &a1, &a2, &a3, &a4);
-	adr = htonl((a1 << 24) | (a2 << 16) | (a3 << 8) | a4);
-	bcopy((void *)&adr, (void *)&hostaddr.sin_addr, sizeof(long));
-	hostaddr.sin_family = AF_INET;
-	hostaddr.sin_port = s_port;
-	if (fmInitialized) {
-	    message(Sprintf("Connecting to %s", hostname)->ptr, 0, 0);
-	    refresh();
-	}
-	if (connect(sock, (struct sockaddr *)&hostaddr,
-		    sizeof(struct sockaddr_in)) < 0) {
-#ifdef SOCK_DEBUG
-	    sock_log("openSocket: connect() failed. reason: %s\n",
-		     strerror(errno));
-#endif
-	    goto error;
-	}
-    }
-    else {
-	char **h_addr_list;
-	int result = -1;
-	if (fmInitialized) {
-	    message(Sprintf("Performing hostname lookup on %s", hostname)->ptr,
-		    0, 0);
-	    refresh();
-	}
-	if ((entry = gethostbyname(hostname)) == NULL) {
-#ifdef SOCK_DEBUG
-	    sock_log("openSocket: gethostbyname() failed. reason: %s\n",
-		     strerror(errno));
-#endif
-	    goto error;
-	}
-	hostaddr.sin_family = AF_INET;
-	hostaddr.sin_port = s_port;
-	for (h_addr_list = entry->h_addr_list; *h_addr_list; h_addr_list++) {
-	    bcopy((void *)h_addr_list[0], (void *)&hostaddr.sin_addr,
-		  entry->h_length);
-#ifdef SOCK_DEBUG
-	    adr = ntohl(*(long *)&hostaddr.sin_addr);
-	    sock_log("openSocket: connecting %d.%d.%d.%d\n",
-		     (adr >> 24) & 0xff,
-		     (adr >> 16) & 0xff, (adr >> 8) & 0xff, adr & 0xff);
-#endif
-	    if (fmInitialized) {
-		message(Sprintf("Connecting to %s", hostname)->ptr, 0, 0);
-		refresh();
-	    }
-	    if ((result = connect(sock, (struct sockaddr *)&hostaddr,
-				  sizeof(struct sockaddr_in))) == 0) {
-		break;
-	    }
-#ifdef SOCK_DEBUG
-	    else {
-		sock_log("openSocket: connect() failed. reason: %s\n",
-			 strerror(errno));
-	    }
-#endif
-	}
-	if (result < 0) {
-	    goto error;
-	}
-    }
-#endif				/* not INET6 */
 
     TRAP_OFF;
     return sock;
+  canceled:
+#ifdef SOCK_DEBUG
+    sock_log("openSocket() failed. reason: user abort\n");
+#endif
+    goto error;
   error:
     TRAP_OFF;
+    if (sock >= 0)
+	close(sock);
+    if (res0)
+	w3m_freeaddrinfo(res0);
     return -1;
-
 }
 
 
@@ -1992,49 +1937,25 @@
     /* 
      * to check noproxy by network addr
      */
-    if (SETJMP(AbortLoading) != 0) {
-	ret = 0;
-	goto end;
-    }
     TRAP_ON;
     {
-#ifndef INET6
-	struct hostent *he;
-	int n;
-	unsigned char **h_addr_list;
-	char addr[4 * 16], buf[5];
-
-	he = gethostbyname(domain);
-	if (!he) {
-	    ret = 0;
-	    goto end;
-	}
-	for (h_addr_list = (unsigned char **)he->h_addr_list; *h_addr_list;
-	     h_addr_list++) {
-	    sprintf(addr, "%d", h_addr_list[0][0]);
-	    for (n = 1; n < he->h_length; n++) {
-		sprintf(buf, ".%d", h_addr_list[0][n]);
-		strcat(addr, buf);
-	    }
-	    for (tl = NO_proxy_domains->first; tl != NULL; tl = tl->next) {
-		if (strncmp(tl->ptr, addr, strlen(tl->ptr)) == 0) {
-		    ret = 1;
-		    goto end;
-		}
-	    }
-	}
-#else				/* INET6 */
 	int error;
-	struct addrinfo hints;
-	struct addrinfo *res, *res0;
-	char addr[4 * 16];
+	struct w3m_addrinfo hints;
+	struct w3m_addrinfo *res, *res0;
+#ifdef INET6
+	char addr[INET6_ADDRSTRLEN];
+#else
+	char addr[INET_ADDRSTRLEN];
+#endif
 	int *af;
 
 	for (af = ai_family_order_table[DNS_order];; af++) {
 	    memset(&hints, 0, sizeof(hints));
 	    hints.ai_family = *af;
-	    error = getaddrinfo(domain, NULL, &hints, &res0);
-	    if (error) {
+	    error = w3m_getaddrinfo_intr(domain, NULL, &hints, &res0, NULL);
+	    if (error == W3M_RESOLV_CANCELED) {
+		break;
+	    } else if (error == W3M_RESOLV_FAILED) {
 		if (*af == PF_UNSPEC) {
 		    break;
 		}
@@ -2044,33 +1965,34 @@
 	    for (res = res0; res != NULL; res = res->ai_next) {
 		switch (res->ai_family) {
 		case AF_INET:
-		    inet_ntop(AF_INET,
+		    w3m_inet_ntop(AF_INET,
 			      &((struct sockaddr_in *)res->ai_addr)->sin_addr,
 			      addr, sizeof(addr));
 		    break;
+#ifdef INET6
 		case AF_INET6:
-		    inet_ntop(AF_INET6,
+		    w3m_inet_ntop(AF_INET6,
 			      &((struct sockaddr_in6 *)res->ai_addr)->
 			      sin6_addr, addr, sizeof(addr));
 		    break;
+#endif
 		default:
 		    /* unknown */
 		    continue;
 		}
 		for (tl = NO_proxy_domains->first; tl != NULL; tl = tl->next) {
 		    if (strncmp(tl->ptr, addr, strlen(tl->ptr)) == 0) {
-			freeaddrinfo(res0);
+			w3m_freeaddrinfo(res0);
 			ret = 1;
 			goto end;
 		    }
 		}
 	    }
-	    freeaddrinfo(res0);
+	    w3m_freeaddrinfo(res0);
 	    if (*af == PF_UNSPEC) {
 		break;
 	    }
 	}
-#endif				/* INET6 */
     }
   end:
     TRAP_OFF;
Index: w3m/resolv/.cvsignore
diff -u /dev/null w3m/resolv/.cvsignore:1.1.2.3
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/.cvsignore	Sat Mar 27 23:41:39 2004
@@ -0,0 +1,3 @@
+libw3mresolv.a
+generated
+Makefile
Index: w3m/resolv/Makefile.in
diff -u /dev/null w3m/resolv/Makefile.in:1.1.2.1
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/Makefile.in	Sat Mar 27 23:44:04 2004
@@ -0,0 +1,56 @@
+#
+# Makefile
+# @configure_input@
+#
+@SET_MAKE@
+SHELL=@SHELL@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = .
+VPATH = $(top_srcdir):.
+AR=ar
+RANLIB=@RANLIB@
+RM=rm
+
+CFLAGS = $(OPTS) @CFLAGS@ $(CPPFLAGS) $(DEFS)
+CPPFLAGS = @CPPFLAGS@
+DEFS = @DEFS@ -I$(top_srcdir)
+
+INET4_OBJS = generated/getaddrinfo4.o generated/getnameinfo4.o inet_pton.o
+OBJS = w3mresolv.o @EXTRA_RESOLV_OBJS@
+
+REPLACE = $(SHELL) $(srcdir)/replace.sh $(srcdir)/namespace.sed
+REPLACED_DEPS = generated/stamp namespace.sed
+HEADERS = generated/addrinfo4.h addrinfo6.h w3mresolv.h
+
+all: libw3mresolv.a
+
+.SUFFIXES: .c .o
+
+.c.o:
+	$(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) $(DEFS)
+
+libw3mresolv.a: $(OBJS)
+	$(AR) cru $@ $(OBJS)
+	$(RANLIB) $@
+
+generated/stamp:
+	-test -d generated || mkdir generated
+	touch generated/stamp
+generated/getaddrinfo4.c: getaddrinfo4.c.in $(REPLACED_DEPS)
+	$(REPLACE) getaddrinfo4.c.in > $@
+generated/getnameinfo4.c: getnameinfo4.c.in $(REPLACED_DEPS)
+	$(REPLACE) getnameinfo4.c.in > $@
+generated/addrinfo4.h: addrinfo4.h.in $(REPLACED_DEPS)
+	$(REPLACE) addrinfo4.h.in > $@
+
+generated/getaddrinfo4.o: $(HEADERS)
+generated/getnameinfo4.o: $(HEADERS)
+inet_pton.o: $(HEADERS)
+w3mresolv.o: $(HEADERS)
+
+clean:
+	rm -rf generated
+	rm -f *.o libw3mresolv.a
Index: w3m/resolv/addrinfo4.h.in
diff -u /dev/null w3m/resolv/addrinfo4.h.in:1.1.2.3
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/addrinfo4.h.in	Sat Mar 27 02:29:37 2004
@@ -0,0 +1,95 @@
+/* $Id: addrinfo4.h.in,v 1.1.2.3 2004/03/26 17:29:37 shinra Exp $ */
+/* This file is derived from KAME-20040322-snap kit. */
+/*	$KAME: addrinfo.h,v 1.6 2001/01/26 08:14:55 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+#ifndef W3M_ADDRINFO4_H
+#define W3M_ADDRINFO4_H
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+/* #define	EAI_ADDRFAMILY	 1	obsoleted by EAI_FAMILY */
+#define	EAI_AGAIN	 2	/* temporary failure in name resolution */
+#define	EAI_BADFLAGS	 3	/* invalid value for ai_flags */
+#define	EAI_FAIL	 4	/* non-recoverable failure in name resolution */
+#define	EAI_FAMILY	 5	/* ai_family not supported */
+#define	EAI_MEMORY	 6	/* memory allocation failure */
+/* #define	EAI_NODATA	 7	obsoleted by EAI_NONAME */
+#define	EAI_NONAME	 8	/* hostname nor servname provided, or not known */
+#define	EAI_SERVICE	 9	/* servname not supported for ai_socktype */
+#define	EAI_SOCKTYPE	10	/* ai_socktype not supported */
+#define	EAI_SYSTEM	11	/* system error returned in errno */
+#define EAI_BADHINTS	12
+#define EAI_PROTOCOL	13
+#define EAI_MAX		14
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#define	AI_PASSIVE	0x00000001 /* get address to use bind() */
+#define	AI_CANONNAME	0x00000002 /* fill ai_canonname */
+#define	AI_NUMERICHOST	0x00000004 /* prevent name resolution */
+/* valid flags for addrinfo */
+#define	AI_MASK		(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
+
+#define	AI_ALL		0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
+#define	AI_V4MAPPED_CFG	0x00000200 /* accept IPv4-mapped if kernel supports */
+#define	AI_ADDRCONFIG	0x00000400 /* only if any address is assigned */
+#define	AI_V4MAPPED	0x00000800 /* accept IPv4-mapped IPv6 address */
+
+extern char *w3m_gai_strerror(int);
+extern int w3m_getaddrinfo(const char *, const char *,
+			    const struct addrinfo *, struct addrinfo **);
+extern int w3m_getnameinfo(const struct sockaddr *, w3m_socklen_t, char *,
+			    size_t, char *, size_t, int);
+
+#ifndef NI_MAXSERV
+/*
+ * Constants for getnameinfo()
+ */
+#define	NI_MAXHOST	1025
+#define	NI_MAXSERV	32
+#endif
+
+#ifndef NI_NAMEREQD
+/*
+ * Flag values for getnameinfo()
+ */
+#define	NI_NOFQDN	0x00000001
+#define	NI_NUMERICHOST	0x00000002
+#define	NI_NAMEREQD	0x00000004
+#define	NI_NUMERICSERV	0x00000008
+#define	NI_DGRAM	0x00000010
+#endif
+
+#endif /* W3M_ADDRINFO4_H */
+/* vim: set sw=8: */
Index: w3m/resolv/addrinfo6.h
diff -u /dev/null w3m/resolv/addrinfo6.h:1.1.2.3
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/addrinfo6.h	Sat Mar 27 02:29:37 2004
@@ -0,0 +1,55 @@
+/* $Id: addrinfo6.h,v 1.1.2.3 2004/03/26 17:29:37 shinra Exp $ */
+#ifndef W3M_ADDRINFO6_H
+#define W3M_ADDRINFO6_H
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+#define	W3M_EAI_AGAIN		EAI_AGAIN
+#define	W3M_EAI_BADFLAGS	EAI_BADFLAGS
+#define	W3M_EAI_FAIL		EAI_FAIL
+#define	W3M_EAI_FAMILY		EAI_FAMILY
+#define	W3M_EAI_MEMORY		EAI_MEMORY
+#define	W3M_EAI_NONAME		EAI_NONAME
+#define	W3M_EAI_SERVICE		EAI_SERVICE
+#define	W3M_EAI_SOCKTYPE	EAI_SOCKTYPE
+#define	W3M_EAI_SYSTEM		EAI_SYSTEM
+#define W3M_EAI_BADHINTS	EAI_BADHINTS
+#define W3M_EAI_PROTOCOL	EAI_PROTOCOL
+#define W3M_EAI_MAX		EAI_MAX
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#define	W3M_AI_PASSIVE		AI_PASSIVE
+#define	W3M_AI_CANONNAME	AI_CANONNAME
+#define	W3M_AI_NUMERICHOST	AI_NUMERICHOST
+/* valid flags for addrinfo */
+#define	W3M_AI_MASK		(W3M_AI_PASSIVE | W3M_AI_CANONNAME | W3M_AI_NUMERICHOST)
+
+#define	W3M_AI_ALL		AI_ALL
+#define	W3M_AI_V4MAPPED_CFG	AI_V4MAPPED_CFG
+#define	W3M_AI_ADDRCONFIG	AI_ADDRCONFIG
+#define	W3M_AI_V4MAPPED		AI_V4MAPPED
+
+#define w3m_gai_strerror gai_strerror
+#define w3m_getnameinfo getnameinfo
+extern int w3m_getaddrinfo(const char *, const char *,
+	const struct w3m_addrinfo *, struct w3m_addrinfo **);
+
+/*
+ * Constants for getnameinfo()
+ */
+#define	W3M_NI_MAXHOST		NI_MAXHOST
+#define	W3M_NI_MAXSERV		NI_MAXSERV
+
+/*
+ * Flag values for getnameinfo()
+ */
+#define	W3M_NI_NOFQDN		NI_NOFQDN
+#define	W3M_NI_NUMERICHOST	NI_NUMERICHOST
+#define	W3M_NI_NAMEREQD		NI_NAMEREQD
+#define	W3M_NI_NUMERICSERV	NI_NUMERICSERV
+#define	W3M_NI_DGRAM		NI_DGRAM
+
+#endif /* W3M_ADDRINFO6_H */
Index: w3m/resolv/getaddrinfo4.c.in
diff -u /dev/null w3m/resolv/getaddrinfo4.c.in:1.1.2.7
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/getaddrinfo4.c.in	Sat Mar 27 23:37:14 2004
@@ -0,0 +1,829 @@
+/* $Id: getaddrinfo4.c.in,v 1.1.2.7 2004/03/27 14:37:14 shinra Exp $ */
+/* This file is derived from KAME-20040322-snap kit. */
+/*	$KAME: getaddrinfo.c,v 1.160 2003/05/17 01:30:42 itojun Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+#include "resolv/w3mresolv.h"
+#ifndef INET6
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define ANY 0
+#define YES 1
+#define NO  0
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in_loopback[] = { 127, 0, 0, 1 };
+
+static const struct afd {
+	int a_af;
+	int a_addrlen;
+	int a_socklen;
+	int a_off;
+	const char *a_addrany;
+	const char *a_loopback;
+	int a_scoped;
+} afdl [] = {
+	{PF_INET, sizeof(struct in_addr),
+	 sizeof(struct sockaddr_in),
+	 offsetof(struct sockaddr_in, sin_addr),
+	 in_addrany, in_loopback, 0},
+	{0, 0, 0, 0, NULL, NULL, 0},
+};
+#define AFD_INET 0
+
+#define PTON_MAX	4
+
+struct explore {
+	int e_af;
+	int e_socktype;
+	int e_protocol;
+	const char *e_protostr;
+	int e_wild;
+#define WILD_AF(ex)		((ex)->e_wild & 0x01)
+#define WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
+#define WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
+#define WILD_ACTIVE(ex)		((ex)->e_wild & 0x08)
+#define WILD_PASSIVE(ex)	((ex)->e_wild & 0x10)
+};
+
+static const struct explore explore[] = {
+	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x1f },
+#ifdef USE_SCTP
+	{ PF_INET, SOCK_DGRAM, IPPROTO_SCTP, "sctp", 0x1f },
+	{ PF_INET, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x0f },	/* !PASSIVE */
+#endif
+	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x0f },	/* !PASSIVE */
+	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x17 },	/* PASSIVE */
+#ifdef USE_SCTP
+	{ PF_INET, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x17 },	/* PASSIVE */
+	{ PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x1f },
+#endif
+#ifdef USE_RAW
+	{ PF_INET, SOCK_RAW, ANY, NULL, 0x1d },
+#endif
+	{ -1, 0, 0, NULL, 0 },
+};
+
+/* functions in OS independent portion */
+#ifndef __P
+# define __P(proto) proto
+#endif
+static int str_isnumber __P((const char *));
+static int explore_copy __P((const struct addrinfo *, const struct addrinfo *,
+	struct addrinfo **));
+static int explore_null __P((const struct addrinfo *,
+	const char *, struct addrinfo **));
+static int explore_numeric __P((const struct addrinfo *, const char *,
+	const char *, struct addrinfo **, const char *));
+static int get_canonname __P((const struct addrinfo *,
+	struct addrinfo *, const char *));
+static struct addrinfo *get_ai __P((const struct addrinfo *,
+	const struct afd *, const char *));
+static struct addrinfo *copy_ai __P((const struct addrinfo *));
+static int get_portmatch __P((const struct addrinfo *, const char *));
+static int get_port __P((struct addrinfo *, const char *, int));
+
+/* functions in OS dependent portion */
+static int explore_fqdn __P((const struct addrinfo *, const char *,
+	const char *, struct addrinfo **));
+
+static struct ai_errlist {
+	const char *str;
+	int code;
+} ai_errlist[] = {
+	{ "Success",					0, },
+#ifdef EAI_ADDRFAMILY
+	{ "Address family for hostname not supported",	EAI_ADDRFAMILY, },
+#endif
+	{ "Temporary failure in name resolution",	EAI_AGAIN, },
+	{ "Invalid value for ai_flags",		       	EAI_BADFLAGS, },
+	{ "Non-recoverable failure in name resolution", EAI_FAIL, },
+	{ "ai_family not supported",			EAI_FAMILY, },
+	{ "Memory allocation failure", 			EAI_MEMORY, },
+#ifdef EAI_NODATA
+	{ "No address associated with hostname", 	EAI_NODATA, },
+#endif
+	{ "hostname nor servname provided, or not known", EAI_NONAME, },
+	{ "servname not supported for ai_socktype",	EAI_SERVICE, },
+	{ "ai_socktype not supported", 			EAI_SOCKTYPE, },
+	{ "System error returned in errno", 		EAI_SYSTEM, },
+	{ "Invalid value for hints",			EAI_BADHINTS, },
+	{ "Resolved protocol is unknown",		EAI_PROTOCOL, },
+	{ NULL,						-1, },
+};
+
+/* XXX macros that make external reference is BAD. */
+
+#define GET_AI(ai, afd, addr) \
+do { \
+	/* external reference: pai, error, and label free */ \
+	(ai) = get_ai(pai, (afd), (addr)); \
+	if ((ai) == NULL) { \
+		error = EAI_MEMORY; \
+		goto free; \
+	} \
+} while (/*CONSTCOND*/0)
+
+#define GET_PORT(ai, serv) \
+do { \
+	/* external reference: error and label free */ \
+	error = get_port((ai), (serv), 0); \
+	if (error != 0) \
+		goto free; \
+} while (/*CONSTCOND*/0)
+
+#define GET_CANONNAME(ai, str) \
+do { \
+	/* external reference: pai, error and label free */ \
+	error = get_canonname(pai, (ai), (str)); \
+	if (error != 0) \
+		goto free; \
+} while (/*CONSTCOND*/0)
+
+#define ERR(err) \
+do { \
+	/* external reference: error, and label bad */ \
+	error = (err); \
+	goto bad; \
+	/*NOTREACHED*/ \
+} while (/*CONSTCOND*/0)
+
+#define MATCH(x, y, w) \
+	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
+
+char *
+w3m_gai_strerror(ecode)
+	int ecode;
+{
+	struct ai_errlist *p;
+
+	for (p = ai_errlist; p->str; p++) {
+		if (p->code == ecode)
+			return (char *)p->str;
+	}
+	return "Unknown error";
+}
+
+static int
+str_isnumber(p)
+	const char *p;
+{
+	char *ep;
+
+	if (*p == '\0')
+		return NO;
+	ep = NULL;
+	errno = 0;
+	(void)strtoul(p, &ep, 10);
+	if (errno == 0 && ep && *ep == '\0')
+		return YES;
+	else
+		return NO;
+}
+
+int
+w3m_getaddrinfo(hostname, servname, hints, res)
+	const char *hostname, *servname;
+	const struct addrinfo *hints;
+	struct addrinfo **res;
+{
+	struct addrinfo sentinel;
+	struct addrinfo *cur;
+	int error = 0;
+	struct addrinfo ai, ai0, *tmpres = NULL;
+	struct addrinfo *pai;
+	const struct explore *ex;
+	int numeric = 0;
+
+	/* ensure we return NULL on errors */
+	*res = NULL;
+
+	memset(&sentinel, 0, sizeof(sentinel));
+	cur = &sentinel;
+	pai = &ai;
+	pai->ai_flags = 0;
+	pai->ai_family = PF_INET;
+	pai->ai_socktype = ANY;
+	pai->ai_protocol = ANY;
+	pai->ai_addrlen = 0;
+	pai->ai_canonname = NULL;
+	pai->ai_addr = NULL;
+	pai->ai_next = NULL;
+
+	if (hostname == NULL && servname == NULL)
+		return EAI_NONAME;
+	if (hints) {
+		/* error check for hints */
+		if (hints->ai_addrlen || hints->ai_canonname ||
+		    hints->ai_addr || hints->ai_next)
+			ERR(EAI_BADHINTS); /* xxx */
+		if (hints->ai_flags & ~AI_MASK)
+			ERR(EAI_BADFLAGS);
+		switch (hints->ai_family) {
+		case PF_UNSPEC:
+		case PF_INET:
+			break;
+		default:
+			ERR(EAI_FAMILY);
+		}
+		memcpy(pai, hints, sizeof(*pai));
+		pai->ai_family = PF_INET;
+
+		/*
+		 * if both socktype/protocol are specified, check if they
+		 * are meaningful combination.
+		 */
+		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
+			for (ex = explore; ex->e_af >= 0; ex++) {
+				if (!MATCH(pai->ai_socktype, ex->e_socktype,
+				    WILD_SOCKTYPE(ex)))
+					continue;
+				if (!MATCH(pai->ai_protocol, ex->e_protocol,
+				    WILD_PROTOCOL(ex)))
+					continue;
+
+				/* matched */
+				break;
+			}
+
+			if (ex->e_af < 0) {
+				ERR(EAI_BADHINTS);
+			}
+		}
+	}
+
+	ai0 = *pai;
+
+	/*
+	 * check for special cases.  (1) numeric servname is disallowed if
+	 * socktype/protocol are left unspecified. (2) servname is disallowed
+	 * for raw and other inet{,6} sockets.
+	 */
+	error = get_portmatch(pai, servname);
+	if (error)
+		ERR(error);
+
+	/*
+	 * NULL hostname, or numeric hostname.
+	 */
+	if (hostname == NULL)
+		error = explore_null(pai, servname, &tmpres);
+	else
+		error = explore_numeric(pai, hostname, servname, &tmpres,
+			hostname);
+
+	if (!error && tmpres) {
+		numeric = 1;
+		goto globcopy;
+	}
+
+	if (hostname == NULL)
+		ERR(EAI_NONAME);	/* used to be EAI_NODATA */
+	if (pai->ai_flags & AI_NUMERICHOST)
+		ERR(EAI_NONAME);
+
+	/*
+	 * hostname as alphabetical name.
+	 * first, try to query DNS for all possible address families.
+	 */
+	error = explore_fqdn(pai, hostname, servname, &tmpres);
+
+globcopy:
+	for (ex = explore; ex->e_af >= 0; ex++) {
+		*pai = ai0;
+
+		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
+			continue;
+		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
+			continue;
+
+		if ((pai->ai_flags & AI_PASSIVE) != 0 && WILD_PASSIVE(ex))
+			;
+		else if ((pai->ai_flags & AI_PASSIVE) == 0 && WILD_ACTIVE(ex))
+			;
+		else
+			continue;
+
+		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+			pai->ai_socktype = ex->e_socktype;
+		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+			pai->ai_protocol = ex->e_protocol;
+
+		/*
+		 * if the servname does not match socktype/protocol, ignore it.
+		 */
+		if (get_portmatch(pai, servname) != 0)
+			continue;
+
+		error = explore_copy(pai, tmpres, &cur->ai_next);
+
+		while (cur && cur->ai_next)
+			cur = cur->ai_next;
+	}
+
+	/* XXX inhibit errors if we have the result */
+	if (sentinel.ai_next)
+		error = 0;
+
+	/*
+	 * ensure we return either:
+	 * - error == 0, non-NULL *res
+	 * - error != 0, NULL *res
+	 */
+	if (error == 0) {
+		if (sentinel.ai_next) {
+			*res = sentinel.ai_next;
+			error = 0;
+		} else
+			error = EAI_FAIL;
+	}
+
+bad:
+	if (tmpres)
+		freeaddrinfo(tmpres);
+	if (!*res)
+		if (sentinel.ai_next)
+			freeaddrinfo(sentinel.ai_next);
+	return error;
+}
+
+static int
+explore_copy(pai, src0, res)
+	const struct addrinfo *pai;	/* seed */
+	const struct addrinfo *src0;	/* source */
+	struct addrinfo **res;
+{
+	int error;
+	struct addrinfo sentinel, *cur;
+	const struct addrinfo *src;
+
+	error = 0;
+	sentinel.ai_next = NULL;
+	cur = &sentinel;
+
+	for (src = src0; src != NULL; src = src->ai_next) {
+		if (src->ai_family != pai->ai_family)
+			continue;
+
+		cur->ai_next = copy_ai(src);
+		if (!cur->ai_next) {
+			error = EAI_MEMORY;
+			goto fail;
+		}
+
+		cur->ai_next->ai_socktype = pai->ai_socktype;
+		cur->ai_next->ai_protocol = pai->ai_protocol;
+		cur = cur->ai_next;
+	}
+
+	*res = sentinel.ai_next;
+	return 0;
+
+fail:
+	freeaddrinfo(sentinel.ai_next);
+	return error;
+}
+
+/*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+static int
+explore_null(pai, servname, res)
+	const struct addrinfo *pai;
+	const char *servname;
+	struct addrinfo **res;
+{
+	const struct afd *afd;
+	struct addrinfo *cur;
+	struct addrinfo sentinel;
+	int error;
+
+	*res = NULL;
+	sentinel.ai_next = NULL;
+	cur = &sentinel;
+
+	/*
+	 * if the servname does not match socktype/protocol, ignore it.
+	 */
+	if (get_portmatch(pai, servname) != 0)
+		return 0;
+
+	afd = &afdl[AFD_INET];
+
+	if (pai->ai_flags & AI_PASSIVE) {
+		GET_AI(cur->ai_next, afd, afd->a_addrany);
+		/* xxx meaningless?
+		 * GET_CANONNAME(cur->ai_next, "anyaddr");
+		 */
+		GET_PORT(cur->ai_next, servname);
+	} else {
+		GET_AI(cur->ai_next, afd, afd->a_loopback);
+		/* xxx meaningless?
+		 * GET_CANONNAME(cur->ai_next, "localhost");
+		 */
+		GET_PORT(cur->ai_next, servname);
+	}
+	cur = cur->ai_next;
+
+	*res = sentinel.ai_next;
+	return 0;
+
+free:
+	if (sentinel.ai_next)
+		freeaddrinfo(sentinel.ai_next);
+	return error;
+}
+
+/*
+ * numeric hostname
+ */
+static int
+explore_numeric(pai, hostname, servname, res, canonname)
+	const struct addrinfo *pai;
+	const char *hostname;
+	const char *servname;
+	struct addrinfo **res;
+	const char *canonname;
+{
+	const struct afd *afd;
+	struct addrinfo *cur;
+	struct addrinfo sentinel;
+	int error;
+	char pton[PTON_MAX];
+
+	*res = NULL;
+	sentinel.ai_next = NULL;
+	cur = &sentinel;
+
+	afd = &afdl[AFD_INET];
+
+	switch (afd->a_af) {
+	default:
+		if (inet_pton(afd->a_af, hostname, pton) == 1) {
+			if (pai->ai_family == afd->a_af ||
+			    pai->ai_family == PF_UNSPEC /*?*/) {
+				GET_AI(cur->ai_next, afd, pton);
+				GET_PORT(cur->ai_next, servname);
+				if ((pai->ai_flags & AI_CANONNAME)) {
+					/*
+					 * Set the numeric address itself as
+					 * the canonical name, based on a
+					 * clarification in rfc2553bis-03.
+					 */
+					GET_CANONNAME(cur->ai_next, canonname);
+				}
+				while (cur && cur->ai_next)
+					cur = cur->ai_next;
+			} else
+				ERR(EAI_FAMILY);	/* XXX */
+		}
+		break;
+	}
+
+	*res = sentinel.ai_next;
+	return 0;
+
+free:
+bad:
+	if (sentinel.ai_next)
+		freeaddrinfo(sentinel.ai_next);
+	return error;
+}
+
+static int
+get_canonname(pai, ai, str)
+	const struct addrinfo *pai;
+	struct addrinfo *ai;
+	const char *str;
+{
+	if ((pai->ai_flags & AI_CANONNAME) != 0) {
+		size_t l = strlen(str) + 1;
+		ai->ai_canonname = malloc(l);
+		if (ai->ai_canonname == NULL)
+			return EAI_MEMORY;
+		strcpy(ai->ai_canonname, str);
+	}
+	return 0;
+}
+
+static struct addrinfo *
+get_ai(pai, afd, addr)
+	const struct addrinfo *pai;
+	const struct afd *afd;
+	const char *addr;
+{
+	char *p;
+	struct addrinfo *ai;
+
+	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
+		+ (afd->a_socklen));
+	if (ai == NULL)
+		return NULL;
+
+	memcpy(ai, pai, sizeof(struct addrinfo));
+	ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+	memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+	ai->ai_addr->sa_len = afd->a_socklen;
+#endif
+	ai->ai_addrlen = afd->a_socklen;
+	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
+	p = (char *)(void *)(ai->ai_addr);
+	memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
+	return ai;
+}
+
+/* XXX need to malloc() the same way we do from other functions! */
+static struct addrinfo *
+copy_ai(pai)
+	const struct addrinfo *pai;
+{
+	struct addrinfo *ai;
+	size_t l;
+
+	l = sizeof(*ai) + pai->ai_addrlen;
+	if ((ai = (struct addrinfo *)malloc(l)) == NULL)
+		return NULL;
+	memset(ai, 0, l);
+	memcpy(ai, pai, sizeof(*ai));
+	ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+	memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
+
+	if (pai->ai_canonname) {
+		l = strlen(pai->ai_canonname) + 1;
+		if ((ai->ai_canonname = malloc(l)) == NULL) {
+			free(ai);
+			return NULL;
+		}
+		strcpy(ai->ai_canonname, pai->ai_canonname);
+	} else {
+		/* just to make sure */
+		ai->ai_canonname = NULL;
+	}
+
+	ai->ai_next = NULL;
+
+	return ai;
+}
+
+static int
+get_portmatch(ai, servname)
+	const struct addrinfo *ai;
+	const char *servname;
+{
+
+	/* get_port does not touch first argument. when matchonly == 1. */
+	/* LINTED const cast */
+	return get_port((struct addrinfo *)ai, servname, 1);
+}
+
+static int
+get_port(ai, servname, matchonly)
+	struct addrinfo *ai;
+	const char *servname;
+	int matchonly;
+{
+	const char *proto;
+	struct servent *sp;
+	int port;
+	int allownumeric;
+
+	if (servname == NULL)
+		return 0;
+	switch (ai->ai_family) {
+	case AF_INET:
+		break;
+	default:
+		return 0;
+	}
+
+	switch (ai->ai_socktype) {
+#ifdef USE_RAW
+	case SOCK_RAW:
+		return EAI_SERVICE;
+#endif
+	case SOCK_DGRAM:
+	case SOCK_STREAM:
+#ifdef USE_SCTP
+	case SOCK_SEQPACKET:
+#endif
+		allownumeric = 1;
+		break;
+	case ANY:
+		allownumeric = 0;
+		break;
+	default:
+		return EAI_SOCKTYPE;
+	}
+
+	if (str_isnumber(servname)) {
+		if (!allownumeric)
+			return EAI_SERVICE;
+		port = atoi(servname);
+		if (port < 0 || port > 65535)
+			return EAI_SERVICE;
+		port = htons(port);
+	} else {
+		switch (ai->ai_protocol) {
+		case IPPROTO_UDP:
+			proto = "udp";
+			break;
+		case IPPROTO_TCP:
+			proto = "tcp";
+			break;
+#ifdef USE_SCTP
+		case IPPROTO_SCTP:
+			proto = "sctp";
+			break;
+#endif
+		default:
+			proto = NULL;
+			break;
+		}
+
+		if ((sp = getservbyname(servname, proto)) == NULL)
+			return EAI_SERVICE;
+		port = sp->s_port;
+	}
+
+	if (!matchonly) {
+		switch (ai->ai_family) {
+		case AF_INET:
+			((struct sockaddr_in *)(void *)
+			    ai->ai_addr)->sin_port = port;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * FQDN hostname, DNS lookup
+ */
+static int
+explore_fqdn(pai, hostname, servname, res)
+	const struct addrinfo *pai;
+	const char *hostname;
+	const char *servname;
+	struct addrinfo **res;
+{
+	struct hostent *hp;
+	int h_error;
+	int af;
+	char **aplist = NULL, *apbuf = NULL;
+	char *ap;
+	struct addrinfo sentinel, *cur;
+	int i;
+	int naddrs;
+	const struct afd *afd;
+	int error = 0;
+
+	*res = NULL;
+	sentinel.ai_next = NULL;
+	cur = &sentinel;
+
+	/*
+	 * if the servname does not match socktype/protocol, ignore it.
+	 */
+	if (get_portmatch(pai, servname) != 0)
+		return 0;
+
+	afd = &afdl[AFD_INET];
+
+	if (pai->ai_family != AF_INET)
+		return 0;
+	hp = gethostbyname(hostname);
+#ifdef HAVE_H_ERRNO
+	h_error = h_errno;
+#else
+	h_error = EINVAL;
+#endif
+
+	if (hp == NULL) {
+		switch (h_error) {
+		case HOST_NOT_FOUND:
+		case NO_DATA:
+			error = EAI_NONAME;
+			break;
+		case TRY_AGAIN:
+			error = EAI_AGAIN;
+			break;
+		case NO_RECOVERY:
+		case NETDB_INTERNAL:
+		default:
+			error = EAI_FAIL;
+			break;
+		}
+	} else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
+			|| (hp->h_addr_list[0] == NULL)) {
+		hp = NULL;
+		error = EAI_FAIL;
+	}
+
+	if (hp == NULL)
+		goto free;
+
+	/*
+	 * hp will be overwritten if we use gethostbyname2().
+	 * always deep copy for simplification.
+	 */
+	for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++)
+		;
+	naddrs++;
+	aplist = (char **)malloc(sizeof(aplist[0]) * naddrs);
+	apbuf = (char *)malloc((size_t)hp->h_length * naddrs);
+	if (aplist == NULL || apbuf == NULL) {
+		error = EAI_MEMORY;
+		goto free;
+	}
+	memset(aplist, 0, sizeof(aplist[0]) * naddrs);
+	for (i = 0; i < naddrs; i++) {
+		if (hp->h_addr_list[i] == NULL) {
+			aplist[i] = NULL;
+			continue;
+		}
+		memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i],
+			(size_t)hp->h_length);
+		aplist[i] = &apbuf[i * hp->h_length];
+	}
+
+	for (i = 0; aplist[i] != NULL; i++) {
+		af = hp->h_addrtype;
+		ap = aplist[i];
+
+		if (af != pai->ai_family)
+			continue;
+
+		GET_AI(cur->ai_next, afd, ap);
+		GET_PORT(cur->ai_next, servname);
+		if ((pai->ai_flags & AI_CANONNAME) != 0) {
+			/*
+			 * RFC2553 says that ai_canonname will be set only for
+			 * the first element.  we do it for all the elements,
+			 * just for convenience.
+			 */
+			GET_CANONNAME(cur->ai_next, hp->h_name);
+		}
+
+		while (cur && cur->ai_next)
+			cur = cur->ai_next;
+	}
+
+	*res = sentinel.ai_next;
+	return 0;
+
+free:
+	if (aplist)
+		free(aplist);
+	if (apbuf)
+		free(apbuf);
+	if (sentinel.ai_next)
+		freeaddrinfo(sentinel.ai_next);
+	return error;
+}
+#endif /* !INET6 */
+/* vim: set sw=8: */
Index: w3m/resolv/getnameinfo4.c.in
diff -u /dev/null w3m/resolv/getnameinfo4.c.in:1.1.2.5
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/getnameinfo4.c.in	Sat Mar 27 02:29:37 2004
@@ -0,0 +1,213 @@
+/*	$KAME: getnameinfo.c,v 1.62 2003/04/22 05:50:00 itojun Exp $	*/
+/* This file is derived from KAME-20040322-snap kit. */
+/* $Id: getnameinfo4.c.in,v 1.1.2.5 2004/03/26 17:29:37 shinra Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * 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.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ * - RFC2553 says that we should raise error on short buffer.  X/Open says
+ *   we need to truncate the result.  We obey RFC2553 (and X/Open should be
+ *   modified).  ipngwg rough consensus seems to follow RFC2553.
+ * - What is "local" in NI_FQDN?
+ * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
+ * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
+ *   sin6_scope_id is filled - standardization status?
+ *   XXX breaks backward compat for code that expects no scopeid.
+ *   beware on merge.
+ * - what should we do if we should do getservbyport("sctp")?
+ */
+
+#include "resolv/w3mresolv.h"
+#ifndef INET6
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stddef.h>
+#include <errno.h>
+
+static const struct afd {
+	int a_af;
+	int a_addrlen;
+	int a_socklen;
+	int a_off;
+} afdl [] = {
+	{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
+		offsetof(struct sockaddr_in, sin_addr)},
+	{0, 0, 0},
+};
+#define AFD_INET 0
+
+int
+w3m_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
+	const struct sockaddr *sa;
+	w3m_socklen_t salen;
+	char *host;
+	size_t hostlen;
+	char *serv;
+	size_t servlen;
+	int flags;
+{
+	const struct afd *afd;
+	struct servent *sp;
+	struct hostent *hp;
+	w3m_in_port_t port;
+	const char *addr;
+	w3m_in_addr_t v4a;
+	int h_error;
+	char numserv[512];
+	char numaddr[512];
+
+	if (sa == NULL)
+		return EAI_FAIL;
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN	/*XXX*/
+	if (sa->sa_len != salen)
+		return EAI_FAIL;
+#endif
+
+	if (sa->sa_family != PF_INET)
+		return EAI_FAMILY;
+	afd = &afdl[AFD_INET];
+	if (salen != afd->a_socklen)
+		return EAI_FAIL;
+
+	/* network byte order */
+	port = ((const struct sockaddr_in *)sa)->sin_port;
+	addr = (const char *)sa + afd->a_off;
+
+	if (serv == NULL || servlen == 0) {
+		/*
+		 * do nothing in this case.
+		 * in case you are wondering if "&&" is more correct than
+		 * "||" here: rfc2553bis-03 says that serv == NULL OR
+		 * servlen == 0 means that the caller does not want the result.
+		 */
+	} else {
+		if (flags & NI_NUMERICSERV)
+			sp = NULL;
+		else {
+			sp = getservbyport(port,
+				(flags & NI_DGRAM) ? "udp" : "tcp");
+		}
+		if (sp) {
+			if (strlen(sp->s_name) + 1 > servlen)
+				return EAI_MEMORY;
+			strcpy(serv, sp->s_name);
+		} else {
+			snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
+			if (strlen(numserv) + 1 > servlen)
+				return EAI_MEMORY;
+			strcpy(serv, numserv);
+		}
+	}
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		v4a = ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
+		if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+			flags |= NI_NUMERICHOST;
+		v4a >>= IN_CLASSA_NSHIFT;
+		if (v4a == 0)
+			flags |= NI_NUMERICHOST;			
+		break;
+	}
+	if (host == NULL || hostlen == 0) {
+		/*
+		 * do nothing in this case.
+		 * in case you are wondering if "&&" is more correct than
+		 * "||" here: rfc2553bis-03 says that host == NULL or
+		 * hostlen == 0 means that the caller does not want the result.
+		 */
+	} else if (flags & NI_NUMERICHOST) {
+		int numaddrlen;
+
+		/* NUMERICHOST and NAMEREQD conflicts with each other */
+		if (flags & NI_NAMEREQD)
+			return EAI_NONAME;
+
+		switch(afd->a_af) {
+		default:
+			if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+			    == NULL)
+				return EAI_SYSTEM;
+			numaddrlen = strlen(numaddr);
+			if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+				return EAI_MEMORY;
+			strcpy(host, numaddr);
+			break;
+		}
+	} else {
+		hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+#ifdef HAVE_H_ERRNO
+		h_error = h_errno;
+#else
+		h_error = EINVAL;
+#endif
+
+		if (hp) {
+#if 0
+			/*
+			 * commented out, since "for local host" is not
+			 * implemented here - see RFC2553 p30
+			 */
+			if (flags & NI_NOFQDN) {
+				char *p;
+				p = strchr(hp->h_name, '.');
+				if (p)
+					*p = '\0';
+			}
+#endif
+			if (strlen(hp->h_name) + 1 > hostlen) {
+				return EAI_MEMORY;
+			}
+			strcpy(host, hp->h_name);
+		} else {
+			if (flags & NI_NAMEREQD)
+				return EAI_NONAME;
+			switch(afd->a_af) {
+			default:
+				if (inet_ntop(afd->a_af, addr, host,
+				    hostlen) == NULL)
+					return EAI_SYSTEM;
+				break;
+			}
+		}
+	}
+	return(0);
+}
+#endif /* !INET6 */
+/* vim: set sw=8: */
Index: w3m/resolv/inet_pton.c
diff -u /dev/null w3m/resolv/inet_pton.c:1.1.2.1
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/inet_pton.c	Wed Mar 24 05:54:02 2004
@@ -0,0 +1,121 @@
+/* $Id: inet_pton.c,v 1.1.2.1 2004/03/23 20:54:02 shinra Exp $ */
+/* This file is derived from KAME-20040322-snap kit. */
+/*	$KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $	*/
+
+/*
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "resolv/w3mresolv.h"
+#ifndef INET6
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef NS_INADDRSZ
+#define NS_INADDRSZ	4
+#endif
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int	inet_pton4(const char *src, unsigned char *dst);
+
+/* int
+ * inet_pton(af, src, dst)
+ *	convert from presentation format (which usually means ASCII printable)
+ *	to network format (which is usually some kind of binary format).
+ * return:
+ *	1 if the address was valid for the specified address family
+ *	0 if the address wasn't valid (`dst' is untouched in this case)
+ *	-1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ *	Paul Vixie, 1996.
+ */
+int
+w3m_inet_pton(af, src, dst)
+	int af;
+	const char *src;
+	void *dst;
+{
+	switch (af) {
+	case AF_INET:
+		return (inet_pton4(src, dst));
+	default:
+		errno = EAFNOSUPPORT;
+		return (-1);
+	}
+	/* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ *	like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ *	1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ *	does not touch `dst' unless it's returning 1.
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static int
+inet_pton4(src, dst)
+	const char *src;
+	unsigned char *dst;
+{
+	static const char digits[] = "0123456789";
+	int saw_digit, octets, ch;
+	unsigned char tmp[NS_INADDRSZ], *tp;
+
+	saw_digit = 0;
+	octets = 0;
+	*(tp = tmp) = 0;
+	while ((ch = *src++) != '\0') {
+		const char *pch;
+
+		if ((pch = strchr(digits, ch)) != NULL) {
+			u_int new = *tp * 10 + (pch - digits);
+
+			if (new > 255)
+				return (0);
+			*tp = new;
+			if (! saw_digit) {
+				if (++octets > 4)
+					return (0);
+				saw_digit = 1;
+			}
+		} else if (ch == '.' && saw_digit) {
+			if (octets == 4)
+				return (0);
+			*++tp = 0;
+			saw_digit = 0;
+		} else
+			return (0);
+	}
+	if (octets < 4)
+		return (0);
+	memcpy(dst, tmp, NS_INADDRSZ);
+	return (1);
+}
+#endif /* INET6 */
+/* vim: set sw=8: */
Index: w3m/resolv/namespace.sed
diff -u /dev/null w3m/resolv/namespace.sed:1.1.2.2
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/namespace.sed	Wed Mar 24 05:29:52 2004
@@ -0,0 +1,8 @@
+s/NI_/W3M_NI_/g
+s/EAI_/W3MEAITMP_/g
+s/AI_/W3M_AI_/g
+s/W3MEAITMP_/W3M_EAI_/g
+s/struct addrinfo/struct w3m_addrinfo/g
+s/freeaddrinfo/w3m_freeaddrinfo/g
+s/inet_ntop/w3m_inet_ntop/g
+s/inet_pton/w3m_inet_pton/g
Index: w3m/resolv/replace.sh
diff -u /dev/null w3m/resolv/replace.sh:1.1.2.1
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/replace.sh	Tue Mar 23 23:24:43 2004
@@ -0,0 +1,3 @@
+#!/bin/sh
+echo "# line 1 \"$2\""
+sed -f "$1" "$2"
Index: w3m/resolv/w3mresolv.c
diff -u /dev/null w3m/resolv/w3mresolv.c:1.1.2.8
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/w3mresolv.c	Sun Mar 28 00:03:33 2004
@@ -0,0 +1,851 @@
+/* $Id: w3mresolv.c,v 1.1.2.8 2004/03/27 15:03:33 shinra Exp $ */
+#include "resolv/w3mresolv.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <unistd.h>
+#include <sys/uio.h>
+#include <fcntl.h>
+#include <sys/select.h>
+#include <signal.h>
+#ifdef HAVE_WAITPID
+# include <sys/wait.h>
+#endif
+
+/* no biteorder conversion nor anything */
+#define HEADERLEN sizeof(size_t)
+#define STORE(pp, data, size) (memcpy(*(pp), data, size), *(pp) += (size))
+#define STORE_VAR(pp, varp) STORE(pp, varp, sizeof(*(varp)))
+#define LOAD(pp, data, size) (memcpy(data, *(pp), size), *(pp) += (size))
+#define LOAD_VAR(pp, varp) LOAD(pp, varp, sizeof(*(varp)))
+
+typedef MySignalHandler (*sighandler_type) (SIGNAL_ARG);
+#ifdef SA_RESTART
+typedef struct sigaction sigaction_type;
+# define ACTION_HANDLER(action) ((action)->sa_handler)
+# define restore_sigaction(sig, old_action) sigaction(sig, old_action, NULL)
+#else
+typedef sighandler_type sigaction_type;
+# define ACTION_HANDLER(action) (action)
+# define restore_sigaction(sig, old_action) signal(sig, *(old_action))
+#endif
+
+enum {
+    CMD_ADDRINFO_WITH_HINTS,
+    CMD_ADDRINFO_WITHOUT_HINTS,
+    CMD_NAMEINFO
+};
+
+volatile static int canceled_flag = 0;
+static int helper_fd = -1;
+
+void
+w3m_freeaddrinfo(struct w3m_addrinfo *wai)
+{
+    assert(wai);
+    while (wai) {
+	struct w3m_addrinfo *next = wai->ai_next;
+	free(wai->ai_canonname);
+	/* no need to free(wai->ai_addr) */
+	free(wai);
+	wai = next;
+    }
+}
+
+void
+w3m_cancel_resolv(void)
+{
+    canceled_flag = 1;
+}
+
+static void
+get_sigaction(int sig, sigaction_type *action)
+{
+#ifdef SA_RESTART
+    sigaction(sig, NULL, action);
+#else
+    *action = signal(sig, SIG_IGN);
+    signal(sig, *action);
+#endif
+}
+
+static void
+trap_signal(int sig, sighandler_type handler, sigaction_type *old_action)
+{
+#ifdef SA_RESTART
+    struct sigaction new_action;
+
+    sigemptyset(&new_action.sa_mask);
+    new_action.sa_handler = handler;
+    new_action.sa_flags = 0
+# ifdef	SA_INTERRUPT
+	| SA_INTERRUPT /* don't restart */
+# endif
+# ifdef SA_NOCLDSTOP
+	| SA_NOCLDSTOP
+# endif
+	;
+    sigaction(sig, &new_action, old_action);
+#else /* !SA_RESTART */
+    sigaction_type r = signal(sig, handler);
+    if (old_action)
+	*old_action = r;
+#endif /* !SA_RESTART */
+}
+
+static MySignalHandler
+sigchld_handler(SIGNAL_ARG)
+{
+    SIGNAL_RETURN;
+}
+
+static int
+waitpid_with_timeout(pid_t pid, const struct timespec *ptimeout)
+{
+#ifdef HAVE_WAITPID
+    struct timespec work;
+    int r = 1;
+    sigaction_type old_sigchld;
+    sighandler_type h;
+
+    /*
+     * If waitpid() returns -1, the zombie was not created (SA_NOCLDWAIT)
+     * or wait()ed by someone (especially caller's SIGCHLD handler).
+     * So we wait the child only if waitpid() returns 0. It always means
+     * that the child is still alive.
+     *
+     * XXX: how to determine if pselect() is implemented and sane?
+     * I don't want to use SIGALRM for implement timeout to sigsuspend().
+     */
+    if (waitpid(pid, NULL, WNOHANG))
+	return 0;
+
+    get_sigaction(SIGCHLD, &old_sigchld);
+    h = ACTION_HANDLER(&old_sigchld);
+    if (h == SIG_DFL || h == SIG_IGN)
+	trap_signal(SIGCHLD, &sigchld_handler, &old_sigchld);
+    /* XXX: SIGCHLD may be delivered just now */
+
+    work = *ptimeout;
+    /* nanosleep() is not affected by SA_RESTART */
+    while (nanosleep(&work, &work) && errno == EINTR) {
+	if (waitpid(pid, NULL, WNOHANG)) {
+	    r = 0;
+	    break;
+	}
+    }
+
+    if (h == SIG_DFL || h == SIG_IGN)
+	restore_sigaction(SIGCHLD, &old_sigchld);
+    return r;
+#else /* !HAVE_WAITPID */
+    return 0; /* no way to implement what we want */
+#endif /* !HAVE_WAITPID */
+}
+
+static int process_one_request(int fd);
+
+static int
+fork_helper(void)
+{
+    int fds[2];
+    pid_t pid;
+
+    if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds))
+	return -1;
+
+    pid = fork();
+    if (pid  == -1) {
+	close(fds[0]);
+	close(fds[1]);
+	return -1;
+    } else if (pid == 0) {
+	/* child */
+	pid = fork();
+	if (pid == -1) {
+	    _exit(1);
+	} else if (pid == 0) {
+	    int fd;
+	    /* grandchild; soon becomes an init(8)'s child */
+	    signal(SIGHUP, SIG_DFL);
+	    signal(SIGINT, SIG_IGN);
+	    signal(SIGQUIT, SIG_DFL);
+	    signal(SIGILL, SIG_DFL);
+	    signal(SIGTRAP, SIG_DFL);
+	    signal(SIGABRT, SIG_DFL);
+	    signal(SIGFPE, SIG_DFL);
+#ifdef SIGBUS
+	    signal(SIGBUS, SIG_DFL);
+#endif
+#ifdef SIGIOT
+	    signal(SIGIOT, SIG_DFL);
+#endif
+#ifdef SIGSEGV
+	    signal(SIGSEGV, SIG_DFL);
+#endif
+	    signal(SIGPIPE, SIG_IGN);
+	    signal(SIGALRM, SIG_DFL);
+	    signal(SIGTERM, SIG_DFL);
+	    signal(SIGTSTP, SIG_DFL);
+	    signal(SIGCHLD, SIG_DFL);
+	    signal(SIGTTIN, SIG_DFL);
+	    signal(SIGTTOU, SIG_DFL);
+#ifdef SIGWINCH
+	    signal(SIGWINCH, SIG_DFL);
+#endif
+
+	    close(fds[0]);
+	    for (fd = 3; fd < 1024; ++fd)
+		if (fd != fds[1])
+		    close(fd);
+	    while (!process_one_request(fds[1]))
+		;
+	    _exit(0);
+	} else {
+	    _exit(0);
+	}
+	/* NOTREACHED */
+    } else {
+	/* parent */
+	struct timespec timeout;
+
+	close(fds[1]);
+	helper_fd = fds[0];
+	timeout.tv_sec = 0;
+	timeout.tv_nsec = 100 * 1000 * 1000; 
+	waitpid_with_timeout(pid, &timeout);
+    }
+    return 0;
+}
+
+static int
+write_all(int fd, const void *data, size_t len)
+{
+    size_t nsent = 0;
+    while (nsent < len) {
+	ssize_t r = write(fd, (const char *)data + nsent, len - nsent);
+	if (r == -1 && errno != EINTR)
+	    return 1;
+	else
+	    nsent += r;
+    }
+    return 0;
+}
+
+static int
+read_all(int fd, void *data, size_t len)
+{
+    size_t ngot = 0;
+    while (ngot < len) {
+	ssize_t r = read(fd, (char *)data + ngot, len - ngot);
+	if (canceled_flag || r == 0 || (r == -1 && errno != EINTR))
+	    return 1;
+	else if (r > 0)
+	    ngot += r;
+    }
+    return 0;
+}
+
+#ifdef W3MRESOLV_DEBUG
+static void
+debug_dump(FILE *fp, const char *data, size_t len)
+{
+    size_t i;
+    for (i = 0; i < len; ++i) {
+	fprintf(fp, "%02x ", (unsigned int)(unsigned char)data[i]);
+	if (i % 16 == 15)
+	    putc('\n', fp);
+    }
+    if (i % 16 != 0)
+	putc('\n', fp);
+}
+#endif
+
+/* ugly: request includes HEADERLEN, but reply excludes HEADERLEN */
+static int
+talk_to_helper(char **data_ret, size_t *len_ret,
+	const char *data, size_t len, int *reason_ret)
+{
+    sigaction_type old_sigpipe;
+    int r;
+#ifdef W3MRESOLV_DEBUG
+    static FILE *logfp = NULL;
+#endif
+
+    assert(len > HEADERLEN);
+#ifdef W3MRESOLV_DEBUG
+    if (!logfp) {
+	logfp = fopen("resolv.log", "a");
+	if (logfp) {
+	    setvbuf(logfp, NULL, _IOLBF, 0);
+	    fprintf(logfp, "### Beginning of log (pid=%d) ###\n\n",
+		    (int)getpid());
+	}
+    }
+    if (logfp) {
+	fprintf(logfp, "Sending %lu bytes:\n", len - HEADERLEN);
+	debug_dump(logfp, data + HEADERLEN, len - HEADERLEN);
+	putc('\n', logfp);
+    }
+#endif
+    if (reason_ret)
+	*reason_ret = W3M_EAI_AGAIN;
+    if (helper_fd == -1)
+	if (fork_helper())
+	    return W3M_RESOLV_FAILED;
+    assert(helper_fd != -1);
+
+    trap_signal(SIGPIPE, SIG_IGN, &old_sigpipe);
+    if (write_all(helper_fd, data, len)) {
+	close(helper_fd);
+	helper_fd = -1;
+	/* restart only once */
+	if (fork_helper()) {
+	    restore_sigaction(SIGPIPE, &old_sigpipe);
+	    return W3M_RESOLV_FAILED;
+	}
+	assert(helper_fd != -1);
+	if (write_all(helper_fd, data, len)) {
+	    close(helper_fd);
+	    helper_fd = -1;
+	    restore_sigaction(SIGPIPE, &old_sigpipe);
+	    return W3M_RESOLV_FAILED;
+	}
+    }
+    restore_sigaction(SIGPIPE, &old_sigpipe);
+
+    if (read_all(helper_fd, (char *)len_ret, HEADERLEN)) {
+	close(helper_fd);
+	helper_fd = -1;
+	return canceled_flag ? W3M_RESOLV_CANCELED : W3M_RESOLV_FAILED;
+    }
+    *data_ret = (char *)malloc(*len_ret);
+    if (!*data_ret) {
+	close(helper_fd);
+	helper_fd = -1;
+	if (reason_ret)
+	    *reason_ret = W3M_EAI_MEMORY;
+	return W3M_RESOLV_FAILED;
+    }
+    r = read_all(helper_fd, *data_ret, *len_ret);
+    if (r) {
+	close(helper_fd);
+	helper_fd = -1;
+	free(*data_ret);
+	*data_ret = NULL;
+	return canceled_flag ? W3M_RESOLV_CANCELED : W3M_RESOLV_FAILED;
+    }
+#ifdef W3MRESOLV_DEBUG
+    if (logfp) {
+	fprintf(logfp, "Received %lu bytes:\n", *len_ret);
+	debug_dump(logfp, *data_ret, *len_ret);
+	putc('\n', logfp);
+    }
+#endif
+    if (reason_ret)
+	*reason_ret = 0;
+    return W3M_RESOLV_OK;
+}
+
+static int process_addrinfo(int cmd, int fd, const char *req, size_t req_rest);
+static int process_nameinfo(int cmd, int fd, const char *req, size_t req_rest);
+
+static int
+process_one_request(int fd)
+{
+    size_t reqsize;
+    char cmd;
+    char *buf, *p;
+    int r;
+
+    if (read_all(fd, &reqsize, HEADERLEN))
+	return -1;
+    buf = p = (char *)malloc(reqsize);
+    if (!buf)
+	return -1;
+
+    if (read_all(fd, buf, reqsize))
+	goto fail;
+    LOAD_VAR(&p, &cmd);
+    switch (cmd) {
+	case CMD_ADDRINFO_WITH_HINTS:
+	case CMD_ADDRINFO_WITHOUT_HINTS:
+	    r = process_addrinfo((int)cmd, fd, p, reqsize - 1);
+	    break;
+	case CMD_NAMEINFO:
+	    r = process_nameinfo((int)cmd, fd, p, reqsize - 1);
+	    break;
+	default:
+	    assert(0);
+    };
+
+    free(buf);
+    return r;
+fail:
+    free(buf);
+    return -1;
+}
+
+static size_t
+size_of_gai_result(int gai_retval, const struct w3m_addrinfo *wai)
+{
+    size_t sum = sizeof gai_retval;
+    const struct w3m_addrinfo *curr;
+
+    if (gai_retval)
+	return sum;
+    assert(wai);
+    sum += sizeof(size_t); /* for number of addresses */
+
+    for (curr = wai; curr; curr = curr->ai_next) {
+	sum += sizeof(curr->ai_flags) + sizeof(curr->ai_family)
+	    + sizeof(curr->ai_socktype) + sizeof(curr->ai_protocol)
+	    + sizeof(curr->ai_addrlen)
+	    + sizeof(size_t) /* for strlen(ai_canonname) + 1 */;
+	sum += curr->ai_canonname ? (strlen(curr->ai_canonname) + 1) : 0;
+	assert((curr->ai_addrlen == 0) || (curr->ai_addr != NULL));
+	sum += curr->ai_addrlen ? curr->ai_addrlen : 1;
+    }
+    return sum;
+}
+
+static void
+store_gai_result(int gai_retval, const struct w3m_addrinfo *wai, char *buf,
+	size_t bufsize)
+{
+    char *p = buf;
+    const struct w3m_addrinfo *curr;
+    size_t naddr = 0;
+
+    STORE_VAR(&p, &gai_retval);
+    if (gai_retval)
+	return;
+    assert(wai);
+    for (curr = wai; curr; curr = curr->ai_next)
+	++naddr;
+    STORE_VAR(&p, &naddr);
+
+    for (curr = wai; curr; curr = curr->ai_next) {
+	STORE_VAR(&p, &curr->ai_flags);
+	STORE_VAR(&p, &curr->ai_family);
+	STORE_VAR(&p, &curr->ai_socktype);
+	STORE_VAR(&p, &curr->ai_protocol);
+	STORE_VAR(&p, &curr->ai_addrlen);
+	if (curr->ai_canonname) {
+	    size_t l = strlen(curr->ai_canonname) + 1;
+	    STORE_VAR(&p, &l);
+	    STORE(&p, curr->ai_canonname, l);
+	} else {
+	    size_t zerosize = 0;
+	    STORE_VAR(&p, &zerosize);
+	}
+	assert((curr->ai_addrlen == 0) || (curr->ai_addr != NULL));
+	if (curr->ai_addrlen) {
+	    STORE(&p, curr->ai_addr, curr->ai_addrlen);
+	} else {
+	    char flag = curr->ai_addr ? 1 : 0;
+	    STORE_VAR(&p, &flag);
+	}
+    }
+    assert(buf + bufsize == p);
+}
+
+/* assume that received data is well-formed */
+static int
+parse_gai_result(const char *buf, size_t bufsize, struct w3m_addrinfo **res)
+{
+    const char *p = buf;
+    int gai_retval;
+    size_t naddr;
+    struct w3m_addrinfo *curr = NULL;
+
+    *res = NULL;
+    LOAD_VAR(&p, &gai_retval);
+    if (gai_retval)
+	return gai_retval;
+    LOAD_VAR(&p, &naddr);
+    assert(naddr);
+
+    for (; naddr; --naddr) {
+	struct w3m_addrinfo tmp, *next;
+	size_t cnlen;
+
+	memset(&tmp, 0, sizeof(struct w3m_addrinfo));
+	LOAD_VAR(&p, &tmp.ai_flags);
+	LOAD_VAR(&p, &tmp.ai_family);
+	LOAD_VAR(&p, &tmp.ai_socktype);
+	LOAD_VAR(&p, &tmp.ai_protocol);
+	LOAD_VAR(&p, &tmp.ai_addrlen);
+	LOAD_VAR(&p, &cnlen);
+
+	next = (struct w3m_addrinfo *)malloc(
+		sizeof(struct w3m_addrinfo) + tmp.ai_addrlen);
+	if (!next)
+	    goto nomem;
+	if (curr)
+	    curr->ai_next = next;
+	curr = next;
+	if (!*res)
+	    *res = curr;
+
+	memcpy(curr, &tmp, sizeof(struct w3m_addrinfo));
+	if (cnlen) {
+	    curr->ai_canonname = (char *)malloc(cnlen);
+	    if (!curr->ai_canonname)
+		goto nomem;
+	    LOAD(&p, curr->ai_canonname, cnlen);
+	}
+	if (tmp.ai_addrlen || *p == 1) {
+	    curr->ai_addr = (struct sockaddr *)(curr + 1);
+	    LOAD(&p, curr->ai_addr, tmp.ai_addrlen);
+	}
+	if (!tmp.ai_addrlen)
+	    p += 1;
+    }
+    assert(buf + bufsize == p);
+    return 0;
+nomem:
+    if (*res)
+	w3m_freeaddrinfo(*res);
+    *res = NULL;
+    return W3M_EAI_MEMORY;
+}
+
+static int
+process_addrinfo(int cmd, int fd, const char *req, size_t req_rest)
+{
+    const char *p = req;
+    const char *hostname, *servname;
+    size_t hostlen, servlen;
+    int gai_retval;
+    int r;
+    struct w3m_addrinfo *tmpres;
+    char *buf;
+    size_t retsize;
+
+    LOAD_VAR(&p, &hostlen);
+    hostname = hostlen ? p : NULL;
+    p += hostlen;
+    LOAD_VAR(&p, &servlen);
+    servname = servlen ? p : NULL;
+    p += servlen;
+    if (cmd == CMD_ADDRINFO_WITH_HINTS) {
+	struct w3m_addrinfo hints;
+
+	memset(&hints, 0, sizeof hints);
+	LOAD_VAR(&p, &hints.ai_flags);
+	LOAD_VAR(&p, &hints.ai_family);
+	LOAD_VAR(&p, &hints.ai_socktype);
+	LOAD_VAR(&p, &hints.ai_protocol);
+	assert(p == req + req_rest);
+	gai_retval = w3m_getaddrinfo(hostname, servname, &hints, &tmpres);
+    } else {
+	assert(p == req + req_rest);
+	gai_retval = w3m_getaddrinfo(hostname, servname, NULL, &tmpres);
+    }
+    retsize = size_of_gai_result(gai_retval, tmpres);
+    buf = (char *)malloc(retsize + HEADERLEN);
+    if (!buf) {
+	if (tmpres)
+	    w3m_freeaddrinfo(tmpres);
+	return -1;
+    }
+    memcpy(buf, &retsize, HEADERLEN);
+    store_gai_result(gai_retval, tmpres, buf + HEADERLEN, retsize);
+
+    if (tmpres)
+	w3m_freeaddrinfo(tmpres);
+    r = write_all(fd, buf, retsize + HEADERLEN);
+    free(buf);
+    return r;
+}
+
+int
+w3m_getaddrinfo_intr(const char *hostname, const char *servname, 
+	const struct w3m_addrinfo *hints, struct w3m_addrinfo **res,
+	int *reason_ret)
+{
+    const char cmd = hints ?
+	CMD_ADDRINFO_WITH_HINTS : CMD_ADDRINFO_WITHOUT_HINTS;
+    size_t hostlen, servlen;
+    size_t reqsize;
+    char *reqbuf = NULL, *p;
+
+    int retval = W3M_RESOLV_MAXERR;
+    char *retbuf = NULL;
+    size_t retsize;
+    int reason;
+
+    canceled_flag = 0;
+
+    hostlen = hostname ? (strlen(hostname) + 1) : 0;
+    servlen = servname ? (strlen(servname) + 1) : 0;
+    reqsize = sizeof cmd + sizeof hostlen + hostlen + sizeof servlen + servlen;
+    if (hints) {
+	reqsize += sizeof(hints->ai_flags) + sizeof(hints->ai_family)
+	+ sizeof(hints->ai_socktype) + sizeof(hints->ai_protocol);
+    }
+
+    reqbuf = p = (char *)malloc(HEADERLEN + reqsize);
+    if (!reqbuf)
+	goto nomem;
+    STORE_VAR(&p, &reqsize);
+    STORE_VAR(&p, &cmd);
+    STORE_VAR(&p, &hostlen);
+    STORE(&p, hostname, hostlen);
+    STORE_VAR(&p, &servlen);
+    STORE(&p, servname, servlen);
+    if (hints) {
+	STORE_VAR(&p, &hints->ai_flags);
+	STORE_VAR(&p, &hints->ai_family);
+	STORE_VAR(&p, &hints->ai_socktype);
+	STORE_VAR(&p, &hints->ai_protocol);
+    }
+    assert(p == reqbuf + HEADERLEN + reqsize);
+
+    retval = talk_to_helper(&retbuf, &retsize,
+	    reqbuf, reqsize + HEADERLEN, reason_ret);
+    if (retval)
+	goto last;
+    reason = parse_gai_result(retbuf, retsize, res);
+    if (reason_ret)
+	*reason_ret = reason;
+    retval = reason ? W3M_RESOLV_FAILED : W3M_RESOLV_OK;
+    goto last;
+nomem:
+    if (reason_ret)
+	*reason_ret = W3M_EAI_MEMORY;
+    retval = W3M_RESOLV_FAILED;
+last:
+    free(retbuf);
+    free(reqbuf);
+    return retval;
+}
+
+static int
+process_nameinfo(int cmd, int fd, const char *req, size_t req_rest)
+{
+    const char *p = req;
+    w3m_socklen_t salen;
+    struct sockaddr *sa = NULL;
+    size_t hostlen, servlen, rhostlen, rservlen;
+    char *buf = NULL, *q, *hostname = NULL, *servname = NULL;
+    int flags;
+    int gni_retval;
+    int r = -1;
+    size_t retsize;
+
+    LOAD_VAR(&p, &salen);
+    sa = (struct sockaddr *)malloc(salen);
+    if (!sa)
+	goto last;
+    LOAD(&p, sa, salen);
+    LOAD_VAR(&p, &hostlen);
+    LOAD_VAR(&p, &servlen);
+    LOAD_VAR(&p, &flags);
+    assert(p == req + req_rest);
+
+    if (hostlen) {
+	hostname = (char *)malloc(hostlen);
+	if (!hostname)
+	    goto last;
+    }
+    if (servlen) {
+	servname = (char *)malloc(servlen);
+	if (!servname)
+	    goto last;
+    }
+
+    gni_retval = w3m_getnameinfo(sa, salen, 
+	    hostname, hostlen, servname, servlen, flags);
+    if (gni_retval) {
+	rhostlen = (size_t)0xdeadbeef;
+	rservlen = (size_t)0xdeadbeef;
+	retsize = sizeof gni_retval;
+    } else {
+	rhostlen = hostname ? (strlen(hostname) + 1) : 0;
+	rservlen = servname ? (strlen(servname) + 1) : 0;
+	retsize = sizeof gni_retval + sizeof rhostlen + rhostlen
+	    + sizeof rservlen + rservlen;
+    }
+    buf = q = (char *)malloc(retsize + HEADERLEN);
+    if (!buf)
+	goto last;
+
+    STORE_VAR(&q, &retsize);
+    STORE_VAR(&q, &gni_retval);
+    if (!gni_retval) {
+	STORE_VAR(&q, &rhostlen);
+	STORE(&q, hostname, rhostlen);
+	STORE_VAR(&q, &rservlen);
+	STORE(&q, servname, rservlen);
+    }
+    assert(q == buf + retsize + HEADERLEN);
+    r = write_all(fd, buf, retsize + HEADERLEN);
+last:
+    free(buf);
+    free(hostname);
+    free(servname);
+    free(sa);
+    return r;
+}
+
+int
+w3m_getnameinfo_intr(const struct sockaddr *sa, w3m_socklen_t salen,
+	char *host, size_t hostlen, char *serv, size_t servlen, int flags,
+	int *reason_ret)
+{
+    const char cmd = CMD_NAMEINFO;
+    size_t reqsize;
+    char *reqbuf = NULL, *p;
+
+    int retval = W3M_RESOLV_MAXERR;
+    char *retbuf = NULL;
+    size_t retsize;
+    int reason;
+
+    assert((host && hostlen) || (!host && !hostlen));
+    assert((serv && servlen) || (!serv && !servlen));
+    canceled_flag = 0;
+
+    reqsize = sizeof cmd + sizeof salen + salen
+	+ sizeof hostlen + sizeof servlen + sizeof flags;
+    reqbuf = p = (char *)malloc(HEADERLEN + reqsize);
+    if (!reqbuf)
+	goto nomem;
+
+    STORE_VAR(&p, &reqsize);
+    STORE_VAR(&p, &cmd);
+    STORE_VAR(&p, &salen);
+    STORE(&p, sa, salen);
+    STORE_VAR(&p, &hostlen);
+    STORE_VAR(&p, &servlen);
+    STORE_VAR(&p, &flags);
+    assert(p == reqbuf + reqsize + HEADERLEN);
+
+    retval = talk_to_helper(&retbuf, &retsize,
+	    reqbuf, reqsize + HEADERLEN, reason_ret);
+    if (retval)
+	goto last;
+
+    p = retbuf;
+    LOAD_VAR(&p, &reason);
+    if (!reason) {
+	size_t rhostlen, rservlen;
+	LOAD_VAR(&p, &rhostlen);
+	assert(rhostlen <= hostlen);
+	LOAD(&p, host, rhostlen);
+	LOAD_VAR(&p, &rservlen);
+	assert(rservlen <= servlen);
+	LOAD(&p, serv, rservlen);
+    }
+    assert(p == retbuf + retsize);
+    retval = reason ? W3M_RESOLV_FAILED : W3M_RESOLV_OK;
+    goto last;
+nomem:
+    if (reason_ret)
+	*reason_ret = W3M_EAI_MEMORY;
+    retval = W3M_RESOLV_FAILED;
+last:
+    free(retbuf);
+    free(reqbuf);
+    return retval;
+}
+
+#ifdef INET6
+static struct w3m_addrinfo *
+sys_to_w3m_addrinfo(struct addrinfo *ai)
+{
+    struct addrinfo *currai;
+    struct w3m_addrinfo *top = NULL, *bot = NULL;
+    
+    for (currai = ai; currai; currai = currai->ai_next) {
+	struct w3m_addrinfo *newbot = calloc(1,
+		sizeof(struct w3m_addrinfo) + currai->ai_addrlen);
+	if (newbot == NULL)
+	    goto nomem;
+	if (top == NULL) {
+	    top = bot = newbot;
+	} else {
+	    bot->ai_next = newbot;
+	    bot = newbot;
+	}
+	newbot->ai_flags = currai->ai_flags;
+	newbot->ai_family = currai->ai_family;
+	newbot->ai_socktype = currai->ai_socktype;
+	newbot->ai_protocol = currai->ai_protocol;
+	newbot->ai_addrlen = currai->ai_addrlen;
+	if (currai->ai_canonname != NULL) {
+	    newbot->ai_canonname = malloc(strlen(currai->ai_canonname) + 1);
+	    if (newbot->ai_canonname == NULL)
+		goto nomem;
+	    strcpy(newbot->ai_canonname, currai->ai_canonname);
+	}
+	if (currai->ai_addr != NULL) {
+	    newbot->ai_addr = (struct sockaddr *)(newbot + 1);
+	    memcpy(newbot->ai_addr, currai->ai_addr, currai->ai_addrlen);
+	}
+    }
+    return top;
+nomem:
+    if (top != NULL)
+	w3m_freeaddrinfo(top);
+    return NULL;
+}
+
+int
+w3m_getaddrinfo(const char *hostname, const char *servname, 
+	const struct w3m_addrinfo *hints, struct w3m_addrinfo **res)
+{
+    struct addrinfo *sysres;
+    int r;
+
+    *res = NULL;
+    if (hints) {
+	struct addrinfo syshint;
+	memset(&syshint, 0, sizeof(syshint));
+	syshint.ai_flags = hints->ai_flags;
+	syshint.ai_family = hints->ai_family;
+	syshint.ai_socktype = hints->ai_socktype;
+	syshint.ai_protocol = hints->ai_protocol;
+	r = getaddrinfo(hostname, servname, &syshint, &sysres);
+    } else {
+	r = getaddrinfo(hostname, servname, NULL, &sysres);
+    }
+    if (r)
+	return r;
+    *res = sys_to_w3m_addrinfo(sysres);
+    freeaddrinfo(sysres);
+    if (*res == NULL)
+	return W3M_EAI_MEMORY;
+    return 0;
+}
+
+#endif /* INET6 */
+
+#ifndef INET6
+char *
+w3m_inet_ntop(int af, const void *src, char *dst, size_t size)
+{
+    char tmp[INET_ADDRSTRLEN];
+    const unsigned char *s = (const unsigned char *)src;
+
+    if (af != AF_INET) {
+	errno = EAFNOSUPPORT;
+	return NULL;
+    }
+    sprintf(tmp, "%u.%u.%u.%u", s[0], s[1], s[2], s[3]);
+    if (strlen(tmp) + 1 > size) {
+	errno = ENOSPC;
+	return NULL;
+    }
+    strcpy(dst, tmp);
+    return dst;
+}
+
+#endif /* !INET6 */
+
+/* vim: set sw=4: */
Index: w3m/resolv/w3mresolv.h
diff -u /dev/null w3m/resolv/w3mresolv.h:1.1.2.5
--- /dev/null	Sun Mar 28 02:43:11 2004
+++ w3m/resolv/w3mresolv.h	Sat Mar 27 02:29:37 2004
@@ -0,0 +1,80 @@
+/* $Id: w3mresolv.h,v 1.1.2.5 2004/03/26 17:29:37 shinra Exp $ */
+#ifndef W3MRESOLV_H
+#define W3MRESOLV_H
+
+#include "../config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_SOCKLEN_T
+typedef socklen_t w3m_socklen_t;
+#else
+typedef int w3m_socklen_t;
+#endif
+
+struct w3m_addrinfo {
+    int	ai_flags;	/* AI_PASSIVE, AI_CANONNAME */
+    int	ai_family;	/* PF_xxx */
+    int	ai_socktype;	/* SOCK_xxx */
+    int	ai_protocol;	/* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+    size_t	ai_addrlen;	/* length of ai_addr */
+    char	*ai_canonname;	/* canonical name for hostname */
+    struct sockaddr *ai_addr;	/* binary address */
+    struct w3m_addrinfo *ai_next;	/* next structure in linked list */
+};
+
+enum {
+    W3M_RESOLV_OK = 0,
+    W3M_RESOLV_FAILED,
+    W3M_RESOLV_CANCELED,
+    W3M_RESOLV_MAXERR
+};
+extern void w3m_freeaddrinfo(struct w3m_addrinfo *);
+extern void w3m_cancel_resolv(void);
+extern int w3m_getaddrinfo_intr(const char *, const char *,
+	const struct w3m_addrinfo *, struct w3m_addrinfo **, int *);
+extern int w3m_getnameinfo_intr(
+	const struct sockaddr *, w3m_socklen_t, char *,
+	size_t, char *, size_t, int, int *);
+
+#include <netdb.h>
+#ifdef INET6
+# include "addrinfo6.h"
+#else
+# include "generated/addrinfo4.h"
+#endif
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#ifndef INET_ADDRSTRLEN
+# define INET_ADDRSTRLEN 16
+#endif
+#ifndef INET6_ADDRSTRLEN
+# define INET6_ADDRSTRLEN 46
+#endif
+
+#if defined(HAVE_IN_ADDR_T)
+typedef in_addr_t w3m_in_addr_t;
+#elif defined(HAVE_U_INT32_T)
+typedef u_int32_t w3m_in_addr_t;
+#else
+typedef unsigned int w3m_in_addr_t; /* ILP32, LP64 */
+#endif
+#if defined(HAVE_IN_PORT_T)
+typedef in_port_t w3m_in_port_t;
+#elif defined(HAVE_U_INT32_T) /* probably have u_int16_t */
+typedef u_int16_t w3m_in_port_t;
+#else
+typedef unsigned short w3m_in_port_t;
+#endif
+
+#ifdef INET6
+# define w3m_inet_ntop inet_ntop
+# define w3m_inet_pton inet_pton
+#else
+extern char *w3m_inet_ntop(int, const void *, char *, size_t);
+extern int w3m_inet_pton(int, const char *, void *);
+#endif
+
+#endif /* W3MRESOLV_H */
+/* vim: set sw=4: */
