---------------------
PatchSet 3676 
Date: 2006/09/03 16:51:20
Author: serassio
Branch: nt
Tag: (none) 
Log:
Drop IPC refactored support (moved to ipc branch) an forward port latest 2.6 changes

Members: 
	configure.in:1.26.2.97->1.26.2.98 
	src/Makefile.am:1.26.2.87->1.26.2.88 
	src/defines.h:1.6.2.9->1.6.2.10 
	src/dns.cc:1.5.2.8->1.5.2.9 
	src/external_acl.cc:1.14.2.37->1.14.2.38 
	src/helper.cc:1.10.2.19->1.10.2.20 
	src/icmp.cc:1.7.2.8->1.7.2.9 
	src/ipc.cc:1.8.2.21->1.8.2.22 
	src/ipc.h:1.1.18.1->1.1.18.2(DEAD) 
	src/ipc_win32.cc:1.1->1.1.2.1 
	src/protos.h:1.19.2.58->1.19.2.59 
	src/redirect.cc:1.5.2.17->1.5.2.18 
	src/unlinkd.cc:1.7.2.10->1.7.2.11 
	src/DiskIO/DiskDaemon/DiskdIOStrategy.cc:1.1.2.3->1.1.2.4 

Index: squid3/configure.in
===================================================================
RCS file: /cvsroot/squid-sf//squid3/configure.in,v
retrieving revision 1.26.2.97
retrieving revision 1.26.2.98
diff -u -r1.26.2.97 -r1.26.2.98
--- squid3/configure.in	3 Sep 2006 08:44:13 -0000	1.26.2.97
+++ squid3/configure.in	3 Sep 2006 16:51:20 -0000	1.26.2.98
@@ -1,7 +1,7 @@
 
 dnl  Configuration input file for Squid
 dnl
-dnl  $Id: configure.in,v 1.26.2.97 2006/09/03 08:44:13 serassio Exp $
+dnl  $Id: configure.in,v 1.26.2.98 2006/09/03 16:51:20 serassio Exp $
 dnl
 dnl
 dnl
@@ -11,7 +11,7 @@
 AC_CONFIG_AUX_DIR(cfgaux)
 AC_CONFIG_SRCDIR([src/main.cc])
 AM_INIT_AUTOMAKE([tar-ustar])
-AC_REVISION($Revision: 1.26.2.97 $)dnl
+AC_REVISION($Revision: 1.26.2.98 $)dnl
 AC_PREFIX_DEFAULT(/usr/local/squid)
 AM_MAINTAINER_MODE
 
@@ -75,8 +75,12 @@
 		LIBS="$LIBS -lpsapi"
 	fi
 	MINGW_LIBS="-lmingwex"
+	AM_CONDITIONAL(USE_IPC_WIN32, true)
 	AC_SUBST(MINGW_LIBS)
 	;;
+*)
+	AM_CONDITIONAL(USE_IPC_WIN32, false)
+	;;
 esac
 
 if test -z "$CACHE_HTTP_PORT"; then
Index: squid3/src/Makefile.am
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/Makefile.am,v
retrieving revision 1.26.2.87
retrieving revision 1.26.2.88
diff -u -r1.26.2.87 -r1.26.2.88
--- squid3/src/Makefile.am	2 Sep 2006 20:07:09 -0000	1.26.2.87
+++ squid3/src/Makefile.am	3 Sep 2006 16:51:22 -0000	1.26.2.88
@@ -1,7 +1,7 @@
 #
 #  Makefile for the Squid Object Cache server
 #
-#  $Id: Makefile.am,v 1.26.2.87 2006/09/02 20:07:09 serassio Exp $
+#  $Id: Makefile.am,v 1.26.2.88 2006/09/03 16:51:22 serassio Exp $
 #
 #  Uncomment and customize the following to suit your needs:
 #
@@ -147,6 +147,12 @@
 WIN32_SOURCE = 
 endif
 
+if USE_IPC_WIN32
+IPC_SOURCE = ipc_win32.cc
+else
+IPC_SOURCE = ipc.cc
+endif
+
 IDENT_ALL_SOURCE = ACLIdent.cc ACLIdent.h ident.cc
 if ENABLE_IDENT
 IDENT_SOURCE = $(IDENT_ALL_SOURCE)
@@ -254,6 +260,8 @@
 	dnsserver.cc \
 	dns_internal.cc \
 	htcp.cc \
+	ipc.cc \
+	ipc_win32.cc \
 	htcp.h \
 	$(IDENT_ALL_SOURCE) \
 	$(ESI_ALL_SOURCE) \
@@ -485,8 +493,7 @@
 	$(IDENT_SOURCE) \
 	int.cc \
 	internal.cc \
-	ipc.cc \
-	ipc.h \
+	$(IPC_SOURCE) \
 	ipcache.cc \
 	$(LEAKFINDERSOURCE) \
 	list.cc \
@@ -782,7 +789,7 @@
 	icp_v3.cc \
 	$(IDENT_SOURCE) \
 	internal.cc \
-	ipc.cc \
+	$(IPC_SOURCE) \
 	ipcache.cc \
 	$(LEAKFINDERSOURCE) \
         list.cc \
@@ -1289,7 +1296,7 @@
 	icp_v2.cc \
 	icp_v3.cc \
 	$(IDENT_SOURCE) \
-	ipc.cc \
+	$(IPC_SOURCE) \
 	ipcache.cc \
 	int.cc \
 	internal.cc \
@@ -1440,7 +1447,7 @@
 	icp_v2.cc \
 	icp_v3.cc \
 	$(IDENT_SOURCE) \
-	ipc.cc \
+	$(IPC_SOURCE) \
 	ipcache.cc \
 	int.cc \
 	internal.cc \
@@ -1590,7 +1597,7 @@
 	icp_v2.cc \
 	icp_v3.cc \
 	$(IDENT_SOURCE) \
-	ipc.cc \
+	$(IPC_SOURCE) \
 	ipcache.cc \
 	int.cc \
 	internal.cc \
@@ -1770,7 +1777,7 @@
 	$(IDENT_SOURCE) \
 	int.cc \
 	internal.cc \
-	ipc.cc \
+	$(IPC_SOURCE) \
 	ipcache.cc \
 	list.cc \
 	logfile.cc \
@@ -1918,7 +1925,7 @@
 	icp_v2.cc \
 	icp_v3.cc \
 	$(IDENT_SOURCE) \
-	ipc.cc \
+	$(IPC_SOURCE) \
 	ipcache.cc \
 	int.cc \
 	internal.cc \
@@ -2251,7 +2258,7 @@
 	icp_v2.cc \
 	icp_v3.cc \
 	$(IDENT_SOURCE) \
-	ipc.cc \
+	$(IPC_SOURCE) \
 	ipcache.cc \
 	int.cc \
 	internal.cc \
Index: squid3/src/defines.h
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/defines.h,v
retrieving revision 1.6.2.9
retrieving revision 1.6.2.10
diff -u -r1.6.2.9 -r1.6.2.10
--- squid3/src/defines.h	22 Aug 2006 10:26:04 -0000	1.6.2.9
+++ squid3/src/defines.h	3 Sep 2006 16:51:23 -0000	1.6.2.10
@@ -1,6 +1,6 @@
 
 /*
- * $Id: defines.h,v 1.6.2.9 2006/08/22 10:26:04 serassio Exp $
+ * $Id: defines.h,v 1.6.2.10 2006/09/03 16:51:23 serassio Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -180,6 +180,21 @@
 #define STORE_META_DIRTY  0x04
 #define STORE_META_BAD    0x05
 
+#define IPC_NONE 0
+#define IPC_TCP_SOCKET 1
+#define IPC_UDP_SOCKET 2
+#define IPC_FIFO 3
+#define IPC_UNIX_STREAM 4
+#define IPC_UNIX_DGRAM 5
+
+#if HAVE_SOCKETPAIR && defined (AF_UNIX)
+#define IPC_STREAM IPC_UNIX_STREAM
+#define IPC_DGRAM IPC_UNIX_DGRAM
+#else
+#define IPC_STREAM IPC_TCP_SOCKET
+#define IPC_DGRAM IPC_UDP_SOCKET
+#endif
+
 #define STORE_META_KEY STORE_META_KEY_MD5
 
 #define STORE_META_TLD_START sizeof(int)+sizeof(char)
Index: squid3/src/dns.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/dns.cc,v
retrieving revision 1.5.2.8
retrieving revision 1.5.2.9
diff -u -r1.5.2.8 -r1.5.2.9
--- squid3/src/dns.cc	31 May 2006 21:17:02 -0000	1.5.2.8
+++ squid3/src/dns.cc	3 Sep 2006 16:51:23 -0000	1.5.2.9
@@ -1,6 +1,6 @@
 
 /*
- * $Id: dns.cc,v 1.5.2.8 2006/05/31 21:17:02 serassio Exp $
+ * $Id: dns.cc,v 1.5.2.9 2006/09/03 16:51:23 serassio Exp $
  *
  * DEBUG: section 34    Dnsserver interface
  * AUTHOR: Harvest Derived
@@ -45,9 +45,6 @@
  */
 #if USE_DNSSERVERS
 
-/* For the IPC type defines */
-#include "ipc.h"
-
 static helper *dnsservers = NULL;
 
 static void
Index: squid3/src/external_acl.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/external_acl.cc,v
retrieving revision 1.14.2.37
retrieving revision 1.14.2.38
diff -u -r1.14.2.37 -r1.14.2.38
--- squid3/src/external_acl.cc	22 Aug 2006 10:26:04 -0000	1.14.2.37
+++ squid3/src/external_acl.cc	3 Sep 2006 16:51:23 -0000	1.14.2.38
@@ -1,6 +1,6 @@
 
 /*
- * $Id: external_acl.cc,v 1.14.2.37 2006/08/22 10:26:04 serassio Exp $
+ * $Id: external_acl.cc,v 1.14.2.38 2006/09/03 16:51:23 serassio Exp $
  *
  * DEBUG: section 82    External ACL
  * AUTHOR: Henrik Nordstrom, MARA Systems AB
@@ -47,7 +47,6 @@
 #include "AuthUserRequest.h"
 #include "SquidTime.h"
 #include "Store.h"
-#include "ipc.h"
 #include "fde.h"
 #include "ACLChecklist.h"
 #include "ACL.h"
Index: squid3/src/helper.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/helper.cc,v
retrieving revision 1.10.2.19
retrieving revision 1.10.2.20
diff -u -r1.10.2.19 -r1.10.2.20
--- squid3/src/helper.cc	22 Aug 2006 10:26:05 -0000	1.10.2.19
+++ squid3/src/helper.cc	3 Sep 2006 16:51:26 -0000	1.10.2.20
@@ -1,6 +1,6 @@
 
 /*
- * $Id: helper.cc,v 1.10.2.19 2006/08/22 10:26:05 serassio Exp $
+ * $Id: helper.cc,v 1.10.2.20 2006/09/03 16:51:26 serassio Exp $
  *
  * DEBUG: section 84    Helper process maintenance
  * AUTHOR: Harvest Derived?
@@ -39,7 +39,6 @@
 #include "Store.h"
 #include "comm.h"
 #include "MemBuf.h"
-#include "ipc.h"
 #include "wordlist.h"
 
 #define HELPER_MAX_ARGS 64
@@ -81,6 +80,10 @@
     helper_server *srv;
     int nargs = 0;
     int k;
+    pid_t pid;
+    int rfd;
+    int wfd;
+    void * hIpc; 
     wordlist *w;
 
     if (hlp->cmdline == NULL)
@@ -111,12 +114,16 @@
 
     for (k = 0; k < hlp->n_to_start; k++) {
         getCurrentTime();
-        IPCResult ipcRV = ipcCreate(hlp->ipc_type,
-                                    progname,
-                                    args,
-                                    shortname);
+        rfd = wfd = -1;
+        pid = ipcCreate(hlp->ipc_type,
+                      progname,
+                      args,
+                      shortname,
+                      &rfd,
+                      &wfd,
+			&hIpc);
 
-        if (!ipcRV.success) {
+        if (pid < 0) {
             debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname);
             continue;
         }
@@ -125,15 +132,11 @@
         hlp->n_active++;
 	CBDATA_INIT_TYPE(helper_server);
         srv = cbdataAlloc(helper_server);
-#ifdef _SQUID_MSWIN_
-
-        srv->hIpc = ipcRV.hIpc;
-#endif
-
-        srv->pid = ipcRV.pid;
+        srv->hIpc = hIpc;
+        srv->pid = pid;
         srv->index = k;
-        srv->rfd = ipcRV.rfd;
-        srv->wfd = ipcRV.wfd;
+        srv->rfd = rfd;
+        srv->wfd = wfd;
         srv->rbuf = (char *)memAllocBuf(8192, &srv->rbuf_sz);
         srv->wqueue = new MemBuf;
         srv->roffset = 0;
@@ -141,22 +144,22 @@
         srv->parent = cbdataReference(hlp);
         dlinkAddTail(srv, &srv->link, &hlp->servers);
 
-        if (srv->rfd == srv->wfd) {
+        if (rfd == wfd) {
             snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", shortname, k + 1);
-            fd_note(srv->rfd, fd_note_buf);
+            fd_note(rfd, fd_note_buf);
         } else {
             snprintf(fd_note_buf, FD_DESC_SZ, "reading %s #%d", shortname, k + 1);
-            fd_note(srv->rfd, fd_note_buf);
+            fd_note(rfd, fd_note_buf);
             snprintf(fd_note_buf, FD_DESC_SZ, "writing %s #%d", shortname, k + 1);
-            fd_note(srv->wfd, fd_note_buf);
+            fd_note(wfd, fd_note_buf);
         }
 
-        commSetNonBlocking(srv->rfd);
+        commSetNonBlocking(rfd);
 
-        if (srv->wfd != srv->rfd)
-            commSetNonBlocking(srv->wfd);
+        if (wfd != rfd)
+            commSetNonBlocking(wfd);
 
-        comm_add_close_handler(srv->rfd, helperServerFree, srv);
+        comm_add_close_handler(rfd, helperServerFree, srv);
 
         comm_read(srv->rfd, srv->rbuf, srv->rbuf_sz - 1, helperHandleRead, srv);
     }
@@ -179,6 +182,10 @@
     helper_stateful_server *srv;
     int nargs = 0;
     int k;
+    pid_t pid;
+    int rfd;
+    int wfd;
+    void * hIpc;
     wordlist *w;
 
     if (hlp->cmdline == NULL)
@@ -209,12 +216,16 @@
 
     for (k = 0; k < hlp->n_to_start; k++) {
         getCurrentTime();
-        IPCResult ipcRV = ipcCreate(hlp->ipc_type,
-                                    progname,
-                                    args,
-                                    shortname);
+        rfd = wfd = -1;
+        pid = ipcCreate(hlp->ipc_type,
+                      progname,
+                      args,
+                      shortname,
+                      &rfd,
+                      &wfd,
+			&hIpc);
 
-        if (!ipcRV.success) {
+        if (pid < 0) {
             debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname);
             continue;
         }
@@ -223,12 +234,8 @@
         hlp->n_active++;
 	CBDATA_INIT_TYPE(helper_stateful_server);
         srv = cbdataAlloc(helper_stateful_server);
-#ifdef _SQUID_MSWIN_
-
-        srv->hIpc = ipcRV.hIpc;
-#endif
-
-        srv->pid = ipcRV.pid;
+        srv->hIpc = hIpc;
+        srv->pid = pid;
         srv->flags.reserved = S_HELPER_FREE;
         srv->deferred_requests = 0;
         srv->stats.deferbyfunc = 0;
@@ -236,9 +243,9 @@
         srv->stats.submits = 0;
         srv->stats.releases = 0;
         srv->index = k;
-        srv->rfd = ipcRV.rfd;
-        srv->wfd = ipcRV.wfd;
-        srv->rbuf = (char *)memAllocBuf(8192, &srv->rbuf_sz);
+        srv->rfd = rfd;
+        srv->wfd = wfd;
+         srv->rbuf = (char *)memAllocBuf(8192, &srv->rbuf_sz);
         srv->roffset = 0;
         srv->parent = cbdataReference(hlp);
 
@@ -247,22 +254,22 @@
 
         dlinkAddTail(srv, &srv->link, &hlp->servers);
 
-        if (srv->rfd == srv->wfd) {
+        if (rfd == wfd) {
             snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", shortname, k + 1);
-            fd_note(srv->rfd, fd_note_buf);
+            fd_note(rfd, fd_note_buf);
         } else {
             snprintf(fd_note_buf, FD_DESC_SZ, "reading %s #%d", shortname, k + 1);
-            fd_note(srv->rfd, fd_note_buf);
+            fd_note(rfd, fd_note_buf);
             snprintf(fd_note_buf, FD_DESC_SZ, "writing %s #%d", shortname, k + 1);
-            fd_note(srv->wfd, fd_note_buf);
+            fd_note(wfd, fd_note_buf);
         }
 
-        commSetNonBlocking(srv->rfd);
+        commSetNonBlocking(rfd);
 
-        if (srv->wfd != srv->rfd)
-            commSetNonBlocking(srv->wfd);
+        if (wfd != rfd)
+            commSetNonBlocking(wfd);
 
-        comm_add_close_handler(srv->rfd, helperStatefulServerFree, srv);
+        comm_add_close_handler(rfd, helperStatefulServerFree, srv);
 
         comm_read(srv->rfd, srv->rbuf, srv->rbuf_sz - 1, helperStatefulHandleRead, srv);
 
Index: squid3/src/icmp.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/icmp.cc,v
retrieving revision 1.7.2.8
retrieving revision 1.7.2.9
diff -u -r1.7.2.8 -r1.7.2.9
--- squid3/src/icmp.cc	2 Sep 2006 16:02:52 -0000	1.7.2.8
+++ squid3/src/icmp.cc	3 Sep 2006 16:51:26 -0000	1.7.2.9
@@ -1,6 +1,6 @@
 
 /*
- * $Id: icmp.cc,v 1.7.2.8 2006/09/02 16:02:52 serassio Exp $
+ * $Id: icmp.cc,v 1.7.2.9 2006/09/03 16:51:26 serassio Exp $
  *
  * DEBUG: section 37    ICMP Routines
  * AUTHOR: Duane Wessels
@@ -36,7 +36,6 @@
 
 #include "squid.h"
 #include "comm.h"
-#include "ipc.h"
 
 #if USE_ICMP
 
@@ -53,9 +52,7 @@
 static void icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf);
 #endif
 
-#ifdef _SQUID_MSWIN_
-static HANDLE hIpc;
-#endif
+static void * hIpc;
 static pid_t pid;
 
 static void
@@ -252,6 +249,8 @@
 {
 #if USE_ICMP
     const char *args[2];
+    int rfd;
+    int wfd;
 
     if (strcmp(Config.Program.pinger, "none") == 0) {
         debug(37, 1) ("Pinger disabled\n");
@@ -260,25 +259,20 @@
 
     args[0] = "(pinger)";
     args[1] = NULL;
-    IPCResult ipcRV = ipcCreate(IPC_DGRAM,
-                                Config.Program.pinger,
-                                args,
-                                "Pinger Socket");
+    pid = ipcCreate(IPC_DGRAM,
+                  Config.Program.pinger,
+                  args,
+                  "Pinger Socket",
+                  &rfd,
+                  &wfd,
+			&hIpc);
 
-    if (!ipcRV.success)
+    if (pid < 0)
         return;
 
-#ifdef _SQUID_MSWIN_
-
-    hIpc = ipcRV.hIpc;
-
-    pid = ipcRV.pid;
-
-#endif
-
-    assert(ipcRV.rfd == ipcRV.wfd);
+    assert(rfd == wfd);
 
-    icmp_sock = ipcRV.rfd;
+    icmp_sock = rfd;
 
     fd_note(icmp_sock, "pinger");
 
Index: squid3/src/ipc.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/ipc.cc,v
retrieving revision 1.8.2.21
retrieving revision 1.8.2.22
diff -u -r1.8.2.21 -r1.8.2.22
--- squid3/src/ipc.cc	14 May 2006 17:11:06 -0000	1.8.2.21
+++ squid3/src/ipc.cc	3 Sep 2006 16:51:26 -0000	1.8.2.22
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ipc.cc,v 1.8.2.21 2006/05/14 17:11:06 serassio Exp $
+ * $Id: ipc.cc,v 1.8.2.22 2006/09/03 16:51:26 serassio Exp $
  *
  * DEBUG: section 54    Interprocess Communication
  * AUTHOR: Duane Wessels
@@ -34,1400 +34,252 @@
  */
 
 #include "squid.h"
-#include "ipc.h"
 #include "comm.h"
 #include "fde.h"
-#include "SquidTime.h"
-
-#ifdef _SQUID_MSWIN_
-#ifndef _MSWSOCK_
-#include <mswsock.h>
-#endif
-#include <process.h>
-#endif
-
-class FDPair
-{
-
-public:
-    FDPair() : rfd (-1), wfd (-1) {}
-
-    FDPair (int anFD) : rfd (anFD), wfd (anFD) {}
-
-    FDPair (int r, int w) : rfd (r), wfd (w) {}
-
-    void close();
-    int rfd;
-    int wfd;
-};
-
-
-/* XXX: The mechanics could be made into a strategy and this
-   class a parent for classes that need to spawn.
-   For now, a callforward will do. Alternatively we could
-   make this a template class and use a unary functor.
-   */
-
-class Spawn
-{
-
-public:
-    static Spawn *GetSpawn();
-    virtual ~Spawn(){}
-
-    virtual Spawn *clone() const = 0;
-    virtual bool success() const = 0;
-    /* For windows, until the spawn object is kept around */
-    virtual void * getHandle() const = 0;
-    virtual pid_t getPid() const = 0;
-    typedef unsigned int Child (void *);
-    virtual void splitExecution(Child*, void *) = 0;
-    // virtual ... startProcess(prog, args);
-
-protected:
-    Spawn (){}
-
-    Spawn (Spawn const &){}
-
-    Spawn &operator= (Spawn const &);
-
-private:
-};
-
-#ifdef _SQUID_MSWIN_
-
-class WindowsSpawn : public Spawn
-{
-
-public:
-    WindowsSpawn();
-    virtual Spawn *clone() const;
-    virtual bool success() const;
-    /* For windows, until the spawn object is kept around */
-    virtual void * getHandle() const;
-    virtual pid_t getPid() const;
-    virtual void splitExecution(Child*, void *);
-    ~WindowsSpawn();
-
-protected:
-    WindowsSpawn (WindowsSpawn const &);
-    WindowsSpawn &operator= (WindowsSpawn const &);
-
-private:
-    static unsigned int __stdcall ThreadReflector (void *);
-    Child* newThread;
-    void *data;
-    pid_t pid;
-    int error;
-    unsigned int childRV;
-    unsigned threadID;
-    void * threadHandle;
-};
-
-#else
-
-class UnixSpawn : public Spawn
-{
-
-public:
-    UnixSpawn();
-    virtual Spawn *clone() const;
-    virtual bool success() const;
-    /* For windows, until the spawn object is kept around */
-    virtual void * getHandle() const;
-    virtual pid_t getPid() const;
-    virtual void splitExecution(Child*, void *);
-
-protected:
-    UnixSpawn (UnixSpawn const &);
-    UnixSpawn &operator= (UnixSpawn const &);
-
-private:
-    void child();
-    Child* newThread;
-    void *data;
-    pid_t pid;
-};
-
-#endif
-
-Spawn *
-Spawn::GetSpawn()
-{
-#ifdef _SQUID_MSWIN_
-    return new WindowsSpawn;
-#else
-
-    return new UnixSpawn;
-#endif
-}
-
-class IPC
-{
-
-public:
-    static IPC *Create(int type, const char *prog, const char *const args[], const char *name);
-    static unsigned int ForkChild(void *);
-    IPCResult result() const { return rv;}
-
-    virtual ~IPC()
-    {
-        safe_free (name_);
-        delete mySpawn;
-    }
-
-    virtual IPC *clone() const = 0;
-
-    /* FIXME: move below again */
-
-    FDPair childFD;
-
-    virtual struct sockaddr_in & PS ();
-    Spawn *mySpawn;
-    const char *prog;
-    char * const *args;
-    virtual void childFDConnect();
-    virtual bool childFDConnected() const;
-    virtual int childWrite(char const *, size_t) = 0;
-    void doExec();
-
-protected:
-    IPC (char const *aName);
-    IPC(IPC const &);
-
-    /* not implemented, but the synthetic operator won't do */
-    IPC &operator= (IPC const &);
-
-    void result (IPCResult const& newRV)
-    {
-        rv = newRV;
-    }
-
-    char const *name() const {return name_;}
-
-    virtual void markFailed();
-    virtual void cleanUp();
-    virtual bool openedInitialFDs() const;
-
-    virtual struct sockaddr_in & CS ();
-    //  virtual struct sockaddr_in & PS ();
-    virtual void prepFDsForSpawn();
-    virtual bool preppedFDsForSpawn() const;
-    //  virtual void childFDConnect();
-    //  virtual bool childFDConnected() const;
-    int prfd;
-    int pwfd;
-    static IPC *Factory(int type, char const *name);
-
-private:
-    IPC (IPCResult aResult):rv(aResult){}
-
-    void closeAllFD();
-    IPCResult rv;
-    char const *name_;
-};
-
-#ifndef _SQUID_MSWIN_
-#if ! (HAVE_POLL && defined(_SQUID_OSF_))
-
-class IPCFIFO : public IPC
-{
-
-public:
-    virtual IPC *clone() const;
-    virtual int childWrite(char const *, size_t);
-
-private:
-    friend IPC *IPC::Factory(int, char const *);
-    IPCFIFO (char const *aName);
-};
-
-IPCFIFO::IPCFIFO (char const *aName) : IPC(aName)
-{
-    int p2c[2];
-    int c2p[2];
-
-    if (pipe(p2c) < 0) {
-        debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
-        return;
-    }
-
-    if (pipe(c2p) < 0) {
-        debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
-        return;
-    }
-
-    childFD = FDPair (c2p[0], p2c[1]);
-    fdc_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read");
-    fdc_open(childFD.wfd, FD_PIPE, "IPC FIFO Child Write");
-    fdc_open(childFD.rfd, FD_PIPE, "IPC FIFO Child Read");
-    fdc_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write");
-}
-
-IPC *
-IPCFIFO::clone() const
-{
-    IPCFIFO *rv = new IPCFIFO (*this);
-    return rv;
-}
-
-int
-IPCFIFO::childWrite(char const *buf , size_t len)
-{
-    int result = write(childFD.wfd, buf, len);
-
-    if (result < 0)
-        debug(50, 0) ("write FD %d: %s\n", childFD.wfd, xstrerror());
-
-    return result;
-}
-
-#endif
-#endif
-
-class IPCSocket : public IPC
-{
-
-public:
-    virtual IPC *clone() const = 0;
-
-protected:
-    IPCSocket (char const *aName, int socktype, int proto);
-    IPCSocket (IPCSocket const &);
-    /* not implemented */
-    IPCSocket &operator=(IPCSocket const &);
-
-    virtual struct sockaddr_in & CS ();
-
-    virtual struct sockaddr_in & PS ();
-    virtual void prepFDsForSpawn();
-    virtual bool preppedFDsForSpawn() const;
-    bool fdDetailsRetrieved;
-
-private:
-    int openASocket(int socktype, int proto, int flags) const;
-
-    struct sockaddr_in CS_;
-
-    struct sockaddr_in PS_;
-};
-
-IPCSocket::IPCSocket (char const *aName, int socktype, int proto) : IPC (aName),
-        fdDetailsRetrieved (false)
-{
-#ifdef _SQUID_MSWIN_ /* Windows IPC needs Overlapped sockets */
-    int opt = 0;
-    int optlen = sizeof(opt);
-
-    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
-
-    childFD = FDPair (openASocket (socktype, proto, COMM_NOCLOEXEC));
-
-    prfd = pwfd = openASocket (socktype, proto, 0); /* blocking */
-
-#ifdef _SQUID_MSWIN_ /* Restore sockets to synchronous mode*/
-
-    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
-
-}
-
-IPCSocket::IPCSocket (IPCSocket const &old) : IPC(old), fdDetailsRetrieved (old.fdDetailsRetrieved),
-        CS_(old.CS_), PS_(old.PS_)
-{}
-
-struct sockaddr_in &
-            IPCSocket::CS()
-{
-    return CS_;
-}
-
-struct sockaddr_in &
-            IPCSocket::PS()
-{
-    return PS_;
-}
-
-void
-IPCSocket::prepFDsForSpawn()
-{
-    socklen_t len = sizeof(PS_);
-    memset(&PS_, '\0', len);
-
-    if (getsockname(pwfd, (struct sockaddr *) &PS_, &len) < 0) {
-        debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
-        return;
-    }
-
-    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(childFD.rfd, (struct sockaddr *) &CS_, &len) < 0) {
-        debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
-        return;
-    }
-
-    debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
-                  childFD.rfd, inet_ntoa(CS_.sin_addr), ntohs(CS_.sin_port));
-
-    fdDetailsRetrieved = true;
-}
-
-bool
-IPCSocket::preppedFDsForSpawn() const
-{
-    return fdDetailsRetrieved;
-}
-
-int
-IPCSocket::openASocket(int socktype, int proto, int flags) const
-{
-    return comm_open(socktype,
-                     proto,	/* protocol */
-                     local_addr,
-                     0,		/* port */
-                     flags,	/* blocking */
-                     name());
-}
-
-class IPCTCP : public IPCSocket
-{
-
-public:
-    virtual void prepFDsForSpawn();
-    virtual bool preppedFDsForSpawn() const;
-    virtual IPC *clone() const;
-    virtual int childWrite(char const *, size_t);
-
-protected:
-    virtual void childFDConnect();
-    virtual bool childFDConnected() const;
-
-private:
-    friend IPC *IPC::Factory(int, char const *);
-    IPCTCP (char const *aName);
-    bool childConnected;
-};
-
-IPCTCP::IPCTCP (char const *aName) :
-        IPCSocket(aName, SOCK_STREAM, IPPROTO_TCP) , childConnected(false)
-{}
-
-void
-IPCTCP::prepFDsForSpawn()
-{
-    IPCSocket::prepFDsForSpawn();
-
-    if (!IPCSocket::preppedFDsForSpawn())
-        return;
-
-    if (listen(childFD.rfd, 1) < 0) {
-        debug(50, 1) ("ipcCreate: listen FD %d: %s\n", childFD.rfd, xstrerror());
-        /* Naughty abstraction break ! */
-        fdDetailsRetrieved = false;
-        return;
-    }
-
-    debug(54, 3) ("ipcCreate: FD %d listening...\n", childFD.rfd);
-}
-
-bool
-IPCTCP::preppedFDsForSpawn() const
-{
-    /* TODO: heal the abstraction - call this if our flag is ok, otherwise
-     * return false. (See preFDsForSpawn)
-     */
-    return IPCSocket::preppedFDsForSpawn();
-}
-
-IPC *
-IPCTCP::clone() const
-{
-    IPCTCP *rv = new IPCTCP (*this);
-    return rv;
-}
-
-void
-IPCTCP::childFDConnect()
-{
-    debug(54, 3) ("ipcCreate: calling accept on FD %d\n", childFD.rfd);
-    int tempFD;
-
-    if ((tempFD = accept(childFD.rfd, NULL, NULL)) < 0) {
-        debug(50, 0) ("ipcCreate: FD %d accept: %s\n", childFD.rfd, xstrerror());
-        return;
-    }
-
-    debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", tempFD);
-
-    comm_close(childFD.rfd);
-#ifdef _SQUID_MSWIN_
-
-    char buf1[8192];
-    snprintf(buf1, 8191, "%s CHILD socket", prog);
-    fdc_open(tempFD, FD_SOCKET, buf1);
-    fd_table[tempFD].flags.ipc = 1;
-#endif
-
-    childFD = FDPair (tempFD);
-
-    childConnected = true;
-}
-
-bool
-IPCTCP::childFDConnected() const
-{
-    return childConnected;
-}
-
-int
-IPCTCP::childWrite(char const *buf , size_t len)
-{
-#ifndef _SQUID_MSWIN_
-    int result = write(childFD.wfd, buf, len);
-
-    if (result < 0)
-        debug(50, 0) ("write FD %d: %s\n", childFD.wfd, xstrerror());
-
-#else
-
-    int result = send (childFD.wfd, (const void *) buf, len, 0);
-
-    if (result < 0)
-        debug(50, 0) ("send FD %d: %s\n", childFD.wfd, xstrerror());
-
-#endif
-
-    return result;
-}
-
-
-class IPCUDP : public IPCSocket
-{
-
-public:
-    virtual IPC *clone() const;
-    virtual int childWrite(char const *, size_t);
-
-protected:
-    virtual void childFDConnect();
-    virtual bool childFDConnected() const;
-
-private:
-    friend IPC *IPC::Factory(int, char const *);
-    IPCUDP (char const *aName);
-    bool childConnected;
-};
-
-IPCUDP::IPCUDP (char const *aName) :
-        IPCSocket(aName, SOCK_DGRAM, IPPROTO_UDP), childConnected (false)
-{}
-
-IPC *
-IPCUDP::clone() const
-{
-    IPCUDP *rv = new IPCUDP (*this);
-    return rv;
-}
-
-void
-IPCUDP::childFDConnect()
-{
-    if (comm_connect_addr(childFD.rfd, &PS()) == COMM_ERROR)
-        return;
-
-    childConnected = true;
-}
-
-bool
-IPCUDP::childFDConnected() const
-{
-    return childConnected;
-}
-
-int
-IPCUDP::childWrite(char const *buf , size_t len)
-{
-    int result = comm_udp_send(childFD.wfd, buf, len, 0);
-
-    if (result < 0)
-        debug(50, 0) ("sendto FD %d: %s\n", childFD.wfd, xstrerror());
-
-    return result;
-}
-
-#if HAVE_SOCKETPAIR && defined(AF_UNIX)
-#ifndef _SQUID_MSWIN_
-
-class IPCUNIXStream : public IPC
-{
-
-public:
-    virtual IPC *clone() const;
-    virtual int childWrite(char const *, size_t);
-
-private:
-    friend IPC *IPC::Factory(int, char const *);
-    IPCUNIXStream (char const *aName);
-};
-
-IPCUNIXStream::IPCUNIXStream (char const *aName) : IPC(aName)
-{
-    int fds[2];
-    int buflen = 32768;
-
-    if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
-        debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror());
-        return;
-    }
-
-    setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen));
-    setsockopt(fds[0], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen));
-    setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen));
-    setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen));
-    childFD = FDPair (fds[1]);
-    fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX STREAM Parent");
-    fdc_open(childFD.rfd, FD_PIPE, "IPC UNIX STREAM Child");
-}
-
-IPC *
-IPCUNIXStream::clone() const
-{
-    IPCUNIXStream *rv = new IPCUNIXStream (*this);
-    return rv;
-}
-
-int
-IPCUNIXStream::childWrite(char const *buf , size_t len)
-{
-    int result = write(childFD.wfd, buf, len);
-
-    if (result < 0)
-        debug(50, 0) ("write FD %d: %s\n", childFD.wfd, xstrerror());
-
-    return result;
-}
-
-class IPCUNIXDGram : public IPC
-{
-
-public:
-    virtual IPC *clone() const;
-    virtual int childWrite(char const *, size_t);
-
-private:
-    friend IPC *IPC::Factory(int, char const *);
-    IPCUNIXDGram (char const *aName);
-};
-
-IPCUNIXDGram::IPCUNIXDGram (char const *aName) : IPC(aName)
-{
-    int fds[2];
-
-    if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) < 0) {
-        debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror());
-        return;
-    }
-
-    childFD = FDPair (fds[1]);
-    fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX DGRAM Parent");
-    fdc_open(childFD.rfd, FD_PIPE, "IPC UNIX DGRAM Child");
-}
-
-IPC *
-IPCUNIXDGram::clone() const
-{
-    IPCUNIXDGram *rv = new IPCUNIXDGram (*this);
-    return rv;
-}
-
-int
-IPCUNIXDGram::childWrite(char const *buf , size_t len)
-{
-    int result = comm_udp_send(childFD.wfd, buf, len, 0);
-
-    if (result < 0)
-        debug(50, 0) ("sendto FD %d: %s\n", childFD.wfd, xstrerror());
-
-    return result;
-}
-
-#endif
-#endif
-
-IPC *
-IPC::Factory (int type, char const *name)
-{
-    if (type == IPC_TCP_SOCKET)
-        return new IPCTCP (name);
-
-#ifndef _SQUID_MSWIN_
-#if !(USE_POLL && defined(_SQUID_OSF_))
-
-    if (type == IPC_FIFO)
-        return new IPCFIFO (name);
-
-#endif
-#endif
-
-    if (type == IPC_UDP_SOCKET)
-        return new IPCUDP (name);
-
-#if HAVE_SOCKETPAIR && defined(AF_UNIX)
-#ifndef _SQUID_MSWIN_
-
-    if (type == IPC_UNIX_STREAM)
-        return new IPCUNIXStream (name);
-
-    if (type == IPC_UNIX_DGRAM)
-        return new IPCUNIXDGram (name);
-
-#endif
-#endif
-
-    fatal ("Unexpected IPC type : check your source\n");
-
-    return NULL;
-}
-
-void
-IPC::markFailed()
-{
-    result(IPCResult(false));
-}
-
-struct sockaddr_in &
-            IPC::CS ()
-{
-    fatal("attempt to get Client Socket for non socket IPC class\n");
-
-    struct sockaddr_in *f = new struct sockaddr_in;
-    return *f;
-}
-
-struct sockaddr_in &
-            IPC::PS ()
-{
-    fatal("attempt to get Parent Socket for non socket IPC class\n");
-
-    struct sockaddr_in *f = new struct sockaddr_in;
-    return *f;
-}
-
-void
-IPC::prepFDsForSpawn()
-{}
-
-bool
-IPC::preppedFDsForSpawn() const
-{
-    return true;
-}
-
-void
-IPC::childFDConnect()
-{}
-
-bool
-IPC::childFDConnected() const
-{
-    return true;
-}
-
-class IPCInstance
-{
-
-public:
-    static char const *ShutdownMessage;
-
-    IPCInstance(int aType, pid_t aPid, char const *program, int fromChildFD, int toParentFD) : type (aType),
-            pid(aPid), prog (xstrdup(program)), prfd (fromChildFD),
-    send_fd (toParentFD){}
-
-    virtual ~IPCInstance()
-    {
-        safe_free(prog);
-    }
-
-    virtual void childToParentLoop();
-
-protected:
-    /* Not implemented */
-    IPCInstance(IPCInstance const &);
-    IPCInstance &operator= (IPCInstance const &);
-
-private:
-    /* what sort of IPC we are */
-    int const type;
-    /* if this is really IPC to another process, the process id. */
-    pid_t pid;
-    /* What program it is */
-    char *prog;
-    /* the parent uses this to read from the child */
-    int const prfd;
-    int const send_fd;
-};
-
-char const *IPCInstance::ShutdownMessage = "$shutdown\n";
-
-#ifdef _SQUID_MSWIN_
-
-struct ipc_params
-{
-    static unsigned int ThreadReflector (void *); // ipc_params *
-    ipc_params (int aType) : type(aType), prfd_ipc (-1), pwfd_ipc(-1), crfd_ipc(-1), cwfd_ipc(-1),
-            hProcess(NULL), thread(NULL), pid (-1), niceprog(NULL)
-#if HAVE_PUTENV
-            , env_str(NULL)
-#endif
-    {
-        p2c[0]=-1;
-        p2c[1]=-1;
-        c2p[0]=-1;
-        c2p[1]=-1;
-    }
-    ~ipc_params()
-    {
-        delete myIPC;
-    }
-
-    int const type;
-    const char *prog;
-    char **args;
-    IPC *myIPC;
-
-private:
-    unsigned int threadLoop();
-    void freeResources();
-    void normalExit();
-    void parentToChildLoop();
-    int p2c[2];
-    int c2p[2];
-    int prfd_ipc, pwfd_ipc, crfd_ipc, cwfd_ipc;
-    HANDLE hProcess;
-    HANDLE thread;
-    pid_t pid;
-    char *niceprog;
-    char buf1[8192];
-#if HAVE_PUTENV
-
-    char *env_str;
-#endif
-};
-
-struct thread_params
-{
-    int type;
-    int rfd;
-    int send_fd;
-    const char *prog;
-    pid_t pid;
-};
-
-static unsigned int __stdcall ipc_thread_2(void *); // thread_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];
-
-void
-FDPair::close()
-{
-    if (rfd >= 0)
-        comm_close(rfd);
-
-    if (rfd != wfd &&
-            wfd >= 0)
-        comm_close (wfd);
-
-    rfd = wfd = -1;
-}
-
-#ifdef _SQUID_MSWIN_
-static void
-ipcCloseAllFD(int prfd, int pwfd)
-{
-    FDPair (prfd, pwfd).close();
-}
-
-#endif
-
-static void
-PutEnvironment()
-{
-#if HAVE_PUTENV
-    char *env_str;
-    int tmp_s;
-    env_str = (char *)xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
-    snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
-    putenv(env_str);
-#endif
-}
-
-void
-IPC::closeAllFD()
-{
-    FDPair (prfd, pwfd).close();
-    childFD.close();
-}
-
-void
-IPC::cleanUp()
-{
-    delete mySpawn;
-    mySpawn = NULL;
-    closeAllFD();
-}
-
-void
-reserveFD0Thru2(int crfd)
-{
-    /*
-     * This double-dup stuff avoids problems when one of 
-     *  crfd, cwfd, or debug_log are in the range 0-2.
-     */
-    int openrv;
-
-    do {
-        /* First make sure 0-2 is occupied by something. Gets cleaned up later */
-        openrv = dup(crfd);
-        assert(openrv > -1);
-    } while (openrv < 3 && openrv > -1);
-
-    close(openrv);
-}
-
-void
-IPC::doExec()
-{
-#ifndef _SQUID_MSWIN_
-    int t1, t2, t3;
-    reserveFD0Thru2(childFD.rfd);
-    t1 = dup(childFD.rfd);
-    t2 = dup(childFD.wfd);
-    t3 = dup(fileno(debug_log));
-    assert(t1 > 2 && t2 > 2 && t3 > 2);
-    close(childFD.rfd);
-    close(childFD.wfd);
-    close(fileno(debug_log));
-    dup2(t1, 0);
-    dup2(t2, 1);
-    dup2(t3, 2);
-    close(t1);
-    close(t2);
-    close(t3);
-    /* Make sure all other filedescriptors are closed */
-
-    for (int loopIndex = 3; loopIndex < SQUID_MAXFD; ++loopIndex)
-        close(loopIndex);
-
-    if (opt_no_daemon) {
-        squid_signal(SIGINT, SIG_IGN, SA_RESETHAND);
-        squid_signal(SIGHUP, SIG_IGN, SA_RESETHAND);
-    }
-
-    execvp(prog, (char *const *) args);
-
-    debug_log = fdopen(2, "a+");
-
-    debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror());
-
-    _exit(1);
-
-#else
-    /* NT code goes here eventually */
-#endif
-}
-
-IPCResult
-ipcCreate(int type, const char *prog, const char *const args[], const char *name)
-{
-    IPC *newIPC = IPC::Create(type, prog, args, name);
-    IPCResult result = newIPC->result();
-    delete newIPC;
-    return result;
-}
-
-IPC::IPC(char const *aName): mySpawn(NULL), prfd(-1), pwfd(-1)
-        , rv(false) , name_ (xstrdup(aName))
-{}
-
-/* yes. we have *real* remote ownership issues with prog and args */
-IPC::IPC (IPC const &old):childFD(old.childFD), mySpawn(old.mySpawn->clone()),
-        prog (old.prog), args (old.args),
-        prfd(old.prfd), pwfd (old.pwfd)
-        , rv(old.rv), name_ (xstrdup(old.name_))
-{}
-
-bool
-IPC::openedInitialFDs() const
-{
-    if (childFD.rfd < 0) {
-        debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
-        return false;
-    }
-
-    if (pwfd < 0) {
-        debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
-        return false;
-    }
-
-    return true;
-}
-
-#ifdef _SQUID_MSWIN_
-static int
-ipcSend(int cwfd, const char *buf, int len)
-{
-    int result = send(cwfd, (const void *) buf, len, 0);
-
-    if (result < 0) {
-        debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
-        debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
-    }
-
-    return result;
-}
-
-struct SpawnResult
-{
-    SpawnResult() : hProcess (NULL), pid (-1), error (0){}
-
-    HANDLE hProcess;
-    pid_t pid;
-    int error;
-};
-
-static
-SpawnResult
-ipc_spawn(const char *prog, char **args)
-{
-    char buf1[8192];
-    STARTUPINFO si;
-    PROCESS_INFORMATION pi;
-
-    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 (int x = 3; x < SQUID_MAXFD; x++) {
-        fde *F = &fd_table[x];
-
-        if (F->win32.handle == 0)
-            continue;
-
-        SetHandleInformation((HANDLE) F->win32.handle, HANDLE_FLAG_INHERIT, 0);
-    }
-
-    *buf1 = '\0';
-    strcpy(buf1 + 4096, prog);
-    char *str = strtok(buf1 + 4096, w_space);
-
-    do {
-        strcat(buf1, str);
-        strcat(buf1, " ");
-    } while ((str = strtok(NULL, w_space)));
-
-    int loopIndex = 1;
-
-    while (args[loopIndex]) {
-        strcat(buf1, args[loopIndex++]);
-        strcat(buf1, " ");
-    }
-
-    SpawnResult result;
-
-    if (CreateProcess(buf1 + 4096, buf1, NULL, NULL, TRUE, CREATE_NO_WINDOW,
-                      NULL, NULL, &si, &pi)) {
-        result.pid = pi.dwProcessId;
-        result.hProcess = pi.hProcess;
-    } else {
-        WIN32_maperror(GetLastError());
-        result.error = errno;
-    }
-
-    return result;
-}
-
-unsigned int
-ipc_params::ThreadReflector(void *voidParam)
-{
-
-    struct ipc_params *params = static_cast<struct ipc_params *>(voidParam);
-    unsigned int result = params->threadLoop();
-    delete params;
-    return result;
-}
-
-#endif
-
-#ifdef _SQUID_MSWIN_
-
-WindowsSpawn::WindowsSpawn(): newThread (NULL), data(NULL),
-        pid(-1), error (0), childRV (0), threadID (0), threadHandle(NULL)
-{}
-
-WindowsSpawn::WindowsSpawn(WindowsSpawn const &old) : Spawn (old), newThread (old.newThread),
-        data (old.data), pid (old.pid), error (old.error), childRV (old.childRV), threadID (old.threadID)
-{
-    if (old.threadHandle)
-        DuplicateHandle (GetCurrentProcess(), old.threadHandle,GetCurrentProcess(), &threadHandle, 0,FALSE,DUPLICATE_SAME_ACCESS);
-}
-
-WindowsSpawn::~WindowsSpawn()
-{
-    if (threadHandle != NULL)
-        CloseHandle(threadHandle);
-
-    threadHandle = NULL;
-}
-
-unsigned int __stdcall
-WindowsSpawn::ThreadReflector (void *me_)
-{
-    WindowsSpawn *me = static_cast<WindowsSpawn*>(me_);
-    assert (me->newThread != NULL);
-    me->childRV = me->newThread (me->data);
-    return me->childRV;
-}
-
-Spawn *
-WindowsSpawn::clone() const
-{
-    WindowsSpawn *result = new WindowsSpawn (*this);
-    return result;
-}
-
-bool
-WindowsSpawn::success() const
-{
-    return threadID != 0;
-}
-
-void *
-WindowsSpawn::getHandle() const
-{
-    return threadHandle;
-}
-
-pid_t
-WindowsSpawn::getPid() const
-{
-    assert (0);
-    return pid;
-}
+static char hello_buf[HELLO_BUF_SZ];
 
-void
-WindowsSpawn::splitExecution(Spawn::Child *_newThread, void *_data)
+static int
+ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd)
 {
-    newThread = _newThread;
-    data = _data;
-    HANDLE beginRv =
-        (HANDLE) _beginthreadex(NULL, 0, ThreadReflector, this, 0, &threadID);
-
-    if (!beginRv) {
-        debug(50, 1) ("ipcCreate: _beginthreadex: %s\n", xstrerror());
-    } else {
-        assert (threadID != 0);
-        /* undocumented! */
-        threadHandle =  beginRv;
-        debug(50, 1) ("WindowsSpawn::splitExecution: Handle: 0x%x, ThreadID: %d\n", (unsigned) threadHandle,threadID);
-    }
-}
+    if (prfd >= 0)
+        comm_close(prfd);
 
-#else
-UnixSpawn::UnixSpawn() :newThread (NULL), data(NULL),
-        pid(-1)
-{}
+    if (prfd != pwfd)
+        if (pwfd >= 0)
+            comm_close(pwfd);
 
-UnixSpawn::UnixSpawn(UnixSpawn const &old)
-{}
+    if (crfd >= 0)
+        comm_close(crfd);
 
-Spawn *
-UnixSpawn::clone() const
-{
-    UnixSpawn *result = new UnixSpawn (*this);
-    return result;
-}
+    if (crfd != cwfd)
+        if (cwfd >= 0)
+            comm_close(cwfd);
 
-bool
-UnixSpawn::success() const
-{
-    return pid > -1;
+    return -1;
 }
 
-void *
-UnixSpawn::getHandle() const
+static void
+PutEnvironment()
 {
-    assert (0);
-    return NULL;
+#if HAVE_PUTENV
+    char *env_str;
+    int tmp_s;
+    env_str = (char *)xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
+    snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
+    putenv(env_str);
+#endif
 }
 
-pid_t
-UnixSpawn::getPid() const
+int
+ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd)
 {
-    return pid;
-}
+    pid_t pid;
 
-void
-UnixSpawn::splitExecution(Spawn::Child *_newThread, void *_data)
-{
-    newThread = _newThread;
-    data = _data;
+    struct sockaddr_in ChS;
 
-    if ((pid = fork()) < 0) {
-        debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror());
-    } else if (pid > 0) {
-        /* parent */
-        return;
-    } else {
-        /* Still checked outside here */
-        child();
-    }
-}
+    struct sockaddr_in PaS;
+    int crfd = -1;
+    int prfd = -1;
+    int cwfd = -1;
+    int pwfd = -1;
+    int fd;
+    int t1, t2, t3;
+    socklen_t len;
+    int x;
 
-void
-UnixSpawn::child()
-{
-    /*exit(*/newThread(data)/*)*/;
-}
+#if USE_POLL && defined(_SQUID_OSF_)
 
+    assert(type != IPC_FIFO);
 #endif
 
-unsigned int
-IPC::ForkChild(void *data)
-{
-    IPC *result = static_cast<IPC*>(data);
-    assert (result);
-#ifndef _SQUID_MSWIN_
-    /* child */
-    no_suid();			/* give up extra priviliges */
-    /* close shared socket with parent */
-    comm_close(result->prfd);
-
-    if (result->pwfd != result->prfd)
-        close(result->pwfd);
+    if (rfd)
+        *rfd = -1;
 
-    result->pwfd = result->prfd = -1;
-
-#else
-#endif
-
-    /* Until we are entire in this routine */
-    return 0;
-}
+    if (wfd)
+        *wfd = -1;
+
+    if (type == IPC_TCP_SOCKET) {
+        crfd = cwfd = comm_open(SOCK_STREAM,
+                                0,
+                                local_addr,
+                                0,
+                                COMM_NOCLOEXEC,
+                                name);
+        prfd = pwfd = comm_open(SOCK_STREAM,
+                                0,			/* protocol */
+                                local_addr,
+                                0,			/* port */
+                                0,			/* blocking */
+                                name);
+    } else if (type == IPC_UDP_SOCKET) {
+        crfd = cwfd = comm_open(SOCK_DGRAM,
+                                0,
+                                local_addr,
+                                0,
+                                COMM_NOCLOEXEC,
+                                name);
+        prfd = pwfd = comm_open(SOCK_DGRAM,
+                                0,
+                                local_addr,
+                                0,
+                                0,
+                                name);
+    } else if (type == IPC_FIFO) {
+        int p2c[2];
+        int c2p[2];
+
+        if (pipe(p2c) < 0) {
+            debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
+            return -1;
+        }
+
+        if (pipe(c2p) < 0) {
+            debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
+            return -1;
+        }
+
+        fdc_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read");
+        fdc_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write");
+        fdc_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read");
+        fdc_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write");
+#if HAVE_SOCKETPAIR && defined(AF_UNIX)
 
-IPC *
-IPC::Create (int type, const char *prog, const char *const args[], const char *name)
-{
-    IPC *result = NULL;
-    /* get our candidate object */
-    assert (result = Factory (type, name));
-#ifndef _SQUID_MSWIN_
+    } else if (type == IPC_UNIX_STREAM) {
+        int fds[2];
+        int buflen = 32768;
+
+        if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
+            debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror());
+            return -1;
+        }
+
+        setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen));
+        setsockopt(fds[0], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen));
+        setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen));
+        setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen));
+        fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX STREAM Parent");
+        fdc_open(crfd = cwfd = fds[1], FD_PIPE, "IPC UNIX STREAM Parent");
+    } else if (type == IPC_UNIX_DGRAM) {
+        int fds[2];
+
+        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) < 0) {
+            debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror());
+            return -1;
+        }
 
-    int tempFD;
+        fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX DGRAM Parent");
+        fdc_open(crfd = cwfd = fds[1], FD_PIPE, "IPC UNIX DGRAM Parent");
 #endif
 
-    int x;
-
-    debug(54, 3) ("ipcCreate: prfd FD %d\n", result->prfd);
-    debug(54, 3) ("ipcCreate: pwfd FD %d\n", result->pwfd);
-    debug(54, 3) ("ipcCreate: crfd FD %d\n", result->childFD.rfd);
-    debug(54, 3) ("ipcCreate: cwfd FD %d\n", result->childFD.wfd);
-
-    if (!result->openedInitialFDs()) {
-        result->cleanUp();
-        return result;
+    } else {
+        assert(IPC_NONE);
     }
 
-    result->prepFDsForSpawn();
+    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 (!result->preppedFDsForSpawn()) {
-        result->cleanUp();
-        return result;
+    if (crfd < 0) {
+        debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
+        return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
     }
 
-    /* flush or else we get dup data if unbuffered_logs is set */
-    logsFlush();
-
-    result->mySpawn = Spawn::GetSpawn();
-
-    result->prog = prog;
-
-    result->args = const_cast<char* const*>(args);
-
-#ifdef _SQUID_MSWIN_
+    if (pwfd < 0) {
+        debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
+        return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+    }
 
-    ipc_params *params = new ipc_params (type);
+    if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
+        len = sizeof(PaS);
+        memset(&PaS, '\0', len);
 
-    /* Note to self: we must always clone result, even if
-       we eliminate the ipc_params class, because using a single instance
-       might overlap on variable usage. Until the code is fully 
-       reorganised, cloning is safer.
-       Later on we might want to make threadsafe IPC classes ..
-       */
-    params->myIPC = result->clone();
+        if (getsockname(pwfd, (struct sockaddr *) &PaS, &len) < 0) {
+            debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
+            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+        }
 
-    params->prog = prog;
+        debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
+                      pwfd, inet_ntoa(PaS.sin_addr), ntohs(PaS.sin_port));
+        len = sizeof(ChS);
+        memset(&ChS, '\0', len);
 
-    params->args = (char **) args;
+        if (getsockname(crfd, (struct sockaddr *) &ChS, &len) < 0) {
+            debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
+            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+        }
 
-    result->mySpawn->splitExecution ((Spawn::Child *)ipc_params::ThreadReflector, params);
+        debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
+                      crfd, inet_ntoa(ChS.sin_addr), ntohs(ChS.sin_port));
+    }
 
-#else
+    if (type == IPC_TCP_SOCKET) {
+        if (listen(crfd, 1) < 0) {
+            debug(50, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror());
+            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+        }
 
-    result->mySpawn->splitExecution (ForkChild, result);
+        debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd);
+    }
 
-#endif
+    /* flush or else we get dup data if unbuffered_logs is set */
+    logsFlush();
 
-    if (!result->mySpawn->success()) {
-        result->cleanUp();
-        return result;
+    if ((pid = fork()) < 0) {
+        debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror());
+        return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
     }
 
-#ifndef _SQUID_MSWIN_
-    if (result->mySpawn->getPid() > 0) {		/* parent */
+    if (pid > 0) {		/* parent */
         /* close shared socket with child */
-        result->childFD.close();
+        comm_close(crfd);
 
-        if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
-#else
-    {
-        {
-#endif
+        if (cwfd != crfd)
+            comm_close(cwfd);
+
+        cwfd = crfd = -1;
 
-            if (comm_connect_addr(result->pwfd, &result->CS()) == COMM_ERROR)
-            {
-                result->cleanUp();
-                return result;
-            }
+        if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
+            if (comm_connect_addr(pwfd, &ChS) == COMM_ERROR)
+                return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
         }
-        memset(hello_buf, '\0', HELLO_BUF_SZ);
-#ifdef _SQUID_MSWIN_
 
-        x = recv(result->prfd, (void *) hello_buf, HELLO_BUF_SZ - 1, 0);
-#else
+        memset(hello_buf, '\0', HELLO_BUF_SZ);
 
         if (type == IPC_UDP_SOCKET)
-            x = comm_udp_recv(result->prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
+            x = comm_udp_recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
         else
-            x = read(result->prfd, hello_buf, HELLO_BUF_SZ - 1);
-
-#endif
+            x = read(prfd, hello_buf, HELLO_BUF_SZ - 1);
 
-        if (x < 0)
-        {
+        if (x < 0) {
             debug(50, 0) ("ipcCreate: PARENT: hello read test failed\n");
             debug(50, 0) ("--> read: %s\n", xstrerror());
-            result->cleanUp();
-            return result;
-        } else if (strcmp(hello_buf, hello_string))
-        {
+            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
+        } 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));
-            result->cleanUp();
-            return result;
-        }
-
-#ifdef _SQUID_MSWIN_
-        x = send(result->pwfd, (const void *) ok_string, strlen(ok_string), 0);
-
-        if (x < 0)
-        {
-            debug(50, 0) ("ipcCreate: PARENT: OK write test failed\n");
-            debug(50, 0) ("--> read: %s\n", xstrerror());
-            result->cleanUp();
-            return result;
-        }
-
-        memset(hello_buf, '\0', HELLO_BUF_SZ);
-        x = recv(result->prfd, (void *) hello_buf, HELLO_BUF_SZ - 1, 0);
-
-        if (x < 0)
-        {
-            debug(50, 0) ("ipcCreate: PARENT: OK read test failed\n");
-            debug(50, 0) ("--> read: %s\n", xstrerror());
-            result->cleanUp();
-            return result;
-        } 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));
-            result->cleanUp();
-            return result;
+            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
         }
 
-        hello_buf[x] = '\0';
-        pid_t pid = atol(hello_buf);
-        HANDLE HProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
-
-#endif
-
-        commSetTimeout(result->prfd, -1, NULL, NULL);
-        commSetNonBlocking(result->prfd);
-        commSetNonBlocking(result->pwfd);
-        fd_table[result->prfd].flags.ipc = 1;
-        fd_table[result->pwfd].flags.ipc = 1;
-#ifdef _SQUID_MSWIN_
-
-        fd_table[result->childFD.rfd].flags.ipc = 1;
-        fd_table[result->childFD.wfd].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;
+        commSetTimeout(prfd, -1, NULL, NULL);
+        commSetNonBlocking(prfd);
+        commSetNonBlocking(pwfd);
 
-            Sleep(sl);
-        }
+        if (rfd)
+            *rfd = prfd;
 
-        DWORD ecode = 0;
+        if (wfd)
+            *wfd = pwfd;
 
-        if (GetExitCodeThread(result->mySpawn->getHandle(), &ecode) && ecode == STILL_ACTIVE)
-        {
-            result->result (IPCResult(true, pid, result->prfd, result->pwfd, HProcess));
-            debugs(50, 1, "IPC::Create: Program: " << prog << ", PID: " << ", Handle: 0x" << HProcess);
-
-            return result;
-        } else
-        {
-            result->cleanUp();
-            return result;
-        }
+        fd_table[prfd].flags.ipc = 1;
 
-#else
+        fd_table[pwfd].flags.ipc = 1;
 
-        if (Config.sleep_after_fork)
-        {
+        if (Config.sleep_after_fork) {
             /* XXX emulation of usleep() */
 
             struct timeval sl;
@@ -1436,210 +288,79 @@
             select(0, NULL, NULL, NULL, &sl);
         }
 
-        result->result (IPCResult (true, result->mySpawn->getPid(), result->prfd, result->pwfd));
-        return result;
-#endif
-
+        return pid;
     }
-#ifdef _SQUID_MSWIN_
-}
-
-unsigned int
-ipc_params::threadLoop() {
-    int t1, t2, t3;
-
-    struct thread_params thread_params;
-    int tempFD = -1;
-    char *str;
-    int tmp_s;
-
-    struct sockaddr_in CS_ipc, PS_ipc;
-
-    strcpy(buf1, prog);
-    niceprog = strtok(buf1, w_space);
-
-    if ((str = strrchr(niceprog, '/')))
-        niceprog = ++str;
-
-    if ((str = strrchr(niceprog, '\\')))
-        niceprog = ++str;
-
-    niceprog = xstrdup(niceprog);
-
-    assert (myIPC);
 
-    IPC *result = myIPC;
-
-    /* ForkChild is called directly from non windows routines */
-    IPC::ForkChild (myIPC);
-
-#endif
-
-    result->childFDConnect();
-
-    if (!result->childFDConnected())  {
-#ifdef _SQUID_MSWIN_
-        freeResources();
-        return 1;
-#else
-
-        result->cleanUp();
-        _exit (1);
-#endif
-
-    }
+    /* child */
+    no_suid();			/* give up extra priviliges */
 
-    tempFD = result->childFD.rfd;
+    /* close shared socket with parent */
+    close(prfd);
 
-    /* XXX: candidate for extract method */
-    {
-        int sendresult = result->childWrite(hello_string, strlen(hello_string) + 1);
+    if (pwfd != prfd)
+        close(pwfd);
 
-        if (sendresult < 0)
-        {
-            debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
-#ifdef _SQUID_MSWIN_
+    pwfd = prfd = -1;
 
-            freeResources();
-            return 1;
-#else
+    if (type == IPC_TCP_SOCKET) {
+        debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd);
 
-            result->cleanUp();
+        if ((fd = accept(crfd, NULL, NULL)) < 0) {
+            debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
             _exit(1);
-#endif
-
         }
-    }
-    PutEnvironment();
-#ifndef _SQUID_MSWIN_
-
-    result->doExec();
-    return 0;
-#else
-
-    memset(buf1, '\0', sizeof(buf1));
-    int recvresult = recv(myIPC->childFD.rfd, (void *) buf1, 8191, 0);
-
-    if (recvresult < 0) {
-        debug(50, 0) ("ipcCreate: CHILD: OK read test failed\n");
-        debug(50, 0) ("--> read: %s\n", xstrerror());
-        freeResources();
-        return 1;
-    } else if (strcmp(buf1, ok_string)) {
-        debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
-        debug(54, 0) ("--> read returned %d\n", recvresult);
-        debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
-        freeResources();
-        return 1;
-    }
-
-    /* create FDs for child */
-
-    if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
-        debug(50, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
-        ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-        freeResources();
-        return 1;
-    }
 
-    if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
-        debug(50, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
-        ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-        freeResources();
-        return 1;
+        debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd);
+        close(crfd);
+        cwfd = crfd = fd;
+    } else if (type == IPC_UDP_SOCKET) {
+        if (comm_connect_addr(crfd, &PaS) == COMM_ERROR)
+            return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
     }
 
-    /* assign file descriptors to child process */
     if (type == IPC_UDP_SOCKET) {
-        snprintf(buf1, 8192, "%s(%ld) <-> ipc CHILD socket", niceprog, -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",
-                      niceprog);
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        }
-
-        snprintf(buf1, 8192, "%s(%ld) <-> ipc PARENT socket", niceprog, -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",
-                      niceprog);
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        }
-
-        tmp_s = sizeof(PS_ipc);
-        memset(&PS_ipc, '\0', tmp_s);
-
-        if (getsockname(pwfd_ipc, (struct sockaddr *) &PS_ipc, &tmp_s) < 0) {
-            debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        }
-
-        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(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        }
-
-        debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
-                      crfd_ipc, inet_ntoa(CS_ipc.sin_addr), ntohs(CS_ipc.sin_port));
+        x = comm_udp_send(cwfd, hello_string, strlen(hello_string) + 1, 0);
 
-        if (comm_connect_addr(pwfd_ipc, &CS_ipc) == COMM_ERROR) {
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
+        if (x < 0) {
+            debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
+            debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
+            _exit(1);
         }
-
-        tempFD = myIPC->childFD.rfd;
-
-        if (comm_connect_addr(crfd_ipc, &PS_ipc) == COMM_ERROR) {
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
+    } else {
+        if (write(cwfd, hello_string, strlen(hello_string) + 1) < 0) {
+            debug(50, 0) ("write FD %d: %s\n", cwfd, xstrerror());
+            debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
+            _exit(1);
         }
-    }		/* IPC_UDP_SOCKET */
-
-    assert (tempFD == myIPC->childFD.rfd);
-
-    t1 = dup(0);
-
-    t2 = dup(1);
+    }
 
-    t3 = dup(2);
+    PutEnvironment();
+    /*
+     * This double-dup stuff avoids problems when one of 
+     *  crfd, cwfd, or debug_log are in the rage 0-2.
+     */
 
-    dup2(c2p[0], 0);
+    do {
+        /* First make sure 0-2 is occupied by something. Gets cleaned up later */
+        x = dup(crfd);
+        assert(x > -1);
+    } while (x < 3 && x > -1);
 
-    dup2(p2c[1], 1);
+    close(x);
 
-    dup2(fileno(debug_log), 2);
+    t1 = dup(crfd);
 
-    close(c2p[0]);
+    t2 = dup(cwfd);
 
-    close(p2c[1]);
+    t3 = dup(fileno(debug_log));
 
-    commUnsetNonBlocking(tempFD);
+    assert(t1 > 2 && t2 > 2 && t3 > 2);
 
-    SpawnResult spawnResult = ipc_spawn (prog, args);
+    close(crfd);
 
-    pid = spawnResult.pid;
+    close(cwfd);
 
-    hProcess = spawnResult.hProcess;
+    close(fileno(debug_log));
 
     dup2(t1, 0);
 
@@ -1653,315 +374,22 @@
 
     close(t3);
 
-    if (pid == -1) {
-        errno = spawnResult.error;
-        debug(50, 0) ("ipcCreate: CHILD: %s: %s\n", prog, xstrerror());
-        ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-        freeResources();
-        return 1;
-    }
-
-    /* Ok, the child has started */
-    if (type == IPC_UDP_SOCKET) {
-        WSAPROTOCOL_INFO wpi;
-
-        memset(&wpi, 0, sizeof(wpi));
-
-        if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc, pid, &wpi)) {
-            debug(50, 0) ("ipcCreate: CHILD: WSADuplicateSocket: %s\n",
-                          xstrerror());
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        }
-
-        int writeresult = write(c2p[1], (const char *) &wpi, sizeof(wpi));
-
-        if (writeresult < 0 || static_cast <size_t>(writeresult) < sizeof(wpi)) {
-            debug(50, 0)
-            ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
-             xstrerror());
-            debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-                          niceprog);
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        }
-
-        int readresult = read(p2c[0], buf1, 8192);
-
-        if (readresult < 0) {
-            debug(50, 0)
-            ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
-             xstrerror());
-            debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-                          niceprog);
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        } else if (strncmp(buf1, ok_string, strlen(ok_string))) {
-            debug(54, 0)
-            ("ipcCreate: CHILD: %s: socket exchange failed\n",
-             niceprog);
-            debug(54, 0) ("--> read returned %d\n", readresult);
-            buf1[readresult] = '\0';
-            debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        }
-
-        int write2result = write(c2p[1], (const char *) &PS_ipc, sizeof(PS_ipc));
-
-        if (write2result < 0 || static_cast<size_t>(write2result) < sizeof(PS_ipc)) {
-            debug(50, 0)
-            ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
-             xstrerror());
-            debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-                          niceprog);
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        }
-
-        int read2result = read(p2c[0], buf1, 8192);
-
-        if (read2result < 0) {
-            debug(50, 0)
-            ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
-             xstrerror());
-            debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
-                          niceprog);
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        } else if (strncmp(buf1, ok_string, strlen(ok_string))) {
-            debug(54, 0)
-            ("ipcCreate: CHILD: %s: socket exchange failed\n",
-             niceprog);
-            debug(54, 0) ("--> read returned %d\n", read2result);
-            buf1[read2result] = '\0';
-            debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
-            ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-            freeResources();
-            return 1;
-        }
-
-        /* We should error check this send */
-        send(pwfd_ipc, (const void *) ok_string, strlen(ok_string), 0);
-        int recvrv = recv(prfd_ipc, (void *) (buf1 + 200), 8191 - 200, 0);
-        assert((size_t) recvrv == strlen(ok_string)
-               && !strncmp(ok_string, buf1 + 200, strlen(ok_string)));
-    }	/* IPC_UDP_SOCKET */
-
-    snprintf(buf1, 8191, "%s(%ld) CHILD socket", niceprog, (long int)pid);
-
-    fd_note(tempFD, buf1);
-
-    if (prfd_ipc != -1) {
-        snprintf(buf1, 8191, "%s(%ld) <-> ipc CHILD socket", niceprog, (long int)pid);
-        fd_note(crfd_ipc, buf1);
-        snprintf(buf1, 8191, "%s(%ld) <-> ipc PARENT socket", niceprog, (long int)pid);
-        fd_note(prfd_ipc, buf1);
-    }				/* else {                      // IPC_TCP_SOCKET
-
-    * commSetNoLinger(fd);
-    * }
-    */
-    thread_params.prog = niceprog;
-
-    thread_params.send_fd = myIPC->childFD.wfd;
-
-    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(50, 0) ("ipcCreate: CHILD: _beginthreadex: %s\n", xstrerror());
-        ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string));
-        freeResources();
-        return 1;
-    }
-
-    snprintf(buf1, 8191, "%ld\n", (long int)pid);
-
-    if (-1 == ipcSend(myIPC->childFD.wfd, buf1, strlen(buf1))) {
-        freeResources();
-        return 1;
-    }
-
-    debug(54, 2) ("ipc(%s,%ld): started successfully\n", niceprog, (long int)pid);
-    parentToChildLoop();
-
-    normalExit();
-    freeResources();
-    return 0;
-}
-
-void
-ipc_params::normalExit() {
-    debug(54, 2) ("ipc(%s,%d): normal exit\n", niceprog, pid);
-}
-
-void
-ipc_params::freeResources() {
-    if (c2p[1] != -1)
-        close(c2p[1]);
-
-    if (fd_table[myIPC->childFD.rfd].flags.open)
-        myIPC->childFD.close();
-
-    if (prfd_ipc != -1) {
-        send(crfd_ipc, (const void *) shutdown_string, strlen(shutdown_string), 0);
-        shutdown(crfd_ipc, SD_BOTH);
-        shutdown(prfd_ipc, SD_BOTH);
-    }
-
-    ipcCloseAllFD(prfd_ipc, pwfd_ipc);
-    myIPC->childFD.close();
-
-    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",
-                      niceprog, pid, niceprog, 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",
-         niceprog, pid);
-    }
-
-    getCurrentTime();
-    safe_free(niceprog);
-#if HAVE_PUTENV
-
-    safe_free(env_str);
-#endif
-
-    if (thread)
-        CloseHandle(thread);
-
-    if (hProcess)
-        CloseHandle(hProcess);
-
-    if (p2c[0] != -1)
-        close(p2c[0]);
-
-#endif
-}
-
-#ifdef _SQUID_MSWIN_
-void
-ipc_params::parentToChildLoop() {
-    /* cycle */
-
-    for (;;) {
-        int recvrv = recv(myIPC->childFD.rfd, (void *) buf1, 8192, 0);
-
-        if (recvrv <= 0) {
-            debug(54, 3) ("ipc(%s,%d): %d bytes received from parent. Exiting...\n",
-                          niceprog, pid, recvrv);
-            return;
-        }
-
-        buf1[recvrv] = '\0';
-
-        if (type == IPC_UDP_SOCKET && !strcmp(buf1, shutdown_string)) {
-            debug(54, 3)
-            ("ipc(%s,%d): request for shutdown received from parent. Exiting...\n",
-             niceprog, pid);
-            //            TerminateProcess(hProcess, 0);
-            return;
-        }
-
-        debug(54, 5) ("ipc(%s,%d): received from parent: %s\n", niceprog, pid,
-                      rfc1738_escape_unescaped(buf1));
-        int writerv;
-
-        if (type == IPC_TCP_SOCKET)
-            writerv = write(c2p[1], buf1, recvrv);
-        else
-            writerv = send(pwfd_ipc, (const void *) buf1, recvrv, 0);
+    /* Make sure all other filedescriptors are closed */
+    for (x = 3; x < SQUID_MAXFD; x++)
+        close(x);
 
-        if (writerv <= 0) {
-            debug(54, 3) ("ipc(%s,%d): %d bytes written to %s. Exiting...\n",
-                          niceprog, pid, writerv, niceprog);
-            return;
-        }
+    if (opt_no_daemon) {
+        squid_signal(SIGINT, SIG_IGN, SA_RESETHAND);
+        squid_signal(SIGHUP, SIG_IGN, SA_RESETHAND);
     }
-}
-
-#endif
-
-void
-IPCInstance::childToParentLoop() {
-    char buf2[8192];
-
-    for (;;) {
-        int x;
-
-        if (type == IPC_TCP_SOCKET)
-            x = read(prfd, buf2, 8192);
-        else
-            x = recv(prfd, (void *) 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, ShutdownMessage)) {
-            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, (const void *) 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;
-        }
-    }
-}
+    execvp(prog, (char *const *) args);
 
-#ifdef _SQUID_MSWIN_
-static unsigned int __stdcall
-ipc_thread_2(void *voidParam) {
+    debug_log = fdopen(2, "a+");
 
-    struct thread_params *params = static_cast<struct thread_params *>(voidParam);
-    IPCInstance *newInstance = new IPCInstance(params->type, params->pid, params->prog, params->rfd, params->send_fd);
+    debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror());
 
-    newInstance->childToParentLoop();
+    _exit(1);
 
-    delete newInstance;
     return 0;
 }
-
-#endif
--- squid3/src/ipc.h	Wed Feb 14 13:37:49 2007
+++ /dev/null	Wed Feb 14 13:37:19 2007
@@ -1,88 +0,0 @@
-
-/*
- * $Id: ipc.h,v 1.1.18.1 2003/02/25 02:49:12 hno Exp $
- *
- *
- * 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.
- *
- */
-
-#ifndef SQUID_IPC_H
-#define SQUID_IPC_H
-
-
-#define IPC_NONE 0
-#define IPC_TCP_SOCKET 1
-#define IPC_UDP_SOCKET 2
-
-#ifndef _SQUID_MSWIN_
-
-#if !(USE_POLL && defined(_SQUID_OSF_))
-
-#define IPC_FIFO 3
-
-#endif
-
-#define IPC_UNIX_STREAM 4
-#define IPC_UNIX_DGRAM 5
-#endif
-
-#if HAVE_SOCKETPAIR && defined (AF_UNIX)
-#define IPC_STREAM IPC_UNIX_STREAM
-#define IPC_DGRAM IPC_UNIX_DGRAM
-#else
-#define IPC_STREAM IPC_TCP_SOCKET
-#define IPC_DGRAM IPC_UDP_SOCKET
-#endif
-
-struct IPCResult {
-    IPCResult (int causelinkfailure);
-    IPCResult (bool aBool, pid_t aPid=-1, int _rfd=-1, int _wfd = -1
-#ifdef _SQUID_MSWIN_
-      ,HANDLE aHandle=NULL
-#endif
-      ) : success(aBool), pid (aPid), rfd (_rfd), wfd (_wfd)
-#ifdef _SQUID_MSWIN_
-      ,hIpc(aHandle)
-#endif
-	{}
-    bool success;
-    pid_t pid;
-    int rfd;
-    int wfd;
-#ifdef _SQUID_MSWIN_
-    HANDLE hIpc;
-#endif
-};
-
-IPCResult ipcCreate(int type,
-    const char *prog,
-    const char *const args[],
-    const char *name
-);
-
-#endif /* SQUID_IPC_H */
--- /dev/null	Wed Feb 14 13:37:19 2007
+++ squid3/src/ipc_win32.cc	Wed Feb 14 13:37:49 2007
@@ -0,0 +1,863 @@
+
+/*
+ * $Id: ipc_win32.cc,v 1.1.2.1 2006/09/03 16:51:26 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"
+#include "comm.h"
+#include "fde.h"
+#include "SquidTime.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;
+}
+
+static void
+PutEnvironment()
+{
+#if HAVE_PUTENV
+    char *env_str;
+    int tmp_s;
+    env_str = (char *)xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
+    snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
+    putenv(env_str);
+#endif
+}
+
+pid_t
+ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, void **hIpc)
+{
+    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 (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, (void *)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, (const void *)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, (void *)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;
+
+        return pid;
+    } 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, (const void *)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;
+    ssize_t x;
+    int tmp_s, fd = -1;
+    char *str;
+    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 = (char *)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, (const void *)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;
+    }
+
+    PutEnvironment();
+    memset(buf1, '\0', sizeof(buf1));
+    x = recv(crfd, (void *)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 < (ssize_t)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 < (ssize_t)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, (const void *)ok_string, strlen(ok_string), 0);
+        x = recv(prfd_ipc, (void *)(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, (void *)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, (const void *)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, (const void *)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 (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 = (char *)xcalloc(1, 8192);
+
+    for (;;) {
+        if (type == IPC_TCP_SOCKET)
+            x = read(rfd, buf2, 8192);
+        else
+            x = recv(rfd, (void *)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, (const void *)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;
+}
Index: squid3/src/protos.h
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/protos.h,v
retrieving revision 1.19.2.58
retrieving revision 1.19.2.59
diff -u -r1.19.2.58 -r1.19.2.59
--- squid3/src/protos.h	22 Aug 2006 10:26:05 -0000	1.19.2.58
+++ squid3/src/protos.h	3 Sep 2006 16:51:26 -0000	1.19.2.59
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.19.2.58 2006/08/22 10:26:05 serassio Exp $
+ * $Id: protos.h,v 1.19.2.59 2006/09/03 16:51:26 serassio Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -676,6 +676,16 @@
 SQUIDCEXTERN void strwordquote(MemBuf * mb, const char *str);
 
 
+/*
+ * ipc.c
+ */
+SQUIDCEXTERN int ipcCreate(int type,
+                           const char *prog,
+                           const char *const args[],
+                           const char *name,
+                           int *rfd,
+                           int *wfd,
+                           void **hIpc);
 
 
 /* CacheDigest */
Index: squid3/src/redirect.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/redirect.cc,v
retrieving revision 1.5.2.17
retrieving revision 1.5.2.18
diff -u -r1.5.2.17 -r1.5.2.18
--- squid3/src/redirect.cc	22 Aug 2006 10:26:06 -0000	1.5.2.17
+++ squid3/src/redirect.cc	3 Sep 2006 16:51:26 -0000	1.5.2.18
@@ -1,6 +1,6 @@
 
 /*
- * $Id: redirect.cc,v 1.5.2.17 2006/08/22 10:26:06 serassio Exp $
+ * $Id: redirect.cc,v 1.5.2.18 2006/09/03 16:51:26 serassio Exp $
  *
  * DEBUG: section 61    Redirector
  * AUTHOR: Duane Wessels
@@ -37,7 +37,6 @@
 #include "AuthUserRequest.h"
 #include "CacheManager.h"
 #include "Store.h"
-#include "ipc.h"
 #include "fde.h"
 #include "client_side_request.h"
 #include "ACLChecklist.h"
Index: squid3/src/unlinkd.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/unlinkd.cc,v
retrieving revision 1.7.2.10
retrieving revision 1.7.2.11
diff -u -r1.7.2.10 -r1.7.2.11
--- squid3/src/unlinkd.cc	2 Sep 2006 16:02:52 -0000	1.7.2.10
+++ squid3/src/unlinkd.cc	3 Sep 2006 16:51:26 -0000	1.7.2.11
@@ -1,6 +1,6 @@
 
 /*
- * $Id: unlinkd.cc,v 1.7.2.10 2006/09/02 16:02:52 serassio Exp $
+ * $Id: unlinkd.cc,v 1.7.2.11 2006/09/03 16:51:26 serassio Exp $
  *
  * DEBUG: section 2     Unlink Daemon
  * AUTHOR: Duane Wessels
@@ -34,7 +34,6 @@
  */
 
 #include "squid.h"
-#include "ipc.h"
 
 #ifdef UNLINK_DAEMON
 
@@ -86,9 +85,7 @@
 static int unlinkd_wfd = -1;
 static int unlinkd_rfd = -1;
 
-#ifdef _SQUID_MSWIN_
-static HANDLE hIpc;
-#endif
+static void * hIpc;
 static pid_t pid;
 
 #define UNLINKD_QUEUE_LIMIT 20
@@ -233,7 +230,7 @@
     struct timeval slp;
     args[0] = "(unlinkd)";
     args[1] = NULL;
-    IPCResult ipcRV = ipcCreate(
+    pid = ipcCreate(
 #if USE_POLL && defined(_SQUID_OSF_)
                           /* pipes and poll() don't get along on DUNIX -DW */
                           IPC_STREAM,
@@ -244,25 +241,16 @@
 /* We currently need to use FIFO.. see below */
 IPC_FIFO,
 #endif
-                          Config.Program.unlinkd,
-                          args,
-                          "unlinkd");
+                    Config.Program.unlinkd,
+                    args,
+                    "unlinkd",
+                    &unlinkd_rfd,
+                    &unlinkd_wfd,
+		    &hIpc);
 
-    if (!ipcRV.success)
+    if (pid < 0)
         fatal("Failed to create unlinkd subprocess");
 
-    pid = ipcRV.pid;
-
-    unlinkd_rfd = ipcRV.rfd;
-
-    unlinkd_wfd = ipcRV.wfd;
-
-#ifdef _SQUID_MSWIN_
-
-    hIpc = ipcRV.hIpc;
-
-#endif
-
     slp.tv_sec = 0;
 
     slp.tv_usec = 250000;
Index: squid3/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc
===================================================================
RCS file: /cvsroot/squid-sf//squid3/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -u -r1.1.2.3 -r1.1.2.4
--- squid3/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc	13 May 2006 12:21:10 -0000	1.1.2.3
+++ squid3/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc	3 Sep 2006 16:51:27 -0000	1.1.2.4
@@ -1,6 +1,6 @@
 
 /*
- * $Id: DiskdIOStrategy.cc,v 1.1.2.3 2006/05/13 12:21:10 serassio Exp $
+ * $Id: DiskdIOStrategy.cc,v 1.1.2.4 2006/09/03 16:51:27 serassio Exp $
  *
  * DEBUG: section 79    Squid-side DISKD I/O functions.
  * AUTHOR: Duane Wessels
@@ -153,7 +153,8 @@
 void
 DiskdIOStrategy::init()
 {
-    int x;
+    int pid;
+    void * hIpc 
     int rfd;
     int ikey;
     const char *args[5];
@@ -186,14 +187,15 @@
     args[2] = skey2;
     args[3] = skey3;
     args[4] = NULL;
-    x = ipcCreate(IPC_STREAM,
+    pid = ipcCreate(IPC_STREAM,
                   Config.Program.diskd,
                   args,
                   "diskd",
                   &rfd,
-                  &wfd);
+                  &wfd,
+                  &hIpc);
 
-    if (x < 0)
+    if (pid < 0)
         fatalf("execl: %s", Config.Program.diskd);
 
     if (rfd != wfd)
