diff options
Diffstat (limited to 'WWW/Library/Implementation/HTTCP.c')
-rw-r--r-- | WWW/Library/Implementation/HTTCP.c | 399 |
1 files changed, 172 insertions, 227 deletions
diff --git a/WWW/Library/Implementation/HTTCP.c b/WWW/Library/Implementation/HTTCP.c index ba4a4b0f..56243a70 100644 --- a/WWW/Library/Implementation/HTTCP.c +++ b/WWW/Library/Implementation/HTTCP.c @@ -17,18 +17,20 @@ */ #include <HTUtils.h> +#include <tcp.h> /* Defines SHORT_NAMES if necessary */ #include <HTAccess.h> #include <HTParse.h> #include <HTAlert.h> #include <HTTCP.h> -#include <LYUtils.h> #ifdef NSL_FORK #include <signal.h> #include <sys/wait.h> #endif /* NSL_FORK */ -#define OK_HOST(p) ((p) != 0 && (p->h_length) != 0) +#define FREE(x) if (x) {free(x); x = NULL;} + +extern int HTCheckForInterrupt NOPARAMS; #ifdef SVR4_BSDSELECT PUBLIC int BSDselect PARAMS(( @@ -117,14 +119,11 @@ extern int sys_nerr; #ifdef _WINDOWS_NSL char host[512]; - struct hostent *phost; /* Pointer to host - See netdb.h */ - int donelookup; + struct hostent *phost; /* Pointer to host - See netdb.h */ unsigned long _fork_func (void *arglist) { - phost = gethostbyname(host); - donelookup = TRUE; - return (unsigned long)(phost); + return (unsigned long)(phost = gethostbyname(host)); } #endif /* _WINDOWS_NSL */ @@ -309,19 +308,6 @@ PUBLIC CONST char * HTInetString ARGS1( } #endif /* !DECNET */ -#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 */ - /* Parse a network node address and port ** ------------------------------------- ** @@ -342,15 +328,19 @@ PUBLIC int HTParseInet ARGS2( int dotcount_ip = 0; /* for dotted decimal IP addr */ #ifndef _WINDOWS_NSL char *host = NULL; + struct hostent *phost; /* Pointer to host - See netdb.h */ #endif /* _WINDOWS_NSL */ if (!str) { - CTRACE(tfp, "HTParseInet: Can't parse `NULL'.\n"); + if (TRACE) { + fprintf(stderr, "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); + if (TRACE) { + fprintf (stderr, "HTParseInet: INTERRUPTED for '%s'.\n", str); + } return -1; } #ifdef _WINDOWS_NSL @@ -378,8 +368,8 @@ PUBLIC int HTParseInet ARGS2( 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); + } else if (TRACE) { + fprintf(stderr, "TCP: Unknown service %s\n", port); } #endif /* SUPPRESS */ } @@ -392,8 +382,11 @@ PUBLIC int HTParseInet ARGS2( */ 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", + if (TRACE) { + fprintf(stderr, + "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: */ @@ -434,7 +427,10 @@ PUBLIC int HTParseInet ARGS2( #endif /* _WINDOWS_NSL */ } else { /* Alphanumeric node name: */ #ifdef MVS /* Outstanding problem with crash in MVS gethostbyname */ - CTRACE(tfp, "HTParseInet: Calling gethostbyname(%s)\n", host); + if (TRACE) { + fprintf(stderr, + "HTParseInet: Calling gethostbyname(%s)\n", host); + } #endif /* MVS */ #ifdef NSL_FORK @@ -443,208 +439,160 @@ PUBLIC int HTParseInet ARGS2( ** checks for interrupts. - Tom Zerucha (tz@execpc.com) & FM */ { - int success = 0; /* - ** Pipe, child pid, status buffers, cycle count, select() - ** control variables. + ** Pipe, child pid, and status buffers. */ - 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; - - /* - ** Reap any children that have terminated since last time - ** through. This might include children that we killed, - ** then waited with WNOHANG before they were actually ready - ** to be reaped. (Should be max of 1 in this state, but - ** the loop is safe if waitpid() is implemented correctly: - ** 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; + pid_t fpid, waitret = (pid_t)0; + int pfd[2], cstat, cst1 = 0; pipe(pfd); 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); - - /* - ** Child won't use read side. -BL */ - close(pfd[0]); phost = gethostbyname(host); -#ifdef MVS - CTRACE(tfp, "HTParseInet: gethostbyname() returned %d\n", phost); -#endif /* MVS */ - + cst1 = 0; /* - ** Send length of subsequent value to parent (as a - ** native int). + ** Return value (or nulls). */ - 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... - */ + if (phost != NULL) write(pfd[1], phost->h_addr, phost->h_length); - _exit(0); - } else { - /* - ** ... or return error as exit code. - */ - _exit(1); - } + else + write(pfd[1], &cst1, 4); + /* + ** Return an error code. + */ + _exit(phost == NULL); } /* - ** (parent) Wait until lookup finishes, or interrupt, - ** or cycled too many times (just in case) -BL + ** (parent) Wait until lookup finishes, or interrupt. */ - - 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++; - - timeout.tv_sec = 1; - timeout.tv_usec = 0; - FD_ZERO(&readfds); - FD_SET(pfd[0], &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 - */ - FD_SET(0, &readfds); /* stdin -BL */ -#endif /* USE_SLANG */ - + cstat = 0; + while (cstat <= 0) { /* - ** Return when data received, interrupted, or failed. - ** If nothing is waiting, we sleep for 1 second in - ** select(), to be nice to the system. -BL + ** Exit when data sent. */ -#ifdef SOCKS - 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); - - 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) { - /* - ** Then get address itself. -BL - */ - readret = read(pfd[0], (void *)&soc_in->sin_addr, h_length); - if (readret == h_length) success = 1; - } - /* - ** 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); - } + IOCTL(pfd[0], FIONREAD, &cstat); + if (cstat > 0) break; - } - /* - ** Clean up if child exited before & no data received. -BL + ** Exit if child exited. */ - if (child_exited) { - waitret = waitpid(fpid, &waitstat, WNOHANG); + if ((waitret = waitpid(fpid, &cst1, WNOHANG)) > 0) { 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; - } - - /* ** Abort if interrupt key pressed. */ if (HTCheckForInterrupt()) { - CTRACE(tfp, "HTParseInet: INTERRUPTED gethostbyname.\n"); - kill(fpid, SIGTERM); - waitpid(fpid, NULL, WNOHANG); + if (TRACE) { + fprintf(stderr, + "HTParseInet: INTERRUPTED gethostbyname.\n"); + } + kill(fpid , SIGKILL); + waitpid(fpid, NULL, 0); FREE(host); close(pfd[0]); + close(pfd[1]); return HT_INTERRUPTED; } + /* + ** Be nice to the system. + */ + sleep(1); } - close(pfd[0]); if (waitret <= 0) { - kill(fpid, SIGTERM); - waitret = waitpid(fpid, &waitstat, WNOHANG); + waitret = waitpid(fpid, &cst1, WNOHANG); } - 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); + if (TRACE) { + if (WIFEXITED(cst1)) { + fprintf(stderr, + "HTParseInet: NSL_FORK child %d exited, status 0x%x.\n", + (int)waitret, cst1); + } else if (WIFSIGNALED(cst1)) { + fprintf(stderr, + "HTParseInet: NSL_FORK child %d got signal, status 0x%x!\n", + (int)waitret, cst1); #ifdef WCOREDUMP - if (WCOREDUMP(waitstat)) { - CTRACE(tfp, "HTParseInet: NSL_FORK child %d dumped core!\n", - (int)waitret); + if (WCOREDUMP(cst1)) { + fprintf(stderr, + "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); + } else if (WIFSTOPPED(cst1)) { + fprintf(stderr, + "HTParseInet: NSL_FORK child %d is stopped, status 0x%x!\n", + (int)waitret, cst1); } } - if (!success) { - memset((void *)&soc_in->sin_addr, 0, sizeof(soc_in->sin_addr)); - goto failed; + /* + ** Read as much as we can - should be the address. + */ + IOCTL(pfd[0], FIONREAD, &cstat); + if (cstat < 4) { + if (TRACE) { + fprintf(stderr, + "HTParseInet: NSL_FORK child returns only %d bytes.\n", + cstat); + fprintf(stderr, + " Trying again without forking.\n"); + } + phost = gethostbyname(host); /* See netdb.h */ + if (!phost) { + if (TRACE) { + fprintf(stderr, + "HTParseInet: Can't find internet node name `%s'.\n", + host); + } + memset((void *)&soc_in->sin_addr, 0, sizeof(soc_in->sin_addr)); + } else { + memcpy((void *)&soc_in->sin_addr, + phost->h_addr, phost->h_length); + } +#ifdef NOTDEFINED + cstat = read(pfd[0], (void *)&soc_in->sin_addr , 4); +#endif /* NOTDEFINED */ + } else { + cstat = read(pfd[0], (void *)&soc_in->sin_addr , cstat); } + close(pfd[0]); + close(pfd[1]); } + if (soc_in->sin_addr.s_addr == 0) { + if (TRACE) { + fprintf(stderr, + "HTParseInet: Can't find internet node name `%s'.\n", + host); + } +#ifndef _WINDOWS_NSL + FREE(host); +#endif /* _WINDOWS_NSL */ + return -1; + } +#ifndef _WINDOWS_NSL + FREE(host); +#endif /* _WINDOWS_NSL */ +#ifdef MVS + if (TRACE) { + fprintf(stderr, + "HTParseInet: gethostbyname() returned %d\n", phost); + } +#endif /* MVS */ + #else /* Not NSL_FORK: */ #ifdef DJGPP soc_in->sin_addr.s_addr = htonl(resolve(host)); + FREE(host); if (soc_in->sin_addr.s_addr == 0) { - goto failed; + if (TRACE) + fprintf(stderr, + "HTTPAccess: Can't find internet node name `%s'.\n",host); + return -1; /* Fail? */ } -#else /* !NSL_FORK, !DJGPP: */ +#else #ifdef _WINDOWS_NSL { #ifdef __BORLANDC__ @@ -663,9 +611,7 @@ PUBLIC int HTParseInet ARGS2( if (!hThread) MessageBox((void *)NULL, "CreateThread", "CreateThread Failed", 0L); - - donelookup = FALSE; - while (!donelookup) + while (!phost) if (HTCheckForInterrupt()) { /* Note that host is a character array and is not freed */ @@ -676,56 +622,54 @@ PUBLIC int HTParseInet ARGS2( return HT_INTERRUPTED; }; }; - if (!phost) goto failed; - memcpy((void *)&soc_in->sin_addr, phost->h_addr, phost->h_length); -#else /* !NSL_FORK, !DJGPP, !_WINDOWS_NSL: */ - { - struct hostent *phost; - phost = gethostbyname(host); /* See netdb.h */ +#else /* !_WINDOWS_NSL */ + phost = gethostbyname(host); /* See netdb.h */ +#endif /* _WINDOWS_NSL */ #ifdef MVS - CTRACE(tfp, "HTParseInet: gethostbyname() returned %d\n", phost); + if (TRACE) { + fprintf(stderr, + "HTParseInet: gethostbyname() returned %d\n", phost); + } #endif /* MVS */ - if (!phost) goto failed; + if (!phost) { + if (TRACE) { + fprintf(stderr, + "HTParseInet: Can't find internet node name `%s'.\n", + host); + } + FREE(host); + return -1; /* Fail? */ + } + FREE(host); #if defined(VMS) && defined(CMU_TCP) - /* - ** In LIBCMU, phost->h_length contains not the length of one address - ** (four bytes) but the number of bytes in *h_addr, i.e. some multiple - ** of four. Thus we need to hard code the value here, and remember to - ** change it if/when IP addresses change in size. :-( LIBCMU is no - ** longer supported, and CMU users are encouraged to obtain and use - ** SOCKETSHR/NETLIB instead. - S. Bjorndahl - */ - memcpy((void *)&soc_in->sin_addr, phost->h_addr, 4); + /* + ** In LIBCMU, phost->h_length contains not the length of one address + ** (four bytes) but the number of bytes in *h_addr, i.e. some multiple + ** of four. Thus we need to hard code the value here, and remember to + ** change it if/when IP addresses change in size. :-( LIBCMU is no + ** longer supported, and CMU users are encouraged to obtain and use + ** SOCKETSHR/NETLIB instead. - S. Bjorndahl + */ + memcpy((void *)&soc_in->sin_addr, phost->h_addr, 4); #else - memcpy((void *)&soc_in->sin_addr, phost->h_addr, phost->h_length); + 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 */ -#ifndef _WINDOWS_NSL - FREE(host); -#endif /* _WINDOWS_NSL */ - +#endif /* DJGPP */ +#endif /* NSL_FORK */ } - CTRACE(tfp, "HTParseInet: Parsed address as port %d, IP address %d.%d.%d.%d\n", + if (TRACE) { + fprintf(stderr, + "HTParseInet: Parsed address as port %d, IP address %d.%d.%d.%d\n", (int)ntohs(soc_in->sin_port), (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)); + } #endif /* Internet vs. Decnet */ return 0; /* OK */ - -failed: - CTRACE(tfp, "HTParseInet: Can't find internet node name `%s'.\n", - host); -#ifndef _WINDOWS_NSL - FREE(host); -#endif /* _WINDOWS_NSL */ - return -1; } /* Free our name for the host on which we are - FM @@ -779,15 +723,16 @@ PRIVATE void get_host_details NOARGS #ifndef DECNET /* Decnet ain't got no damn name server 8#OO */ #ifdef NEED_HOST_ADDRESS /* no -- needs name server! */ phost = gethostbyname(name); /* See netdb.h */ - if (!OK_HOST(phost)) { - CTRACE(tfp, "TCP: Can't find my own internet node address for `%s'!!\n", - name); + if (!phost) { + if (TRACE) fprintf(stderr, + "TCP: Can't find my own internet node address for `%s'!!\n", + name); return; /* Fail! */ } StrAllocCopy(hostname, phost->h_name); memcpy(&HTHostAddress, &phost->h_addr, phost->h_length); - CTRACE(tfp, " Name server says that I am `%s' = %s\n", - hostname, HTInetString(&HTHostAddress)); + if (TRACE) fprintf(stderr, " Name server says that I am `%s' = %s\n", + hostname, HTInetString(&HTHostAddress)); #endif /* NEED_HOST_ADDRESS */ #endif /* !DECNET */ @@ -821,7 +766,6 @@ PUBLIC int HTDoConnect ARGS4( /* ** Set up defaults. */ - memset(soc_in, 0, sizeof(*soc_in)); soc_in->sin_family = AF_INET; soc_in->sin_port = htons(default_port); @@ -1046,7 +990,8 @@ PUBLIC int HTDoConnect ARGS4( } } if (HTCheckForInterrupt()) { - CTRACE(tfp, "*** INTERRUPTED in middle of connect.\n"); + if (TRACE) + fprintf(stderr, "*** INTERRUPTED in middle of connect.\n"); status = HT_INTERRUPTED; SOCKET_ERRNO = EINTR; break; |