about summary refs log tree commit diff stats
path: root/WWW/Library/Implementation/HTTCP.c
diff options
context:
space:
mode:
Diffstat (limited to 'WWW/Library/Implementation/HTTCP.c')
-rw-r--r--WWW/Library/Implementation/HTTCP.c399
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;