httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r..@apache.org
Subject cvs commit: httpd-2.0/modules/generators mod_cgi.c mod_cgid.c
Date Mon, 05 Feb 2001 22:57:21 GMT
rbb         01/02/05 14:57:21

  Modified:    .        CHANGES
               modules/filters mod_include.c mod_include.h
               modules/generators mod_cgi.c mod_cgid.c
  Log:
  Move the logic for creating CGI processes from mod_include to mod_cgi(d).
  This removes a good deal of duplicate logic for creating CGI scripts.
  
  Revision  Changes    Path
  1.75      +5 -0      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.74
  retrieving revision 1.75
  diff -u -d -b -w -u -r1.74 -r1.75
  --- CHANGES	2001/02/05 15:04:30	1.74
  +++ CHANGES	2001/02/05 22:57:20	1.75
  @@ -1,5 +1,10 @@
   Changes with Apache 2.0b1
   
  +  *) Move the CGI creation logic from mod_include to mod_cgi(d).  This
  +     should reduce the amount of duplicate code that is required to
  +     create CGI processes.
  +     [Paul J. Reder <rederpj@raleigh.ibm.com>]
  +
     *) ap_new_connection() closes the socket and returns NULL if a socket
        call fails.  Usually this is due to a connection which has been 
        reset.  [Jeff Trawick]
  
  
  
  1.93      +57 -326   httpd-2.0/modules/filters/mod_include.c
  
  Index: mod_include.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/filters/mod_include.c,v
  retrieving revision 1.92
  retrieving revision 1.93
  diff -u -d -b -w -u -r1.92 -r1.93
  --- mod_include.c	2001/01/31 22:45:12	1.92
  +++ mod_include.c	2001/02/05 22:57:20	1.93
  @@ -83,6 +83,7 @@
   #include "http_main.h"
   #include "util_script.h"
   #include "http_core.h"
  +#include "apr_optional.h"
   #include "mod_include.h"
   #ifdef HAVE_STRING_H
   #include <string.h>
  @@ -94,6 +95,8 @@
   
   
   static apr_hash_t *include_hash;
  +static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;
  +
   
   /* ------------------------ Environment function -------------------------- */
   
  @@ -496,7 +499,7 @@
   
   #define SKIP_TAG_WHITESPACE(ptr) while ((*ptr != '\0') && (apr_isspace (*ptr))) ptr++
   
  -static void get_tag_and_value(include_ctx_t *ctx, char **tag,
  +static void ap_ssi_get_tag_and_value(include_ctx_t *ctx, char **tag,
                                 char **tag_val, int dodecode)
   {
       char *c = ctx->curr_tag_pos;
  @@ -574,7 +577,7 @@
   /*
    * Do variable substitution on strings
    */
  -static void parse_string(request_rec *r, const char *in, char *out,
  +static void ap_ssi_parse_string(request_rec *r, const char *in, char *out,
   			size_t length, int leave_name)
   {
       char ch;
  @@ -601,7 +604,6 @@
               break;
           case '$':
               {
  -/* pjr hack     char var[MAX_STRING_LEN]; */
   		const char *start_of_var_name;
   		char *end_of_var_name;	/* end of var name + 1 */
   		const char *expansion, *temp_end, *val;
  @@ -637,17 +639,10 @@
   		 * pass a non-nul terminated string */
   		l = end_of_var_name - start_of_var_name;
   		if (l != 0) {
  -/* pjr - this is a test hack to avoid a memcpy. Make sure that this works...
  -*		    l = (l > sizeof(var) - 1) ? (sizeof(var) - 1) : l;
  -*		    memcpy(var, start_of_var_name, l);
  -*		    var[l] = '\0';
  -*
  -*		    val = apr_table_get(r->subprocess_env, var);
  -*/
  -/* pjr hack */      tmp_store        = *end_of_var_name;
  -/* pjr hack */      *end_of_var_name = '\0';
  -/* pjr hack */      val = apr_table_get(r->subprocess_env, start_of_var_name);
  -/* pjr hack */      *end_of_var_name = tmp_store;
  +                    tmp_store        = *end_of_var_name;
  +                    *end_of_var_name = '\0';
  +                    val = apr_table_get(r->subprocess_env, start_of_var_name);
  +                    *end_of_var_name = tmp_store;
   
   		    if (val) {
   			expansion = val;
  @@ -685,68 +680,6 @@
   
   /* --------------------------- Action handlers ---------------------------- */
   
  -static int include_cgi(char *s, request_rec *r, ap_filter_t *next,
  -                       apr_bucket *head_ptr, apr_bucket **inserted_head)
  -{
  -    request_rec *rr = ap_sub_req_lookup_uri(s, r, next);
  -    int rr_status;
  -    apr_bucket  *tmp_buck, *tmp2_buck;
  -
  -    if (rr->status != HTTP_OK) {
  -        return -1;
  -    }
  -
  -    /* No hardwired path info or query allowed */
  -
  -    if ((rr->path_info && rr->path_info[0]) || rr->args) {
  -        return -1;
  -    }
  -    if (rr->finfo.filetype == 0) {
  -        return -1;
  -    }
  -
  -    /* Script gets parameters of the *document*, for back compatibility */
  -
  -    rr->path_info = r->path_info;       /* hard to get right; see mod_cgi.c */
  -    rr->args = r->args;
  -
  -    /* Force sub_req to be treated as a CGI request, even if ordinary
  -     * typing rules would have called it something else.
  -     */
  -
  -    rr->content_type = CGI_MAGIC_TYPE;
  -
  -    /* Run it. */
  -
  -    rr_status = ap_run_sub_req(rr);
  -    if (ap_is_HTTP_REDIRECT(rr_status)) {
  -        apr_size_t len_loc, h_wrt;
  -        const char *location = apr_table_get(rr->headers_out, "Location");
  -
  -        location = ap_escape_html(rr->pool, location);
  -        len_loc = strlen(location);
  -
  -        tmp_buck = apr_bucket_create_immortal("<A HREF=\"", sizeof("<A HREF=\""));
  -        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
  -        tmp2_buck = apr_bucket_create_heap(location, len_loc, 1, &h_wrt);
  -        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  -        tmp2_buck = apr_bucket_create_immortal("\">", sizeof("\">"));
  -        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  -        tmp2_buck = apr_bucket_create_heap(location, len_loc, 1, &h_wrt);
  -        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  -        tmp2_buck = apr_bucket_create_immortal("</A>", sizeof("</A>"));
  -        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  -
  -        if (*inserted_head == NULL) {
  -            *inserted_head = tmp_buck;
  -        }
  -    }
  -
  -    ap_destroy_sub_req(rr);
  -
  -    return 0;
  -}
  -
   /* ensure that path is relative, and does not contain ".." elements
    * ensentially ensure that it does not match the regex:
    * (^/|(^|/)\.\.(/|$))
  @@ -798,7 +731,7 @@
       *inserted_head = NULL;
       if (ctx->flags & FLAG_PRINTING) {
           while (1) {
  -            get_tag_and_value(ctx, &tag, &tag_val, 1);
  +            ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
               if (tag_val == NULL) {
                   if (tag == NULL) {
                       return (0);
  @@ -811,7 +744,7 @@
                   request_rec *rr = NULL;
                   char *error_fmt = NULL;
   
  -                parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +                ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
                   if (tag[0] == 'f') {
                       /* be safe; only files in this directory or below allowed */
       		if (!is_only_below(parsed_string)) {
  @@ -884,10 +817,9 @@
       		ap_set_module_config(rr->request_config, &includes_module, r);
   
                   if (!error_fmt) {
  -                    SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx);
  -/*
  -                    rr->output_filters = f->next;
  -*/                    if (ap_run_sub_req(rr)) {
  +                    SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
  +                    
  +                    if (ap_run_sub_req(rr)) {
                           error_fmt = "unable to include \"%s\" in parsed file %s";
                       }
                   }
  @@ -915,214 +847,7 @@
       return 0;
   }
   
  -typedef struct {
  -#ifdef TPF
  -    TPF_FORK_CHILD t;
  -#endif
  -    request_rec *r;
  -    char *s;
  -} include_cmd_arg;
  -
  -
  -
  -static apr_status_t build_argv_list(char ***argv, request_rec *r, apr_pool_t *p)
  -{
  -    int numwords, x, idx;
  -    char *w;
  -    const char *args = r->args;
  -
  -    if (!args || !args[0] || ap_strchr_c(args, '=')) {
  -       numwords = 1;
  -    }
  -    else {
  -        /* count the number of keywords */
  -        for (x = 0, numwords = 1; args[x]; x++) {
  -            if (args[x] == '+') {
  -                ++numwords;
  -            }
  -        }
  -    }
  -    /* Everything is - 1 to account for the first parameter which is the
  -     * program name.  We didn't used to have to do this, but APR wants it.
  -     */
  -    if (numwords > APACHE_ARG_MAX - 1) {
  -        numwords = APACHE_ARG_MAX - 1;	/* Truncate args to prevent overrun */
  -    }
  -    *argv = (char **) apr_palloc(p, (numwords + 2) * sizeof(char *));
  - 
  -    for (x = 1, idx = 1; x < numwords; x++) {
  -        w = ap_getword_nulls(p, &args, '+');
  -        ap_unescape_url(w);
  -        (*argv)[idx++] = ap_escape_shell_cmd(p, w);
  -    }
  -    (*argv)[idx] = NULL;
  -
  -    return APR_SUCCESS;
  -}
  -
   
  -
  -static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb, char *s,
  -                       request_rec *r, ap_filter_t *f)
  -{
  -    include_cmd_arg arg;
  -    apr_procattr_t *procattr;
  -    apr_proc_t *procnew;
  -    apr_status_t rc;
  -    apr_table_t *env = r->subprocess_env;
  -    char **argv;
  -    apr_file_t *file = NULL;
  -#if defined(RLIMIT_CPU)  || defined(RLIMIT_NPROC) || \
  -    defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
  -    core_dir_config *conf; 
  -    conf = (core_dir_config *) ap_get_module_config(r->per_dir_config,
  -                                                    &core_module);
  -#endif
  -
  -    arg.r = r;
  -    arg.s = s;
  -#ifdef TPF
  -    arg.t.filename = r->filename;
  -    arg.t.subprocess_env = r->subprocess_env;
  -    arg.t.prog_type = FORK_FILE;
  -#endif
  -
  -    if (r->path_info && r->path_info[0] != '\0') {
  -        request_rec *pa_req;
  -
  -        apr_table_setn(env, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info));
  -
  -        pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, f->next);
  -        if (pa_req->filename) {
  -            apr_table_setn(env, "PATH_TRANSLATED",
  -                      apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info,
  -                              NULL));
  -        }
  -    }
  -
  -    if (r->args) {
  -        char *arg_copy = apr_pstrdup(r->pool, r->args);
  -
  -        apr_table_setn(env, "QUERY_STRING", r->args);
  -        ap_unescape_url(arg_copy);
  -        apr_table_setn(env, "QUERY_STRING_UNESCAPED",
  -                  ap_escape_shell_cmd(r->pool, arg_copy));
  -    }
  -
  -    if (((rc = apr_createprocattr_init(&procattr, r->pool)) != APR_SUCCESS) ||
  -        ((rc = apr_setprocattr_io(procattr, APR_NO_PIPE, 
  -                                  APR_FULL_BLOCK, APR_NO_PIPE)) != APR_SUCCESS) ||
  -        ((rc = apr_setprocattr_dir(procattr, ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
  -#ifdef RLIMIT_CPU
  -        ((rc = apr_setprocattr_limit(procattr, APR_LIMIT_CPU, conf->limit_cpu)) != APR_SUCCESS) ||
  -#endif
  -#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
  -        ((rc = apr_setprocattr_limit(procattr, APR_LIMIT_MEM, conf->limit_mem)) != APR_SUCCESS) ||
  -#endif
  -#ifdef RLIMIT_NPROC
  -        ((rc = apr_setprocattr_limit(procattr, APR_LIMIT_NPROC, conf->limit_nproc)) != APR_SUCCESS) ||
  -#endif
  -        ((rc = apr_setprocattr_cmdtype(procattr, APR_SHELLCMD)) != APR_SUCCESS)) {
  -        /* Something bad happened, tell the world. */
  -	ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
  -            "couldn't initialize proc attributes: %s %s", r->filename, s);
  -        rc = !APR_SUCCESS;
  -    }
  -    else {
  -        SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx);
  -        build_argv_list(&argv, r, r->pool);
  -        argv[0] = apr_pstrdup(r->pool, s);
  -        procnew = apr_pcalloc(r->pool, sizeof(*procnew));
  -        rc = apr_create_process(procnew, s, (const char * const *) argv,
  -                                (const char * const *)ap_create_environment(r->pool, env),
  -                                procattr, r->pool);
  -
  -        if (rc != APR_SUCCESS) {
  -            /* Bad things happened. Everyone should have cleaned up. */
  -            ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
  -                        "couldn't create child process: %d: %s", rc, s);
  -        }
  -        else {
  -            apr_bucket_brigade *bcgi;
  -            apr_bucket *b;
  -
  -            apr_note_subprocess(r->pool, procnew, kill_after_timeout);
  -            /* Fill in BUFF structure for parents pipe to child's stdout */
  -            file = procnew->out;
  -            if (!file)
  -                return APR_EBADF;
  -            bcgi = apr_brigade_create(r->pool);
  -            b = apr_bucket_create_pipe(file);
  -            APR_BRIGADE_INSERT_TAIL(bcgi, b);
  -            ap_pass_brigade(f->next, bcgi);
  -        
  -            /* We can't close the pipe here, because we may return before the
  -             * full CGI has been sent to the network.  That's okay though,
  -             * because we can rely on the pool to close the pipe for us.
  -             */
  -        }
  -    }
  -
  -    return 0;
  -}
  -
  -static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
  -                       ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
  -{
  -    char *tag     = NULL;
  -    char *tag_val = NULL;
  -    char *file = r->filename;
  -    apr_bucket  *tmp_buck;
  -    char parsed_string[MAX_STRING_LEN];
  -
  -    *inserted_head = NULL;
  -    if (ctx->flags & FLAG_PRINTING) {
  -        if (ctx->flags & FLAG_NO_EXEC) {
  -            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  -                      "exec used but not allowed in %s", r->filename);
  -            CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  -        }
  -        else {
  -            while (1) {
  -                get_tag_and_value(ctx, &tag, &tag_val, 1);
  -                if (tag_val == NULL) {
  -                    if (tag == NULL) {
  -                        return (0);
  -                    }
  -                    else {
  -                        return 1;
  -                    }
  -                }
  -                if (!strcmp(tag, "cmd")) {
  -                    parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 1);
  -                    if (include_cmd(ctx, bb, parsed_string, r, f) == -1) {
  -                        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  -                                    "execution failure for parameter \"%s\" "
  -                                    "to tag exec in file %s", tag, r->filename);
  -                        CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  -                    }
  -                    /* just in case some stooge changed directories */
  -                }
  -                else if (!strcmp(tag, "cgi")) {
  -                    parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  -                    SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx);
  -                    if (include_cgi(parsed_string, r, f->next, head_ptr, inserted_head) == -1) {
  -                        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  -                                    "invalid CGI ref \"%s\" in %s", tag_val, file);
  -                        CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  -                    }
  -                }
  -                else {
  -                    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  -                                "unknown parameter \"%s\" to tag exec in %s", tag, file);
  -                    CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  -                }
  -            }
  -        }
  -    }
  -    return 0;
  -}
  -
   static int handle_echo(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
                          ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
   {
  @@ -1138,7 +863,7 @@
       *inserted_head = NULL;
       if (ctx->flags & FLAG_PRINTING) {
           while (1) {
  -            get_tag_and_value(ctx, &tag, &tag_val, 1);
  +            ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
               if (tag_val == NULL) {
                   if (tag != NULL) {
                       return 1;
  @@ -1206,7 +931,7 @@
       *inserted_head = NULL;
       if (ctx->flags & FLAG_PRINTING) {
           while (1) {
  -            get_tag_and_value(ctx, &tag, &tag_val, 0);
  +            ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 0);
               if (tag_val == NULL) {
                   if (tag == NULL) {
                       return 0;  /* Reached the end of the string. */
  @@ -1216,20 +941,20 @@
                   }
               }
               if (!strcmp(tag, "errmsg")) {
  -                parse_string(r, tag_val, ctx->error_str, MAX_STRING_LEN, 0);
  +                ap_ssi_parse_string(r, tag_val, ctx->error_str, MAX_STRING_LEN, 0);
                   ctx->error_length = strlen(ctx->error_str);
               }
               else if (!strcmp(tag, "timefmt")) {
                   apr_time_t date = r->request_time;
   
  -                parse_string(r, tag_val, ctx->time_str, MAX_STRING_LEN, 0);
  +                ap_ssi_parse_string(r, tag_val, ctx->time_str, MAX_STRING_LEN, 0);
                   apr_table_setn(env, "DATE_LOCAL", ap_ht_time(r->pool, date, ctx->time_str, 0));
                   apr_table_setn(env, "DATE_GMT", ap_ht_time(r->pool, date, ctx->time_str, 1));
                   apr_table_setn(env, "LAST_MODIFIED",
                                  ap_ht_time(r->pool, r->finfo.mtime, ctx->time_str, 0));
               }
               else if (!strcmp(tag, "sizefmt")) {
  -                parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +                ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
                   decodehtml(parsed_string);
                   if (!strcmp(parsed_string, "bytes")) {
                       ctx->flags |= FLAG_SIZE_IN_BYTES;
  @@ -1367,7 +1092,7 @@
       *inserted_head = NULL;
       if (ctx->flags & FLAG_PRINTING) {
           while (1) {
  -            get_tag_and_value(ctx, &tag, &tag_val, 1);
  +            ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
               if (tag_val == NULL) {
                   if (tag == NULL) {
                       return 0;
  @@ -1377,7 +1102,7 @@
                   }
               }
               else {
  -                parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +                ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
                   if (!find_file(r, "fsize", tag, parsed_string, &finfo)) {
                       char buff[50];
   
  @@ -1429,7 +1154,7 @@
       *inserted_head = NULL;
       if (ctx->flags & FLAG_PRINTING) {
           while (1) {
  -            get_tag_and_value(ctx, &tag, &tag_val, 1);
  +            ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
               if (tag_val == NULL) {
                   if (tag == NULL) {
                       return 0;
  @@ -1439,7 +1164,7 @@
                   }
               }
               else {
  -                parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +                ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
                   if (!find_file(r, "flastmod", tag, parsed_string, &finfo)) {
                       char *t_val;
   
  @@ -1981,7 +1706,7 @@
                       sizeof ("     Evaluate string\n"));
               debug_pos += sizeof ("     Evaluate string\n");
   #endif
  -            parse_string(r, current->token.value, buffer, sizeof(buffer), 0);
  +            ap_ssi_parse_string(r, current->token.value, buffer, sizeof(buffer), 0);
   	    apr_cpystrn(current->token.value, buffer, sizeof(current->token.value));
               current->value = (current->token.value[0] != '\0');
               current->done = 1;
  @@ -2006,7 +1731,7 @@
               if (!current->left->done) {
                   switch (current->left->token.type) {
                   case token_string:
  -                    parse_string(r, current->left->token.value,
  +                    ap_ssi_parse_string(r, current->left->token.value,
                                    buffer, sizeof(buffer), 0);
                       apr_cpystrn(current->left->token.value, buffer,
                               sizeof(current->left->token.value));
  @@ -2021,7 +1746,7 @@
               if (!current->right->done) {
                   switch (current->right->token.type) {
                   case token_string:
  -                    parse_string(r, current->right->token.value,
  +                    ap_ssi_parse_string(r, current->right->token.value,
                                    buffer, sizeof(buffer), 0);
                       apr_cpystrn(current->right->token.value, buffer,
                               sizeof(current->right->token.value));
  @@ -2070,11 +1795,11 @@
                   *was_error = 1;
                   goto RETURN;
               }
  -            parse_string(r, current->left->token.value,
  +            ap_ssi_parse_string(r, current->left->token.value,
                            buffer, sizeof(buffer), 0);
               apr_cpystrn(current->left->token.value, buffer,
   			sizeof(current->left->token.value));
  -            parse_string(r, current->right->token.value,
  +            ap_ssi_parse_string(r, current->right->token.value,
                            buffer, sizeof(buffer), 0);
               apr_cpystrn(current->right->token.value, buffer,
   			sizeof(current->right->token.value));
  @@ -2141,11 +1866,11 @@
                   *was_error = 1;
                   goto RETURN;
               }
  -            parse_string(r, current->left->token.value,
  +            ap_ssi_parse_string(r, current->left->token.value,
                            buffer, sizeof(buffer), 0);
               apr_cpystrn(current->left->token.value, buffer,
   			sizeof(current->left->token.value));
  -            parse_string(r, current->right->token.value,
  +            ap_ssi_parse_string(r, current->right->token.value,
                            buffer, sizeof(buffer), 0);
               apr_cpystrn(current->right->token.value, buffer,
   			sizeof(current->right->token.value));
  @@ -2307,7 +2032,7 @@
       }
       else {
           while (1) {
  -            get_tag_and_value(ctx, &tag, &tag_val, 0);
  +            ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 0);
               if (tag == NULL) {
                   if (expr == NULL) {
                       ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  @@ -2375,7 +2100,7 @@
       *inserted_head = NULL;
       if (!ctx->if_nesting_level) {
           while (1) {
  -            get_tag_and_value(ctx, &tag, &tag_val, 0);
  +            ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 0);
               if (tag == '\0') {
                   LOG_COND_STATUS(ctx, tmp_buck, head_ptr, *inserted_head, " elif");
                   
  @@ -2443,7 +2168,7 @@
   
       *inserted_head = NULL;
       if (!ctx->if_nesting_level) {
  -        get_tag_and_value(ctx, &tag, &tag_val, 1);
  +        ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
           if ((tag != NULL) || (tag_val != NULL)) {
               ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
                           "else directive does not take tags in %s", r->filename);
  @@ -2476,7 +2201,7 @@
   
       *inserted_head = NULL;
       if (!ctx->if_nesting_level) {
  -        get_tag_and_value(ctx, &tag, &tag_val, 1);
  +        ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
           if ((tag != NULL) || (tag_val != NULL)) {
               ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
                           "endif directive does not take tags in %s", r->filename);
  @@ -2507,7 +2232,7 @@
       *inserted_head = NULL;
       if (ctx->flags & FLAG_PRINTING) {
           while (1) {
  -            get_tag_and_value(ctx, &tag, &tag_val, 1);
  +            ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
               if ((tag == NULL) && (tag_val == NULL)) {
                   return 0;
               }
  @@ -2525,7 +2250,7 @@
                       CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
                       return (-1);
                   }
  -                parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +                ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
                   apr_table_setn(r->subprocess_env, apr_pstrdup(r->pool, var),
                                  apr_pstrdup(r->pool, parsed_string));
               }
  @@ -2548,7 +2273,7 @@
       apr_bucket *tmp_buck;
   
       if (ctx->flags & FLAG_PRINTING) {
  -        get_tag_and_value(ctx, &tag, &tag_val, 1);
  +        ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
           if ((tag == NULL) && (tag_val == NULL)) {
               apr_array_header_t *arr = apr_table_elts(r->subprocess_env);
               apr_table_entry_t *elts = (apr_table_entry_t *)arr->elts;
  @@ -3016,7 +2741,7 @@
       return OK;
   }
   
  -void ap_register_include_handler(char *tag, handler func)
  +static void ap_register_include_handler(char *tag, include_handler func)
   {
       apr_hash_set(include_hash, tag, strlen(tag) + 1, (const void *)func);
   }
  @@ -3026,18 +2751,21 @@
   {
       include_hash = apr_make_hash(p);
   
  -    ap_register_include_handler("if", handle_if);
  -    ap_register_include_handler("set", handle_set);
  -    ap_register_include_handler("else", handle_else);
  -    ap_register_include_handler("elif", handle_elif);
  -    ap_register_include_handler("exec", handle_exec);
  -    ap_register_include_handler("echo", handle_echo);
  -    ap_register_include_handler("endif", handle_endif);
  -    ap_register_include_handler("fsize", handle_fsize);
  -    ap_register_include_handler("config", handle_config);
  -    ap_register_include_handler("include", handle_include);
  -    ap_register_include_handler("flastmod", handle_flastmod);
  -    ap_register_include_handler("printenv", handle_printenv);
  +    ssi_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
  +
  +    if(ssi_pfn_register) {
  +        ssi_pfn_register("if", handle_if);
  +        ssi_pfn_register("set", handle_set);
  +        ssi_pfn_register("else", handle_else);
  +        ssi_pfn_register("elif", handle_elif);
  +        ssi_pfn_register("echo", handle_echo);
  +        ssi_pfn_register("endif", handle_endif);
  +        ssi_pfn_register("fsize", handle_fsize);
  +        ssi_pfn_register("config", handle_config);
  +        ssi_pfn_register("include", handle_include);
  +        ssi_pfn_register("flastmod", handle_flastmod);
  +        ssi_pfn_register("printenv", handle_printenv);
  +    }
   }
   
   /*
  @@ -3052,6 +2780,9 @@
   
   static void register_hooks(apr_pool_t *p)
   {
  +    APR_REGISTER_OPTIONAL_FN(ap_ssi_get_tag_and_value);
  +    APR_REGISTER_OPTIONAL_FN(ap_ssi_parse_string);
  +    APR_REGISTER_OPTIONAL_FN(ap_register_include_handler);
       ap_hook_post_config(include_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
       ap_register_output_filter("INCLUDES", includes_filter, AP_FTYPE_CONTENT);
   }
  
  
  
  1.9       +20 -11    httpd-2.0/modules/filters/mod_include.h
  
  Index: mod_include.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/filters/mod_include.h,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -d -b -w -u -r1.8 -r1.9
  --- mod_include.h	2001/01/20 05:18:05	1.8
  +++ mod_include.h	2001/02/05 22:57:21	1.9
  @@ -59,8 +59,6 @@
   #ifndef _MOD_INCLUDE_H
   #define _MOD_INCLUDE_H 1
   
  -
  -
   #define STARTING_SEQUENCE "<!--#"
   #define ENDING_SEQUENCE "-->"
   
  @@ -186,20 +184,31 @@
       }                                                             \
   }
   
  -#define SPLIT_AND_PASS_PRETAG_BUCKETS(brgd, cntxt)               \
  +#define SPLIT_AND_PASS_PRETAG_BUCKETS(brgd, cntxt, next)          \
   if ((APR_BRIGADE_EMPTY(cntxt->ssi_tag_brigade)) &&                \
       (cntxt->head_start_bucket != NULL)) {                        \
       apr_bucket_brigade *tag_plus;                                 \
                                                                    \
       tag_plus = apr_brigade_split(brgd, cntxt->head_start_bucket); \
  -    ap_pass_brigade(f->next, brgd);                              \
  +    ap_pass_brigade(next, brgd);                                  \
       brgd = tag_plus;                                             \
   }
   
  -typedef int (*handler)(include_ctx_t *ctx, apr_bucket_brigade **bb, 
  +
  +typedef int (*include_handler)(include_ctx_t *ctx, apr_bucket_brigade **bb, 
                          request_rec *r, ap_filter_t *f, apr_bucket *head_ptr, 
                          apr_bucket **inserted_head);
   
  -void ap_register_include_handler(char *tag, handler func);
  +APR_DECLARE_OPTIONAL_FN(void, ap_ssi_get_tag_and_value, (include_ctx_t *ctx,
  +                                                        char **tag,
  +                                                        char **tag_val,
  +                                                        int dodecode))
  +APR_DECLARE_OPTIONAL_FN(void, ap_ssi_parse_string, (request_rec *r,
  +                                                    const char *in,
  +                                                    char *out,
  +                                                    size_t length,
  +                                                    int leave_name))
  +APR_DECLARE_OPTIONAL_FN(void, ap_register_include_handler, (char *tag,
  +                                                         include_handler func))
   
   #endif /* MOD_INCLUDE */
  
  
  
  1.83      +288 -23   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.82
  retrieving revision 1.83
  diff -u -d -b -w -u -r1.82 -r1.83
  --- mod_cgi.c	2001/01/31 22:45:16	1.82
  +++ mod_cgi.c	2001/02/05 22:57:21	1.83
  @@ -88,6 +88,8 @@
   #include "util_script.h"
   #include "ap_mpm.h"
   #include "http_conf_globals.h"
  +#include "apr_optional.h"
  +#include "../filters/mod_include.h"
   #ifdef HAVE_STRING_H
   #include <string.h>
   #endif
  @@ -97,6 +99,23 @@
   
   module AP_MODULE_DECLARE_DATA cgi_module;
   
  +static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *cgi_pfn_reg_with_ssi;
  +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;
  +
  +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;
  +
   /* KLUDGE --- for back-combatibility, we don't have to check ExecCGI
    * in ScriptAliased directories, which means we need to know if this
    * request came through ScriptAlias or not... so the Alias module
  @@ -313,16 +332,47 @@
       return ret;
   }
   
  +
  +/* This is the special environment used for running the "exec cmd="
  + *   variety of SSI directives.
  + */
  +static void add_ssi_vars(request_rec *r, ap_filter_t *next)
  +{
  +    apr_table_t *e = r->subprocess_env;
  +
  +    if (r->path_info && r->path_info[0] != '\0') {
  +        request_rec *pa_req;
  +
  +        apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info));
  +
  +        pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, next);
  +        if (pa_req->filename) {
  +            apr_table_setn(e, "PATH_TRANSLATED",
  +                           apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL));
  +        }
  +    }
  +
  +    if (r->args) {
  +        char *arg_copy = apr_pstrdup(r->pool, r->args);
  +
  +        apr_table_setn(e, "QUERY_STRING", r->args);
  +        ap_unescape_url(arg_copy);
  +        apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy));
  +    }
  +}
  +
   static apr_status_t run_cgi_child(apr_file_t **script_out,
                                     apr_file_t **script_in,
                                     apr_file_t **script_err, 
                                     const char *command,
                                     const char * const argv[],
  -                                  request_rec *r, apr_pool_t *p)
  +                                  request_rec *r,
  +                                  apr_pool_t *p,
  +                                  exec_info *e_info)
   {
       const char * const *env;
       apr_procattr_t *procattr;
  -    apr_proc_t *procnew = apr_pcalloc(p, sizeof(*procnew));
  +    apr_proc_t *procnew;
       apr_status_t rc = APR_SUCCESS;
   #if defined(RLIMIT_CPU)  || defined(RLIMIT_NPROC) || \
       defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
  @@ -347,7 +397,13 @@
   	    r->filename, cld->nph ? "NPH " : "", argv0);
   #endif
   
  +    if (e_info->prog_type == RUN_AS_CGI) {
       ap_add_cgi_vars(r);
  +    }
  +    else /* SSIs want a controlled environment and a special path. */
  +    {
  +        add_ssi_vars(r, e_info->next);
  +    }
       env = (const char * const *)ap_create_environment(p, r->subprocess_env);
   
   #ifdef DEBUG_CGI
  @@ -361,9 +417,9 @@
        */
       if (((rc = apr_createprocattr_init(&procattr, p)) != APR_SUCCESS) ||
           ((rc = apr_setprocattr_io(procattr, 
  -                                 APR_CHILD_BLOCK, 
  -                                 APR_CHILD_BLOCK,
  -                                 APR_CHILD_BLOCK)) != APR_SUCCESS) ||
  +                                  e_info->in_pipe,
  +                                  e_info->out_pipe,
  +                                  e_info->err_pipe)) != APR_SUCCESS) ||
           ((rc = apr_setprocattr_dir(procattr, 
                                     ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
   #ifdef RLIMIT_CPU
  @@ -375,12 +431,17 @@
   #ifdef RLIMIT_NPROC
           ((rc = apr_setprocattr_limit(procattr, APR_LIMIT_NPROC, conf->limit_nproc)) != APR_SUCCESS) ||
   #endif
  -        ((rc = apr_setprocattr_cmdtype(procattr, APR_PROGRAM)) != APR_SUCCESS)) {
  +        ((rc = apr_setprocattr_cmdtype(procattr, e_info->cmd_type)) != 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);
       }
       else {
  +        procnew = apr_pcalloc(p, sizeof(*procnew));
  +        if (e_info->prog_type == RUN_AS_SSI) {
  +            SPLIT_AND_PASS_PRETAG_BUCKETS(*(e_info->bb), e_info->ctx, e_info->next);
  +        }
  +
           rc = ap_os_create_privileged_process(r, procnew, command, argv, env, procattr, p);
       
           if (rc != APR_SUCCESS) {
  @@ -394,22 +455,21 @@
               *script_in = procnew->out;
               if (!script_in)
                   return APR_EBADF;
  -            apr_set_pipe_timeout(*script_in, 
  -                                 (int)(r->server->timeout * APR_USEC_PER_SEC));
  +            apr_set_pipe_timeout(*script_in, (int)(r->server->timeout * APR_USEC_PER_SEC));
   
  +            if (e_info->prog_type == RUN_AS_CGI) {
               *script_out = procnew->in;
               if (!*script_out)
                   return APR_EBADF;
  -            apr_set_pipe_timeout(*script_out, 
  -                                 (int)(r->server->timeout * APR_USEC_PER_SEC));
  +                apr_set_pipe_timeout(*script_out, (int)(r->server->timeout * APR_USEC_PER_SEC));
   
               *script_err = procnew->err;
               if (!*script_err)
                   return APR_EBADF;
  -            apr_set_pipe_timeout(*script_err, 
  -                                 (int)(r->server->timeout * APR_USEC_PER_SEC));
  +                apr_set_pipe_timeout(*script_err, (int)(r->server->timeout * APR_USEC_PER_SEC));
           }
       }
  +    }
       return (rc);
   }
   
  @@ -516,6 +576,7 @@
       apr_pool_t *p;
       cgi_server_conf *conf;
       apr_status_t rv;
  +    exec_info e_info;
   
       if(strcmp(r->handler,CGI_MAGIC_TYPE) && strcmp(r->handler,"cgi-script"))
   	return DECLINED;
  @@ -600,9 +661,18 @@
       }
       argv[0] = apr_pstrdup(p, command);
   
  +    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;
  +
       /* run the script in its own process */
       if ((rv = run_cgi_child(&script_out, &script_in, &script_err,
  -                            command, argv, r, p)) != APR_SUCCESS) {
  +                            command, argv, r, p, &e_info)) != APR_SUCCESS) {
           ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                         "couldn't spawn child process: %s", r->filename);
           return HTTP_INTERNAL_SERVER_ERROR;
  @@ -723,9 +793,204 @@
       return OK;			/* NOT r->status, even if it has changed. */
   }
   
  +/*============================================================================
  + *============================================================================
  + * This is the beginning of the cgi filter code moved from mod_include. This
  + *   is the code required to handle the "exec" SSI directive.
  + *============================================================================
  + *============================================================================*/
  +static int include_cgi(char *s, request_rec *r, ap_filter_t *next,
  +                       apr_bucket *head_ptr, apr_bucket **inserted_head)
  +{
  +    request_rec *rr = ap_sub_req_lookup_uri(s, r, next);
  +    int rr_status;
  +    apr_bucket  *tmp_buck, *tmp2_buck;
  +
  +    if (rr->status != HTTP_OK) {
  +        return -1;
  +    }
  +
  +    /* No hardwired path info or query allowed */
  +
  +    if ((rr->path_info && rr->path_info[0]) || rr->args) {
  +        return -1;
  +    }
  +    if (rr->finfo.protection == 0) {
  +        return -1;
  +    }
  +
  +    /* Script gets parameters of the *document*, for back compatibility */
  +
  +    rr->path_info = r->path_info;       /* hard to get right; see mod_cgi.c */
  +    rr->args = r->args;
  +
  +    /* Force sub_req to be treated as a CGI request, even if ordinary
  +     * typing rules would have called it something else.
  +     */
  +
  +    rr->content_type = CGI_MAGIC_TYPE;
  +
  +    /* Run it. */
  +
  +    rr_status = ap_run_sub_req(rr);
  +    if (ap_is_HTTP_REDIRECT(rr_status)) {
  +        apr_size_t len_loc, h_wrt;
  +        const char *location = apr_table_get(rr->headers_out, "Location");
  +
  +        location = ap_escape_html(rr->pool, location);
  +        len_loc = strlen(location);
  +
  +        tmp_buck = apr_bucket_create_immortal("<A HREF=\"", sizeof("<A HREF=\""));
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
  +        tmp2_buck = apr_bucket_create_heap(location, len_loc, 1, &h_wrt);
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  +        tmp2_buck = apr_bucket_create_immortal("\">", sizeof("\">"));
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  +        tmp2_buck = apr_bucket_create_heap(location, len_loc, 1, &h_wrt);
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  +        tmp2_buck = apr_bucket_create_immortal("</A>", sizeof("</A>"));
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  +
  +        if (*inserted_head == NULL) {
  +            *inserted_head = tmp_buck;
  +        }
  +    }
  +
  +    ap_destroy_sub_req(rr);
  +
  +    return 0;
  +}
  +
  +
  +static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb, char *command,
  +                       request_rec *r, ap_filter_t *f)
  +{
  +    exec_info      e_info;
  +    const char   **argv;
  +    apr_file_t    *script_out = NULL, *script_in = NULL, *script_err = NULL;
  +    apr_bucket_brigade *bcgi;
  +    apr_bucket *b;
  +
  +    if (build_argv_list(&argv, r, r->pool) != APR_SUCCESS) {
  +        ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
  +                      "couldn't spawn cmd child process: %s", r->filename);
  +        return HTTP_INTERNAL_SERVER_ERROR;
  +    }
  +    argv[0] = apr_pstrdup(r->pool, command);
  +
  +    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;
  +
  +    /* run the script in its own process */
  +    if (run_cgi_child(&script_out, &script_in, &script_err,
  +                      command, argv, r, r->pool, &e_info) != APR_SUCCESS) {
  +        ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
  +                      "couldn't spawn child process: %s", r->filename);
  +        return HTTP_INTERNAL_SERVER_ERROR;
  +    }
  +
  +    bcgi = apr_brigade_create(r->pool);
  +    b = apr_bucket_create_pipe(script_in);
  +    APR_BRIGADE_INSERT_TAIL(bcgi, b);
  +    ap_pass_brigade(f->next, bcgi);
  +
  +    /* We can't close the pipe here, because we may return before the
  +     * full CGI has been sent to the network.  That's okay though,
  +     * because we can rely on the pool to close the pipe for us.
  +     */
  +
  +    return 0;
  +}
  +
  +static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
  +                       ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
  +{
  +    char *tag     = NULL;
  +    char *tag_val = NULL;
  +    char *file = r->filename;
  +    apr_bucket  *tmp_buck;
  +    char parsed_string[MAX_STRING_LEN];
  +
  +    *inserted_head = NULL;
  +    if (ctx->flags & FLAG_PRINTING) {
  +        if (ctx->flags & FLAG_NO_EXEC) {
  +            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +                      "exec used but not allowed in %s", r->filename);
  +            CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  +        }
  +        else {
  +            while (1) {
  +                cgi_pfn_gtv(ctx, &tag, &tag_val, 1);
  +                if (tag_val == NULL) {
  +                    if (tag == NULL) {
  +                        return (0);
  +                    }
  +                    else {
  +                        return 1;
  +                    }
  +                }
  +                if (!strcmp(tag, "cmd")) {
  +                    cgi_pfn_ps(r, tag_val, parsed_string, sizeof(parsed_string), 1);
  +                    if (include_cmd(ctx, bb, parsed_string, r, f) == -1) {
  +                        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +                                    "execution failure for parameter \"%s\" "
  +                                    "to tag exec in file %s", tag, r->filename);
  +                        CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  +                    }
  +                }
  +                else if (!strcmp(tag, "cgi")) {
  +                    cgi_pfn_ps(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +                    SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
  +                    if (include_cgi(parsed_string, r, f->next, head_ptr, inserted_head) == -1) {
  +                        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +                                    "invalid CGI ref \"%s\" in %s", tag_val, file);
  +                        CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  +                    }
  +                }
  +                else {
  +                    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +                                "unknown parameter \"%s\" to tag exec in %s", tag, file);
  +                    CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  +                }
  +            }
  +        }
  +    }
  +    return 0;
  +}
  +
  +
  +/*============================================================================
  + *============================================================================
  + * This is the end of the cgi filter code moved from mod_include.
  + *============================================================================
  + *============================================================================*/
  +
  +
  +static void cgi_post_config(apr_pool_t *p, apr_pool_t *plog,
  +                                apr_pool_t *ptemp, server_rec *s)
  +{
  +    cgi_pfn_reg_with_ssi = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
  +    cgi_pfn_gtv          = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_get_tag_and_value);
  +    cgi_pfn_ps           = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_parse_string);
  +
  +    if ((cgi_pfn_reg_with_ssi) && (cgi_pfn_gtv) && (cgi_pfn_ps)) {
  +        /* Required by mod_include filter. This is how mod_cgi registers
  +         *   with mod_include to provide processing of the exec directive.
  +         */
  +        cgi_pfn_reg_with_ssi("exec", handle_exec);
  +    }
  +}
  +
   static void register_hooks(apr_pool_t *p)
   {
       ap_hook_handler(cgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
  +    ap_hook_post_config(cgi_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
   }
   
   module AP_MODULE_DECLARE_DATA cgi_module =
  
  
  
  1.67      +309 -16   httpd-2.0/modules/generators/mod_cgid.c
  
  Index: mod_cgid.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/generators/mod_cgid.c,v
  retrieving revision 1.66
  retrieving revision 1.67
  diff -u -d -b -w -u -r1.66 -r1.67
  --- mod_cgid.c	2001/02/01 22:09:08	1.66
  +++ mod_cgid.c	2001/02/05 22:57:21	1.67
  @@ -92,6 +92,8 @@
   #include "ap_mpm.h"
   #include "unixd.h"
   #include "mod_suexec.h"
  +#include "apr_optional.h"
  +#include "../filters/mod_include.h"
   #include <sys/stat.h>
   #ifdef HAVE_SYS_SOCKET_H
   #include <sys/socket.h>
  @@ -108,6 +110,12 @@
   module AP_MODULE_DECLARE_DATA cgid_module; 
   
   static void cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server); 
  +static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
  +                       ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head);
  +
  +static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *cgid_pfn_reg_with_ssi;
  +static APR_OPTIONAL_FN_TYPE(ap_ssi_get_tag_and_value) *cgid_pfn_gtv;
  +static APR_OPTIONAL_FN_TYPE(ap_ssi_parse_string) *cgid_pfn_ps;
   
   static apr_pool_t *pcgi; 
   static int total_modules = 0;
  @@ -132,6 +140,9 @@
   
   #define SHELL_PATH "/bin/sh"
   
  +#define CGI_REQ 1
  +#define SSI_REQ 2
  +
   /* DEFAULT_CGID_LISTENBACKLOG controls the max depth on the unix socket's
    * pending connection queue.  If a bunch of cgi requests arrive at about
    * the same time, connections from httpd threads/processes will back up
  @@ -228,7 +239,7 @@
   #endif
   }
   
  -static void get_req(int fd, request_rec *r, char **filename, char **argv0, char ***env) 
  +static void get_req(int fd, request_rec *r, char **filename, char **argv0, char ***env, int *req_type) 
   { 
       int i, len, j; 
       unsigned char *data; 
  @@ -239,6 +250,7 @@
   
       r->server = apr_pcalloc(r->pool, sizeof(server_rec)); 
   
  +    read(fd, req_type, sizeof(int));
       read(fd, &j, sizeof(int)); 
       read(fd, &len, sizeof(int)); 
       data = apr_pcalloc(r->pool, len + 1); /* get a cleared byte for final '\0' */
  @@ -321,9 +333,9 @@
   
   
   
  -static void send_req(int fd, request_rec *r, char *argv0, char **env) 
  +static void send_req(int fd, request_rec *r, char *argv0, char **env, int req_type) 
   { 
  -    int len; 
  +    int len, r_type = req_type; 
       int i = 0; 
       char *data; 
       module *suexec_mod = ap_find_linked_module("mod_suexec.c");
  @@ -335,6 +347,13 @@
           continue; 
       } 
   
  +    /* Write the request type (SSI "exec cmd" or cgi). */
  +    if (write(fd, &r_type, sizeof(int)) < 0) {
  +        ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
  +                     "write to cgi daemon process");
  +    }
  +
  +    /* Write the number of entries in the environment. */
       if (write(fd, &i, sizeof(int)) < 0) {
           ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, 
                        "write to cgi daemon process"); 
  @@ -345,14 +364,17 @@
       } 
       data = apr_pstrcat(r->pool, data, r->args, NULL); 
       len = strlen(data); 
  +    /* Write the length of the concatenated env string. */
       if (write(fd, &len, sizeof(int)) < 0) { 
           ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, 
                        "write to cgi daemon process"); 
           }     
  +    /* Write the concatted env string. */     
       if (write(fd, data, len) < 0) {
           ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, 
                        "write to cgi daemon process"); 
           }     
  +    /* Write module_index id value. */     
       if (write(fd, &core_module.module_index, sizeof(int)) < 0) { 
           ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r, 
                        "write to cgi daemon process"); 
  @@ -409,7 +431,7 @@
   static int cgid_server(void *data) 
   { 
       struct sockaddr_un unix_addr;
  -    int sd, sd2, rc;
  +    int sd, sd2, rc, req_type;
       mode_t omask;
       apr_socklen_t len;
       server_rec *main_server = data;
  @@ -466,6 +488,10 @@
           char *filename; 
           char **env; 
           const char * const *argv; 
  +        apr_int32_t   in_pipe  = APR_CHILD_BLOCK;
  +        apr_int32_t   out_pipe = APR_CHILD_BLOCK;
  +        apr_int32_t   err_pipe = APR_CHILD_BLOCK;
  +        apr_cmdtype_e cmd_type = APR_PROGRAM;
           apr_pool_t *p; 
           request_rec *r; 
           apr_procattr_t *procattr = NULL;
  @@ -489,21 +515,29 @@
           r = apr_pcalloc(p, sizeof(request_rec)); 
           procnew = apr_pcalloc(p, sizeof(*procnew));
           r->pool = p; 
  -        get_req(sd2, r, &filename, &argv0, &env); 
  +        get_req(sd2, r, &filename, &argv0, &env, &req_type); 
           apr_put_os_file(&r->server->error_log, &errfileno, r->pool);
           apr_put_os_file(&inout, &sd2, r->pool);
   
  +        if (req_type == SSI_REQ) {
  +            in_pipe  = APR_NO_PIPE;
  +            out_pipe = APR_FULL_BLOCK;
  +            err_pipe = APR_NO_PIPE;
  +            cmd_type = APR_SHELLCMD;
  +        }
  +
           if (((rc = apr_createprocattr_init(&procattr, p)) != APR_SUCCESS) ||
  -            ((rc = apr_setprocattr_io(procattr,
  -                                     APR_CHILD_BLOCK,
  -                                     APR_CHILD_BLOCK,
  -                                     APR_CHILD_BLOCK)) != APR_SUCCESS) ||
  -            ((rc = apr_setprocattr_childin(procattr, inout, NULL)) != APR_SUCCESS) ||
  -            ((rc = apr_setprocattr_childout(procattr, inout, NULL)) != APR_SUCCESS) ||
  +            ((req_type == CGI_REQ) && 
  +             (((rc = apr_setprocattr_io(procattr,
  +                                        in_pipe,
  +                                        out_pipe,
  +                                        err_pipe)) != APR_SUCCESS) ||
               ((rc = apr_setprocattr_childerr(procattr, r->server->error_log, NULL)) != APR_SUCCESS) ||
  +              ((rc = apr_setprocattr_childin(procattr, inout, NULL)) != APR_SUCCESS))) ||
  +            ((rc = apr_setprocattr_childout(procattr, inout, NULL)) != APR_SUCCESS) ||
               ((rc = apr_setprocattr_dir(procattr,
                                     ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
  -            ((rc = apr_setprocattr_cmdtype(procattr, APR_PROGRAM)) != APR_SUCCESS)) {
  +            ((rc = apr_setprocattr_cmdtype(procattr, cmd_type)) != 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);
  @@ -565,8 +599,19 @@
   #if APR_HAS_OTHER_CHILD
           apr_register_other_child(procnew, cgid_maint, &procnew->pid, NULL, p);
   #endif
  +
  +        cgid_pfn_reg_with_ssi = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
  +        cgid_pfn_gtv          = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_get_tag_and_value);
  +        cgid_pfn_ps           = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_parse_string);
  +
  +        if ((cgid_pfn_reg_with_ssi) && (cgid_pfn_gtv) && (cgid_pfn_ps)) {
  +            /* Required by mod_include filter. This is how mod_cgid registers
  +             *   with mod_include to provide processing of the exec directive.
  +             */
  +            cgid_pfn_reg_with_ssi("exec", handle_exec);
       }
   } 
  +} 
   
   static void *create_cgid_config(apr_pool_t *p, server_rec *s) 
   { 
  @@ -847,7 +892,7 @@
                                      "unable to connect to cgi daemon");
       } 
   
  -    send_req(sd, r, argv0, env); 
  +    send_req(sd, r, argv0, env, CGI_REQ); 
   
       /* We are putting the tempsock variable into a file so that we can use
        * a pipe bucket to send the data to the client.
  @@ -963,6 +1008,254 @@
   
       return OK; /* NOT r->status, even if it has changed. */ 
   } 
  +
  +
  +
  +
  +/*============================================================================
  + *============================================================================
  + * This is the beginning of the cgi filter code moved from mod_include. This
  + *   is the code required to handle the "exec" SSI directive.
  + *============================================================================
  + *============================================================================*/
  +static int include_cgi(char *s, request_rec *r, ap_filter_t *next,
  +                       apr_bucket *head_ptr, apr_bucket **inserted_head)
  +{
  +    request_rec *rr = ap_sub_req_lookup_uri(s, r, next);
  +    int rr_status;
  +    apr_bucket  *tmp_buck, *tmp2_buck;
  +
  +    if (rr->status != HTTP_OK) {
  +        return -1;
  +    }
  +
  +    /* No hardwired path info or query allowed */
  +
  +    if ((rr->path_info && rr->path_info[0]) || rr->args) {
  +        return -1;
  +    }
  +    if (rr->finfo.protection == 0) {
  +        return -1;
  +    }
  +
  +    /* Script gets parameters of the *document*, for back compatibility */
  +
  +    rr->path_info = r->path_info;       /* hard to get right; see mod_cgi.c */
  +    rr->args = r->args;
  +
  +    /* Force sub_req to be treated as a CGI request, even if ordinary
  +     * typing rules would have called it something else.
  +     */
  +
  +    rr->content_type = CGI_MAGIC_TYPE;
  +
  +    /* Run it. */
  +
  +    rr_status = ap_run_sub_req(rr);
  +    if (ap_is_HTTP_REDIRECT(rr_status)) {
  +        apr_size_t len_loc, h_wrt;
  +        const char *location = apr_table_get(rr->headers_out, "Location");
  +
  +        location = ap_escape_html(rr->pool, location);
  +        len_loc = strlen(location);
  +
  +        tmp_buck = apr_bucket_create_immortal("<A HREF=\"", sizeof("<A HREF=\""));
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
  +        tmp2_buck = apr_bucket_create_heap(location, len_loc, 1, &h_wrt);
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  +        tmp2_buck = apr_bucket_create_immortal("\">", sizeof("\">"));
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  +        tmp2_buck = apr_bucket_create_heap(location, len_loc, 1, &h_wrt);
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  +        tmp2_buck = apr_bucket_create_immortal("</A>", sizeof("</A>"));
  +        APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
  +
  +        if (*inserted_head == NULL) {
  +            *inserted_head = tmp_buck;
  +        }
  +    }
  +
  +    ap_destroy_sub_req(rr);
  +
  +    return 0;
  +}
  +
  +
  +/* This is the special environment used for running the "exec cmd="
  + *   variety of SSI directives.
  + */
  +static void add_ssi_vars(request_rec *r, ap_filter_t *next)
  +{
  +    apr_table_t *e = r->subprocess_env;
  +
  +    if (r->path_info && r->path_info[0] != '\0') {
  +        request_rec *pa_req;
  +
  +        apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info));
  +
  +        pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, next);
  +        if (pa_req->filename) {
  +            apr_table_setn(e, "PATH_TRANSLATED",
  +                           apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL));
  +        }
  +    }
  +
  +    if (r->args) {
  +        char *arg_copy = apr_pstrdup(r->pool, r->args);
  +
  +        apr_table_setn(e, "QUERY_STRING", r->args);
  +        ap_unescape_url(arg_copy);
  +        apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy));
  +    }
  +}
  +
  +static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb, char *command,
  +                       request_rec *r, ap_filter_t *f)
  +{
  +    char **env; 
  +    const char *location; 
  +    int sd;
  +    int retval; 
  +    apr_bucket_brigade *bcgi;
  +    apr_bucket *b;
  +    struct sockaddr_un unix_addr;
  +    apr_file_t *tempsock = NULL;
  +    void *sconf = r->server->module_config; 
  +    cgid_server_conf *conf = (cgid_server_conf *) ap_get_module_config(sconf, &cgid_module); 
  +
  +    add_ssi_vars(r, f->next);
  +    env = ap_create_environment(r->pool, r->subprocess_env);
  +
  +    if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
  +            return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, 0, 
  +                                   "unable to create socket to cgi daemon");
  +    }
  +
  +    memset(&unix_addr, 0, sizeof(unix_addr));
  +    unix_addr.sun_family = AF_UNIX;
  +    strcpy(unix_addr.sun_path, conf->sockname);
  +
  +    if (connect(sd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0) {
  +            return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, 0, 
  +                                   "unable to connect to cgi daemon");
  +    } 
  +
  +    SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
  +
  +    send_req(sd, r, command, env, SSI_REQ); 
  +
  +    /* We are putting the tempsock variable into a file so that we can use
  +     * a pipe bucket to send the data to the client.
  +     */
  +    apr_put_os_file(&tempsock, &sd, r->pool);
  +
  +    if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) 
  +        return retval; 
  +    
  +    location = apr_table_get(r->headers_out, "Location"); 
  +
  +    if (location && location[0] == '/' && r->status == 200) { 
  +        char argsbuffer[HUGE_STRING_LEN]; 
  +
  +        /* Soak up all the script output */ 
  +        while (apr_fgets(argsbuffer, HUGE_STRING_LEN, tempsock) > 0) { 
  +            continue; 
  +        } 
  +        /* This redirect needs to be a GET no matter what the original 
  +         * method was. 
  +         */ 
  +        r->method = apr_pstrdup(r->pool, "GET"); 
  +        r->method_number = M_GET; 
  +
  +        /* We already read the message body (if any), so don't allow 
  +         * the redirected request to think it has one. We can ignore 
  +         * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR. 
  +         */ 
  +        apr_table_unset(r->headers_in, "Content-Length"); 
  +
  +        ap_internal_redirect_handler(location, r); 
  +        return OK; 
  +    } 
  +    else if (location && r->status == 200) { 
  +        /* XX Note that if a script wants to produce its own Redirect 
  +         * body, it now has to explicitly *say* "Status: 302" 
  +         */ 
  +        return HTTP_MOVED_TEMPORARILY; 
  +    } 
  +
  +    ap_send_http_header(r); 
  +    if (!r->header_only) { 
  +        bcgi = apr_brigade_create(r->pool);
  +        b    = apr_bucket_create_pipe(tempsock);
  +        APR_BRIGADE_INSERT_TAIL(bcgi, b);
  +        ap_pass_brigade(f->next, bcgi);
  +    } 
  +
  +    return 0;
  +}
  +
  +static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
  +                       ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
  +{
  +    char *tag     = NULL;
  +    char *tag_val = NULL;
  +    char *file = r->filename;
  +    apr_bucket  *tmp_buck;
  +    char parsed_string[MAX_STRING_LEN];
  +
  +    *inserted_head = NULL;
  +    if (ctx->flags & FLAG_PRINTING) {
  +        if (ctx->flags & FLAG_NO_EXEC) {
  +            ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +                      "exec used but not allowed in %s", r->filename);
  +            CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  +        }
  +        else {
  +            while (1) {
  +                cgid_pfn_gtv(ctx, &tag, &tag_val, 1);
  +                if (tag_val == NULL) {
  +                    if (tag == NULL) {
  +                        return (0);
  +                    }
  +                    else {
  +                        return 1;
  +                    }
  +                }
  +                if (!strcmp(tag, "cmd")) {
  +                    cgid_pfn_ps(r, tag_val, parsed_string, sizeof(parsed_string), 1);
  +                    if (include_cmd(ctx, bb, parsed_string, r, f) == -1) {
  +                        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +                                    "execution failure for parameter \"%s\" "
  +                                    "to tag exec in file %s", tag, r->filename);
  +                        CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  +                    }
  +                    /* just in case some stooge changed directories */
  +                }
  +                else if (!strcmp(tag, "cgi")) {
  +                    cgid_pfn_ps(r, tag_val, parsed_string, sizeof(parsed_string), 0);
  +                    SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
  +                    if (include_cgi(parsed_string, r, f->next, head_ptr, inserted_head) == -1) {
  +                        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +                                    "invalid CGI ref \"%s\" in %s", tag_val, file);
  +                        CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  +                    }
  +                }
  +                else {
  +                    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
  +                                "unknown parameter \"%s\" to tag exec in %s", tag, file);
  +                    CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
  +                }
  +            }
  +        }
  +    }
  +    return 0;
  +}
  +/*============================================================================
  + *============================================================================
  + * This is the end of the cgi filter code moved from mod_include.
  + *============================================================================
  + *============================================================================*/
  +
   
   static void register_hook(apr_pool_t *p)
   {
  
  
  

Mime
View raw message