Wesley Chun's SF patch 511380: add CGIHTTPServer error supt for Win32

This uses os.popen3 (if it exists) to ensure that errors from a
non-Python CGI script are logged.

Bugfix candidate.
diff --git a/Lib/CGIHTTPServer.py b/Lib/CGIHTTPServer.py
index e724601..7a7e075 100644
--- a/Lib/CGIHTTPServer.py
+++ b/Lib/CGIHTTPServer.py
@@ -41,6 +41,7 @@
     # Determine platform specifics
     have_fork = hasattr(os, 'fork')
     have_popen2 = hasattr(os, 'popen2')
+    have_popen3 = hasattr(os, 'popen3')
 
     # Make rfile unbuffered -- we need to read one line and then pass
     # the rest to a subprocess, so we can't use buffered input.
@@ -123,7 +124,7 @@
             return
         ispy = self.is_python(scriptname)
         if not ispy:
-            if not (self.have_fork or self.have_popen2):
+            if not (self.have_fork or self.have_popen2 or self.have_popen3):
                 self.send_error(403, "CGI script is not a Python script (%s)" %
                                 `scriptname`)
                 return
@@ -214,9 +215,13 @@
                 self.server.handle_error(self.request, self.client_address)
                 os._exit(127)
 
-        elif self.have_popen2:
-            # Windows -- use popen2 to create a subprocess
+        elif self.have_popen2 or self.have_popen3:
+            # Windows -- use popen2 or popen3 to create a subprocess
             import shutil
+            if self.have_popen3:
+                popenx = os.popen3
+            else:
+                popenx = os.popen2
             os.environ.update(env)
             cmdline = scriptfile
             if self.is_python(scriptfile):
@@ -232,12 +237,21 @@
                 nbytes = int(length)
             except:
                 nbytes = 0
-            fi, fo = os.popen2(cmdline, 'b')
+            files = popenx(cmdline, 'b')
+            fi = files[0]
+            fo = files[1]
+            if self.have_popen3:
+                fe = files[2]
             if self.command.lower() == "post" and nbytes > 0:
                 data = self.rfile.read(nbytes)
                 fi.write(data)
             fi.close()
             shutil.copyfileobj(fo, self.wfile)
+            if self.have_popen3:
+                errors = fe.read()
+                fe.close()
+                if errors:
+                    self.log_error('%s', errors)
             sts = fo.close()
             if sts:
                 self.log_error("CGI script exit status %#x", sts)