You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Ralf S. Engelschall" <rs...@engelschall.com> on 1998/05/21 14:04:42 UTC

[PATCH] Spawning-stuff in mod_rewrite for Win32 with pinfo (FOR BEN!)

The below patch is the best solution I found to repair the spawning-stuff in
mod_rewrite for Win32 with pinfo. I _HAVEN'T TESTED IT_ because I cannot test
it (currently not even a useable Windows NT). I've created it blindly
extracting the relevant parts from ap_call_exec() which should only be
relavant for mod_rewrite.

Background: 

The "RewriteMap ... prg:/path/to/program" directive spawns /path/to/program
once at startup and communicates with it via STDIN/STDOUT.  In principle
ap_open_piped_log() should be used but this doesn't work correctly for really
reading _AND_ writing to a program even when I patch http_log.c to make STDOUT
available. The communication loops and we have not the time to make such a big
change. On the other hand the old mechanism needs to exec() the child
manually. Here the other modules use ap_call_exec() which does a lot of
horrible hacking for Win32, EMX, etc. This also cannot be used by mod_rewrite
because it assumes to have a request_rec to operate on. But the RewriteMap
program is run at startup only one (and not started in the middle of
requests), there is no such request_rec available. And third, to make
RewriteMap programs available to Win32 the new pinfo stuff should be used.
ARGL, what an ugly situation I was forced into...

Workaround:

I looked at the rewritemap_program_child() where the pinfo stuff was still not
used and tried to place there the minimal stuff from ap_call_exec() which
should be needed to make Win32 happy. 

NOT IT'S YOUR TURN, BEN: I cannot test it. You have to test it for us, please.
Or at least review it in theory. When you want to test it, you could use
a ruleset like

   RewriteEngine   on
   RewriteLog      logs/rewrite_log
   RewriteLogLevel 9
   RewriteMap      test         prg:/path/to/test.pl
   RewriteRule     ^/foo/(.*)$  /foo/${test:$1|$1}       [R,L]

and a test.pl with

   #!/sw/bin/perl
   $|++;
   while (<STDIN>) {
       $url = $_;
       $url =~ s|\n$||;
       print STDOUT $url . '/fucking_win32_stuff/' . "\n";
   }

This should redirect any /foo/ URLs to a simular one with
/fucking_win32_stuff/ appended.

Greetings,
                                       Ralf S. Engelschall
                                       rse@engelschall.com
                                       www.engelschall.com

Index: mod_rewrite.c
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/modules/standard/mod_rewrite.c,v
retrieving revision 1.106
diff -u -r1.106 mod_rewrite.c
--- mod_rewrite.c	1998/05/21 10:48:35	1.106
+++ mod_rewrite.c	1998/05/21 11:51:44
@@ -3127,6 +3127,7 @@
     rewrite_server_conf *conf;
     FILE *fpin;
     FILE *fpout;
+    FILE *fperr;
     array_header *rewritemaps;
     rewritemap_entry *entries;
     rewritemap_entry *map;
@@ -3154,16 +3155,18 @@
             continue;
         fpin  = NULL;
         fpout = NULL;
-        rc = spawn_child(p, rewritemap_program_child, (void *)map->datafile,
-                         kill_after_timeout, &fpin, &fpout);
+        rc = ap_spawn_child_err(p, rewritemap_program_child, 
+                                (void *)map->datafile, kill_after_timeout, 
+                                &fpin, &fpout, &fperr);
         if (rc == 0 || fpin == NULL || fpout == NULL) {
-            perror("spawn_child");
+            perror("ap_spawn_child");
             fprintf(stderr, "mod_rewrite: "
                     "could not fork child for RewriteMap process\n");
             exit(1);
         }
         map->fpin  = fileno(fpin);
         map->fpout = fileno(fpout);
+        map->fperr = fileno(fperr);
     }
     return;
 }
@@ -3173,17 +3176,48 @@
 {
     int child_pid = 1;
 
+    /* 
+     * Prepare for exec 
+     */
     ap_cleanup_for_exec();
 #ifdef SIGHUP
     signal(SIGHUP, SIG_IGN);
 #endif
+
+    /* 
+     * Exec() the child program
+     */
 #if defined(WIN32)
-    child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH,
-                       "/c", (char *)cmd, NULL);
+    /* MS Windows */
+    {
+        char *pCommand;
+        STARTUPINFO si;
+        PROCESS_INFORMATION pi;
+
+        pCommand = strcat("CMD.EXE", " /C ", cmd, NULL);
+
+        memset(&si, 0, sizeof(si));
+        memset(&pi, 0, sizeof(pi));
+
+        si.cb          = sizeof(si);
+        si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+        si.wShowWindow = SW_HIDE;
+        si.hStdInput   = pinfo->hPipeInputRead;
+        si.hStdOutput  = pinfo->hPipeOutputWrite;
+        si.hStdError   = pinfo->hPipeErrorWrite;
+
+        if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, 0, 
+                          environ, NULL, &si, &pi)) {
+            CloseHandle(pi.hProcess);
+            CloseHandle(pi.hThread);
+            child_pid = pi.dwProcessId;
+        }
+    }
 #elif defined(__EMX__)
-    /* OS/2 needs a '/' */
+    /* IBM OS/2 */
     execl(SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
 #else
+    /* Standard Unix */
     execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
 #endif
     return(child_pid);
Index: mod_rewrite.h
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/modules/standard/mod_rewrite.h,v
retrieving revision 1.51
diff -u -r1.51 mod_rewrite.h
--- mod_rewrite.h	1998/05/20 15:34:27	1.51
+++ mod_rewrite.h	1998/05/21 11:34:39
@@ -252,6 +252,7 @@
     int   type;                    /* the type of the map */
     int   fpin;                    /* in  file pointer for program maps */
     int   fpout;                   /* out file pointer for program maps */
+    int   fperr;                   /* err file pointer for program maps */
     char *(*func)(request_rec *,   /* function pointer for internal maps */
                   char *);
 } rewritemap_entry;