]> granicus.if.org Git - apache/commitdiff
Consolidated the startup attributes for building the command line for a CGI
authorBradley Nicholes <bnicholes@apache.org>
Wed, 5 Jun 2002 22:58:03 +0000 (22:58 +0000)
committerBradley Nicholes <bnicholes@apache.org>
Wed, 5 Jun 2002 22:58:03 +0000 (22:58 +0000)
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.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@95534 13f79535-47bb-0310-9956-ffa450edef68

modules/arch/netware/mod_netware.c
modules/generators/mod_cgi.c
modules/generators/mod_cgi.h

index cf3aa02f5de2cf2d04611d28ca0ea8c5f06715f6..ee7b8a88de426aa69d6c953c0bdc2df286008451 100644 (file)
@@ -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 @@ static const char *set_extension_map(cmd_parms *cmd, netware_dir_config *m, char
     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 @@ static apr_status_t ap_cgi_build_command(const char **cmd, const char ***argv,
     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,106 +157,11 @@ static apr_status_t ap_cgi_build_command(const char **cmd, const char ***argv,
     }
 
     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)
 {
     APR_REGISTER_OPTIONAL_FN(ap_cgi_build_command);
index bbcc44ea6998f061eea45700402e605a46d3ba01..1b6902fc482b23410c953ce31410dfd14be991c4 100644 (file)
@@ -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_get_tag_and_value) *cgi_pfn_gtv;
 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 @@ static apr_status_t run_cgi_child(apr_file_t **script_out,
                                   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 @@ static apr_status_t run_cgi_child(apr_file_t **script_out,
                                       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 run_cgi_child(apr_file_t **script_out,
 
 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 @@ static int cgi_handler(request_rec *r)
     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 @@ static int cgi_handler(request_rec *r)
 */
     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_cgi(char *s, request_rec *r, ap_filter_t *next,
 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;
-
-    if ((rv = cgi_build_command(&command, &argv, r, r->pool, 0,
-                                &e_info.cmd_type)) != APR_SUCCESS) {
+    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, &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);
index b51d5cb0854c951d68b7902883877720b51f50d0..d293d6d43b0e03fe8a2fb71d40a6c6c1e24db11f 100644 (file)
 #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 */