lynx-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

lynx-dev 2.8.2dev.15 patch 1 - LYGetHostByname


From: Klaus Weide
Subject: lynx-dev 2.8.2dev.15 patch 1 - LYGetHostByname
Date: Wed, 3 Feb 1999 17:10:41 -0600 (CST)

Some notes on the name resolution stuff below.  Why change it?
First, a function to drop-in in place of gethostbyname() is just nice
to have...  The URL guessing code was changed a while ago to use
HTParseInet() instead of gethostbyname() to get the benefit of being
interruptible, but HTParseInet() isn't really the most appropriate (it
does a bit more).  This had some side effects which I assume were not
intended (if one typed in something with a ':' not followed by a
number, e.g. a mistyped URL scheme, lookup was done for the part
before the ':'), although it seems they are now mostly gone due to
changes in is_url() and the valid_hostname() check.

Second, I'm working on incorporating the DNS cache from libwww 5.x.
That also needs to call gethostbyname() or a function like it (using
more pieces of the lookup result than Lynx up to now), so having such a
function makes things simpler.  (There's a function HTGetHostByName in
that code, that is why I use the name LYGetHostByName even though it is
in the WWW directory.)  I actually have the DNS cache already working,
but would like to see this patch tested a bit first.  Did I break
anything so far, especially for non-Unix?

Now to potential problems - In order to ship a (struct hostent)
lookup result from the NSL_FORK child process to its parent so
that it's still valid in the parent, all the struct hostent
elements have to be shuffled into a new buffer.  This requires
some knowledge about what the elements are.  I have:
in /usr/include/netdb.h:

  struct hostent
  {
    char *h_name;                       /* Official name of host.  */
    char **h_aliases;           /* Alias list.  */
    int h_addrtype;             /* Host address type.  */
    int h_length;                       /* Length of address.  */
    char **h_addr_list;         /* List of addresses from name server.  */
  #define       h_addr  h_addr_list[0]  /* Address, for backward compatibility. 
 */
  };

As far as I know that looks the same nearly everywhere, but are
there some systems (that Lynx has to care about) where the header
declaration is different?  Specifically, where some of the fields
are missing, or h_addr is not #defined the same way?

The code below currently assumes that all the elements are there
and that h_addr is h_addr_list[0], but (I hope) doesn't require
a specific order.

DJGPP is a different story - The code uses resolve() instead of
gethostbyname(), so I assume that DJGPP has no struct hostent.
Is this true?  Or maybe only in some versions?  Or is there a
struct hostent declared somewhere but no gethostbyname()?

   Klaus

Patches that (should...) work against 2.8.2dev.15:

* Except for DJGPP, move lookup code for domain names (not dotted-
  quad IP addresses) from HTParseInet into a new function:
  LYGetHostByName acts like the normal gethostbyname, but includes
  the NSL_FORK logic.  Interruption is indicated in global variable
  lynx_nsl_status.
* Use LYGetHostByName instead of HTParseInet for URL guessing.
* Select on tty file descriptor in NSL_FORK loop also if compiled
  with slang.  This should make 'z' during lookup more responsive.
* Don't compile in the rules implementation code if NO_RULES is
  defined (suggested by BL)



--- lynx2-8-2.old/src/HTAlert.c Thu Jan 28 10:31:28 1999
+++ lynx2-8-2/src/HTAlert.c     Wed Feb  3 14:09:59 1999
@@ -46,13 +46,16 @@
            fprintf(((TRACE) ? stdout : stderr),
                    "%s %s!\n",
                    extra_prefix, Msg);
+           fflush(stdout);
+           sleep(AlertSecs);
        } else {
            fprintf(((TRACE) ? stdout : stderr),
                    ALERT_FORMAT,
                    (Msg == 0) ? "" : Msg);
-       }
        fflush(stdout);
        sleep(AlertSecs);
+           fprintf(((TRACE) ? stdout : stderr), "\n");
+       }
        CTRACE(tfp, "\nAlert!: %s\n\n", Msg);
        CTRACE_FLUSH(tfp);
     }
--- lynx2-8-2.old/src/LYUtils.c Thu Jan 28 10:31:28 1999
+++ lynx2-8-2/src/LYUtils.c     Wed Feb  3 14:06:19 1999
@@ -2000,6 +2000,43 @@
     return;
 }
 
+#ifdef NSL_FORK
+/*
+ *  Returns the file descriptor from which keyboard input is expected,
+ *  or INVSOC (-1) if not available.
+ *  If need_selectable is true, returns non-INVSOC fd only if select()
+ *  is possible - actually, currently only checks if fd is connected
+ *  to a tty. - kw
+ */
+PUBLIC int LYConsoleInputFD ARGS1(
+    BOOLEAN,           need_selectable)
+{
+    int fd = INVSOC;
+#ifdef USE_SLANG
+    if (!LYCursesON)
+       fd = fileno(stdin);
+#if SLANG_VERSION >= 9919
+    /* SLang_TT_Read_FD introduced in slang 0.99.19, from its changelog:
+     *   SLang_TT_Read_FD variable is now available for unix.  This is the file
+     *   descriptor used by SLang_getkey. */
+    else
+       fd = SLang_TT_Read_FD;
+#endif /* SLANG_VERSION >= 9919 */
+#else  /* !USE_SLANG */
+    fd = fileno(stdin);
+#endif /* !USE_SLANG */
+
+    if (need_selectable && fd != INVSOC) {
+       if (isatty(fd)) {
+           return fd;
+       } else {
+           return INVSOC;
+       }
+    }
+    return fd;
+}
+#endif /* NSL_FORK */
+
 PRIVATE int fake_zap = 0;
 
 PUBLIC void LYFakeZap ARGS1(
@@ -4138,8 +4175,6 @@
     char *Host = NULL, *HostColon = NULL, *host = NULL;
     char *Path = NULL;
     char *Fragment = NULL;
-    int hoststat;
-    SockA sock;
     BOOLEAN GotHost = FALSE;
     BOOLEAN Startup = (helpfilepath == NULL);
 
@@ -4214,8 +4249,7 @@
        fprintf(stdout, "%s '%s'%s\n", WWW_FIND_MESSAGE, host, FIRST_SEGMENT);
     }
 #ifndef DJGPP
-    sock.sin_port = htons(80);
-    if ((hoststat = HTParseInet(&sock, host)) == 0)
+    if (LYGetHostByName(host) != NULL)
 #else
     if (resolve(host) != 0)
 #endif /* DJGPP */
@@ -4237,7 +4271,7 @@
        FREE(MsgStr);
        return GotHost;
 #ifndef DJGPP
-    } else if (LYCursesON && (hoststat == HT_INTERRUPTED)) {
+    } else if (LYCursesON && (lynx_nsl_status == HT_INTERRUPTED)) {
 #else /* DJGPP */
     } else if (LYCursesON && HTCheckForInterrupt()) {
 #endif /* DJGPP */
@@ -4336,8 +4370,7 @@
                fprintf(stdout, "%s '%s'%s\n", WWW_FIND_MESSAGE, host, 
GUESSING_SEGMENT);
            }
 #ifndef DJGPP
-           sock.sin_port = htons(80);
-           GotHost = ((hoststat = HTParseInet(&sock, host)) == 0);
+           GotHost = (LYGetHostByName(host) != NULL);
 #else
            GotHost = (resolve(host) != 0);
 #endif /* DJGPP */
@@ -4349,7 +4382,7 @@
                 *  Give the user chance to interrupt lookup cycles. - KW
                 */
 #ifndef DJGPP
-               if (LYCursesON && (hoststat == HT_INTERRUPTED))
+               if (LYCursesON && (lynx_nsl_status == HT_INTERRUPTED))
 #else /* DJGPP */
                if (LYCursesON && HTCheckForInterrupt())
 #endif /* DJGPP */
--- lynx2-8-2.old/src/LYUtils.h Wed Jan 13 05:37:34 1999
+++ lynx2-8-2/src/LYUtils.h     Fri Jan 22 10:16:37 1999
@@ -65,6 +65,7 @@
 extern char *LYgetXDisplay NOPARAMS;
 extern char *strip_trailing_slash PARAMS((char * my_dirname));
 extern char *wwwName PARAMS((CONST char *pathname));
+extern int LYConsoleInputFD PARAMS((BOOLEAN need_selectable));
 extern int HTCheckForInterrupt NOPARAMS;
 extern int LYCheckForProxyURL PARAMS((char *filename));
 extern int LYCopyFile PARAMS((char *src, char *dst));
--- lynx2-8-2.old/WWW/Library/Implementation/tcp.h      Thu Jan 28 10:31:28 1999
+++ lynx2-8-2/WWW/Library/Implementation/tcp.h  Wed Feb  3 12:27:17 1999
@@ -53,6 +53,9 @@
 #define GOT_PIPE
 #endif /* unix */
 
+#define INVSOC (-1)             /* Unix invalid socket */
+               /* NB: newer libwww has something different for Windows */
+
 typedef struct sockaddr_in SockA;  /* See netinet/in.h */
 
 #ifndef VMS
--- lynx2-8-2.old/WWW/Library/Implementation/HTUtils.h  Thu Jan 28 10:31:28 1999
+++ lynx2-8-2/WWW/Library/Implementation/HTUtils.h      Wed Feb  3 13:03:29 1999
@@ -333,6 +333,8 @@
 #define HT_FORBIDDEN            -403    /* Access forbidden */
 #define HT_NOT_ACCEPTABLE       -406    /* Not Acceptable */
 
+#define HT_H_ERRNO_VALID       -800    /* see h_errno for resolver error */
+
 #define HT_INTERNAL             -900    /* Weird -- should never happen. */
 #define HT_BAD_EOF      -12             /* Premature EOF */
 
--- lynx2-8-2.old/WWW/Library/Implementation/HTTCP.h    Thu Jan 28 10:31:28 1999
+++ lynx2-8-2/WWW/Library/Implementation/HTTCP.h        Wed Feb  3 12:33:58 1999
@@ -69,7 +69,33 @@
                 char            **pp,
                 unsigned int    max_value));
 
+/*     Check whether string is a valid Internet hostname
+**     -------------------------------------------------
+*/
+
 extern BOOL valid_hostname PARAMS((CONST char * name));
+
+/*     Resolve an internet hostname, like gethostbyname
+**     ------------------------------------------------
+**
+**  On entry,
+**     str     points to the given host name, not numeric address,
+**             without colon or port number.
+**
+**  On exit,
+**     returns a pointer to a struct hostent in static storage,
+**     or NULL in case of error or user interruption.
+**
+**  The interface is intended to be the same as for gethostbyname(),
+**  but additional status is returned in lynx_nsl_status.
+*/
+extern int lynx_nsl_status;
+
+#ifndef DJGPP
+extern struct hostent * LYGetHostByName PARAMS((
+       CONST char *    str));
+#endif /* DJGPP */
+
 
 /*      Parse an internet node address and port
 **      ---------------------------------------
--- lynx2-8-2.old/WWW/Library/Implementation/HTTCP.c    Thu Jan 28 10:31:28 1999
+++ lynx2-8-2/WWW/Library/Implementation/HTTCP.c        Wed Feb  3 13:03:22 1999
@@ -28,7 +28,7 @@
 #include <sys/wait.h>
 #endif /* NSL_FORK */
 
-#define OK_HOST(p) ((p) != 0 && (p->h_length) != 0)
+#define OK_HOST(p) ((p) != 0 && ((p)->h_length) != 0)
 
 #ifdef SVR4_BSDSELECT
 PUBLIC int BSDselect PARAMS((
@@ -368,152 +368,337 @@
 }
 #endif /* NSL_FORK */
 
-/*     Parse a network node address and port
-**     -------------------------------------
-**
-**  On entry,
-**     str     points to a string with a node name or number,
-**             with optional trailing colon and port number.
-**     soc_in  points to the binary internet or decnet address field.
+PUBLIC int lynx_nsl_status = HT_OK;
+
+#ifndef DJGPP                  /* much excluded! */
+
+#define DEBUG_HOSTENT          /* disable in case of problems */
+#define DEBUG_HOSTENT_CHILD  /* for NSL_FORK, may screw up trace file */
+
+/*
+**  Two auxiliary functions for name lookup and struct hostent.
 **
-**  On exit,
-**     *soc_in is filled in.  If no port is specified in str, that
-**             field is left unchanged in *soc_in.
+**  dump_hostent - dumps the contents of a struct hostent to the
+**  trace log or stderr, including all pointer values, strings, and
+**  addresses, in a format inspired by gdb's print format. - kw
 */
-PUBLIC int HTParseInet ARGS2(
-       SockA *,        soc_in,
-       CONST char *,   str)
+PRIVATE void dump_hostent ARGS2(
+    CONST char *,              msgprefix,
+    CONST struct hostent *,    phost)
 {
-    char *port;
-    int dotcount_ip = 0;       /* for dotted decimal IP addr */
-#ifndef _WINDOWS_NSL
-    char *host = NULL;
-#endif /* _WINDOWS_NSL */
-
-    if (!str) {
-       CTRACE(tfp, "HTParseInet: Can't parse `NULL'.\n");
-       return -1;
-    }
-    CTRACE(tfp, "HTParseInet: parsing `%s'.\n", str);
-    if (HTCheckForInterrupt()) {
-       CTRACE (tfp, "HTParseInet: INTERRUPTED for '%s'.\n", str);
-       return -1;
-    }
-#ifdef _WINDOWS_NSL
-    strncpy(host, str, (size_t)512);
-#else
-    StrAllocCopy(host, str);   /* Make a copy we can mutilate */
-#endif /*  _WINDOWS_NSL */
-    /*
-    ** Parse port number if present.
-    */
-    if ((port = strchr(host, ':')) != NULL) {
-       *port++ = 0;            /* Chop off port */
-       if (port[0] >= '0' && port[0] <= '9') {
-#ifdef unix
-           soc_in->sin_port = htons(atol(port));
-#else /* VMS: */
-#ifdef DECNET
-           soc_in->sdn_objnum = (unsigned char)(strtol(port, (char**)0, 10));
-#else
-           soc_in->sin_port = htons((unsigned short)strtol(port,(char**)0,10));
-#endif /* Decnet */
-#endif /* Unix vs. VMS */
-#ifdef SUPPRESS        /* 1. crashes!?!.  2. Not recommended */
-       } else {
-           struct servent * serv = getservbyname(port, (char*)0);
-           if (serv) {
-               soc_in->sin_port = serv->s_port;
+    if (TRACE) {
+       int i;
+       char **pcnt;
+       CTRACE(tfp,"%s: %p ", msgprefix, phost);
+       if (phost) {
+           CTRACE(tfp,"{ h_name = %p", phost->h_name);
+           if (phost->h_name) {
+               CTRACE(tfp, " \"%s\",", phost->h_name);
            } else {
-               CTRACE(tfp, "TCP: Unknown service %s\n", port);
+               CTRACE(tfp, ",");
+           }
+           CTRACE(tfp,"\n\t h_aliases = %p", phost->h_aliases);
+           if (phost->h_aliases) {
+               CTRACE(tfp, " {");
+               for (pcnt = phost->h_aliases; *pcnt; pcnt++) {
+                   CTRACE(tfp,"%s %p \"%s\"",
+                          (pcnt == phost->h_aliases ? " " : ", "),
+                          *pcnt, *pcnt);
+               }
+               CTRACE(tfp, "%s0x0 },\n\t",
+                      (*phost->h_aliases ? ", " : " "));
+           } else {
+               CTRACE(tfp, ",\n\t");
+           }
+           CTRACE(tfp," h_addrtype = %d,", phost->h_addrtype);
+           CTRACE(tfp," h_length = %d,\n\t", phost->h_length);
+           CTRACE(tfp," h_addr_list = %p", phost->h_addr_list);
+           if (phost->h_addr_list) {
+               CTRACE(tfp, " {");
+               for (pcnt = phost->h_addr_list; *pcnt; pcnt++) {
+                   CTRACE(tfp,"%s %p",
+                          (pcnt == phost->h_addr_list ? "" : ","),
+                          *pcnt);
+                   for (i = 0; i < phost->h_length; i++) {
+                       CTRACE(tfp, "%s%d%s", (i==0 ? " \"" : "."),
+                              (int)*((unsigned char *)(*pcnt)+i),
+                              (i+1 == phost->h_length ? "\"" : ""));
+                   }
+               }
+               if (*phost->h_addr_list) {
+                   CTRACE(tfp, ", 0x0 } }");
+               } else {
+                   CTRACE(tfp, " 0x0 } }");
+               }
+           } else {
+               CTRACE(tfp, "}");
            }
-#endif /* SUPPRESS */
        }
+       CTRACE(tfp,"\n");
+       fflush(tfp);
     }
+}
 
-#ifdef DECNET
-    /*
-    ** Read Decnet node name. @@ Should know about DECnet addresses, but
-    ** it's probably worth waiting until the Phase transition from IV to V.
-    */
-    soc_in->sdn_nam.n_len = min(DN_MAXNAML, strlen(host));  /* <=6 in phase 4 
*/
-    strncpy(soc_in->sdn_nam.n_name, host, soc_in->sdn_nam.n_len + 1);
-    CTRACE(tfp, "DECnet: Parsed address as object number %d on host %.6s...\n",
-               soc_in->sdn_objnum, host);
-#else  /* parse Internet host: */
+/*
+**  fill_rehostent - copies as much as possible relevant content from
+**  the struct hostent pointed to by phost to the char buffer given
+**  by rehostent, subject to maximum output length rehostentsize,
+**  following pointers and building self-contained output which can be
+**  cast to a struct hostent. - kw
+**  See also description of LYGetHostByName.
+*/
+PRIVATE size_t fill_rehostent ARGS3(
+    char *,                    rehostent,
+    size_t,                    rehostentsize,
+    CONST struct hostent *,    phost)
+{
+    int num_addrs = 0;
+    int num_aliases = 0;
+    char **pcnt;
+    char *p_next_char;
+    char **p_next_charptr;
+    size_t name_len = 0;
+    size_t required_per_addr;
+    size_t curlen = sizeof(struct hostent);
+    size_t available = rehostentsize - curlen;
+    size_t chk_available, mem_this_alias, required_this_alias;
+    int i_addr, i_alias;
 
-    if (*host >= '0' && *host <= '9') {   /* Test for numeric node address: */
-       char *strptr = host;
-       while (*strptr) {
-           if (*strptr == '.') {
-               dotcount_ip++;
-           } else if (!isdigit(*strptr)) {
+    if (!phost)
+       return 0;
+    required_per_addr = phost->h_length + sizeof(char *);
+    if (phost->h_addr_list)
+       available -= sizeof(phost->h_addr_list[0]);
+    if (phost->h_aliases)
+       available -= sizeof(phost->h_aliases[0]);
+    if (phost->h_name)
+       available--;
+    if (phost->h_addr_list) {
+       if (phost->h_addr_list[0]) {
+           if (available >= required_per_addr) {
+               num_addrs++;
+               available -= required_per_addr;
+           }
+       }
+    }
+    if (phost->h_name) {
+       name_len = strlen(phost->h_name);
+       if (available >= name_len) {
+           available -= name_len;
+       } else {
+           name_len = 0;
+       }
+    }
+    if (num_addrs) {
+       for (pcnt=phost->h_addr_list+1; *pcnt; pcnt++) {
+           if (available >= required_per_addr) {
+               num_addrs++;
+               available -= required_per_addr;
+           } else {
                break;
            }
-           strptr++;
        }
-       if (*strptr) {          /* found non-numeric, assume domain name */
-           dotcount_ip = 0;
+    }
+    chk_available = available;
+    if (phost->h_aliases) {
+       for (pcnt=phost->h_aliases; *pcnt; pcnt++) {
+           required_this_alias = sizeof(phost->h_aliases[0]) +
+               strlen(*pcnt) + 1;
+           if (chk_available >= required_this_alias) {
+               num_aliases++;
+               chk_available -= required_this_alias;
+           }
        }
     }
 
-    /*
-    ** Parse host number if present.
-    */
-    if (dotcount_ip == 3) {   /* Numeric node address: */
+    ((struct hostent *)rehostent)->h_addrtype = phost->h_addrtype;
+    ((struct hostent *)rehostent)->h_length = phost->h_length;
+    p_next_charptr = (char **)(rehostent + curlen);
+    p_next_char = rehostent + curlen;
+    if (phost->h_addr_list)
+       p_next_char += (num_addrs+1) * sizeof(phost->h_addr_list[0]);
+    if (phost->h_aliases)
+       p_next_char += (num_aliases+1) * sizeof(phost->h_aliases[0]);
+
+    if (phost->h_addr_list) {
+       ((struct hostent *)rehostent)->h_addr_list = p_next_charptr;
+       for (pcnt=phost->h_addr_list, i_addr = 0;
+            i_addr < num_addrs;
+            pcnt++, i_addr++) {
+           memcpy(p_next_char, *pcnt, sizeof(phost->h_addr_list[0]));
+           *p_next_charptr++ = p_next_char; 
+           p_next_char += sizeof(phost->h_addr_list[0]);
+       }
+       *p_next_charptr++ = NULL;
+    } else {
+       ((struct hostent *)rehostent)->h_addr_list = NULL;
+    }
 
-#ifdef DJGPP
-       soc_in->sin_addr.s_addr = htonl(aton(host));
-#else
-#ifdef DGUX_OLD
-       soc_in->sin_addr.s_addr = inet_addr(host).s_addr; /* See arpa/inet.h */
-#else
-#ifdef GUSI
-       soc_in->sin_addr = inet_addr(host);             /* See netinet/in.h */
-#else
-#ifdef HAVE_INET_ATON
-       if (!inet_aton(host, &(soc_in->sin_addr))) {
-           CTRACE(tfp, "inet_aton(%s) returns error\n", host);
-           return -1;
+    if (phost->h_name) {
+       ((struct hostent *)rehostent)->h_name = p_next_char;
+       if (name_len) {
+           strcpy(p_next_char, phost->h_name);
+           p_next_char += name_len + 1;
+       } else {
+           *p_next_char++ = '\0';
        }
-#else
-       soc_in->sin_addr.s_addr = inet_addr(host);      /* See arpa/inet.h */
-#endif /* HAVE_INET_ATON */
-#endif /* GUSI */
-#endif /* DGUX_OLD */
-#endif /* DJGPP */
-#ifndef _WINDOWS_NSL
-       FREE(host);
-#endif /* _WINDOWS_NSL */
-    } else {               /* Alphanumeric node name: */
-       if (!valid_hostname(host)) {
+    } else {
+       ((struct hostent *)rehostent)->h_name = NULL;
+    }
+
+    if (phost->h_aliases) {
+       ((struct hostent *)rehostent)->h_aliases = p_next_charptr;
+       for (pcnt=phost->h_aliases, i_alias = 0;
+            (*pcnt && i_alias < num_addrs);
+            pcnt++, i_alias++) {
+           mem_this_alias = strlen(*pcnt) + 1;
+           required_this_alias = sizeof(phost->h_aliases[0]) +
+               mem_this_alias;
+           if (available >= required_this_alias) {
+               i_alias++;
+               available -= required_this_alias;
+               strcpy(p_next_char, *pcnt);
+               *p_next_charptr++ = p_next_char; 
+               p_next_char += mem_this_alias;
+           }
+           p_next_char += sizeof(phost->h_aliases[0]);
+       }
+       *p_next_charptr++ = NULL;
+    } else {
+       ((struct hostent *)rehostent)->h_aliases = NULL;
+    }
+    curlen = p_next_char - (char *)rehostent;
+    return curlen;
+}
+
+#define REHOSTENT_SIZE 128             /* not bigger than pipe buffer! */
+
+/*     Resolve an internet hostname, like gethostbyname
+**     ------------------------------------------------
+**
+**  On entry,
+**     str     points to the given host name, not numeric address,
+**             without colon or port number.
+**
+**  On exit,
+**     returns a pointer to a struct hostent in static storage,
+**     or NULL in case of error or user interruption.
+**
+**  The interface is intended to be exactly the same as for (Unix)
+**  gethostbyname(), except for the following:
+**
+**  If NSL_FORK is not used, the result of gethostbyname is returned
+**  directly.  Otherwise:
+**  All lists, addresses, and strings referred to by pointers in the
+**  returned struct are located, together with the returned struct
+**  itself, in a buffer of size REHOSTENT_SIZE.  If not everything fits,
+**  some info is omitted, but the function is careful to still return
+**  a valid structure, without truncating strings; it tries to return,
+**  in order of decreasing priority, the first address (h_addr), the
+**  official name (h_name), the additional addresses, then alias names.
+**
+**  If NULL is returned, the reason is made available in the global
+**  variable lynx_nsl_status, with one of the following values:
+**     HT_INTERRUPTED          Interrupted by user
+**     HT_NOT_ACCEPTABLE       Hostname detected as invalid
+**                             (also sets h_errno)
+**     HT_H_ERRNO_VALID        An error occurred, and h_errno holds
+**                             an appropriate value
+**     HT_ERROR                Resolver error, reason not known
+**     HT_INTERNAL             Internal error
+*/
+PUBLIC struct hostent * LYGetHostByName ARGS1(
+       CONST char *,   str)
+{
 #ifndef _WINDOWS_NSL
-           FREE(host);
+    CONST char *host = str;
 #endif /* _WINDOWS_NSL */
-           return HT_NOT_ACCEPTABLE; /* only HTDoConnect checks this. */
-       }
+#ifdef NSL_FORK
+    /* for transfer of result between from child to parent: */
+    static struct {
+       struct hostent  h;
+       char            rest[REHOSTENT_SIZE];
+    } aligned_full_rehostent;
+    /*
+     * We could define rehosten directly as a
+     * static char rehostent[REHOSTENT_SIZE],
+     * but the indirect approach via the above struct
+     * should automatically take care of alignment requirements.
+     * Note that, in addition,
+     *  - this must be static, as we shall return a pointer to it
+     *    which must remain valid, and
+     *  - we have to use the same rehostent in the child process as
+     *    in the parent (its address in the parent's address space
+     *    must be the same as in the child's, otherwise the internal
+     *    pointers built by the child's call to fill_rehostent would
+     *    be invalid when seen by the parent). - kw
+     */
+    char *rehostent = (char *)&aligned_full_rehostent;
+
+    /* for transfer of status from child to parent: */
+    struct _statuses {
+       size_t rehostentlen;
+       int h_length;
+       int child_errno;  /* maybe not very useful */
+       int child_h_errno;
+       BOOL h_errno_valid;
+    } statuses;
+
+    size_t rehostentlen = 0;
+#endif /* NSL_FORK */
+
+    struct hostent *result_phost = NULL;
+
+    if (!str) {
+       CTRACE(tfp, "LYGetHostByName: Can't parse `NULL'.\n");
+       lynx_nsl_status = HT_INTERNAL;
+       return NULL;
+    }
+    CTRACE(tfp, "LYGetHostByName: parsing `%s'.\n", str);
+
+       /*  Could disable this if all our callers already check - kw */
+    if (HTCheckForInterrupt()) {
+       CTRACE (tfp, "LYGetHostByName: INTERRUPTED for '%s'.\n", str);
+       lynx_nsl_status = HT_INTERRUPTED;
+       return NULL;
+    }
+
+    if (!valid_hostname(host)) {
+       lynx_nsl_status = HT_NOT_ACCEPTABLE;
+       h_errno = NO_RECOVERY;
+       return NULL;
+    }
+
+#ifdef _WINDOWS_NSL
+    strncpy(host, str, (size_t)512);
+#else
+    host = str;
+#endif /*  _WINDOWS_NSL */
 
 #ifdef MVS     /* Outstanding problem with crash in MVS gethostbyname */
-       CTRACE(tfp, "HTParseInet: Calling gethostbyname(%s)\n", host);
+    CTRACE(tfp, "LYGetHostByName: Calling gethostbyname(%s)\n", host);
 #endif /* MVS */
 
+    lynx_nsl_status = HT_INTERNAL;     /* should be set to something else 
below */
+
 #ifdef NSL_FORK
+    statuses.h_errno_valid = NO;
        /*
        **  Start block for fork-based gethostbyname() with
        **  checks for interrupts. - Tom Zerucha (address@hidden) & FM
        */
-       {
-           int success = 0;
-           /*
-           **  Pipe, child pid, status buffers, cycle count, select()
-           **  control variables.
+    {
+       int got_rehostent = 0;
+       /*
+       **      Pipe, child pid, status buffers, cycle count, select()
+       **      control variables.
            */
-           pid_t fpid, waitret;
-           int pfd[2], h_length, selret, readret, waitstat = 0, cycle = 0;
-           fd_set readfds;
-           struct timeval timeout;
-           int dns_patience = 30; /* how many seconds will we wait for DNS? */
-           int child_exited = 0;
+       pid_t fpid, waitret;
+       int pfd[2], selret, readret, waitstat = 0, cycle = 0;
+       fd_set readfds;
+       struct timeval timeout;
+       int dns_patience = 30; /* how many seconds will we wait for DNS? */
+       int child_exited = 0;
 
            /*
            **  Reap any children that have terminated since last time
@@ -524,113 +709,135 @@
            **  returns 0 when children exist but none have exited; -1
            **  with errno == ECHILD when no children.)  -BL
            */
-           do {
-               waitret = waitpid(-1, 0, WNOHANG);
-           } while (waitret > 0 || (waitret == -1 && errno == EINTR));
-           waitret = 0;
+       do {
+           waitret = waitpid(-1, 0, WNOHANG);
+       } while (waitret > 0 || (waitret == -1 && errno == EINTR));
+       waitret = 0;
 
-           pipe(pfd);
+       pipe(pfd);
 
-           if ((fpid = fork()) == 0 ) {
-               struct hostent  *phost; /* Pointer to host - See netdb.h */
-               /*
-               **  Child - for the long call.
+       if ((fpid = fork()) == 0 ) {
+           struct hostent  *phost;     /* Pointer to host - See netdb.h */
+           /*
+           **  Child - for the long call.
                **
                **  Make sure parent can kill us at will.  -BL
                */
-               (void) signal(SIGTERM, quench);
+           (void) signal(SIGTERM, quench);
 
-               /*
+           /*
                **  Also make sure the child does not run one of the
                **  signal handlers that may have been installed by
                **  Lynx if one of those signals occurs.  For example
                **  we don't want the child to remove temp files on
                **  ^C, let the parent deal with that. - kw
                */
-               (void) signal(SIGINT, quench);
+           (void) signal(SIGINT, quench);
 #ifndef NOSIGHUP
-               (void) signal(SIGHUP, quench);
+           (void) signal(SIGHUP, quench);
 #endif /* NOSIGHUP */
 #ifdef SIGTSTP
-               if (no_suspend)
-                   (void) signal(SIGTSTP, SIG_IGN);
-               else
-                   (void) signal(SIGTSTP, SIG_DFL);
+           if (no_suspend)
+               (void) signal(SIGTSTP, SIG_IGN);
+           else
+               (void) signal(SIGTSTP, SIG_DFL);
 #endif /* SIGTSTP */
 #ifdef SIGWINCH
-               (void) signal(SIGWINCH, SIG_IGN);
+           (void) signal(SIGWINCH, SIG_IGN);
 #endif /* SIGWINCH */
 #ifndef __linux__
 #ifndef DOSPATH
-               signal(SIGBUS, SIG_DFL);
+           signal(SIGBUS, SIG_DFL);
 #endif /* DOSPATH */
 #endif /* !__linux__ */
-               signal(SIGSEGV, SIG_DFL);
-               signal(SIGILL, SIG_DFL);
+           signal(SIGSEGV, SIG_DFL);
+           signal(SIGILL, SIG_DFL);
 
-               /*
+           /*
                **  Child won't use read side.  -BL
                */
-               close(pfd[0]);
-               phost = gethostbyname(host);
+           close(pfd[0]);
+           phost = gethostbyname(host);
+           statuses.child_h_errno = h_errno;
+           statuses.h_errno_valid = YES;
 #ifdef MVS
-               CTRACE(tfp, "HTParseInet: gethostbyname() returned %d\n", 
phost);
+           CTRACE(tfp, "LYGetHostByName: gethostbyname() returned %d\n", 
phost);
 #endif /* MVS */
 
-               /*
-               **  Send length of subsequent value to parent (as a
-               **  native int).
-               */
-               if (OK_HOST(phost))
-                       h_length = phost->h_length;
-               else
-                       h_length = 0;
-               write(pfd[1], &h_length, sizeof h_length);
-
-               if (h_length) {
-                   /*
-                   **  Return value through pipe...
-                   */
-                   write(pfd[1], phost->h_addr, phost->h_length);
-                   _exit(0);
-               } else {
-                   /*
-                   **  ... or return error as exit code.
-                   */
-                   _exit(1);
-               }
+#ifdef DEBUG_HOSTENT_CHILD
+           dump_hostent("CHILD gethostbyname", phost);
+#endif
+           if (OK_HOST(phost)) {
+               rehostentlen = fill_rehostent(rehostent, REHOSTENT_SIZE, phost);
+#ifdef DEBUG_HOSTENT_CHILD
+               dump_hostent("CHILD fill_rehostent", (struct hostent 
*)rehostent);
+#endif
+           }
+           if (rehostentlen <= sizeof(struct hostent) ||
+               !OK_HOST((struct hostent *)rehostent)) {
+               rehostentlen = 0;
+               statuses.h_length = 0;
+           } else {
+               statuses.h_length = ((struct hostent *)rehostent)->h_length;
            }
-
            /*
-           **  (parent) Wait until lookup finishes, or interrupt,
-           **  or cycled too many times (just in case) -BL
+           **  Send variables indicating status of lookup to parent.
+           **  That includes rehostentlen, which the parent will use
+           **  as the size for the second read (if > 0).
            */
+           statuses.child_errno = errno;
+           statuses.rehostentlen = rehostentlen;
+           write(pfd[1], &statuses, sizeof(statuses));
 
-           close(pfd[1]);      /* parent won't use write side -BL */
 
-           while (cycle < dns_patience) {
+           if (rehostentlen) {
+               /*
+               **  Return our resulting rehostent through pipe...
+               */
+               write(pfd[1], rehostent, rehostentlen);
+               _exit(0);
+           } else {
                /*
+               **  ... or return error as exit code.
+               */
+               _exit(1);
+           }
+       }
+
+       /*
+       **      (parent) Wait until lookup finishes, or interrupt,
+       **      or cycled too many times (just in case) -BL
+       */
+
+       close(pfd[1]);      /* parent won't use write side -BL */
+
+       while (cycle < dns_patience) {
+           /*
                **  Avoid infinite loop in the face of the unexpected.  -BL
                */
-               cycle++;
+           cycle++;
 
-               FD_ZERO(&readfds);
-#ifndef USE_SLANG
-               /*
-               **  This allows us to abort immediately, not after 1-second
-               **  timeout, when user hits abort key.  Can't do this when
-               **  using SLANG (or at least I don't know how), so SLANG
-               **  users must live with up-to-1s timeout.  -BL
-               **
-               **  Whoops -- we need to make sure stdin is actually
-               **  selectable!  /dev/null isn't, on some systems, which
-               **  makes some useful Lynx invocations fail.  -BL
-               */
-               if (isatty(fileno(stdin))) FD_SET(fileno(stdin), &readfds);
-#endif /* USE_SLANG */
-               timeout.tv_sec = 1;
-               timeout.tv_usec = 0;
-               FD_SET(pfd[0], &readfds);
+           FD_ZERO(&readfds);
+           /*
+           **  This allows us to abort immediately, not after 1-second
+           **  timeout, when user hits abort key.  Can't do this when
+           **  using SLANG (or at least I don't know how), so SLANG
+           **  users must live with up-to-1s timeout.  -BL
+           **
+           **  Whoops -- we need to make sure stdin is actually
+           **  selectable!  /dev/null isn't, on some systems, which
+           **  makes some useful Lynx invocations fail.  -BL
+           */
+           {
+               int kbd_fd = LYConsoleInputFD(TRUE);
+               if (kbd_fd != INVSOC) {
+                   FD_SET(kbd_fd, &readfds);
+               }
+           }
+               
+           timeout.tv_sec = 1;
+           timeout.tv_usec = 0;
+           FD_SET(pfd[0], &readfds);
 
                /*
                **  Return when data received, interrupted, or failed.
@@ -638,107 +845,117 @@
                **  select(), to be nice to the system.  -BL
                */
 #ifdef SOCKS
-               if (socks_flag)
-                   selret = Rselect(pfd[0] + 1, (void *)&readfds, NULL, NULL, 
&timeout);
-               else
+           if (socks_flag)
+               selret = Rselect(pfd[0] + 1, (void *)&readfds, NULL, NULL, 
&timeout);
+           else
 #endif /* SOCKS */
-                   selret = select(pfd[0] + 1, (void *)&readfds, NULL, NULL, 
&timeout);
+               selret = select(pfd[0] + 1, (void *)&readfds, NULL, NULL, 
&timeout);
 
-               if ((selret > 0) && FD_ISSET(pfd[0], &readfds)) {
-                   /*
-                   **  First get length of address.  -BL
-                   */
-                   readret = read(pfd[0], (void *)&h_length, sizeof h_length);
-                   if (readret == sizeof h_length &&
-                       h_length == sizeof soc_in->sin_addr) {
+           if ((selret > 0) && FD_ISSET(pfd[0], &readfds)) {
+               /*
+               **      First get status, including length of address.  -BL, kw
+               */
+               readret = read(pfd[0], &statuses, sizeof(statuses));
+               if (readret == sizeof(statuses)) {
+                   h_errno = statuses.child_h_errno;
+                   errno = statuses.child_errno;
+                   if (statuses.h_errno_valid)
+                       lynx_nsl_status = HT_H_ERRNO_VALID;
+                   if (statuses.rehostentlen > sizeof(struct hostent)) {
                        /*
-                       **  Then get address itself.  -BL
+                       **  Then get the full reorganized hostent.  -BL, kw
                        */
-                       readret = read(pfd[0], (void *)&soc_in->sin_addr, 
h_length);
-                       if (readret == h_length) success = 1;
+                       readret = read(pfd[0], rehostent, 
statuses.rehostentlen);
+#ifdef DEBUG_HOSTENT
+                       dump_hostent("Read from pipe", (struct hostent 
*)rehostent);
+#endif
+                       if (readret == statuses.rehostentlen) {
+                           got_rehostent = 1;
+                           result_phost = (struct hostent *)rehostent;
+                           lynx_nsl_status = HT_OK;
+                       } else if (!statuses.h_errno_valid) {
+                           lynx_nsl_status = HT_INTERNAL;
+                       }
                    }
-                   /*
+               } else {
+                   lynx_nsl_status = HT_ERROR;
+               }
+               /*
                    **  Make sure child is cleaned up.  -BL
                    */
-                   if (!child_exited)
-                       waitret = waitpid(fpid, &waitstat, WNOHANG);
-                   if (!WIFEXITED(waitstat) && !WIFSIGNALED(waitstat)) {
-                       kill(fpid, SIGTERM);
-                       waitret = waitpid(fpid, &waitstat, WNOHANG);
-                   }
-                   break;
-               }
+               if (!child_exited)
+                   waitret = waitpid(fpid, &waitstat, WNOHANG);
+               if (!WIFEXITED(waitstat) && !WIFSIGNALED(waitstat)) {
+                   kill(fpid, SIGTERM);
+                   waitret = waitpid(fpid, &waitstat, WNOHANG);
+               }
+               break;
+           }
 
-               /*
+           /*
                **  Clean up if child exited before & no data received.  -BL
                */
-               if (child_exited) {
-                   waitret = waitpid(fpid, &waitstat, WNOHANG);
-                   break;
-               }
-               /*
+           if (child_exited) {
+               waitret = waitpid(fpid, &waitstat, WNOHANG);
+               break;
+           }
+           /*
                **  If child exited, loop once more looking for data.  -BL
                */
-               if ((waitret = waitpid(fpid, &waitstat, WNOHANG)) > 0) {
-                   /*
-                   **  Data will be arriving right now, so make sure we
-                   **  don't short-circuit out for too many loops, and
-                   **  skip the interrupt check.  -BL
-                   */
-                   child_exited = 1;
-                   cycle--;
-                   continue;
-               }
-
+           if ((waitret = waitpid(fpid, &waitstat, WNOHANG)) > 0) {
                /*
-               **  Abort if interrupt key pressed.
+               **      Data will be arriving right now, so make sure we
+               **      don't short-circuit out for too many loops, and
+               **      skip the interrupt check.  -BL
                */
-               if (HTCheckForInterrupt()) {
-                   CTRACE(tfp, "HTParseInet: INTERRUPTED gethostbyname.\n");
-                   kill(fpid, SIGTERM);
-                   waitpid(fpid, NULL, WNOHANG);
-                   FREE(host);
-                   close(pfd[0]);
-                   return HT_INTERRUPTED;
-               }
+               child_exited = 1;
+               cycle--;
+               continue;
            }
-           close(pfd[0]);
-           if (waitret <= 0) {
+
+           /*
+           **  Abort if interrupt key pressed.
+           */
+           if (HTCheckForInterrupt()) {
+               CTRACE(tfp, "LYGetHostByName: INTERRUPTED gethostbyname.\n");
                kill(fpid, SIGTERM);
-               waitret = waitpid(fpid, &waitstat, WNOHANG);
+               waitpid(fpid, NULL, WNOHANG);
+               close(pfd[0]);
+               lynx_nsl_status = HT_INTERRUPTED;
+               return NULL;
            }
-           if (waitret > 0) {
-               if (WIFEXITED(waitstat)) {
-                   CTRACE(tfp, "HTParseInet: NSL_FORK child %d exited, status 
0x%x.\n",
-                               (int)waitret, waitstat);
-               } else if (WIFSIGNALED(waitstat)) {
-                   CTRACE(tfp, "HTParseInet: NSL_FORK child %d got signal, 
status 0x%x!\n",
-                               (int)waitret, waitstat);
+       }
+       close(pfd[0]);
+       if (waitret <= 0) {
+           kill(fpid, SIGTERM);
+           waitret = waitpid(fpid, &waitstat, WNOHANG);
+       }
+       if (waitret > 0) {
+           if (WIFEXITED(waitstat)) {
+               CTRACE(tfp, "LYGetHostByName: NSL_FORK child %d exited, status 
0x%x.\n",
+                      (int)waitret, waitstat);
+           } else if (WIFSIGNALED(waitstat)) {
+               CTRACE(tfp, "LYGetHostByName: NSL_FORK child %d got signal, 
status 0x%x!\n",
+                      (int)waitret, waitstat);
 #ifdef WCOREDUMP
-                   if (WCOREDUMP(waitstat)) {
-                       CTRACE(tfp, "HTParseInet: NSL_FORK child %d dumped 
core!\n",
-                                   (int)waitret);
-                   }
-#endif /* WCOREDUMP */
-               } else if (WIFSTOPPED(waitstat)) {
-                   CTRACE(tfp, "HTParseInet: NSL_FORK child %d is stopped, 
status 0x%x!\n",
-                               (int)waitret, waitstat);
+               if (WCOREDUMP(waitstat)) {
+                   CTRACE(tfp, "LYGetHostByName: NSL_FORK child %d dumped 
core!\n",
+                          (int)waitret);
                }
-           }
-           if (!success) {
-               memset((void *)&soc_in->sin_addr, 0, sizeof(soc_in->sin_addr));
-               goto failed;
+#endif /* WCOREDUMP */
+           } else if (WIFSTOPPED(waitstat)) {
+               CTRACE(tfp, "LYGetHostByName: NSL_FORK child %d is stopped, 
status 0x%x!\n",
+                      (int)waitret, waitstat);
            }
        }
-#else /* Not NSL_FORK: */
-#ifdef DJGPP
-       soc_in->sin_addr.s_addr = htonl(resolve(host));
-       if (soc_in->sin_addr.s_addr == 0) {
+       if (!got_rehostent) {
            goto failed;
        }
-#else /* !NSL_FORK, !DJGPP: */
+    }
+#else /* Not NSL_FORK: */
+
 #ifdef _WINDOWS_NSL
-       {
+    {
 #ifdef __BORLANDC__
                HANDLE hThread, dwThreadID;
 #else
@@ -765,18 +982,197 @@
                          if (!CloseHandle(hThread))
                                 MessageBox((void *)NULL, 
"CloseHandle","CloseHandle Failed",
                                                0L);
-                         return HT_INTERRUPTED;
+                         lynx_nsl_status = HT_INTERRUPTED;
+                         return NULL;
                        };
-       };
+               if (phost) {
+                   lynx_nsl_status = HT_OK;
+                   result_phost = phost;
+               } else {
+                   lynx_nsl_status = HT_ERROR;
+                   goto failed;
+               }
+    };
+
+#else /* !NSL_FORK, !_WINDOWS_NSL: */
+    {
+       struct hostent  *phost;
+       phost = gethostbyname(host);    /* See netdb.h */
+#ifdef MVS
+       CTRACE(tfp, "LYGetHostByName: gethostbyname() returned %d\n", phost);
+#endif /* MVS */
+       if (phost) {
+           lynx_nsl_status = HT_OK;
+           result_phost = phost;
+       } else {
+           lynx_nsl_status = HT_H_ERRNO_VALID;
+           goto failed;
+       }
+    }
+#endif /* !NSL_FORK, !_WINDOWS_NSL */
+#endif /* !NSL_FORK */
+
+#ifdef DEBUG_HOSTENT
+    dump_hostent("End of LYGetHostByName", result_phost);
+    CTRACE(tfp, "LYGetHostByName: Resolved name to a hostent.\n");
+#endif
+
+    return result_phost;       /* OK */
+
+failed:
+    CTRACE(tfp, "LYGetHostByName: Can't find internet node name `%s'.\n",
+               host);
+    return NULL;
+}
+
+#endif /* from here on DJGPP joins us again. */
+
+
+/*     Parse a network node address and port
+**     -------------------------------------
+**
+**  On entry,
+**     str     points to a string with a node name or number,
+**             with optional trailing colon and port number.
+**     soc_in  points to the binary internet or decnet address field.
+**
+**  On exit,
+**     *soc_in is filled in.  If no port is specified in str, that
+**             field is left unchanged in *soc_in.
+*/
+PUBLIC int HTParseInet ARGS2(
+       SockA *,        soc_in,
+       CONST char *,   str)
+{
+    char *port;
+    int dotcount_ip = 0;       /* for dotted decimal IP addr */
+#ifndef _WINDOWS_NSL
+    char *host = NULL;
+#endif /* _WINDOWS_NSL */
+
+    if (!str) {
+       CTRACE(tfp, "HTParseInet: Can't parse `NULL'.\n");
+       return -1;
+    }
+    CTRACE(tfp, "HTParseInet: parsing `%s'.\n", str);
+    if (HTCheckForInterrupt()) {
+       CTRACE (tfp, "HTParseInet: INTERRUPTED for '%s'.\n", str);
+       return -1;
+    }
+#ifdef _WINDOWS_NSL
+    strncpy(host, str, (size_t)512);
+#else
+    StrAllocCopy(host, str);   /* Make a copy we can mutilate */
+#endif /*  _WINDOWS_NSL */
+    /*
+    ** Parse port number if present.
+    */
+    if ((port = strchr(host, ':')) != NULL) {
+       *port++ = 0;            /* Chop off port */
+       if (port[0] >= '0' && port[0] <= '9') {
+#ifdef unix
+           soc_in->sin_port = htons(atol(port));
+#else /* VMS: */
+#ifdef DECNET
+           soc_in->sdn_objnum = (unsigned char)(strtol(port, (char**)0, 10));
+#else
+           soc_in->sin_port = htons((unsigned short)strtol(port,(char**)0,10));
+#endif /* Decnet */
+#endif /* Unix vs. VMS */
+#ifdef SUPPRESS        /* 1. crashes!?!.  2. Not recommended */
+       } else {
+           struct servent * serv = getservbyname(port, (char*)0);
+           if (serv) {
+               soc_in->sin_port = serv->s_port;
+           } else {
+               CTRACE(tfp, "TCP: Unknown service %s\n", port);
+           }
+#endif /* SUPPRESS */
+       }
+    }
+
+#ifdef DECNET
+    /*
+    ** Read Decnet node name. @@ Should know about DECnet addresses, but
+    ** it's probably worth waiting until the Phase transition from IV to V.
+    */
+    soc_in->sdn_nam.n_len = min(DN_MAXNAML, strlen(host));  /* <=6 in phase 4 
*/
+    strncpy(soc_in->sdn_nam.n_name, host, soc_in->sdn_nam.n_len + 1);
+    CTRACE(tfp, "DECnet: Parsed address as object number %d on host %.6s...\n",
+               soc_in->sdn_objnum, host);
+#else  /* parse Internet host: */
+
+    if (*host >= '0' && *host <= '9') {   /* Test for numeric node address: */
+       char *strptr = host;
+       while (*strptr) {
+           if (*strptr == '.') {
+               dotcount_ip++;
+           } else if (!isdigit(*strptr)) {
+               break;
+           }
+           strptr++;
+       }
+       if (*strptr) {          /* found non-numeric, assume domain name */
+           dotcount_ip = 0;
+       }
+    }
+
+    /*
+    ** Parse host number if present.
+    */
+    if (dotcount_ip == 3) {   /* Numeric node address: */
+
+#ifdef DJGPP
+       soc_in->sin_addr.s_addr = htonl(aton(host));
+#else
+#ifdef DGUX_OLD
+       soc_in->sin_addr.s_addr = inet_addr(host).s_addr; /* See arpa/inet.h */
+#else
+#ifdef GUSI
+       soc_in->sin_addr = inet_addr(host);             /* See netinet/in.h */
+#else
+#ifdef HAVE_INET_ATON
+       if (!inet_aton(host, &(soc_in->sin_addr))) {
+           CTRACE(tfp, "inet_aton(%s) returns error\n", host);
+#ifndef _WINDOWS_NSL
+           FREE(host);
+#endif /* _WINDOWS_NSL */
+           return -1;
+       }
+#else
+       soc_in->sin_addr.s_addr = inet_addr(host);      /* See arpa/inet.h */
+#endif /* HAVE_INET_ATON */
+#endif /* GUSI */
+#endif /* DGUX_OLD */
+#endif /* DJGPP */
+#ifndef _WINDOWS_NSL
+       FREE(host);
+#endif /* _WINDOWS_NSL */
+    } else {               /* Alphanumeric node name: */
+
+#ifdef MVS     /* Outstanding problem with crash in MVS gethostbyname */
+       CTRACE(tfp, "HTParseInet: Calling LYGetHostByName(%s)\n", host);
+#endif /* MVS */
+
+#ifdef DJGPP
+       if (!valid_hostname(host)) {
+           FREE(host);
+           return HT_NOT_ACCEPTABLE; /* only HTDoConnect checks this. */
+       }
+       soc_in->sin_addr.s_addr = htonl(resolve(host));
+       if (soc_in->sin_addr.s_addr == 0) {
+           goto failed;
+       }
+#else /* !DJGPP: */
+#ifdef _WINDOWS_NSL
+       phost = LYGetHostByName(host);  /* See above */
        if (!phost) goto failed;
        memcpy((void *)&soc_in->sin_addr, phost->h_addr, phost->h_length);
-#else /* !NSL_FORK, !DJGPP, !_WINDOWS_NSL: */
+#else /* !DJGPP, !_WINDOWS_NSL: */
        {
            struct hostent  *phost;
-           phost = gethostbyname(host);        /* See netdb.h */
-#ifdef MVS
-           CTRACE(tfp, "HTParseInet: gethostbyname() returned %d\n", phost);
-#endif /* MVS */
+           phost = LYGetHostByName(host);      /* See above */
+
            if (!phost) goto failed;
 #if defined(VMS) && defined(CMU_TCP)
            /*
@@ -789,17 +1185,20 @@
            */
            memcpy((void *)&soc_in->sin_addr, phost->h_addr, 4);
 #else
+           if (!phost) goto failed;
+           if (phost->h_length != sizeof soc_in->sin_addr) {
+               HTAlwaysAlert(host, gettext("Address length looks invalid"));
+           }
            memcpy((void *)&soc_in->sin_addr, phost->h_addr, phost->h_length);
 #endif /* VMS && CMU_TCP */
        }
-#endif /* !NSL_FORK, !DJGPP, !_WINDOWS_NSL */
-#endif /* !NSL_FORK, !DJGPP */
-#endif /* !NSL_FORK */
+#endif /* !DJGPP, !_WINDOWS_NSL */
+#endif /* !DJGPP */
 #ifndef _WINDOWS_NSL
        FREE(host);
 #endif /* _WINDOWS_NSL */
 
-    }
+    }  /* Alphanumeric node name */
 
     CTRACE(tfp, "HTParseInet: Parsed address as port %d, IP address 
%d.%d.%d.%d\n",
                (int)ntohs(soc_in->sin_port),
@@ -817,7 +1216,13 @@
 #ifndef _WINDOWS_NSL
     FREE(host);
 #endif /* _WINDOWS_NSL */
+    switch (lynx_nsl_status) {
+    case HT_NOT_ACCEPTABLE:
+    case HT_INTERRUPTED:
+       return lynx_nsl_status;
+    default:
     return -1;
+}
 }
 
 /*     Free our name for the host on which we are - FM
--- lynx2-8-2.old/WWW/Library/Implementation/HTRules.c  Thu Jan 28 10:31:28 1999
+++ lynx2-8-2/WWW/Library/Implementation/HTRules.c      Wed Feb  3 14:42:09 1999
@@ -38,6 +38,7 @@
        char *          equiv;
 } rule;
 
+#ifndef NO_RULES
 /*     Global variables
 **     ----------------
 */
@@ -401,3 +402,4 @@
 }
 
 
+#endif /* NO_RULES */
--- lynx2-8-2.old/WWW/Library/Implementation/HTRules.h  Thu Jan 28 10:31:28 1999
+++ lynx2-8-2/WWW/Library/Implementation/HTRules.h      Wed Feb  3 14:42:07 1999
@@ -29,6 +29,7 @@
         HT_Protect
 } HTRuleOp;
 
+#ifndef NO_RULES
 #ifdef SHORT_NAMES
 #define HTSearchScript HTSearSc
 #endif /*SHORT_NAMES*/
@@ -141,5 +142,5 @@
 
  */
 
-
+#endif /* NO_RULES */
 #endif /* HTUtils.h */

reply via email to

[Prev in Thread] Current Thread [Next in Thread]