📄 httcp.c
字号:
/* Generic Communication Code HTTCP.c** ==========================**** This code is in common between client and server sides.**** 16 Jan 92 TBL Fix strtol() undefined on CMU Mach.** 25 Jun 92 JFG Added DECNET option through TCP socket emulation.** 13 Sep 93 MD Added correct return of vmserrorno for HTInetStatus.** Added decoding of vms error message for MULTINET.** 7-DEC-1993 Bjorn S. Nilsson, ALEPH, CERN, VMS UCX ioctl() changes** (done of Mosaic)** 19 Feb 94 Danny Mayer Added Bjorn Fixes to Lynx version** 7 Mar 94 Danny Mayer Added Fix UCX version for full domain name** 20 May 94 Andy Harper Added support for CMU TCP/IP transport** 17 Nov 94 Andy Harper Added support for SOCKETSHR transport** 16 Jul 95 S. Bjorndahl added kluge to deal with LIBCMU bug*/#include <HTUtils.h>#include <HTParse.h>#include <HTAlert.h>#include <HTTCP.h>#include <LYGlobalDefs.h> /* added for no_suspend */#include <LYUtils.h>#ifdef NSL_FORK#include <signal.h>#include <www_wait.h>#endif /* NSL_FORK */#ifdef HAVE_RESOLV_H#include <resolv.h>#endif#ifdef __DJGPP__#include <netdb.h>#endif /* __DJGPP__ */#define OK_HOST(p) ((p) != 0 && ((p)->h_length) != 0)#ifdef SVR4_BSDSELECTPUBLIC int BSDselect PARAMS(( int nfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * select_timeout));#ifdef select#undef select#endif /* select */#define select BSDselect#ifdef SOCKS#ifdef Rselect#undef Rselect#endif /* Rselect */#define Rselect BSDselect#endif /* SOCKS */#endif /* SVR4_BSDSELECT */#include <LYLeaks.h>#ifndef FD_SETSIZE#if defined(UCX) || defined(SOCKETSHR_TCP) || defined(CMU_TCP)#define FD_SETSIZE 32#else#define FD_SETSIZE 256#endif /* Limit # sockets to 32 for UCX, BSN - also SOCKETSHR and CMU, AH */#endif /* FD_SETSIZE *//*** Module-Wide variables*/PRIVATE char *hostname = NULL; /* The name of this host *//*** PUBLIC VARIABLES*/#ifdef SOCKSextern BOOLEAN socks_flag;PUBLIC unsigned long socks_bind_remoteAddr; /* for long Rbind */#endif /* SOCKS *//* PUBLIC SockA HTHostAddress; */ /* The internet address of the host */ /* Valid after call to HTHostName() *//* Encode INET status (as in sys/errno.h) inet_status()** ------------------**** On entry,** where gives a description of what caused the error** global errno gives the error number in the Unix way.**** On return,** returns a negative status in the Unix way.*/#ifdef DECL_SYS_ERRLISTextern char *sys_errlist[]; /* see man perror on cernvax */extern int sys_nerr;#endif /* DECL_SYS_ERRLIST */#ifdef _WINDOWS_NSLchar host[512];struct hostent *phost; /* Pointer to host - See netdb.h */int donelookup;static unsigned long _fork_func (void *arglist){#ifdef SH_EX unsigned long addr; addr = (unsigned long)inet_addr(host); if ((int)addr != -1) phost = gethostbyaddr((char *)&addr, sizeof (addr), AF_INET); else phost = gethostbyname(host);#else phost = gethostbyname(host);#endif donelookup = TRUE; return (unsigned long)(phost);}#endif /* _WINDOWS_NSL */#if defined(VMS) && defined(UCX)/*** A routine to mimic the ioctl function for UCX.** Bjorn S. Nilsson, 25-Nov-1993. Based on an example in the UCX manual.*/#include <HTioctl.h>PUBLIC int HTioctl ARGS3( int, d, int, request, int *, argp){ int sdc, status; unsigned short fun, iosb[4]; char *p5, *p6; struct comm { int command; char *addr; } ioctl_comm; struct it2 { unsigned short len; unsigned short opt; struct comm *addr; } ioctl_desc; if ((sdc = vaxc$get_sdc (d)) == 0) { set_errno(EBADF); return -1; } ioctl_desc.opt = UCX$C_IOCTL; ioctl_desc.len = sizeof(struct comm); ioctl_desc.addr = &ioctl_comm; if (request & IOC_OUT) { fun = IO$_SENSEMODE; p5 = 0; p6 = (char *)&ioctl_desc; } else { fun = IO$_SETMODE; p5 = (char *)&ioctl_desc; p6 = 0; } ioctl_comm.command = request; ioctl_comm.addr = (char *)argp; status = sys$qiow (0, sdc, fun, iosb, 0, 0, 0, 0, 0, 0, p5, p6); if (!(status & 01)) { set_errno(status); return -1; } if (!(iosb[0] & 01)) { set_errno(iosb[0]); return -1; } return 0;}#endif /* VMS && UCX */#define MY_FORMAT "TCP: Error %d in `SOCKET_ERRNO' after call to %s() failed.\n\t%s\n" /* third arg is transport/platform specific *//* Report Internet Error** ---------------------*/PUBLIC int HTInetStatus ARGS1( char *, where){ int status; int saved_errno = errno;#ifdef VMS#ifdef MULTINET SOCKET_ERRNO = vmserrno;#endif /* MULTINET */#endif /* VMS */#ifdef VM CTRACE((tfp, MY_FORMAT, SOCKET_ERRNO, where, "(Error number not translated)")); /* What Is the VM equiv? */#define ER_NO_TRANS_DONE#endif /* VM */#ifdef VMS#ifdef MULTINET CTRACE((tfp, MY_FORMAT, SOCKET_ERRNO, where, vms_errno_string()));#else CTRACE((tfp, MY_FORMAT, SOCKET_ERRNO, where, ((SOCKET_ERRNO > 0 && SOCKET_ERRNO <= 65) ? strerror(SOCKET_ERRNO) : "(Error number not translated)")));#endif /* MULTINET */#define ER_NO_TRANS_DONE#endif /* VMS */#ifdef HAVE_STRERROR CTRACE((tfp, MY_FORMAT, SOCKET_ERRNO, where, strerror(SOCKET_ERRNO)));#define ER_NO_TRANS_DONE#endif /* HAVE_STRERROR */#ifndef ER_NO_TRANS_DONE CTRACE((tfp, MY_FORMAT, SOCKET_ERRNO, where, (SOCKET_ERRNO < sys_nerr ? sys_errlist[SOCKET_ERRNO] : "Unknown error" )));#endif /* !ER_NO_TRANS_DONE */#ifdef VMS#ifndef MULTINET CTRACE((tfp, " Unix error number (SOCKET_ERRNO) = %ld dec\n", SOCKET_ERRNO)); CTRACE((tfp, " VMS error (vaxc$errno) = %lx hex\n", vaxc$errno));#endif /* MULTINET */#endif /* VMS */ set_errno(saved_errno);#ifdef VMS /* ** uerrno and errno happen to be zero if vmserrno <> 0 */#ifdef MULTINET status = -vmserrno;#else status = -vaxc$errno;#endif /* MULTINET */#else status = -SOCKET_ERRNO;#endif /* VMS */ return status;}/* Parse a cardinal value parse_cardinal()** ----------------------**** On entry,** *pp points to first character to be interpreted, terminated by** non 0:9 character.** *pstatus points to status already valid** maxvalue gives the largest allowable value.**** On exit,** *pp points to first unread character** *pstatus points to status updated iff bad*/PUBLIC unsigned int HTCardinal ARGS3( int *, pstatus, char **, pp, unsigned int, max_value){ unsigned int n; if ((**pp<'0') || (**pp>'9')) { /* Null string is error */ *pstatus = -3; /* No number where one expected */ return 0; } n = 0; while ((**pp >= '0') && (**pp <= '9')) n = n*10 + *((*pp)++) - '0'; if (n > max_value) { *pstatus = -4; /* Cardinal outside range */ return 0; } return n;}#ifndef DECNET /* Function only used below for a trace message *//* Produce a string for an Internet address** ----------------------------------------**** On exit,** returns a pointer to a static string which must be copied if** it is to be kept.*/PUBLIC CONST char * HTInetString ARGS1( SockA*, soc_in){#ifdef INET6 static char hostbuf[MAXHOSTNAMELEN]; getnameinfo((struct sockaddr *)soc_in, SOCKADDR_LEN(soc_in), hostbuf, sizeof(hostbuf), NULL, 0, NI_NUMERICHOST); return hostbuf;#else static char string[20]; sprintf(string, "%d.%d.%d.%d", (int)*((unsigned char *)(&soc_in->sin_addr)+0), (int)*((unsigned char *)(&soc_in->sin_addr)+1), (int)*((unsigned char *)(&soc_in->sin_addr)+2), (int)*((unsigned char *)(&soc_in->sin_addr)+3)); return string;#endif /* INET6 */}#endif /* !DECNET *//* Check whether string is a valid Internet hostname - kw** -------------------------------------------------**** Checks whether** - contains only valid chars for domain names (actually, the** restrictions are somewhat relaxed),** - no leading dots or empty segments,** - no segment starts with '-' or '+' [this protects telnet command],** - max. length of dot-separated segment <= 63 (RFC 1034,1035),** - total length <= 254 (if it ends with dot) or 253 (otherwise)** [an interpretation of RFC 1034,1035, although RFC 1123** suggests 255 as limit - kw].**** Note: user (before '@') and port (after ':') components from** host part of URL should be already stripped (if appropriate)** from the input string.**** On exit,** returns 1 if valid, otherwise 0.*/PUBLIC BOOL valid_hostname ARGS1( char *, name){ int i=1, iseg = 0; char *cp = name; if (!(name && *name)) return NO; for (; (*cp && i <= 253); cp++, i++) { if (*cp == '.') { if (iseg == 0) { return NO; } else { iseg = 0; continue; } } else if (iseg == 0 && (*cp == '-' || *cp == '+')) { return NO; } else if (++iseg > 63) { return NO; } if (!isalnum(UCH(*cp)) && *cp != '-' && *cp != '_' && *cp != '$' && *cp != '+') { return NO; } } return (BOOL) (*cp == '\0' || (*cp == '.' && iseg != 0 && cp[1] == '\0'));}#ifdef NSL_FORK/*** Function to allow us to be killed with a normal signal (not** SIGKILL), but don't go through normal libc exit() processing, which** would screw up parent's stdio. -BL*/PRIVATE void quench ARGS1( int, sig GCC_UNUSED){ _exit(2);}#endif /* NSL_FORK */PUBLIC int lynx_nsl_status = HT_OK;#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.**** 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*/PRIVATE void dump_hostent ARGS2( CONST char *, msgprefix, CONST struct hostent *, phost){ 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); }}/*** 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.*/#ifdef NSL_FORK#define REHOSTENT_SIZE 128 /* not bigger than pipe buffer! */typedef struct { struct hostent h; char rest[REHOSTENT_SIZE]; } AlignedHOSTENT;PRIVATE size_t fill_rehostent ARGS3( char *, rehostent, size_t, rehostentsize, CONST struct hostent *, phost){ AlignedHOSTENT *data = (AlignedHOSTENT *)rehostent; 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; } } } 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; } } } 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; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -