You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by W G Stoddard <wg...@us.ibm.com> on 1998/06/17 22:00:26 UTC

[PATCH] ap_call_exec patch #2

This patch makes some structural changes to ap_call_exec to make it more
readable and friendly to a couple of patches that will follow (capability to
query the Win32 registry for interpreter name and a fix for mod_include
exec=cmd processing). This patch does not change the function of ap_call_exec.

Summary of changes:
1. Changed interpreter[2048] to buffer[2048]. interpreter is now a char*
pointer to buffer.
2. Changed the sense of the line that detects presence of arguments
 From: if (!(r->args) || !(r->args[0]) || strchr(r->args, '=')) {
 To: if ((r->args) && (r->args[0]) && !strchr(r->args, '=')) {
3. Changed inside the brackets for the above change
4. Removed three redundant ap_pstrcat calls to build pCommand that previously
handled the case of no arguments received.
Now, if no arguments are received, the argument string is set to NULL and the
same set of ap_pstrcat calls are used to build pCommand.
5. Moved some blocks of code around a bit

There are a couple of places where there appear to be alignment problems.
Those are places where I eliminated tab characters and replaced them with
spaces (all according to the style guidelines).

There are a lot of changes to review. My apologies...

Bill Stoddard
wgstodda@us.ibm.com


*** util_script.c.original Tue Jun 16 13:42:02 1998
--- util_script.c Wed Jun 17 11:57:45 1998
***************
*** 703,714 ****
   /* Adapted from work by Alec Kloss, to allow exec'ing of scripts
under OS/2 */
   int is_script = 0;
   int is_binary = 0;
!  char interpreter[2048]; /* hope this is large enough for the
interpreter path */
   FILE *program;
   int i, sz;
   char *dot;
   char *exename;
!  int is_exe = 0;
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
          char *pCommand;
--- 703,717 ----
   /* Adapted from work by Alec Kloss, to allow exec'ing of scripts
under OS/2 */
   int is_script = 0;
   int is_binary = 0;
!  int is_exe = 0;
!         char buffer[2048];  /* hope this is large enough for the interpreter
path */
!         char *interpreter = NULL;
   FILE *program;
   int i, sz;
   char *dot;
   char *exename;
!         char *arguments="";
!
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
          char *pCommand;
***************
*** 718,725 ****
   memset(&si, 0, sizeof(si));
   memset(&pi, 0, sizeof(pi));

!  interpreter[0] = 0;
!  pid = -1;

   exename = strrchr(r->filename, '/');
   if (!exename)
--- 721,727 ----
   memset(&si, 0, sizeof(si));
   memset(&pi, 0, sizeof(pi));

!         pid = -1;

   exename = strrchr(r->filename, '/');
   if (!exename)
***************
*** 744,773 ****
         "fopen(%s) failed", r->filename);
    return (pid);
       }
!      sz = fread(interpreter, 1, sizeof(interpreter) - 1, program);
       if (sz < 0) {
    ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
         "fread of %s failed", r->filename);
    fclose(program);
    return (pid);
       }
!      interpreter[sz] = 0;
       fclose(program);
!      if (!strncmp(interpreter, "#!", 2)) {
    is_script = 1;
!   for (i = 2; i < sizeof(interpreter); i++) {
!       if ((interpreter[i] == '\r') ||
!    (interpreter[i] == '\n'))
     break;
    }
!   interpreter[i] = 0;
!   for (i = 2; interpreter[i] == ' '; ++i)
        ;
!   memmove(interpreter+2,interpreter+i,strlen(interpreter+i)+1);
       }
       else {
!                         /* Check to see if it's a executable */
!                 IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)interpreter;
                  if (hdr->e_magic == IMAGE_DOS_SIGNATURE && hdr->e_cblp < 512)
                      is_binary = 1;
       }
--- 746,775 ----
         "fopen(%s) failed", r->filename);
    return (pid);
       }
!      sz = fread(buffer, 1, sizeof(buffer) - 1, program);
       if (sz < 0) {
    ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
         "fread of %s failed", r->filename);
    fclose(program);
    return (pid);
       }
!      buffer[sz] = 0;
       fclose(program);
!      if (!strncmp(buffer, "#!", 2)) {
    is_script = 1;
!   for (i = 2; i < sizeof(buffer); i++) {
!       if ((buffer[i] == '\r') ||
!    (buffer[i] == '\n'))
     break;
    }
!   buffer[i] = 0;
!   for (i = 2; buffer[i] == ' '; ++i)
        ;
!   interpreter = buffer + i;
       }
       else {
!                 /* Check to see if it's a executable */
!                 IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)buffer;
                  if (hdr->e_magic == IMAGE_DOS_SIGNATURE && hdr->e_cblp < 512)
                      is_binary = 1;
       }
***************
*** 782,823 ****
              return (pid);
          }

!  /*
!   * Make child process use hPipeOutputWrite as standard out,
!   * and make sure it does not show on screen.
!   */
!  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 ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) {
!      if (is_exe || is_binary) {
!          /*
!           * When the CGI is a straight binary executable,
!    * we can run it as is
!           */
!          pCommand = r->filename;
!      }
!      else if (is_script) {
!                 /* When an interpreter is needed, we need to create
!                  * a command line that has the interpreter name
!                  * followed by the CGI script name.
!    */
!          pCommand = ap_pstrcat(r->pool, interpreter + 2, " ",
!           r->filename, NULL);
!      }
!      else {
!          /* If not an executable or script, just execute it
!                  * from a command prompt.
!                  */
!          pCommand = ap_pstrcat(r->pool, SHELL_PATH, " /C ",
!           r->filename, NULL);
!      }
!  }
!  else {

              /* If we are in this leg, there are some other arguments
               * that we must include in the execution of the CGI.
--- 784,791 ----
              return (pid);
          }

!         /* Build the arguments list */
!         if ((r->args) && (r->args[0]) && !strchr(r->args, '=')) {

              /* If we are in this leg, there are some other arguments
               * that we must include in the execution of the CGI.
***************
*** 830,836 ****
               * and each argument is separated by a '+'.  We'll replace
               * these pluses with spaces.
        */
!      char *arguments=NULL;
       int iStringSize = 0;
       int x;

--- 798,804 ----
               * and each argument is separated by a '+'.  We'll replace
               * these pluses with spaces.
        */
!
       int iStringSize = 0;
       int x;

***************
*** 854,878 ****
        */
       ap_unescape_url(arguments);
       arguments = ap_escape_shell_cmd(r->pool, arguments);
!
!      /*
!       * The argument list should now be good to use,
!       * so now build the command line.
!       */
!      if (is_exe || is_binary) {
!          pCommand = ap_pstrcat(r->pool, r->filename, " ",
!           arguments, NULL);
!      }
!      else if (is_script) {
!          pCommand = ap_pstrcat(r->pool, interpreter + 2, " ",
!           r->filename, " ", arguments, NULL);
!      }
!      else {
!          pCommand = ap_pstrcat(r->pool, SHELL_PATH, " /C ",
!           r->filename, " ", arguments, NULL);
!      }
!  }
!
          /*
           * Win32's CreateProcess call requires that the environment
           * be passed in an environment block, a null terminated block of
--- 822,855 ----
        */
       ap_unescape_url(arguments);
       arguments = ap_escape_shell_cmd(r->pool, arguments);
!         }
!
!         /*
!          * Build the command line.
!          */
!         if (is_exe || is_binary) {
!             /* When the CGI is a straight binary executable,
!              * we can run it as is
!              */
!             pCommand = ap_pstrcat(r->pool, r->filename, " ",
!                                   arguments, NULL);
!         }
!         else if (is_script) {
!             /* When an interpreter is needed, we need to create
!              * a command line that has the interpreter name
!              * followed by the CGI script name.
!              */
!             pCommand = ap_pstrcat(r->pool, interpreter, " ",
!                                   r->filename, " ", arguments, NULL);
!         }
!         else {
!             /* If not an executable or script, just execute it
!              * from a command prompt.
!              */
!             pCommand = ap_pstrcat(r->pool, SHELL_PATH, " /C ",
!                                   r->filename, " ", arguments, NULL);
!         }
!
          /*
           * Win32's CreateProcess call requires that the environment
           * be passed in an environment block, a null terminated block of
***************
*** 895,900 ****
--- 872,888 ----
              pNext = pNext + strlen(pNext) + 1;
              i++;
          }
+
+         /*
+          * Make child process use hPipeOutputWrite as standard out,
+          * and make sure it does not show on screen.
+          */
+         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, pEnvBlock,
                            ap_make_dirstr_parent(r->pool, r->filename),




Users of the Apache webserver are hereby granted a non-exclusive, irrevocable,
world-wide, royalty-free, non-transferable license to use, execute, prepare
derivative works of, and distribute (internally and externally, and including
derivative works) the code accompanying this license as part of, and integrated
into the Apache webserver.

This code is provided "AS IS" WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTY OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK ARISING OUT OF THE USE
OR PERFORMANCE OF THIS CODE REMAINS WITH USERS OF THE APACHE WEBSERVER.

I represent and warrant that I am legally entitled to grant the above license.