diff options
Diffstat (limited to 'WWW')
-rw-r--r-- | WWW/Library/Implementation/HTAnchor.c | 42 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTAnchor.h | 20 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTNews.c | 157 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTRules.c | 4 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTRules.h | 4 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTTCP.c | 961 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTTCP.h | 26 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTTelnet.c | 8 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTUtils.h | 2 | ||||
-rw-r--r-- | WWW/Library/Implementation/SGML.c | 2 | ||||
-rw-r--r-- | WWW/Library/Implementation/SGML.h | 1 | ||||
-rw-r--r-- | WWW/Library/Implementation/tcp.h | 3 |
12 files changed, 913 insertions, 317 deletions
diff --git a/WWW/Library/Implementation/HTAnchor.c b/WWW/Library/Implementation/HTAnchor.c index 74399c91..9e3933ad 100644 --- a/WWW/Library/Implementation/HTAnchor.c +++ b/WWW/Library/Implementation/HTAnchor.c @@ -699,6 +699,8 @@ PUBLIC BOOL HTAnchor_delete ARGS1( FREE(me->content_disposition); FREE(me->content_location); FREE(me->content_md5); + FREE(me->message_id); + FREE(me->subject); FREE(me->date); FREE(me->expires); FREE(me->last_modified); @@ -1060,6 +1062,44 @@ PUBLIC CONST char * HTAnchor_content_location ARGS1( return( me ? me->content_location : NULL); } +/* Message-ID, used for mail replies - kw +*/ +PUBLIC CONST char * HTAnchor_messageID ARGS1( + HTParentAnchor *, me) +{ + return( me ? me->message_id : NULL); +} + +PUBLIC BOOL HTAnchor_setMessageID ARGS2( + HTParentAnchor *, me, + CONST char *, messageid) +{ + if (!(me && messageid && *messageid)) { + return FALSE; + } + StrAllocCopy(me->message_id, messageid); + return TRUE; +} + +/* Subject, used for mail replies - kw +*/ +PUBLIC CONST char * HTAnchor_subject ARGS1( + HTParentAnchor *, me) +{ + return( me ? me->subject : NULL); +} + +PUBLIC BOOL HTAnchor_setSubject ARGS2( + HTParentAnchor *, me, + CONST char *, subject) +{ + if (!(me && subject && *subject)) { + return FALSE; + } + StrAllocCopy(me->subject, subject); + return TRUE; +} + /* Link me Anchor to another given one ** ------------------------------------- */ @@ -1203,7 +1243,7 @@ PUBLIC void HTAnchor_setPhysical ARGS2( ** text/plain ** from file: HTFile.c -> HTPlain.c -> GridText.c ** -** The lock/set_by is used to lock e.g., a charset set by an explicit +** The lock/set_by is used to lock e.g. a charset set by an explicit ** HTTP MIME header against overriding by a HTML META tag - the MIME ** header has higher priority. Defaults (from -assume_.. options etc.) ** will not override charset explicitly given by server. diff --git a/WWW/Library/Implementation/HTAnchor.h b/WWW/Library/Implementation/HTAnchor.h index ea28d5cd..eb2633bc 100644 --- a/WWW/Library/Implementation/HTAnchor.h +++ b/WWW/Library/Implementation/HTAnchor.h @@ -118,6 +118,8 @@ struct _HTParentAnchor { char * content_disposition; /* Content-Disposition */ char * content_location; /* Content-Location */ char * content_md5; /* Content-MD5 */ + char * message_id; /* Message-ID */ + char * subject; /* Subject */ int content_length; /* Content-Length */ char * date; /* Date */ char * expires; /* Expires */ @@ -358,6 +360,24 @@ extern CONST char * HTAnchor_content_base PARAMS(( extern CONST char * HTAnchor_content_location PARAMS(( HTParentAnchor * me)); +/* Message-ID, used for mail replies - kw +*/ +extern CONST char * HTAnchor_messageID PARAMS(( + HTParentAnchor * me)); + +extern BOOL HTAnchor_setMessageID PARAMS(( + HTParentAnchor * me, + CONST char * messageid)); + +/* Subject, used for mail replies - kw +*/ +extern CONST char * HTAnchor_subject PARAMS(( + HTParentAnchor * me)); + +extern BOOL HTAnchor_setSubject PARAMS(( + HTParentAnchor * me, + CONST char * subject)); + /* Link this Anchor to another given one ** ------------------------------------- */ diff --git a/WWW/Library/Implementation/HTNews.c b/WWW/Library/Implementation/HTNews.c index f0490e2c..4640f106 100644 --- a/WWW/Library/Implementation/HTNews.c +++ b/WWW/Library/Implementation/HTNews.c @@ -46,7 +46,6 @@ PUBLIC int HTNewsMaxChunk = 40; /* Largest number of articles in one window */ #include <LYGlobalDefs.h> #include <LYLeaks.h> -#define BIG 1024 /* @@@ */ struct _HTStructured { CONST HTStructuredClass * isa; @@ -85,6 +84,9 @@ PRIVATE HTParentAnchor *node_anchor; /* Its anchor */ PRIVATE int diagnostic; /* level: 0=none 2=source */ PRIVATE BOOL rawtext = NO; /* Flag: HEAD or -mime_headers */ PRIVATE HTList *NNTP_AuthInfo = NULL; /* AUTHINFO database */ +PRIVATE char *name = NULL; +PRIVATE char *address = NULL; +PRIVATE char *dbuf = NULL; /* dynamic buffer for long messages etc. */ #define PUTC(c) (*targetClass.put_character)(target, c) #define PUTS(s) (*targetClass.put_string)(target, s) @@ -113,6 +115,9 @@ PRIVATE void free_news_globals NOARGS FREE(HTNewsHost); FREE(NewsHost); FREE(NewsHREF); + FREE(name); + FREE(address); + FREE(dbuf); } PRIVATE void free_NNTP_AuthInfo NOARGS @@ -423,7 +428,7 @@ PRIVATE NNTPAuthResult HTHandleAuthInfo ARGS1( if (status == 381) { /* - ** Handle the password. - FM + ** Handle the password. - FM */ tries = 3; while (tries) { @@ -545,7 +550,6 @@ PRIVATE NNTPAuthResult HTHandleAuthInfo ARGS1( */ PRIVATE char * author_name ARGS1 (char *,email) { - static char *name = NULL; char *p, *e; StrAllocCopy(name, email); @@ -582,7 +586,6 @@ PRIVATE char * author_name ARGS1 (char *,email) */ PRIVATE char * author_address ARGS1(char *,email) { - static char *address = NULL; char *p, *at, *e; StrAllocCopy(address, email); @@ -935,7 +938,8 @@ PRIVATE void post_article ARGS1( ** s Global socket number is OK ** HT Global hypertext object is ready for appending text */ -PRIVATE int read_article NOARGS +PRIVATE int read_article ARGS1( + HTParentAnchor *, thisanchor) { char line[LINE_LENGTH+1]; char *full_line = NULL; @@ -949,6 +953,8 @@ PRIVATE int read_article NOARGS char *followupto = NULL; /* Followup list */ char *href = NULL; char *p = line; + char *cp; + CONST char *ccp; BOOL done = NO; /* @@ -1009,6 +1015,9 @@ PRIVATE int read_article NOARGS HTmmdecode(subject, subject); HTrjis(subject, subject); } + if (*subject) { + HTAnchor_setSubject(thisanchor, subject); + } } else if (match(full_line, "DATE:")) { StrAllocCopy(date, HTStrip(strchr(full_line,':')+1)); @@ -1044,6 +1053,14 @@ PRIVATE int read_article NOARGS } else if (match(full_line, "FOLLOWUP-TO:")) { StrAllocCopy(followupto, HTStrip(strchr(full_line,':')+1)); + } else if (match(full_line, "MESSAGE-ID:")) { + char * msgid = HTStrip(full_line+11); + if (msgid[0] == '<' && msgid[strlen(msgid)-1] == '>') { + msgid[strlen(msgid)-1] = '\0'; /* Chop > */ + msgid++; /* Chop < */ + HTAnchor_setMessageID(thisanchor, msgid); + } + } /* end if match */ p = line; /* Restart at beginning */ } /* if end of line */ @@ -1064,9 +1081,15 @@ PRIVATE int read_article NOARGS */ if (from || replyto) { char *temp=NULL; - StrAllocCopy(temp, replyto ? replyto : from); + StrAllocCopy(temp, author_address(replyto ? replyto : from)); StrAllocCopy(href,"mailto:"); - StrAllocCat(href, author_address(temp)); + if (strchr(temp, '%') || strchr(temp, '?')) { + cp = HTEscape(temp, URL_XPALPHAS); + StrAllocCat(href, cp); + FREE(cp); + } else { + StrAllocCat(href, temp); + } start_link(href, "made"); PUTC('\n'); FREE(temp); @@ -1097,7 +1120,7 @@ PRIVATE int read_article NOARGS if (from) PUTS(from); else - PUTS(from); + PUTS(replyto); MAYBE_END(HTML_DT); PUTC('\n'); @@ -1146,6 +1169,59 @@ PRIVATE int read_article NOARGS FREE(organization); } + /* sanitize some headers - kw */ + if (newsgroups && + ((cp = strchr(newsgroups, '/')) || + (cp = strchr(newsgroups, '(')))) { + *cp = '\0'; + } + if (newsgroups && !*newsgroups) { + FREE(newsgroups); + } + if (followupto && + ((cp = strchr(followupto, '/')) || + (cp = strchr(followupto, '(')))) { + *cp = '\0'; + } + if (followupto && !*followupto) { + FREE(followupto); + } + + if (newsgroups && HTCanPost) { + START(HTML_DT); + START(HTML_B); + PUTS("Newsgroups:"); + END(HTML_B); + PUTC('\n'); + MAYBE_END(HTML_DT); + START(HTML_DD); + write_anchors(newsgroups); + MAYBE_END(HTML_DD); + PUTC('\n'); + } + + if (followupto && !strcasecomp(followupto, "poster")) { + /* + ** "Followup-To: poster" has special meaning. + ** Don't use it to construct a newsreply link. -kw + */ + START(HTML_DT); + START(HTML_B); + PUTS("Followup to:"); + END(HTML_B); + PUTC(' '); + if (href) { + start_anchor(href); + PUTS("poster"); + END(HTML_A); + } else { + PUTS("poster"); + } + MAYBE_END(HTML_DT); + PUTC('\n'); + FREE(followupto); + } + if (newsgroups && HTCanPost) { /* ** We have permission to POST to this host, @@ -1159,17 +1235,20 @@ PRIVATE int read_article NOARGS StrAllocCat(href, NewsHost); StrAllocCat(href, "/"); StrAllocCat(href, (followupto ? followupto : newsgroups)); - - START(HTML_DT); - START(HTML_B); - PUTS("Newsgroups:"); - END(HTML_B); - PUTC('\n'); - MAYBE_END(HTML_DT); - START(HTML_DD); - write_anchors(newsgroups); - MAYBE_END(HTML_DD); - PUTC('\n'); + if (*href == 'n' && + (ccp = HTAnchor_messageID(thisanchor)) && *ccp) { + StrAllocCat(href, ";ref="); + if (strchr(ccp, '<') || strchr(ccp, '&') || + strchr(ccp, ' ') || strchr(ccp, ':') || + strchr(ccp, '/') || strchr(ccp, '%') || + strchr(ccp, ';')) { + char *cp1 = HTEscape(ccp, URL_XPALPHAS); + StrAllocCat(href, cp1); + FREE(cp1); + } else { + StrAllocCat(href, ccp); + } + } START(HTML_DT); START(HTML_B); @@ -1177,7 +1256,11 @@ PRIVATE int read_article NOARGS END(HTML_B); PUTC(' '); start_anchor(href); - PUTS("newsgroup(s)"); + if (strchr((followupto ? followupto : newsgroups), ',')) { + PUTS("newsgroups"); + } else { + PUTS("newsgroup"); + } END(HTML_A); MAYBE_END(HTML_DT); PUTC('\n'); @@ -1629,11 +1712,11 @@ PRIVATE int read_group ARGS3( before = first; else before = first_required-HTNewsChunkSize; - sprintf(buffer, "%s%s/%d-%d", NewsHREF, groupName, + HTSprintf0(&dbuf, "%s%s/%d-%d", NewsHREF, groupName, before, first_required-1); - CTRACE(tfp, " Block before is %s\n", buffer); + CTRACE(tfp, " Block before is %s\n", dbuf); PUTC('('); - start_anchor(buffer); + start_anchor(dbuf); PUTS(gettext("Earlier articles")); END(HTML_A); PUTS("...)\n"); @@ -1908,13 +1991,13 @@ PRIVATE int read_group ARGS3( int after; /* End of article after */ after = last_required+HTNewsChunkSize; if (after == last) - sprintf(buffer, "%s%s", NewsHREF, groupName); /* original group */ + HTSprintf0(&dbuf, "%s%s", NewsHREF, groupName); /* original group */ else - sprintf(buffer, "%s%s/%d-%d", NewsHREF, groupName, + HTSprintf0(&dbuf, "%s%s/%d-%d", NewsHREF, groupName, last_required+1, after); - CTRACE(tfp, " Block after is %s\n", buffer); + CTRACE(tfp, " Block after is %s\n", dbuf); PUTC('('); - start_anchor(buffer); + start_anchor(dbuf); PUTS(gettext("Later articles")); END(HTML_A); PUTS("...)\n"); @@ -2352,13 +2435,16 @@ PRIVATE int HTLoadNews ARGS4( return HT_NOT_LOADED; } if (status < 0) { - char message[256]; NEWS_NETCLOSE(s); s = -1; CTRACE(tfp, "HTNews: Unable to connect to news host.\n"); if (retries < 1) continue; - sprintf(message, gettext("Could not access %s."), NewsHost); + if (!(post_wanted || reply_wanted || + spost_wanted || sreply_wanted)) { + ABORT_TARGET; + } + HTSprintf0(&dbuf, gettext("Could not access %s."), NewsHost); FREE(NewsHost); FREE(NewsHREF); FREE(ProxyHost); @@ -2368,7 +2454,7 @@ PRIVATE int HTLoadNews ARGS4( HTSYS_remove(postfile); FREE(postfile); } - return HTLoadError(stream, 500, message); + return HTLoadError(stream, 500, dbuf); } else { CTRACE(tfp, "HTNews: Connected to news host %s.\n", NewsHost); @@ -2379,7 +2465,6 @@ PRIVATE int HTLoadNews ARGS4( status); } if (((status = response(NULL)) / 100) != 2) { - char message[BIG]; NEWS_NETCLOSE(s); s = -1; if (status == HT_INTERRUPTED) { @@ -2401,10 +2486,14 @@ PRIVATE int HTLoadNews ARGS4( } if (retries < 1) continue; - sprintf(message, + if (!(post_wanted || reply_wanted || + spost_wanted || sreply_wanted)) { + ABORT_TARGET; + } + HTSprintf0(&dbuf, gettext("Can't read news info. News host %.20s responded: %.200s"), NewsHost, response_text); - return HTLoadError(stream, 500, message); + return HTLoadError(stream, 500, dbuf); } if (status == 200) { HTCanPost = TRUE; @@ -2627,7 +2716,7 @@ Send_NNTP_command: ** Get an article from a news group. - FM */ _HTProgress(gettext("Reading news article.")); - status = read_article(); + status = read_article(anAnchor); } if (status == HT_INTERRUPTED) { _HTProgress(CONNECTION_INTERRUPTED); diff --git a/WWW/Library/Implementation/HTRules.c b/WWW/Library/Implementation/HTRules.c index 1dd5910d..5b3256d0 100644 --- a/WWW/Library/Implementation/HTRules.c +++ b/WWW/Library/Implementation/HTRules.c @@ -38,6 +38,8 @@ typedef struct _rule { char * equiv; } rule; +#ifndef NO_RULES + /* Global variables ** ---------------- */ @@ -400,4 +402,4 @@ int HTLoadRules ARGS1( return 0; /* No error or syntax errors ignored */ } - +#endif /* NO_RULES */ diff --git a/WWW/Library/Implementation/HTRules.h b/WWW/Library/Implementation/HTRules.h index 1eeccbb5..14862b23 100644 --- a/WWW/Library/Implementation/HTRules.h +++ b/WWW/Library/Implementation/HTRules.h @@ -29,6 +29,8 @@ typedef enum _HTRuleOp { HT_Protect } HTRuleOp; +#ifndef NO_RULES + #ifdef SHORT_NAMES #define HTSearchScript HTSearSc #endif /*SHORT_NAMES*/ @@ -141,5 +143,5 @@ extern int HTLoadRules PARAMS((CONST char * filename)); */ - +#endif /* NO_RULES */ #endif /* HTUtils.h */ diff --git a/WWW/Library/Implementation/HTTCP.c b/WWW/Library/Implementation/HTTCP.c index d58b86d4..f34e0fbf 100644 --- a/WWW/Library/Implementation/HTTCP.c +++ b/WWW/Library/Implementation/HTTCP.c @@ -28,7 +28,11 @@ #include <sys/wait.h> #endif /* NSL_FORK */ -#define OK_HOST(p) ((p) != 0 && (p->h_length) != 0) +#ifdef HAVE_RESOLV_H +#include <resolv.h> +#endif + +#define OK_HOST(p) ((p) != 0 && ((p)->h_length) != 0) #ifdef SVR4_BSDSELECT PUBLIC int BSDselect PARAMS(( @@ -368,152 +372,337 @@ PRIVATE void quench ARGS1( } #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; + 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, ","); + } + 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, "}"); + } + } + CTRACE(tfp,"\n"); + fflush(tfp); } - CTRACE(tfp, "HTParseInet: parsing `%s'.\n", str); - if (HTCheckForInterrupt()) { - CTRACE (tfp, "HTParseInet: INTERRUPTED for '%s'.\n", str); - return -1; +} + +/* +** 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 (!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; + } + } } -#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 */ + if (phost->h_name) { + name_len = strlen(phost->h_name); + if (available >= name_len) { + available -= name_len; } else { - struct servent * serv = getservbyname(port, (char*)0); - if (serv) { - soc_in->sin_port = serv->s_port; + 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 { - CTRACE(tfp, "TCP: Unknown service %s\n", port); + break; } -#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; + 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; } - strptr++; } - if (*strptr) { /* found non-numeric, assume domain name */ - dotcount_ip = 0; + } + + ((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; } - /* - ** Parse host number if present. - */ - if (dotcount_ip == 3) { /* Numeric node address: */ + 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 { + ((struct hostent *)rehostent)->h_name = 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_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]); } -#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)) { + *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 (tz@execpc.com) & 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 +713,135 @@ PUBLIC int HTParseInet ARGS2( ** 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) { /* - ** Avoid infinite loop in the face of the unexpected. -BL + ** Return our resulting rehostent through pipe... */ - cycle++; - - FD_ZERO(&readfds); -#ifndef USE_SLANG + write(pfd[1], rehostent, rehostentlen); + _exit(0); + } else { /* - ** 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 + ** ... 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 */ - 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); + cycle++; + + 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 +849,117 @@ PUBLIC int HTParseInet ARGS2( ** 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 == (int) 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 +986,197 @@ PUBLIC int HTParseInet ARGS2( 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 +1189,20 @@ PUBLIC int HTParseInet ARGS2( */ 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,8 +1220,14 @@ failed: #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 ** ------------------------------------------- diff --git a/WWW/Library/Implementation/HTTCP.h b/WWW/Library/Implementation/HTTCP.h index 63fe03aa..0c7e8e61 100644 --- a/WWW/Library/Implementation/HTTCP.h +++ b/WWW/Library/Implementation/HTTCP.h @@ -69,8 +69,34 @@ extern unsigned int HTCardinal PARAMS((int *pstatus, 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 ** --------------------------------------- ** diff --git a/WWW/Library/Implementation/HTTelnet.c b/WWW/Library/Implementation/HTTelnet.c index e82a218b..3ef9b2c1 100644 --- a/WWW/Library/Implementation/HTTelnet.c +++ b/WWW/Library/Implementation/HTTelnet.c @@ -153,7 +153,7 @@ PRIVATE int remote_session ARGS2(char *, acc_method, char *, host) #if defined(NeXT) && defined(NeXTSTEP) && NeXTSTEP<=20100 #define FMT_TELNET "%s%s%s %s %s" - HTAddParam(&command, FMT_TELNET, 1, TELNET_COMMAND); + HTAddParam(&command, FMT_TELNET, 1, TELNET_PATH); HTOptParam(&command, FMT_TELNET, 2, user ? " -l " : ""); HTAddParam(&command, FMT_TELNET, 3, user); HTAddParam(&command, FMT_TELNET, 4, hostname); @@ -175,7 +175,7 @@ PRIVATE int remote_session ARGS2(char *, acc_method, char *, host) if (login_protocol == rlogin) { - HTAddParam(&command, FMT_RLOGIN, 1, RLOGIN_COMMAND); + HTAddParam(&command, FMT_RLOGIN, 1, RLOGIN_PATH); HTAddParam(&command, FMT_RLOGIN, 2, hostname); HTOptParam(&command, FMT_RLOGIN, 3, user ? " -l " : ""); HTAddParam(&command, FMT_RLOGIN, 4, user); @@ -183,14 +183,14 @@ PRIVATE int remote_session ARGS2(char *, acc_method, char *, host) } else if (login_protocol == tn3270) { - HTAddParam(&command, FMT_TN3270, 1, TN3270_COMMAND); + HTAddParam(&command, FMT_TN3270, 1, TN3270_PATH); HTAddParam(&command, FMT_TN3270, 2, hostname); HTAddParam(&command, FMT_TN3270, 3, port); HTEndParam(&command, FMT_TN3270, 3); } else { /* TELNET */ - HTAddParam(&command, FMT_TELNET, 1, TELNET_COMMAND); + HTAddParam(&command, FMT_TELNET, 1, TELNET_PATH); HTAddParam(&command, FMT_TELNET, 2, hostname); HTAddParam(&command, FMT_TELNET, 3, port); HTEndParam(&command, FMT_TELNET, 3); diff --git a/WWW/Library/Implementation/HTUtils.h b/WWW/Library/Implementation/HTUtils.h index 18f6d661..9f209044 100644 --- a/WWW/Library/Implementation/HTUtils.h +++ b/WWW/Library/Implementation/HTUtils.h @@ -333,6 +333,8 @@ are generally not the response status from any specific protocol. #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 */ diff --git a/WWW/Library/Implementation/SGML.c b/WWW/Library/Implementation/SGML.c index d745cf72..8dd191b3 100644 --- a/WWW/Library/Implementation/SGML.c +++ b/WWW/Library/Implementation/SGML.c @@ -504,6 +504,8 @@ PRIVATE void handle_comment ARGS1( strncmp(s, "!--#", 4) == 0 && LYCheckForCSI(context->node_anchor, (char **)&context->url) == TRUE) { LYDoCSI(context->url, s, (char **)&context->csi); + } else { + LYCommentHacks(context->node_anchor, context->string->data); } return; diff --git a/WWW/Library/Implementation/SGML.h b/WWW/Library/Implementation/SGML.h index 860151d5..71bf90bb 100644 --- a/WWW/Library/Implementation/SGML.h +++ b/WWW/Library/Implementation/SGML.h @@ -229,6 +229,7 @@ typedef struct _HTStructuredClass{ */ extern BOOLEAN LYCheckForCSI PARAMS((HTParentAnchor *anchor, char **url)); extern void LYDoCSI PARAMS((char *url, CONST char *comment, char **csi)); +extern BOOLEAN LYCommentHacks PARAMS((HTParentAnchor *anchor, CONST char *comment)); /* diff --git a/WWW/Library/Implementation/tcp.h b/WWW/Library/Implementation/tcp.h index 97f79d7b..7a3d048f 100644 --- a/WWW/Library/Implementation/tcp.h +++ b/WWW/Library/Implementation/tcp.h @@ -53,6 +53,9 @@ Default values #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 |