---------------------
PatchSet 8583 
Date: 2006/09/01 19:21:07
Author: serassio
Branch: nt
Tag: (none) 
Log:
Split Windows IPC code into ipc_win32.c

Members: 
	src/Makefile.am:1.34.2.11->1.34.2.12 
	src/ipc.c:1.11.2.6->1.11.2.7 
	src/ipc_win32.c:1.1->1.1.2.1 

Index: squid/src/Makefile.am
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/Makefile.am,v
retrieving revision 1.34.2.11
retrieving revision 1.34.2.12
diff -u -r1.34.2.11 -r1.34.2.12
--- squid/src/Makefile.am	19 Aug 2006 08:43:38 -0000	1.34.2.11
+++ squid/src/Makefile.am	1 Sep 2006 19:21:07 -0000	1.34.2.12
@@ -66,8 +66,10 @@
 
 if ENABLE_MINGW32SPECIFIC
 MINGWEXLIB = -lmingwex
+IPC_SOURCE = ipc_win32.c
 else
 MINGWEXLIB =
+IPC_SOURCE = ipc.c
 endif
 
 if USE_POLL
@@ -181,7 +183,7 @@
 	icp_v3.c \
 	ident.c \
 	internal.c \
-	ipc.c \
+	$(IPC_SOURCE) \
 	ipcache.c \
 	$(LEAKFINDERSOURCE) \
 	locrewrite.c \
Index: squid/src/ipc.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/ipc.c,v
retrieving revision 1.11.2.6
retrieving revision 1.11.2.7
diff -u -r1.11.2.6 -r1.11.2.7
--- squid/src/ipc.c	31 Jul 2006 10:21:59 -0000	1.11.2.6
+++ squid/src/ipc.c	1 Sep 2006 19:21:07 -0000	1.11.2.7
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ipc.c,v 1.11.2.6 2006/07/31 10:21:59 serassio Exp $
+ * $Id: ipc.c,v 1.11.2.7 2006/09/01 19:21:07 serassio Exp $
  *
  * DEBUG: section 54    Interprocess Communication
  * AUTHOR: Duane Wessels
@@ -35,39 +35,6 @@
 
 #include "squid.h"
 
-#ifdef _SQUID_MSWIN_
-#ifndef _MSWSOCK_
-#include <mswsock.h>
-#endif
-#include <process.h>
-
-struct ipc_params
-{
-    int type;
-    int crfd;
-    int cwfd;
-    struct sockaddr_in PS;
-    const char *prog;
-    char **args;
-};
-
-struct thread_params
-{
-    int type;
-    int rfd;
-    int send_fd;
-    const char *prog;
-    pid_t pid;
-};
-
-static int __stdcall ipc_thread_1(struct ipc_params *params);
-static int __stdcall ipc_thread_2(struct thread_params *params);
-
-static const char *ok_string = "OK\n";
-static const char *err_string = "ERR\n";
-static const char *shutdown_string = "$shutdown\n";
-#endif
-
 static const char *hello_string = "hi there\n";
 #define HELLO_BUF_SZ 32
 static char hello_buf[HELLO_BUF_SZ];
@@ -89,19 +56,8 @@
 }
 
 int
-#ifdef _SQUID_MSWIN_
-ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, HANDLE * hIpc, pid_t * ppid)
-#else
 ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd)
-#endif
 {
-#ifdef _SQUID_MSWIN_
-    unsigned long thread;
-    struct ipc_params params;
-    int opt;
-    int optlen = sizeof(opt);
-    DWORD ecode = 0;
-#endif
     pid_t pid;
     struct sockaddr_in CS;
     struct sockaddr_in PS;
@@ -109,15 +65,13 @@
     int prfd = -1;
     int cwfd = -1;
     int pwfd = -1;
-    socklen_t len;
-#ifndef _SQUID_MSWIN_
     int fd;
     int t1, t2, t3;
+    socklen_t len;
     int tmp_s;
 #if HAVE_PUTENV
     char *env_str;
 #endif
-#endif
     int x;
 
 #if HAVE_POLL && defined(_SQUID_OSF_)
@@ -130,18 +84,6 @@
 	*rfd = -1;
     if (wfd)
 	*wfd = -1;
-#ifdef _SQUID_MSWIN_
-    if (hIpc)
-	*hIpc = NULL;
-    if (ppid)
-	*ppid = -1;
-
-    if (WIN32_OS_version !=_WIN_OS_WINNT) {
-        getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen);
-        opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT);
-        setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, sizeof(opt));
-    }
-#endif
     if (type == IPC_TCP_SOCKET) {
 	crfd = cwfd = comm_open(SOCK_STREAM,
 	    IPPROTO_TCP,
@@ -169,12 +111,6 @@
 	    0,
 	    name);
     } else if (type == IPC_FIFO) {
-#ifdef _SQUID_MSWIN_
-	debug(54, 0)
-	    ("ipcCreate: %s: use IPC_TCP_SOCKET instead of IP_FIFO on Windows\n",
-	    prog);
-	assert(0);
-#else
 	int p2c[2];
 	int c2p[2];
 	if (pipe(p2c) < 0) {
@@ -189,7 +125,6 @@
 	fd_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write");
 	fd_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read");
 	fd_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write");
-#endif
 #if HAVE_SOCKETPAIR && defined(AF_UNIX)
     } else if (type == IPC_UNIX_STREAM) {
 	int fds[2];
@@ -221,14 +156,6 @@
     debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd);
     debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd);
 
-#ifdef _SQUID_MSWIN_
-    if (WIN32_OS_version !=_WIN_OS_WINNT) {
-        getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen);
-        opt = opt | SO_SYNCHRONOUS_NONALERT;
-        setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen);
-    }
-#endif
-
     if (crfd < 0) {
 	debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
 	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
@@ -264,25 +191,10 @@
     }
     /* flush or else we get dup data if unbuffered_logs is set */
     logsFlush();
-#ifdef _SQUID_MSWIN_
-    params.type = type;
-    params.crfd = crfd;
-    params.cwfd = cwfd;
-    params.PS = PS;
-    params.prog = prog;
-    params.args = (char **) args;
-
-    thread = _beginthreadex(NULL, 0, ipc_thread_1, &params, 0, NULL);
-
-    if (thread == 0) {
-	debug(54, 1) ("ipcCreate: _beginthread: %s\n", xstrerror());
-#else
     if ((pid = fork()) < 0) {
 	debug(54, 1) ("ipcCreate: fork: %s\n", xstrerror());
-#endif
 	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
     }
-#ifndef _SQUID_MSWIN_
     if (pid > 0) {		/* parent */
 	/* close shared socket with child */
 	comm_close(crfd);
@@ -290,74 +202,24 @@
 	    comm_close(cwfd);
 	cwfd = crfd = -1;
 	if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
-#else
-    {
-	{
-#endif
 	    if (comm_connect_addr(pwfd, &CS) == COMM_ERROR)
-#ifdef _SQUID_MSWIN_
-            {
-                CloseHandle((HANDLE)thread);
-                return ipcCloseAllFD(prfd, pwfd, -1, -1);
-            }
-#else
 		return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
-#endif
 	}
 	memset(hello_buf, '\0', HELLO_BUF_SZ);
-#ifdef _SQUID_MSWIN_
-	x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
-#else
 	if (type == IPC_UDP_SOCKET)
 	    x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
 	else
 	    x = read(prfd, hello_buf, HELLO_BUF_SZ - 1);
-#endif
 	if (x < 0) {
 	    debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
 	    debug(54, 0) ("--> read: %s\n", xstrerror());
-#ifdef _SQUID_MSWIN_
-            CloseHandle((HANDLE)thread);
-            return ipcCloseAllFD(prfd, pwfd, -1, -1);
-#else
 	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
-#endif
 	} else if (strcmp(hello_buf, hello_string)) {
 	    debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
 	    debug(54, 0) ("--> read returned %d\n", x);
 	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
-#ifdef _SQUID_MSWIN_
-            CloseHandle((HANDLE)thread);
-            return ipcCloseAllFD(prfd, pwfd, -1, -1);
-#else
 	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
-#endif
 	}
-#ifdef _SQUID_MSWIN_
-	x = send(pwfd, ok_string, strlen(ok_string), 0);
-	if (x < 0) {
-	    debug(54, 0) ("ipcCreate: PARENT: OK write test failed\n");
-	    debug(54, 0) ("--> read: %s\n", xstrerror());
-            CloseHandle((HANDLE)thread);
-            return ipcCloseAllFD(prfd, pwfd, -1, -1);
-	}
-	memset(hello_buf, '\0', HELLO_BUF_SZ);
-	x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
-	if (x < 0) {
-	    debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
-	    debug(54, 0) ("--> read: %s\n", xstrerror());
-            CloseHandle((HANDLE)thread);
-            return ipcCloseAllFD(prfd, pwfd, -1, -1);
-	} else if (!strcmp(hello_buf, err_string)) {
-	    debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
-	    debug(54, 0) ("--> read returned %d\n", x);
-	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
-            CloseHandle((HANDLE)thread);
-            return ipcCloseAllFD(prfd, pwfd, -1, -1);
-	}
-	hello_buf[x] = '\0';
-	pid = atol(hello_buf);
-#endif
 	commSetTimeout(prfd, -1, NULL, NULL);
 	commSetNonBlocking(prfd);
 	commSetNonBlocking(pwfd);
@@ -367,90 +229,12 @@
 	    *rfd = prfd;
 	if (wfd)
 	    *wfd = pwfd;
-#ifdef _SQUID_MSWIN_
-	fd_table[prfd].flags.ipc = 1;
-	fd_table[pwfd].flags.ipc = 1;
-	fd_table[crfd].flags.ipc = 1;
-	fd_table[cwfd].flags.ipc = 1;
-	if (Config.sleep_after_fork) {
-	    /* XXX emulation of usleep() */
-	    DWORD sl;
-	    sl = Config.sleep_after_fork / 1000;
-	    if (sl == 0)
-                    sl = 1;
-	    Sleep(sl);
-	}
-	if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) {
-	    if (hIpc)
-		*hIpc = (HANDLE) thread;
-	    if (ppid)
-		*ppid = pid;
-	    return pwfd;
-        } else {
-            CloseHandle((HANDLE)thread);
-            return ipcCloseAllFD(prfd, pwfd, -1, -1);
-        }
-#else
 	fd_table[prfd].flags.ipc = 1;
 	fd_table[pwfd].flags.ipc = 1;
 	if (Config.sleep_after_fork)
 	    xusleep(Config.sleep_after_fork);
 	return pid;
-#endif
-    }
-#ifdef _SQUID_MSWIN_
-}
-
-static int
-ipcSend(int cwfd, const char *buf, int len)
-{
-    int x;
-
-    x = send(cwfd, buf, len, 0);
-    if (x < 0) {
-	debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
-	debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n");
     }
-    return x;
-}
-
-static int __stdcall
-ipc_thread_1(struct ipc_params *params)
-{
-    int retval = -1;
-    int t1, t2, t3;
-    int p2c[2] = { -1, -1 };
-    int c2p[2] = { -1, -1 };
-    HANDLE hProcess = NULL;
-    pid_t pid;
-    HANDLE thread = NULL;
-    struct thread_params thread_params;
-    int fd;
-    char *str;
-    int tmp_s;
-#if HAVE_PUTENV
-    char *env_str = NULL;
-#endif
-    int x;
-    int type = params->type;
-    int crfd = params->crfd;
-    int cwfd = params->cwfd;
-    int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1;
-    char *prog = NULL;
-    char **args = params->args;
-    struct sockaddr_in PS = params->PS;
-    struct sockaddr_in CS_ipc, PS_ipc;
-    char *buf1 = NULL;
-
-    buf1 = xcalloc(1, 8192);
-    strcpy(buf1, params->prog);
-    prog = strtok(buf1, w_space);
-    if ((str = strrchr(prog, '/')))
-	prog = ++str;
-    if ((str = strrchr(prog, '\\')))
-	prog = ++str;
-    prog = xstrdup(prog);
-#else
     /* child */
     no_suid();			/* give up extra priviliges */
     /* close shared socket with parent */
@@ -458,49 +242,25 @@
     if (pwfd != prfd)
 	close(pwfd);
     pwfd = prfd = -1;
-#endif
 
     if (type == IPC_TCP_SOCKET) {
 	debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd);
 	if ((fd = accept(crfd, NULL, NULL)) < 0) {
 	    debug(54, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
-#ifdef _SQUID_MSWIN_
-	    goto cleanup;
-#else
 	    _exit(1);
-#endif
 	}
 	debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd);
-#ifdef _SQUID_MSWIN_
-	comm_close(crfd);
-	snprintf(buf1, 8191, "%s CHILD socket", prog);
-	fd_open(fd, FD_SOCKET, buf1);
-	fd_table[fd].flags.ipc = 1;
-#else
-    	close(crfd);
-#endif
+	close(crfd);
 	cwfd = crfd = fd;
     } else if (type == IPC_UDP_SOCKET) {
 	if (comm_connect_addr(crfd, &PS) == COMM_ERROR)
-#ifdef _SQUID_MSWIN_
-	    goto cleanup;
-#else
 	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
-#endif
     }
-#ifndef _SQUID_MSWIN_
-    if (type == IPC_UDP_SOCKET)
-#endif
-    {
+    if (type == IPC_UDP_SOCKET) {
 	x = send(cwfd, hello_string, strlen(hello_string) + 1, 0);
 	if (x < 0) {
 	    debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
 	    debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n");
-#ifdef _SQUID_MSWIN_
-	    goto cleanup;
-	}
-    }
-#else
 	    _exit(1);
 	}
     } else {
@@ -510,13 +270,11 @@
 	    _exit(1);
 	}
     }
-#endif
 #if HAVE_PUTENV
     env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
     snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
     putenv(env_str);
 #endif
-#ifndef _SQUID_MSWIN_
     /*
      * This double-dup stuff avoids problems when one of 
      *  crfd, cwfd, or debug_log are in the rage 0-2.
@@ -553,371 +311,4 @@
     debug(54, 0) ("ipcCreate: %s: %s\n", prog, xstrerror());
     _exit(1);
     return 0;
-#else
-    memset(buf1, '\0', sizeof(buf1));
-    x = recv(crfd, buf1, 8191, 0);
-    if (x < 0) {
-	debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
-	debug(54, 0) ("--> read: %s\n", xstrerror());
-	goto cleanup;
-    } else if (strcmp(buf1, ok_string)) {
-	debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
-	debug(54, 0) ("--> read returned %d\n", x);
-	debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
-	goto cleanup;
-    }
-    /* assign file descriptors to child process */
-    if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
-	debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
-	ipcSend(cwfd, err_string, strlen(err_string));
-	goto cleanup;
-    }
-    if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
-	debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
-	ipcSend(cwfd, err_string, strlen(err_string));
-	goto cleanup;
-    }
-
-    if (type == IPC_UDP_SOCKET) {
-	snprintf(buf1, 8192, "%s(%ld) <-> ipc CHILD socket", prog, -1L);
-	crfd_ipc = cwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1);
-
-	if (crfd_ipc < 0) {
-	    debug(54, 0) ("ipcCreate: CHILD: Failed to create child FD for %s.\n",
-		prog);
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-
-	snprintf(buf1, 8192, "%s(%ld) <-> ipc PARENT socket", prog, -1L);
-	prfd_ipc = pwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1);
-	if (pwfd_ipc < 0) {
-	    debug(54, 0) ("ipcCreate: CHILD: Failed to create server FD for %s.\n",
-		prog);
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-
-	tmp_s = sizeof(PS_ipc);
-	memset(&PS_ipc, '\0', tmp_s);
-	if (getsockname(pwfd_ipc, (struct sockaddr *) &PS_ipc, &tmp_s) < 0) {
-	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
-	    pwfd_ipc, inet_ntoa(PS_ipc.sin_addr), ntohs(PS_ipc.sin_port));
-	tmp_s = sizeof(CS_ipc);
-	memset(&CS_ipc, '\0', tmp_s);
-	if (getsockname(crfd_ipc, (struct sockaddr *) &CS_ipc, &tmp_s) < 0) {
-	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
-	    crfd_ipc, inet_ntoa(CS_ipc.sin_addr), ntohs(CS_ipc.sin_port));
-
-	if (comm_connect_addr(pwfd_ipc, &CS_ipc) == COMM_ERROR) {
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-
-	fd = crfd;
-
-	if (comm_connect_addr(crfd_ipc, &PS_ipc) == COMM_ERROR) {
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-    }				/* IPC_UDP_SOCKET */
-    t1 = dup(0);
-    t2 = dup(1);
-    t3 = dup(2);
-    dup2(c2p[0], 0);
-    dup2(p2c[1], 1);
-    dup2(fileno(debug_log), 2);
-    close(c2p[0]);
-    close(p2c[1]);
-
-    commUnsetNonBlocking(fd);
-
-    {
-	STARTUPINFO si;
-	PROCESS_INFORMATION pi;
-        long F;
-
-	memset(&si, 0, sizeof(STARTUPINFO));
-	si.cb = sizeof(STARTUPINFO);
-	si.hStdInput = (HANDLE) _get_osfhandle(0);
-	si.hStdOutput = (HANDLE) _get_osfhandle(1);
-	si.hStdError = (HANDLE) _get_osfhandle(2);
-	si.dwFlags = STARTF_USESTDHANDLES;
-
-        /* Make sure all other valid handles are not inerithable */
-        for (x = 3; x < Squid_MaxFD; x++) {
-	    if ((F = _get_osfhandle(x)) == -1)
-	        continue;
-            SetHandleInformation((HANDLE) F, HANDLE_FLAG_INHERIT, 0);
-        }
-        
-        *buf1 = '\0';
-	strcpy(buf1 + 4096, params->prog);
-	str = strtok(buf1 + 4096, w_space);
-	do {
-	    strcat(buf1, str);
-	    strcat(buf1, " ");
-	} while ((str = strtok(NULL, w_space)));
-	x = 1;
-	while (args[x]) {
-	    strcat(buf1, args[x++]);
-	    strcat(buf1, " ");
-	}
-
-	if (CreateProcess(buf1 + 4096, buf1, NULL, NULL, TRUE, CREATE_NO_WINDOW,
-		NULL, NULL, &si, &pi)) {
-	    pid = pi.dwProcessId;
-	    hProcess = pi.hProcess;
-	} else {
-	    pid = -1;
-	    WIN32_maperror(GetLastError());
-	    x = errno;
-	}
-    }
-    dup2(t1, 0);
-    dup2(t2, 1);
-    dup2(t3, 2);
-    close(t1);
-    close(t2);
-    close(t3);
-
-    if (pid == -1) {
-	errno = x;
-	debug(54, 0) ("ipcCreate: CHILD: %s: %s\n", params->prog, xstrerror());
-	ipcSend(cwfd, err_string, strlen(err_string));
-	goto cleanup;
-    }
-
-    if (type == IPC_UDP_SOCKET) {
-	WSAPROTOCOL_INFO wpi;
-
-	memset(&wpi, 0, sizeof(wpi));
-	if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc, pid, &wpi)) {
-	    debug(54, 0) ("ipcCreate: CHILD: WSADuplicateSocket: %s\n",
-		xstrerror());
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-	x = write(c2p[1], (const char *) &wpi, sizeof(wpi));
-	if (x < sizeof(wpi)) {
-	    debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
-		xstrerror());
-	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-		prog);
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-	x = read(p2c[0], buf1, 8192);
-	if (x < 0) {
-	    debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
-		xstrerror());
-	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-		prog);
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	} else if (strncmp(buf1, ok_string, strlen(ok_string))) {
-	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-		prog);
-	    debug(54, 0) ("--> read returned %d\n", x);
-	    buf1[x] = '\0';
-	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-	x = write(c2p[1], (const char *) &PS_ipc, sizeof(PS_ipc));
-	if (x < sizeof(PS_ipc)) {
-	    debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
-		xstrerror());
-	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-		prog);
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-	x = read(p2c[0], buf1, 8192);
-	if (x < 0) {
-	    debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
-		xstrerror());
-	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-		prog);
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	} else if (strncmp(buf1, ok_string, strlen(ok_string))) {
-	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-		prog);
-	    debug(54, 0) ("--> read returned %d\n", x);
-	    buf1[x] = '\0';
-	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
-	    ipcSend(cwfd, err_string, strlen(err_string));
-	    goto cleanup;
-	}
-	x = send(pwfd_ipc, ok_string, strlen(ok_string), 0);
-	x = recv(prfd_ipc, buf1 + 200, 8191 - 200, 0);
-	assert((size_t) x == strlen(ok_string)
-	    && !strncmp(ok_string, buf1 + 200, strlen(ok_string)));
-    }				/* IPC_UDP_SOCKET */
-    snprintf(buf1, 8191, "%s(%ld) CHILD socket", prog, (long int)pid);
-    fd_note(fd, buf1);
-    if (prfd_ipc != -1) {
-	snprintf(buf1, 8191, "%s(%ld) <-> ipc CHILD socket", prog, (long int)pid);
-	fd_note(crfd_ipc, buf1);
-	snprintf(buf1, 8191, "%s(%ld) <-> ipc PARENT socket", prog, (long int)pid);
-	fd_note(prfd_ipc, buf1);
-    }				/* else {                      // IPC_TCP_SOCKET
-				 * commSetNoLinger(fd);
-				 * }
-				 */
-    thread_params.prog = prog;
-    thread_params.send_fd = cwfd;
-    thread_params.pid = pid;
-    if ((thread_params.type = type) == IPC_TCP_SOCKET)
-	thread_params.rfd = p2c[0];
-    else
-	thread_params.rfd = prfd_ipc;
-
-    thread =
-	(HANDLE) _beginthreadex(NULL, 0, ipc_thread_2, &thread_params, 0, NULL);
-    if (!thread) {
-	debug(54, 0) ("ipcCreate: CHILD: _beginthreadex: %s\n", xstrerror());
-	ipcSend(cwfd, err_string, strlen(err_string));
-	goto cleanup;
-    }
-
-    snprintf(buf1, 8191, "%ld\n", (long int)pid);
-    if (-1 == ipcSend(cwfd, buf1, strlen(buf1)))
-	goto cleanup;
-
-    debug(54, 2) ("ipc(%s,%ld): started successfully\n", prog, (long int)pid);
-    /* cycle */
-    for (;;) {
-	x = recv(crfd, buf1, 8192, 0);
-	if (x <= 0) {
-	    debug(54, 3) ("ipc(%s,%d): %d bytes received from parent. Exiting...\n",
-		prog, pid, x);
-	    break;
-	}
-	buf1[x] = '\0';
-	if (type == IPC_UDP_SOCKET && !strcmp(buf1, shutdown_string)) {
-	    debug(54, 3)
-		("ipc(%s,%d): request for shutdown received from parent. Exiting...\n",
-		prog, pid);
-            TerminateProcess(hProcess, 0);
-	    break;
-	}
-	debug(54, 5) ("ipc(%s,%d): received from parent: %s\n", prog, pid,
-	    rfc1738_escape_unescaped(buf1));
-	if (type == IPC_TCP_SOCKET)
-	    x = write(c2p[1], buf1, x);
-	else
-	    x = send(pwfd_ipc, buf1, x, 0);
-	if (x <= 0) {
-	    debug(54, 3) ("ipc(%s,%d): %d bytes written to %s. Exiting...\n",
-		prog, pid, x, prog);
-	    break;
-	}
-    }
-
-    retval = 0;
-
-  cleanup:
-    if (c2p[1] != -1)
-	close(c2p[1]);
-    if (fd_table[crfd].flags.open)
-	ipcCloseAllFD(-1, -1, crfd, cwfd);
-    if (prfd_ipc != -1) {
-	send(crfd_ipc, shutdown_string, strlen(shutdown_string), 0);
-	shutdown(crfd_ipc, SD_BOTH);
-	shutdown(prfd_ipc, SD_BOTH);
-    }
-    ipcCloseAllFD(prfd_ipc, pwfd_ipc, crfd_ipc, cwfd_ipc);
-    if (hProcess && WAIT_OBJECT_0 !=
-	WaitForSingleObject(hProcess, type == IPC_UDP_SOCKET ? 12000 : 5000)) {
-
-	getCurrentTime();
-	debug(54, 0) ("ipc(%s,%d): WARNING: %s didn't exit in %d seconds.\n",
-	    prog, pid, prog, type == IPC_UDP_SOCKET ? 12 : 5);
-    }
-    if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) {
-	getCurrentTime();
-	debug(54, 0)
-	    ("ipc(%s,%d): WARNING: ipc_thread_2 didn't exit in 3 seconds.\n",
-	    prog, pid);
-    }
-    getCurrentTime();
-    if (!retval)
-	debug(54, 2) ("ipc(%s,%d): normal exit\n", prog, pid);
-
-    if (buf1)
-	xfree(buf1);
-    if (prog)
-	xfree(prog);
-    if (env_str)
-	xfree(env_str);
-    if (thread)
-	CloseHandle(thread);
-    if (hProcess)
-	CloseHandle(hProcess);
-    if (p2c[0] != -1)
-	close(p2c[0]);
-    return retval;
-#endif
 }
-
-#ifdef _SQUID_MSWIN_
-static int __stdcall
-ipc_thread_2(struct thread_params *params)
-{
-    int type = params->type;
-    int rfd = params->rfd;
-    int send_fd = params->send_fd;
-    int x;
-    char *prog = xstrdup(params->prog);
-    pid_t pid = params->pid;
-    char *buf2 = xcalloc(1, 8192);
-
-    for (;;) {
-	if (type == IPC_TCP_SOCKET)
-	    x = read(rfd, buf2, 8192);
-	else
-	    x = recv(rfd, buf2, 8192, 0);
-	if ((x <= 0 && type == IPC_TCP_SOCKET) ||
-	    (x < 0 && type == IPC_UDP_SOCKET)) {
-	    debug(54, 3) ("ipc(%s,%d): %d bytes read from %s. Exiting...\n",
-		prog, pid, x, prog);
-	    break;
-	}
-	buf2[x] = '\0';
-	if (type == IPC_UDP_SOCKET && !strcmp(buf2, shutdown_string)) {
-	    debug(54, 3) ("ipc(%s,%d): request for shutdown received. Exiting...\n",
-		prog, pid);
-	    break;
-	}
-	if (x >= 2) {
-	    if ((buf2[x-1] == '\n') && (buf2[x-2] == '\r')) {
-		buf2[x-2] = '\n';
-		buf2[x-1] = '\0';
-		x--;
-	    }
-	}
-	debug(54, 5) ("ipc(%s,%d): received from child : %s\n", prog, pid,
-	    rfc1738_escape_unescaped(buf2));
-	x = send(send_fd, buf2, x, 0);
-	if ((x <= 0 && type == IPC_TCP_SOCKET) ||
-	    (x < 0 && type == IPC_UDP_SOCKET)) {
-	    debug(54, 3) ("ipc(%s,%d): %d bytes sent to parent. Exiting...\n",
-		prog, pid, x);
-	    break;
-	}
-    }
-    xfree(prog);
-    xfree(buf2);
-    return 0;
-}
-#endif
--- /dev/null	Wed Feb 14 01:16:58 2007
+++ squid/src/ipc_win32.c	Wed Feb 14 01:17:02 2007
@@ -0,0 +1,750 @@
+
+/*
+ * $Id: ipc_win32.c,v 1.1.2.1 2006/09/01 19:21:08 serassio Exp $
+ *
+ * DEBUG: section 54    Interprocess Communication
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+
+#ifndef _MSWSOCK_
+#include <mswsock.h>
+#endif
+#include <process.h>
+
+struct ipc_params {
+    int type;
+    int crfd;
+    int cwfd;
+    struct sockaddr_in PS;
+    const char *prog;
+    char **args;
+};
+
+struct thread_params {
+    int type;
+    int rfd;
+    int send_fd;
+    const char *prog;
+    pid_t pid;
+};
+
+static unsigned int __stdcall ipc_thread_1(void *params);
+static unsigned int __stdcall ipc_thread_2(void *params);
+
+static const char *ok_string = "OK\n";
+static const char *err_string = "ERR\n";
+static const char *shutdown_string = "$shutdown\n";
+
+static const char *hello_string = "hi there\n";
+#define HELLO_BUF_SZ 32
+static char hello_buf[HELLO_BUF_SZ];
+
+static int
+ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd)
+{
+    if (prfd >= 0)
+	comm_close(prfd);
+    if (prfd != pwfd)
+	if (pwfd >= 0)
+	    comm_close(pwfd);
+    if (crfd >= 0)
+	comm_close(crfd);
+    if (crfd != cwfd)
+	if (cwfd >= 0)
+	    comm_close(cwfd);
+    return -1;
+}
+
+int
+ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, HANDLE * hIpc, pid_t * ppid)
+{
+    unsigned long thread;
+    struct ipc_params params;
+    int opt;
+    int optlen = sizeof(opt);
+    DWORD ecode = 0;
+    pid_t pid;
+    struct sockaddr_in CS;
+    struct sockaddr_in PS;
+    int crfd = -1;
+    int prfd = -1;
+    int cwfd = -1;
+    int pwfd = -1;
+    socklen_t len;
+    int x;
+
+    requirePathnameExists(name, prog);
+
+    if (rfd)
+	*rfd = -1;
+    if (wfd)
+	*wfd = -1;
+    if (hIpc)
+	*hIpc = NULL;
+    if (ppid)
+	*ppid = -1;
+
+    if (WIN32_OS_version != _WIN_OS_WINNT) {
+	getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen);
+	opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT);
+	setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, sizeof(opt));
+    }
+    if (type == IPC_TCP_SOCKET) {
+	crfd = cwfd = comm_open(SOCK_STREAM,
+	    IPPROTO_TCP,
+	    local_addr,
+	    0,
+	    COMM_NOCLOEXEC,
+	    name);
+	prfd = pwfd = comm_open(SOCK_STREAM,
+	    IPPROTO_TCP,	/* protocol */
+	    local_addr,
+	    0,			/* port */
+	    0,			/* blocking */
+	    name);
+    } else if (type == IPC_UDP_SOCKET) {
+	crfd = cwfd = comm_open(SOCK_DGRAM,
+	    IPPROTO_UDP,
+	    local_addr,
+	    0,
+	    COMM_NOCLOEXEC,
+	    name);
+	prfd = pwfd = comm_open(SOCK_DGRAM,
+	    IPPROTO_UDP,
+	    local_addr,
+	    0,
+	    0,
+	    name);
+    } else if (type == IPC_FIFO) {
+	debug(54, 0)
+	    ("ipcCreate: %s: use IPC_TCP_SOCKET instead of IP_FIFO on Windows\n",
+	    prog);
+	assert(0);
+    } else {
+	assert(IPC_NONE);
+    }
+    debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd);
+    debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd);
+    debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd);
+    debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd);
+
+    if (WIN32_OS_version != _WIN_OS_WINNT) {
+	getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen);
+	opt = opt | SO_SYNCHRONOUS_NONALERT;
+	setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen);
+    }
+    if (crfd < 0) {
+	debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
+	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+    }
+    if (pwfd < 0) {
+	debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
+	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+    }
+    if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
+	len = sizeof(PS);
+	memset(&PS, '\0', len);
+	if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) {
+	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
+	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+	}
+	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
+	    pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port));
+	len = sizeof(CS);
+	memset(&CS, '\0', len);
+	if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) {
+	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
+	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+	}
+	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
+	    crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port));
+    }
+    if (type == IPC_TCP_SOCKET) {
+	if (listen(crfd, 1) < 0) {
+	    debug(54, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror());
+	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+	}
+	debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd);
+    }
+    /* flush or else we get dup data if unbuffered_logs is set */
+    logsFlush();
+    params.type = type;
+    params.crfd = crfd;
+    params.cwfd = cwfd;
+    params.PS = PS;
+    params.prog = prog;
+    params.args = (char **) args;
+
+    thread = _beginthreadex(NULL, 0, ipc_thread_1, &params, 0, NULL);
+
+    if (thread == 0) {
+	debug(54, 1) ("ipcCreate: _beginthread: %s\n", xstrerror());
+	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+    }
+    if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) {
+	CloseHandle((HANDLE) thread);
+	return ipcCloseAllFD(prfd, pwfd, -1, -1);
+    }
+    memset(hello_buf, '\0', HELLO_BUF_SZ);
+    x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
+
+    if (x < 0) {
+	debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
+	debug(54, 0) ("--> read: %s\n", xstrerror());
+	CloseHandle((HANDLE) thread);
+	return ipcCloseAllFD(prfd, pwfd, -1, -1);
+    } else if (strcmp(hello_buf, hello_string)) {
+	debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
+	debug(54, 0) ("--> read returned %d\n", x);
+	debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
+	CloseHandle((HANDLE) thread);
+	return ipcCloseAllFD(prfd, pwfd, -1, -1);
+    }
+    x = send(pwfd, ok_string, strlen(ok_string), 0);
+
+    if (x < 0) {
+	debug(54, 0) ("ipcCreate: PARENT: OK write test failed\n");
+	debug(54, 0) ("--> read: %s\n", xstrerror());
+	CloseHandle((HANDLE) thread);
+	return ipcCloseAllFD(prfd, pwfd, -1, -1);
+    }
+    memset(hello_buf, '\0', HELLO_BUF_SZ);
+    x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
+
+    if (x < 0) {
+	debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
+	debug(54, 0) ("--> read: %s\n", xstrerror());
+	CloseHandle((HANDLE) thread);
+	return ipcCloseAllFD(prfd, pwfd, -1, -1);
+    } else if (!strcmp(hello_buf, err_string)) {
+	debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
+	debug(54, 0) ("--> read returned %d\n", x);
+	debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
+	CloseHandle((HANDLE) thread);
+	return ipcCloseAllFD(prfd, pwfd, -1, -1);
+    }
+    hello_buf[x] = '\0';
+    pid = atol(hello_buf);
+    commSetTimeout(prfd, -1, NULL, NULL);
+    commSetNonBlocking(prfd);
+    commSetNonBlocking(pwfd);
+    commSetCloseOnExec(prfd);
+    commSetCloseOnExec(pwfd);
+
+    if (rfd)
+	*rfd = prfd;
+    if (wfd)
+	*wfd = pwfd;
+
+    fd_table[prfd].flags.ipc = 1;
+    fd_table[pwfd].flags.ipc = 1;
+    fd_table[crfd].flags.ipc = 1;
+    fd_table[cwfd].flags.ipc = 1;
+
+    if (Config.sleep_after_fork) {
+	/* XXX emulation of usleep() */
+	DWORD sl;
+	sl = Config.sleep_after_fork / 1000;
+	if (sl == 0)
+	    sl = 1;
+	Sleep(sl);
+    }
+    if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) {
+	if (hIpc)
+	    *hIpc = (HANDLE) thread;
+	if (ppid)
+	    *ppid = pid;
+	return pwfd;
+    } else {
+	CloseHandle((HANDLE) thread);
+	return ipcCloseAllFD(prfd, pwfd, -1, -1);
+    }
+}
+
+static int
+ipcSend(int cwfd, const char *buf, int len)
+{
+    int x;
+
+    x = send(cwfd, buf, len, 0);
+
+    if (x < 0) {
+	debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
+	debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n");
+    }
+    return x;
+}
+
+static unsigned int __stdcall
+ipc_thread_1(void *in_params)
+{
+    int t1, t2, t3, retval = -1;
+    int p2c[2] =
+    {-1, -1};
+    int c2p[2] =
+    {-1, -1};
+    HANDLE hProcess = NULL, thread = NULL;
+    pid_t pid = -1;
+    struct thread_params thread_params;
+    int x, tmp_s, fd = -1;
+    char *str;
+#if HAVE_PUTENV
+    char *env_str = NULL;
+#endif
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    long F;
+    int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1;
+    char *prog = NULL, *buf1 = NULL;
+    struct sockaddr_in CS_ipc, PS_ipc;
+
+    struct ipc_params *params = (struct ipc_params *) in_params;
+    int type = params->type;
+    int crfd = params->crfd;
+    int cwfd = params->cwfd;
+    char **args = params->args;
+    struct sockaddr_in PS = params->PS;
+
+
+    buf1 = xcalloc(1, 8192);
+    strcpy(buf1, params->prog);
+    prog = strtok(buf1, w_space);
+
+    if ((str = strrchr(prog, '/')))
+	prog = ++str;
+    if ((str = strrchr(prog, '\\')))
+	prog = ++str;
+
+    prog = xstrdup(prog);
+
+    if (type == IPC_TCP_SOCKET) {
+	debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd);
+	if ((fd = accept(crfd, NULL, NULL)) < 0) {
+	    debug(54, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
+	    goto cleanup;
+	}
+	debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd);
+	comm_close(crfd);
+	snprintf(buf1, 8191, "%s CHILD socket", prog);
+	fd_open(fd, FD_SOCKET, buf1);
+	fd_table[fd].flags.ipc = 1;
+	cwfd = crfd = fd;
+    } else if (type == IPC_UDP_SOCKET) {
+	if (comm_connect_addr(crfd, &PS) == COMM_ERROR)
+	    goto cleanup;
+    }
+    x = send(cwfd, hello_string, strlen(hello_string) + 1, 0);
+
+    if (x < 0) {
+	debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
+	debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n");
+	goto cleanup;
+    }
+#if HAVE_PUTENV
+    env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
+    snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
+    putenv(env_str);
+#endif
+    memset(buf1, '\0', sizeof(buf1));
+    x = recv(crfd, buf1, 8191, 0);
+
+    if (x < 0) {
+	debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
+	debug(54, 0) ("--> read: %s\n", xstrerror());
+	goto cleanup;
+    } else if (strcmp(buf1, ok_string)) {
+	debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
+	debug(54, 0) ("--> read returned %d\n", x);
+	debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
+	goto cleanup;
+    }
+    /* assign file descriptors to child process */
+    if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
+	debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
+	ipcSend(cwfd, err_string, strlen(err_string));
+	goto cleanup;
+    }
+    if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
+	debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
+	ipcSend(cwfd, err_string, strlen(err_string));
+	goto cleanup;
+    }
+    if (type == IPC_UDP_SOCKET) {
+	snprintf(buf1, 8192, "%s(%ld) <-> ipc CHILD socket", prog, -1L);
+	crfd_ipc = cwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1);
+
+	if (crfd_ipc < 0) {
+	    debug(54, 0) ("ipcCreate: CHILD: Failed to create child FD for %s.\n",
+		prog);
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	snprintf(buf1, 8192, "%s(%ld) <-> ipc PARENT socket", prog, -1L);
+	prfd_ipc = pwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1);
+	if (pwfd_ipc < 0) {
+	    debug(54, 0) ("ipcCreate: CHILD: Failed to create server FD for %s.\n",
+		prog);
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	tmp_s = sizeof(PS_ipc);
+	memset(&PS_ipc, '\0', tmp_s);
+	if (getsockname(pwfd_ipc, (struct sockaddr *) &PS_ipc, &tmp_s) < 0) {
+	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
+	    pwfd_ipc, inet_ntoa(PS_ipc.sin_addr), ntohs(PS_ipc.sin_port));
+	tmp_s = sizeof(CS_ipc);
+	memset(&CS_ipc, '\0', tmp_s);
+	if (getsockname(crfd_ipc, (struct sockaddr *) &CS_ipc, &tmp_s) < 0) {
+	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
+	    crfd_ipc, inet_ntoa(CS_ipc.sin_addr), ntohs(CS_ipc.sin_port));
+
+	if (comm_connect_addr(pwfd_ipc, &CS_ipc) == COMM_ERROR) {
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	fd = crfd;
+
+	if (comm_connect_addr(crfd_ipc, &PS_ipc) == COMM_ERROR) {
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+    }				/* IPC_UDP_SOCKET */
+    t1 = dup(0);
+    t2 = dup(1);
+    t3 = dup(2);
+    dup2(c2p[0], 0);
+    dup2(p2c[1], 1);
+    dup2(fileno(debug_log), 2);
+    close(c2p[0]);
+    close(p2c[1]);
+
+    commUnsetNonBlocking(fd);
+
+    memset(&si, 0, sizeof(STARTUPINFO));
+    si.cb = sizeof(STARTUPINFO);
+    si.hStdInput = (HANDLE) _get_osfhandle(0);
+    si.hStdOutput = (HANDLE) _get_osfhandle(1);
+    si.hStdError = (HANDLE) _get_osfhandle(2);
+    si.dwFlags = STARTF_USESTDHANDLES;
+
+    /* Make sure all other valid handles are not inerithable */
+    for (x = 3; x < Squid_MaxFD; x++) {
+	if ((F = _get_osfhandle(x)) == -1)
+	    continue;
+	SetHandleInformation((HANDLE) F, HANDLE_FLAG_INHERIT, 0);
+    }
+
+    *buf1 = '\0';
+    strcpy(buf1 + 4096, params->prog);
+    str = strtok(buf1 + 4096, w_space);
+
+    do {
+	strcat(buf1, str);
+	strcat(buf1, " ");
+    } while ((str = strtok(NULL, w_space)));
+
+    x = 1;
+
+    while (args[x]) {
+	strcat(buf1, args[x++]);
+	strcat(buf1, " ");
+    }
+
+    if (CreateProcess(buf1 + 4096, buf1, NULL, NULL, TRUE, CREATE_NO_WINDOW,
+	    NULL, NULL, &si, &pi)) {
+	pid = pi.dwProcessId;
+	hProcess = pi.hProcess;
+    } else {
+	pid = -1;
+	WIN32_maperror(GetLastError());
+	x = errno;
+    }
+
+    dup2(t1, 0);
+    dup2(t2, 1);
+    dup2(t3, 2);
+    close(t1);
+    close(t2);
+    close(t3);
+
+    if (pid == -1) {
+	errno = x;
+	debug(54, 0) ("ipcCreate: CHILD: %s: %s\n", params->prog, xstrerror());
+	ipcSend(cwfd, err_string, strlen(err_string));
+	goto cleanup;
+    }
+    if (type == IPC_UDP_SOCKET) {
+	WSAPROTOCOL_INFO wpi;
+
+	memset(&wpi, 0, sizeof(wpi));
+	if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc, pid, &wpi)) {
+	    debug(54, 0) ("ipcCreate: CHILD: WSADuplicateSocket: %s\n",
+		xstrerror());
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	x = write(c2p[1], (const char *) &wpi, sizeof(wpi));
+	if (x < sizeof(wpi)) {
+	    debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
+		xstrerror());
+	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
+		prog);
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	x = read(p2c[0], buf1, 8192);
+	if (x < 0) {
+	    debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
+		xstrerror());
+	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
+		prog);
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	} else if (strncmp(buf1, ok_string, strlen(ok_string))) {
+	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
+		prog);
+	    debug(54, 0) ("--> read returned %d\n", x);
+	    buf1[x] = '\0';
+	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	x = write(c2p[1], (const char *) &PS_ipc, sizeof(PS_ipc));
+	if (x < sizeof(PS_ipc)) {
+	    debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
+		xstrerror());
+	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
+		prog);
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	x = read(p2c[0], buf1, 8192);
+	if (x < 0) {
+	    debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
+		xstrerror());
+	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
+		prog);
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	} else if (strncmp(buf1, ok_string, strlen(ok_string))) {
+	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
+		prog);
+	    debug(54, 0) ("--> read returned %d\n", x);
+	    buf1[x] = '\0';
+	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
+	    ipcSend(cwfd, err_string, strlen(err_string));
+	    goto cleanup;
+	}
+	x = send(pwfd_ipc, ok_string, strlen(ok_string), 0);
+	x = recv(prfd_ipc, buf1 + 200, 8191 - 200, 0);
+	assert((size_t) x == strlen(ok_string)
+	    && !strncmp(ok_string, buf1 + 200, strlen(ok_string)));
+    }				/* IPC_UDP_SOCKET */
+    snprintf(buf1, 8191, "%s(%ld) CHILD socket", prog, (long int) pid);
+    fd_note(fd, buf1);
+
+    if (prfd_ipc != -1) {
+	snprintf(buf1, 8191, "%s(%ld) <-> ipc CHILD socket", prog, (long int) pid);
+	fd_note(crfd_ipc, buf1);
+	snprintf(buf1, 8191, "%s(%ld) <-> ipc PARENT socket", prog, (long int) pid);
+	fd_note(prfd_ipc, buf1);
+    }				/* else {                      // IPC_TCP_SOCKET
+				 * * * * commSetNoLinger(fd);
+				 * * * * }
+				 */
+    thread_params.prog = prog;
+    thread_params.send_fd = cwfd;
+    thread_params.pid = pid;
+
+    if ((thread_params.type = type) == IPC_TCP_SOCKET)
+	thread_params.rfd = p2c[0];
+    else
+	thread_params.rfd = prfd_ipc;
+
+    thread =
+	(HANDLE) _beginthreadex(NULL, 0, ipc_thread_2, &thread_params, 0, NULL);
+
+    if (!thread) {
+	debug(54, 0) ("ipcCreate: CHILD: _beginthreadex: %s\n", xstrerror());
+	ipcSend(cwfd, err_string, strlen(err_string));
+	goto cleanup;
+    }
+    snprintf(buf1, 8191, "%ld\n", (long int) pid);
+
+    if (-1 == ipcSend(cwfd, buf1, strlen(buf1)))
+	goto cleanup;
+
+    debug(54, 2) ("ipc(%s,%ld): started successfully\n", prog, (long int) pid);
+
+    /* cycle */
+    for (;;) {
+	x = recv(crfd, buf1, 8192, 0);
+	if (x <= 0) {
+	    debug(54, 3) ("ipc(%s,%d): %d bytes received from parent. Exiting...\n",
+		prog, pid, x);
+	    break;
+	}
+	buf1[x] = '\0';
+	if (type == IPC_UDP_SOCKET && !strcmp(buf1, shutdown_string)) {
+	    debug(54, 3)
+		("ipc(%s,%d): request for shutdown received from parent. Exiting...\n",
+		prog, pid);
+	    TerminateProcess(hProcess, 0);
+	    break;
+	}
+	debug(54, 5) ("ipc(%s,%d): received from parent: %s\n", prog, pid,
+	    rfc1738_escape_unescaped(buf1));
+	if (type == IPC_TCP_SOCKET)
+	    x = write(c2p[1], buf1, x);
+	else
+	    x = send(pwfd_ipc, buf1, x, 0);
+	if (x <= 0) {
+	    debug(54, 3) ("ipc(%s,%d): %d bytes written to %s. Exiting...\n",
+		prog, pid, x, prog);
+	    break;
+	}
+    }
+
+    retval = 0;
+
+  cleanup:
+    if (c2p[1] != -1)
+	close(c2p[1]);
+
+    if (fd_table[crfd].flags.open)
+	ipcCloseAllFD(-1, -1, crfd, cwfd);
+
+    if (prfd_ipc != -1) {
+	send(crfd_ipc, shutdown_string, strlen(shutdown_string), 0);
+	shutdown(crfd_ipc, SD_BOTH);
+	shutdown(prfd_ipc, SD_BOTH);
+    }
+    ipcCloseAllFD(prfd_ipc, pwfd_ipc, crfd_ipc, cwfd_ipc);
+
+    if (hProcess && WAIT_OBJECT_0 !=
+	WaitForSingleObject(hProcess, type == IPC_UDP_SOCKET ? 12000 : 5000)) {
+
+	getCurrentTime();
+	debug(54, 0) ("ipc(%s,%d): WARNING: %s didn't exit in %d seconds.\n",
+	    prog, pid, prog, type == IPC_UDP_SOCKET ? 12 : 5);
+    }
+    if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) {
+	getCurrentTime();
+	debug(54, 0)
+	    ("ipc(%s,%d): WARNING: ipc_thread_2 didn't exit in 3 seconds.\n",
+	    prog, pid);
+    }
+    getCurrentTime();
+
+    if (!retval)
+	debug(54, 2) ("ipc(%s,%d): normal exit\n", prog, pid);
+
+    if (buf1)
+	xfree(buf1);
+
+    if (prog)
+	xfree(prog);
+
+    if (env_str)
+	xfree(env_str);
+
+    if (thread)
+	CloseHandle(thread);
+
+    if (hProcess)
+	CloseHandle(hProcess);
+
+    if (p2c[0] != -1)
+	close(p2c[0]);
+
+    return retval;
+}
+
+static unsigned int __stdcall
+ipc_thread_2(void *in_params)
+{
+    int x;
+    struct thread_params *params = (struct thread_params *) in_params;
+    int type = params->type;
+    int rfd = params->rfd;
+    int send_fd = params->send_fd;
+    char *prog = xstrdup(params->prog);
+    pid_t pid = params->pid;
+    char *buf2 = xcalloc(1, 8192);
+
+    for (;;) {
+	if (type == IPC_TCP_SOCKET)
+	    x = read(rfd, buf2, 8192);
+	else
+	    x = recv(rfd, buf2, 8192, 0);
+	if ((x <= 0 && type == IPC_TCP_SOCKET) ||
+	    (x < 0 && type == IPC_UDP_SOCKET)) {
+	    debug(54, 3) ("ipc(%s,%d): %d bytes read from %s. Exiting...\n",
+		prog, pid, x, prog);
+	    break;
+	}
+	buf2[x] = '\0';
+	if (type == IPC_UDP_SOCKET && !strcmp(buf2, shutdown_string)) {
+	    debug(54, 3) ("ipc(%s,%d): request for shutdown received. Exiting...\n",
+		prog, pid);
+	    break;
+	}
+	if (x >= 2) {
+	    if ((buf2[x - 1] == '\n') && (buf2[x - 2] == '\r')) {
+		buf2[x - 2] = '\n';
+		buf2[x - 1] = '\0';
+		x--;
+	    }
+	}
+	debug(54, 5) ("ipc(%s,%d): received from child : %s\n", prog, pid,
+	    rfc1738_escape_unescaped(buf2));
+	x = send(send_fd, buf2, x, 0);
+	if ((x <= 0 && type == IPC_TCP_SOCKET) ||
+	    (x < 0 && type == IPC_UDP_SOCKET)) {
+	    debug(54, 3) ("ipc(%s,%d): %d bytes sent to parent. Exiting...\n",
+		prog, pid, x);
+	    break;
+	}
+    }
+
+    xfree(prog);
+    xfree(buf2);
+    return 0;
+}
