You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by bn...@apache.org on 2002/06/06 00:58:04 UTC

cvs commit: httpd-2.0/modules/generators mod_cgi.h mod_cgi.c

bnicholes    2002/06/05 15:58:04

  Modified:    modules/arch/netware mod_netware.c
               modules/generators mod_cgi.h mod_cgi.c
  Log:
  Consolidated the startup attributes for building the command line for a CGI
  binary into a single structure.  This allows platform integrator to manipulate
  the startup parameters much more easily.  Also added the detach attribute
  so that each CGI binary can be spawn appropriately for the OS.
  
  Revision  Changes    Path
  1.2       +4 -230    httpd-2.0/modules/arch/netware/mod_netware.c
  
  Index: mod_netware.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/arch/netware/mod_netware.c,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- mod_netware.c	31 May 2002 17:16:09 -0000	1.1
  +++ mod_netware.c	5 Jun 2002 22:58:03 -0000	1.2
  @@ -71,6 +71,7 @@
   #include "mod_core.h"
   #include "apr_optional.h"
   #include "apr_lib.h"
  +#include "mod_cgi.h"
   
   #ifdef NETWARE
   
  @@ -113,141 +114,9 @@
       return NULL;
   }
   
  -
  -static apr_array_header_t *split_argv(apr_pool_t *p, const char *interp,
  -                                      const char *cgiprg, const char *cgiargs)
  -{
  -    apr_array_header_t *args = apr_array_make(p, 8, sizeof(char*));
  -    char *d = apr_palloc(p, strlen(interp)+1);
  -    const char *ch = interp; 
  -    const char **arg;
  -    int prgtaken = 0;
  -    int argtaken = 0;
  -    int inquo;
  -    int sl;
  -
  -    while (*ch) {
  -        /* Skip on through Deep Space */
  -        if (isspace(*ch)) {
  -            ++ch; continue;
  -        }
  -        /* One Arg */
  -        if (((*ch == '$') || (*ch == '%')) && (*(ch + 1) == '*')) {
  -            const char *cgiarg = cgiargs;
  -            argtaken = 1;
  -            for (;;) {
  -                char *w = ap_getword_nulls(p, &cgiarg, '+');
  -                if (!*w) {
  -                    break;
  -                }
  -                ap_unescape_url(w);
  -                arg = (const char**)apr_array_push(args);
  -                *arg = ap_escape_shell_cmd(p, w);
  -            }
  -            ch += 2;
  -            continue;
  -        }
  -        if (((*ch == '$') || (*ch == '%')) && (*(ch + 1) == '1')) {
  -            /* Todo: Make short name!!! */
  -            prgtaken = 1;
  -            arg = (const char**)apr_array_push(args);
  -            if (*ch == '%') {
  -                char *repl = apr_pstrdup(p, cgiprg);
  -                *arg = repl;
  -                while ((repl = strchr(repl, '/'))) {
  -                    *repl++ = '\\';
  -                }
  -            }
  -            else {
  -                *arg = cgiprg;
  -            }
  -            ch += 2;
  -            continue;
  -        }
  -        if ((*ch == '\"') && ((*(ch + 1) == '$') 
  -                              || (*(ch + 1) == '%')) && (*(ch + 2) == '1') 
  -            && (*(ch + 3) == '\"')) {
  -            prgtaken = 1;
  -            arg = (const char**)apr_array_push(args);
  -            if (*(ch + 1) == '%') {
  -                char *repl = apr_pstrdup(p, cgiprg);
  -                *arg = repl;
  -                while ((repl = strchr(repl, '/'))) {
  -                    *repl++ = '\\';
  -                }
  -            }
  -            else {
  -                *arg = cgiprg;
  -            }
  -            ch += 4;
  -            continue;
  -        }
  -        arg = (const char**)apr_array_push(args);
  -        *arg = d;
  -        inquo = 0;
  -        while (*ch) {
  -            if (isspace(*ch) && !inquo) {
  -                ++ch; break;
  -            }
  -            /* Get 'em backslashes */
  -            for (sl = 0; *ch == '\\'; ++sl) {
  -                *d++ = *ch++;
  -            }
  -            if (sl & 1) {
  -                /* last unmatched '\' + '"' sequence is a '"' */
  -                if (*ch == '\"') {
  -                    *(d - 1) = *ch++;
  -                }
  -                continue;
  -            }
  -            if (*ch == '\"') {
  -                /* '""' sequence within quotes is a '"' */
  -                if (*++ch == '\"' && inquo) {
  -                    *d++ = *ch++; continue;
  -                }
  -                /* Flip quote state */
  -                inquo = !inquo;
  -                if (isspace(*ch) && !inquo) {
  -                    ++ch; break;
  -                }
  -                /* All other '"'s are Munched */
  -                continue;
  -            }
  -            /* Anything else is, well, something else */
  -            *d++ = *ch++;
  -        }
  -        /* Term that arg, already pushed on args */
  -        *d++ = '\0';
  -    }
  -
  -    if (!prgtaken) {
  -        arg = (const char**)apr_array_push(args);
  -        *arg = cgiprg;
  -    }
  -
  -    if (!argtaken) {
  -        const char *cgiarg = cgiargs;
  -        for (;;) {
  -            char *w = ap_getword_nulls(p, &cgiarg, '+');
  -            if (!*w) {
  -                break;
  -            }
  -            ap_unescape_url(w);
  -            arg = (const char**)apr_array_push(args);
  -            *arg = ap_escape_shell_cmd(p, w);
  -        }
  -    }
  -
  -    arg = (const char**)apr_array_push(args);
  -    *arg = NULL;
  -
  -    return args;
  -}
  -
  -
   static apr_status_t ap_cgi_build_command(const char **cmd, const char ***argv,
                                            request_rec *r, apr_pool_t *p, 
  -                                         int process_cgi, apr_cmdtype_e *type)
  +                                         cgi_exec_info_t *e_info)
   {
       const char *ext = NULL;
       const char *interpreter = NULL;
  @@ -258,7 +127,7 @@
       d = (netware_dir_config *)ap_get_module_config(r->per_dir_config, 
                                                  &netware_module);
   
  -    if (process_cgi) {
  +    if (e_info->process_cgi) {
           /* Handle the complete file name, we DON'T want to follow suexec, since
            * an unrooted command is as predictable as shooting craps in Win32.
            *
  @@ -288,105 +157,10 @@
       }
   
       apr_tokenize_to_argv(r->filename, (char***)argv, p);
  -    *type = APR_PROGRAM;
  +    e_info->cmd_type = APR_PROGRAM;
   
  -//    /* If the file has an extension and it is not .com and not .exe and
  -//     * we've been instructed to search the registry, then do so.
  -//     * Let apr_proc_create do all of the .bat/.cmd dirty work.
  -//     */
  -//    if (ext && (!strcasecmp(ext,".exe") || !strcasecmp(ext,".com")
  -//                || !strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd"))) {
  -//        interpreter = "";
  -//    }
  -//    if (!interpreter && ext 
  -//          && (d->script_interpreter_source 
  -//                     == INTERPRETER_SOURCE_REGISTRY
  -//           || d->script_interpreter_source 
  -//                     == INTERPRETER_SOURCE_REGISTRY_STRICT)) {
  -//         /* Check the registry */
  -//        int strict = (d->script_interpreter_source 
  -//                      == INTERPRETER_SOURCE_REGISTRY_STRICT);
  -//        interpreter = get_interpreter_from_win32_registry(r->pool, ext,
  -//                                                          strict);
  -//        if (interpreter && *type != APR_SHELLCMD) {
  -//            *type = APR_PROGRAM_PATH;
  -//        }
  -//        else {
  -//            ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
  -//                 strict ? "No ExecCGI verb found for files of type '%s'."
  -//                        : "No ExecCGI or Open verb found for files of type '%s'.", 
  -//                 ext);
  -//        }
  -//    }
  -//    if (!interpreter) {
  -//        apr_status_t rv;
  -//        char buffer[1024];
  -//        apr_size_t bytes = sizeof(buffer);
  -//        int i;
  -//
  -//        /* Need to peek into the file figure out what it really is... 
  -//         * ### aught to go back and build a cache for this one of these days.
  -//         */
  -//        if (((rv = apr_file_open(&fh, *cmd, APR_READ | APR_BUFFERED,
  -//                                 APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) 
  -//            || ((rv = apr_file_read(fh, buffer, &bytes)) != APR_SUCCESS)) {
  -//            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
  -//                          "Failed to read cgi file %s for testing", *cmd);
  -//            return rv;
  -//        }
  -//        apr_file_close(fh);
  -//
  -//        /* Script or executable, that is the question... */
  -//        if ((buffer[0] == '#') && (buffer[1] == '!')) {
  -//            /* Assuming file is a script since it starts with a shebang */
  -//            for (i = 2; i < sizeof(buffer); i++) {
  -//                if ((buffer[i] == '\r') || (buffer[i] == '\n')) {
  -//                    buffer[i] = '\0';
  -//                    break;
  -//                }
  -//            }
  -//            if (i < sizeof(buffer)) {
  -//                interpreter = buffer + 2;
  -//                while (isspace(*interpreter)) {
  -//                    ++interpreter;
  -//                }
  -//                if (*type != APR_SHELLCMD) {
  -//                    *type = APR_PROGRAM_PATH;
  -//                }
  -//            }
  -//        }
  -//        else {
  -//            /* Not a script, is it an executable? */
  -//            IMAGE_DOS_HEADER *hdr = (IMAGE_DOS_HEADER*)buffer;    
  -//            if ((bytes >= sizeof(IMAGE_DOS_HEADER))
  -//                && (hdr->e_magic == IMAGE_DOS_SIGNATURE)) {
  -//                if (hdr->e_lfarlc < 0x40) {
  -//                    /* Ought to invoke this 16 bit exe by a stub, (cmd /c?) */
  -//                    interpreter = "";
  -//                }
  -//                else {
  -//                    interpreter = "";
  -//                }
  -//            }
  -//        }
  -//    }
  -//    if (!interpreter) {
  -//        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
  -//                      "%s is not executable; ensure interpreted scripts have "
  -//                      "\"#!\" first line", *cmd);
  -//        return APR_EBADF;
  -//    }
  -//
  -//    *argv = (const char **)(split_argv(p, interpreter, *cmd,
  -//                                       args)->elts);
  -//    *cmd = (*argv)[0];
       return APR_SUCCESS;
   }
  -
  -APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_cgi_build_command,
  -                        (const char **cmd, const char ***argv, 
  -                         request_rec *r, apr_pool_t *p, 
  -                         int replace_cmd, apr_cmdtype_e *type));
   
   static void register_hooks(apr_pool_t *p)
   {
  
  
  
  1.7       +18 -1     httpd-2.0/modules/generators/mod_cgi.h
  
  Index: mod_cgi.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/generators/mod_cgi.h,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- mod_cgi.h	13 Apr 2002 20:42:35 -0000	1.6
  +++ mod_cgi.h	5 Jun 2002 22:58:03 -0000	1.7
  @@ -59,6 +59,22 @@
   #ifndef _MOD_CGI_H
   #define _MOD_CGI_H 1
   
  +#include "../filters/mod_include.h"
  +
  +typedef enum {RUN_AS_SSI, RUN_AS_CGI} prog_types;
  +
  +typedef struct {
  +    apr_int32_t          in_pipe;
  +    apr_int32_t          out_pipe;
  +    apr_int32_t          err_pipe;
  +    int                  process_cgi;
  +    apr_cmdtype_e        cmd_type;
  +    apr_int32_t          detached;
  +    prog_types           prog_type;
  +    apr_bucket_brigade **bb;
  +    include_ctx_t       *ctx;
  +    ap_filter_t         *next;
  +} cgi_exec_info_t;
   
   /**
    * Registerable optional function to override CGI behavior;
  @@ -71,6 +87,7 @@
    *                    as a CGI invocation, otherwise false
    * @param type Set to APR_SHELLCMD or APR_PROGRAM on entry, may be
    *             changed to invoke the program with alternate semantics.
  + * @param detach Should the child start in detached state?  Default is no. 
    * @remark This callback may be registered by the os-specific module 
    * to correct the command and arguments for apr_proc_create invocation
    * on a given os.  mod_cgi will call the function if registered.
  @@ -78,6 +95,6 @@
   APR_DECLARE_OPTIONAL_FN(apr_status_t, ap_cgi_build_command, 
                           (const char **cmd, const char ***argv,
                            request_rec *r, apr_pool_t *p, 
  -                         int process_cgi, apr_cmdtype_e *type));
  +                         cgi_exec_info_t *e_info));
   
   #endif /* _MOD_CGI_H */
  
  
  
  1.140     +31 -40    httpd-2.0/modules/generators/mod_cgi.c
  
  Index: mod_cgi.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/generators/mod_cgi.c,v
  retrieving revision 1.139
  retrieving revision 1.140
  diff -u -r1.139 -r1.140
  --- mod_cgi.c	30 May 2002 00:36:58 -0000	1.139
  +++ mod_cgi.c	5 Jun 2002 22:58:03 -0000	1.140
  @@ -93,7 +93,6 @@
   #include "util_script.h"
   #include "ap_mpm.h"
   #include "mod_core.h"
  -#include "../filters/mod_include.h"
   #include "mod_cgi.h"
   
   module AP_MODULE_DECLARE_DATA cgi_module;
  @@ -103,19 +102,6 @@
   static APR_OPTIONAL_FN_TYPE(ap_ssi_parse_string) *cgi_pfn_ps;
   static APR_OPTIONAL_FN_TYPE(ap_cgi_build_command) *cgi_build_command;
   
  -typedef enum {RUN_AS_SSI, RUN_AS_CGI} prog_types;
  -
  -typedef struct {
  -    apr_int32_t          in_pipe;
  -    apr_int32_t          out_pipe;
  -    apr_int32_t          err_pipe;
  -    apr_cmdtype_e        cmd_type;
  -    prog_types           prog_type;
  -    apr_bucket_brigade **bb;
  -    include_ctx_t       *ctx;
  -    ap_filter_t         *next;
  -} exec_info;
  -
   /* Read and discard the data in the brigade produced by a CGI script */
   static void discard_script_output(apr_bucket_brigade *bb);
   
  @@ -401,7 +387,7 @@
                                     const char * const argv[],
                                     request_rec *r,
                                     apr_pool_t *p,
  -                                  exec_info *e_info)
  +                                  cgi_exec_info_t *e_info)
   {
       const char * const *env;
       apr_procattr_t *procattr;
  @@ -471,7 +457,10 @@
                                         conf->limit_nproc)) != APR_SUCCESS) ||
   #endif
           ((rc = apr_procattr_cmdtype_set(procattr,
  -                                        e_info->cmd_type)) != APR_SUCCESS)) {
  +                                        e_info->cmd_type)) != APR_SUCCESS) ||
  +
  +        ((rc = apr_procattr_detach_set(procattr,
  +                                        e_info->detached)) != APR_SUCCESS)) {
           /* Something bad happened, tell the world. */
           ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
                         "couldn't set child process attributes: %s", r->filename);
  @@ -530,13 +519,13 @@
   
   static apr_status_t default_build_command(const char **cmd, const char ***argv,
                                             request_rec *r, apr_pool_t *p,
  -                                          int process_cgi, apr_cmdtype_e * type)
  +                                          cgi_exec_info_t *e_info)
   {
       int numwords, x, idx;
       char *w;
       const char *args = NULL;
   
  -    if (process_cgi) {
  +    if (e_info->process_cgi) {
           /* Allow suexec's "/" check to succeed */
           const char *argv0 = strrchr(r->filename, '/');
           if (argv0 != NULL)
  @@ -613,7 +602,7 @@
       apr_pool_t *p;
       cgi_server_conf *conf;
       apr_status_t rv;
  -    exec_info e_info;
  +    cgi_exec_info_t e_info;
   
       if(strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script"))
           return DECLINED;
  @@ -664,18 +653,19 @@
   */
       ap_add_common_vars(r);
   
  -    e_info.cmd_type  = APR_PROGRAM;
  -    e_info.in_pipe   = APR_CHILD_BLOCK;
  -    e_info.out_pipe  = APR_CHILD_BLOCK;
  -    e_info.err_pipe  = APR_CHILD_BLOCK;
  -    e_info.prog_type = RUN_AS_CGI;
  -    e_info.bb        = NULL;
  -    e_info.ctx       = NULL;
  -    e_info.next      = NULL;
  +    e_info.process_cgi = 1;
  +    e_info.cmd_type    = APR_PROGRAM;
  +    e_info.detached    = 0;
  +    e_info.in_pipe     = APR_CHILD_BLOCK;
  +    e_info.out_pipe    = APR_CHILD_BLOCK;
  +    e_info.err_pipe    = APR_CHILD_BLOCK;
  +    e_info.prog_type   = RUN_AS_CGI;
  +    e_info.bb          = NULL;
  +    e_info.ctx         = NULL;
  +    e_info.next        = NULL;
   
       /* build the command line */
  -    if ((rv = cgi_build_command(&command, &argv, r, p, 1, &e_info.cmd_type)) 
  -            != APR_SUCCESS) {
  +    if ((rv = cgi_build_command(&command, &argv, r, p, &e_info)) != APR_SUCCESS) {
           ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                         "don't know how to spawn child process: %s", 
                         r->filename);
  @@ -932,24 +922,25 @@
   static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb,
                          const char *command, request_rec *r, ap_filter_t *f)
   {
  -    exec_info      e_info;
  +    cgi_exec_info_t  e_info;
       const char   **argv;
       apr_file_t    *script_out = NULL, *script_in = NULL, *script_err = NULL;
       apr_bucket_brigade *bcgi;
       apr_bucket *b;
       apr_status_t rv;
   
  -    e_info.cmd_type  = APR_SHELLCMD;
  -    e_info.in_pipe   = APR_NO_PIPE;
  -    e_info.out_pipe  = APR_FULL_BLOCK;
  -    e_info.err_pipe  = APR_NO_PIPE;
  -    e_info.prog_type = RUN_AS_SSI;
  -    e_info.bb        = bb;
  -    e_info.ctx       = ctx;
  -    e_info.next      = f->next;
  +    e_info.process_cgi = 0;
  +    e_info.cmd_type    = APR_SHELLCMD;
  +    e_info.detached    = 0;
  +    e_info.in_pipe     = APR_NO_PIPE;
  +    e_info.out_pipe    = APR_FULL_BLOCK;
  +    e_info.err_pipe    = APR_NO_PIPE;
  +    e_info.prog_type   = RUN_AS_SSI;
  +    e_info.bb          = bb;
  +    e_info.ctx         = ctx;
  +    e_info.next        = f->next;
   
  -    if ((rv = cgi_build_command(&command, &argv, r, r->pool, 0,
  -                                &e_info.cmd_type)) != APR_SUCCESS) {
  +    if ((rv = cgi_build_command(&command, &argv, r, r->pool, &e_info)) != APR_SUCCESS) {
           ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                         "don't know how to spawn cmd child process: %s", 
                         r->filename);