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.c246
1 files changed, 142 insertions, 104 deletions
diff --git a/WWW/Library/Implementation/HTTCP.c b/WWW/Library/Implementation/HTTCP.c
index 2eb3b458..76447fe0 100644
--- a/WWW/Library/Implementation/HTTCP.c
+++ b/WWW/Library/Implementation/HTTCP.c
@@ -121,7 +121,7 @@ extern int sys_nerr;
 
 unsigned long _fork_func (void *arglist)
 {
-		  return (unsigned long)(phost = gethostbyname(host));
+    return (unsigned long)(phost = gethostbyname(host));
 }
 #endif /* _WINDOWS_NSL */
 
@@ -324,15 +324,16 @@ PUBLIC int HTParseInet ARGS2(
 {
     char *port;
     int dotcount_ip = 0;	/* for dotted decimal IP addr */
+    int success = 0;
 #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");
 	return -1;
     }
+    CTRACE(tfp, "HTParseInet: parsing `%s'.\n", str);
     if (HTCheckForInterrupt()) {
 	CTRACE (tfp, "HTParseInet: INTERRUPTED for '%s'.\n", str);
 	return -1;
@@ -428,48 +429,120 @@ PUBLIC int HTParseInet ARGS2(
 	*/
 	{
 	    /*
-	    **	Pipe, child pid, and status buffers.
+	    **	Pipe, child pid, status buffers, cycle count, select()
+	    **	control variables.
 	    */
 	    pid_t fpid, waitret = (pid_t)0;
-	    int pfd[2], cstat, cst1 = 0;
+	    int pfd[2], cstat, cst1 = 0, cycle = 0;
+	    fd_set readfds;
+	    struct timeval timeout;
 
 	    pipe(pfd);
 
 	    if ((fpid = fork()) == 0 ) {
+		struct hostent  *phost;	/* Pointer to host - See netdb.h */
 		/*
 		**  Child - for the long call.
+		**  Child won't use read side.  -BL
 		*/
+		close(pfd[0]);
 		phost = gethostbyname(host);
-		cst1 = 0;
+#ifdef MVS
+		CTRACE(tfp, "HTParseInet: gethostbyname() returned %d\n", phost);
+#endif /* MVS */
+
 		/*
-		**  Return value (or nulls).
+		**  Send length of subsequent value to parent (as a
+		**  native int).
 		*/
-		if (OK_HOST(phost)) {
+		if (OK_HOST(phost))
+			cstat = phost->h_length;
+		else
+			cstat = 0;
+		write(pfd[1], &cstat, sizeof cstat);
+
+		if (cstat) {
+		    /*
+		    **  Return value through pipe...
+		    */
 		    write(pfd[1], phost->h_addr, phost->h_length);
 		    _exit(0);
 		} else {
-		    write(pfd[1], &cst1, 4);
-		    _exit(1);	/* return an error code */
+		    /*
+		    **  ... or return error as exit code.
+		    */
+		    _exit(1);
 		}
 	    }
 
 	    /*
-	    **	(parent) Wait until lookup finishes, or interrupt.
+	    **	(parent) Wait until lookup finishes, or interrupt,
+	    **	or cycled too many times (just in case) -BL
 	    */
-	    cstat = 0;
-	    while (cstat <= 0) {
+
+	    close(pfd[1]);      /* parent won't use write side -BL */
+
+	    while (cycle < 50) {
+		/*
+		**  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 */
+
 		/*
-		**  Exit when data sent.
+		**  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
 		*/
-		IOCTL(pfd[0], FIONREAD, &cstat);
-		if (cstat > 0)
+#ifdef SOCKS
+		if (socks_flag)
+		    cst1 = Rselect(pfd[0] + 1, (void *)&readfds, NULL, NULL, &timeout);
+		else
+#endif /* SOCKS */
+		    cst1 = select(pfd[0] + 1, (void *)&readfds, NULL, NULL, &timeout);
+
+		if ((cst1 > 0) && FD_ISSET(pfd[0], &readfds)) {
+		    /*
+		    **	First get length of address.  -BL
+		    */
+		    cst1 = read(pfd[0], (void *)&cstat, sizeof cstat);
+		    if (cstat == sizeof soc_in->sin_addr) {
+			/*
+			**  Then get address itself.  -BL
+			*/
+			cst1 = read(pfd[0], (void *)&soc_in->sin_addr, cstat);
+			if (cst1 == cstat) success = 1;
+	    	    }
+		    /*
+		    **  Make sure child is cleaned up.  -BL
+		    */
+		    waitret = waitpid(fpid, &cst1, WNOHANG);
+		    if (!WIFEXITED(cst1) && !WIFSIGNALED(cst1)) {
+			kill(fpid, SIGKILL);
+			waitret = waitpid(fpid, &cst1, WNOHANG);
+		    }
 		    break;
+	    	}
+
 		/*
-		**  Exit if child exited.
+		**  End loop if child exited.
 		*/
-		if ((waitret = waitpid(fpid, &cst1, WNOHANG)) > 0) {
+		if ((waitret = waitpid(fpid, &cst1, WNOHANG)) > 0)
 		    break;
-		}
+
 		/*
 		**  Abort if interrupt key pressed.
 		*/
@@ -479,83 +552,43 @@ PUBLIC int HTParseInet ARGS2(
 		    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) {
 		waitret = waitpid(fpid, &cst1, WNOHANG);
 	    }
-	    if (WIFEXITED(cst1)) {
-		CTRACE(tfp, "HTParseInet: NSL_FORK child %d exited, status 0x%x.\n",
-			    (int)waitret, cst1);
-	    } else if (WIFSIGNALED(cst1)) {
-		CTRACE(tfp, "HTParseInet: NSL_FORK child %d got signal, status 0x%x!\n",
-			    (int)waitret, cst1);
+	    if (waitret > 0) {
+		if (WIFEXITED(cst1)) {
+		    CTRACE(tfp, "HTParseInet: NSL_FORK child %d exited, status 0x%x.\n",
+				(int)waitret, cst1);
+		} else if (WIFSIGNALED(cst1)) {
+		    CTRACE(tfp, "HTParseInet: NSL_FORK child %d got signal, status 0x%x!\n",
+				(int)waitret, cst1);
 #ifdef WCOREDUMP
-		if (WCOREDUMP(cst1)) {
-		    CTRACE(tfp, "HTParseInet: NSL_FORK child %d dumped core!\n",
-				(int)waitret);
+		    if (WCOREDUMP(cst1)) {
+			CTRACE(tfp, "HTParseInet: NSL_FORK child %d dumped core!\n",
+				    (int)waitret);
 		    }
 #endif /* WCOREDUMP */
-	    } else if (WIFSTOPPED(cst1)) {
-		CTRACE(tfp, "HTParseInet: NSL_FORK child %d is stopped, status 0x%x!\n",
-			    (int)waitret, cst1);
-	    }
-	    /*
-	    **	Read as much as we can - should be the address.
-	    */
-	    IOCTL(pfd[0], FIONREAD, &cstat);
-	    if (cstat < 4) {
-		CTRACE(tfp, "HTParseInet: NSL_FORK child returns only %d bytes.\n",
-			    cstat);
-		CTRACE(tfp, "             Trying again without forking.\n");
-		phost = gethostbyname(host);	/* See netdb.h */
-		if (!OK_HOST(phost)) {
-		    CTRACE(tfp, "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);
+		} else if (WIFSTOPPED(cst1)) {
+		    CTRACE(tfp, "HTParseInet: NSL_FORK child %d is stopped, status 0x%x!\n",
+				(int)waitret, cst1);
 		}
-#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) {
-	    CTRACE(tfp, "HTParseInet: Can't find internet node name `%s'.\n",
-			host);
-#ifndef _WINDOWS_NSL
-	    FREE(host);
-#endif /* _WINDOWS_NSL */
-	    return -1;
+	    if (!success) {
+		memset((void *)&soc_in->sin_addr, 0, sizeof(soc_in->sin_addr));
+		goto failed;
+	    }
 	}
-#ifndef _WINDOWS_NSL
-	FREE(host);
-#endif /* _WINDOWS_NSL */
-#ifdef MVS
-	CTRACE(tfp, "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) {
-	    CTRACE(tfp, "HTTPAccess: Can't find internet node name `%s'.\n",host);
-	    return -1;  /* Fail? */
+	    goto failed;
 	}
-#else
+#else /* !NSL_FORK, !DJGPP: */
 #ifdef _WINDOWS_NSL
 	{
 #ifdef __BORLANDC__
@@ -585,38 +618,35 @@ PUBLIC int HTParseInet ARGS2(
 			  return HT_INTERRUPTED;
 			};
 	};
-#else /* !_WINDOWS_NSL */
-	phost = gethostbyname(host);	/* See netdb.h */
-#endif /* _WINDOWS_NSL */
+#else /* !NSL_FORK, !DJGPP, !_WINDOWS_NSL: */
+	{
+	    struct hostent  *phost;
+	    phost = gethostbyname(host);	/* See netdb.h */
 #ifdef MVS
-	CTRACE(tfp, "HTParseInet: gethostbyname() returned %d\n", phost);
+	    CTRACE(tfp, "HTParseInet: gethostbyname() returned %d\n", phost);
 #endif /* MVS */
-	if (!phost) {
-	    CTRACE(tfp, "HTParseInet: Can't find internet node name `%s'.\n",
-			host);
-#ifndef _WINDOWS_NSL
-	    FREE(host);
-#endif /* _WINDOWS_NSL */
-	    return -1;	/* Fail? */
+	    if (!phost) goto failed;
+#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);
+#else
+	    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 */
-#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);
-#else
-	memcpy((void *)&soc_in->sin_addr, phost->h_addr, phost->h_length);
-#endif /* VMS && CMU_TCP */
-#endif /* DJGPP */
-#endif /* NSL_FORK */
+
     }
 
     CTRACE(tfp, "HTParseInet: Parsed address as port %d, IP address %d.%d.%d.%d\n",
@@ -628,6 +658,14 @@ PUBLIC int HTParseInet ARGS2(
 #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