You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by jo...@apache.org on 2020/09/08 14:08:22 UTC

svn commit: r1881559 - in /httpd/httpd/trunk: .travis.yml modules/generators/cgi_common.h modules/generators/mod_cgi.c modules/generators/mod_cgid.c

Author: jorton
Date: Tue Sep  8 14:08:22 2020
New Revision: 1881559

URL: http://svn.apache.org/viewvc?rev=1881559&view=rev
Log:
Further re-unification of code duplicated across mod_cgi/mod_cgid into
cgi_common.h.  Functional changes:

- brings the PR 61980 fix to mod_cgid as well, and 
- some mod_cgid-specific APLOGNOs are dropped in favour of the
  code used in the equivalent error path in mod_cgi

... otherwise no user-visible changes (intended).

* modules/generators/cgi_common.h (log_scripterror, log_script_err): Move
  here from mod_cgi.
  (cgi_handle_exec): Move here, renamed from mod_cgi's handle_exec.
  (cgi_optfns_retrieve): New function, split out from mod_cgi's cgi_post_config.
  
* modules/generators/mod_cgid.c: Adjust accordingly, update to pass
  logno separately.
  (register_hooks): Register cgi_optfns_retrieve.

* modules/generators/mod_cgi.c: Adjust accordingly.
  (register_hooks): Register cgi_optfns_retrieve.

Github: closes #141

Modified:
    httpd/httpd/trunk/.travis.yml
    httpd/httpd/trunk/modules/generators/cgi_common.h
    httpd/httpd/trunk/modules/generators/mod_cgi.c
    httpd/httpd/trunk/modules/generators/mod_cgid.c

Modified: httpd/httpd/trunk/.travis.yml
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/.travis.yml?rev=1881559&r1=1881558&r2=1881559&view=diff
==============================================================================
--- httpd/httpd/trunk/.travis.yml (original)
+++ httpd/httpd/trunk/.travis.yml Tue Sep  8 14:08:22 2020
@@ -97,8 +97,8 @@ jobs:
       env: CONFIG="--enable-mods-shared=reallyall"
            TEST_ARGS="-order=random"
     # -------------------------------------------------------------------------
-    - name: Linux Ubuntu, Prefork MPM, all-modules
-      env: CONFIG="--enable-mods-shared=reallyall --with-mpm=prefork"
+    - name: Linux Ubuntu, Prefork MPM, all-modules (except cgid)
+      env: CONFIG="--enable-mods-shared=reallyall --with-mpm=prefork --disable-cgid"
     # -------------------------------------------------------------------------
     - name: Linux Ubuntu, Worker MPM, all-modules
       env: CONFIG="--enable-mods-shared=reallyall --with-mpm=worker"

Modified: httpd/httpd/trunk/modules/generators/cgi_common.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/generators/cgi_common.h?rev=1881559&r1=1881558&r2=1881559&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/generators/cgi_common.h (original)
+++ httpd/httpd/trunk/modules/generators/cgi_common.h Tue Sep  8 14:08:22 2020
@@ -27,6 +27,18 @@
 #include "httpd.h"
 #include "util_filter.h"
 
+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;
+
+/* These functions provided by mod_cgi.c/mod_cgid.c still. */
+static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
+                      char *dbuf, const char *sbuf, apr_bucket_brigade *bb,
+                      apr_file_t *script_err);
+static apr_status_t include_cgi(include_ctx_t *ctx, ap_filter_t *f,
+                                apr_bucket_brigade *bb, char *s);
+static apr_status_t include_cmd(include_ctx_t *ctx, ap_filter_t *f,
+                                apr_bucket_brigade *bb, const char *command);
+
 /* Read and discard all output from the brigade.  Note that with the
  * CGI bucket, the brigade will become empty once the script's stdout
  * is closed (or on error/timeout), but the stderr output may not have
@@ -48,6 +60,166 @@ static void discard_script_output(apr_bu
     }
 }
 
+static int log_scripterror(request_rec *r, cgi_server_conf *conf, int ret,
+                           apr_status_t rv, const char *logno,
+                           const char *error)
+{
+    apr_file_t *f = NULL;
+    apr_finfo_t finfo;
+    char time_str[APR_CTIME_LEN];
+
+    /* Intentional no APLOGNO */
+    /* Callee provides APLOGNO in error text */
+    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                  "%sstderr from %s: %s", logno ? logno : "", r->filename, error);
+
+    /* XXX Very expensive mainline case! Open, then getfileinfo! */
+    if (!conf->logname ||
+        ((apr_stat(&finfo, conf->logname,
+                   APR_FINFO_SIZE, r->pool) == APR_SUCCESS) &&
+         (finfo.size > conf->logbytes)) ||
+        (apr_file_open(&f, conf->logname,
+                       APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT,
+                       r->pool) != APR_SUCCESS)) {
+        return ret;
+    }
+
+    /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
+    apr_ctime(time_str, apr_time_now());
+    apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
+                    r->args ? "?" : "", r->args ? r->args : "", r->protocol);
+    /* "%% 500 /usr/local/apache/cgi-bin */
+    apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
+
+    apr_file_printf(f, "%%error\n%s\n", error);
+
+    apr_file_close(f);
+    return ret;
+}
+
+/* Soak up stderr from a script and redirect it to the error log.
+ */
+static apr_status_t log_script_err(request_rec *r, apr_file_t *script_err)
+{
+    char argsbuffer[HUGE_STRING_LEN];
+    char *newline;
+    apr_status_t rv;
+    cgi_server_conf *conf = ap_get_module_config(r->server->module_config, &cgi_module);
+
+    while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN,
+                               script_err)) == APR_SUCCESS) {
+
+        newline = strchr(argsbuffer, '\n');
+        if (newline) {
+            char *prev = newline - 1;
+            if (prev >= argsbuffer && *prev == '\r') {
+                newline = prev;
+            }
+
+            *newline = '\0';
+        }
+        log_scripterror(r, conf, r->status, 0, APLOGNO(01215), argsbuffer);
+    }
+
+    return rv;
+}
+
+static apr_status_t cgi_handle_exec(include_ctx_t *ctx, ap_filter_t *f,
+                                    apr_bucket_brigade *bb)
+{
+    char *tag = NULL;
+    char *tag_val = NULL;
+    request_rec *r = f->r;
+    char *file = r->filename;
+    char parsed_string[MAX_STRING_LEN];
+
+    if (!ctx->argc) {
+        ap_log_rerror(APLOG_MARK,
+                      (ctx->flags & SSI_FLAG_PRINTING)
+                          ? APLOG_ERR : APLOG_WARNING,
+                      0, r, APLOGNO(03195)
+                      "missing argument for exec element in %s", r->filename);
+    }
+
+    if (!(ctx->flags & SSI_FLAG_PRINTING)) {
+        return APR_SUCCESS;
+    }
+
+    if (!ctx->argc) {
+        SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
+        return APR_SUCCESS;
+    }
+
+    if (ctx->flags & SSI_FLAG_NO_EXEC) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01228) "exec used but not allowed "
+                      "in %s", r->filename);
+        SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
+        return APR_SUCCESS;
+    }
+
+    while (1) {
+        cgi_pfn_gtv(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
+        if (!tag || !tag_val) {
+            break;
+        }
+
+        if (!strcmp(tag, "cmd")) {
+            apr_status_t rv;
+
+            cgi_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
+                       SSI_EXPAND_LEAVE_NAME);
+
+            rv = include_cmd(ctx, f, bb, parsed_string);
+            if (rv != APR_SUCCESS) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01229) "execution failure "
+                              "for parameter \"%s\" to tag exec in file %s",
+                              tag, r->filename);
+                SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
+                break;
+            }
+        }
+        else if (!strcmp(tag, "cgi")) {
+            apr_status_t rv;
+
+            cgi_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
+                       SSI_EXPAND_DROP_NAME);
+
+            rv = include_cgi(ctx, f, bb, parsed_string);
+            if (rv != APR_SUCCESS) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01230) "invalid CGI ref "
+                              "\"%s\" in %s", tag_val, file);
+                SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
+                break;
+            }
+        }
+        else {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01231) "unknown parameter "
+                          "\"%s\" to tag exec in %s", tag, file);
+            SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
+            break;
+        }
+    }
+
+    return APR_SUCCESS;
+}
+
+/* Hook to register exec= handling with mod_include. */
+static void cgi_optfns_retrieve(void)
+{
+    APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *cgi_pfn_reg_with_ssi;
+
+    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", cgi_handle_exec);
+    }
+}
+
 #ifdef WANT_CGI_BUCKET
 /* A CGI bucket type is needed to catch any output to stderr from the
  * script; see PR 22030. */

Modified: httpd/httpd/trunk/modules/generators/mod_cgi.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/generators/mod_cgi.c?rev=1881559&r1=1881558&r2=1881559&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/generators/mod_cgi.c (original)
+++ httpd/httpd/trunk/modules/generators/mod_cgi.c Tue Sep  8 14:08:22 2020
@@ -61,9 +61,6 @@
 
 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;
 static APR_OPTIONAL_FN_TYPE(ap_cgi_build_command) *cgi_build_command;
 
 /* Read and discard the data in the brigade produced by a CGI script */
@@ -96,6 +93,11 @@ typedef struct {
     apr_interval_time_t timeout;
 } cgi_dirconf;
 
+#if APR_FILES_AS_SOCKETS
+#define WANT_CGI_BUCKET
+#endif
+#include "cgi_common.h"
+
 static void *create_cgi_config(apr_pool_t *p, server_rec *s)
 {
     cgi_server_conf *c =
@@ -185,69 +187,6 @@ AP_INIT_TAKE1("CGIScriptTimeout", set_sc
     {NULL}
 };
 
-static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret,
-                           apr_status_t rv, char *logno, char *error)
-{
-    apr_file_t *f = NULL;
-    apr_finfo_t finfo;
-    char time_str[APR_CTIME_LEN];
-
-    /* Intentional no APLOGNO */
-    /* Callee provides APLOGNO in error text */
-    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-                  "%sstderr from %s: %s", logno ? logno : "", r->filename, error);
-
-    /* XXX Very expensive mainline case! Open, then getfileinfo! */
-    if (!conf->logname ||
-        ((apr_stat(&finfo, conf->logname,
-                   APR_FINFO_SIZE, r->pool) == APR_SUCCESS) &&
-         (finfo.size > conf->logbytes)) ||
-        (apr_file_open(&f, conf->logname,
-                       APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT,
-                       r->pool) != APR_SUCCESS)) {
-        return ret;
-    }
-
-    /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
-    apr_ctime(time_str, apr_time_now());
-    apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
-                    r->args ? "?" : "", r->args ? r->args : "", r->protocol);
-    /* "%% 500 /usr/local/apache/cgi-bin */
-    apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
-
-    apr_file_printf(f, "%%error\n%s\n", error);
-
-    apr_file_close(f);
-    return ret;
-}
-
-/* Soak up stderr from a script and redirect it to the error log.
- */
-static apr_status_t log_script_err(request_rec *r, apr_file_t *script_err)
-{
-    char argsbuffer[HUGE_STRING_LEN];
-    char *newline;
-    apr_status_t rv;
-    cgi_server_conf *conf = ap_get_module_config(r->server->module_config, &cgi_module);
-
-    while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN,
-                               script_err)) == APR_SUCCESS) {
-
-        newline = strchr(argsbuffer, '\n');
-        if (newline) {
-            char *prev = newline - 1;
-            if (prev >= argsbuffer && *prev == '\r') {
-                newline = prev;
-            }
-
-            *newline = '\0';
-        }
-        log_scripterror(r, conf, r->status, 0, APLOGNO(01215), argsbuffer);
-    }
-
-    return rv;
-}
-
 static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
                       char *dbuf, const char *sbuf, apr_bucket_brigade *bb,
                       apr_file_t *script_err)
@@ -568,11 +507,6 @@ static apr_status_t default_build_comman
     return APR_SUCCESS;
 }
 
-#if APR_FILES_AS_SOCKETS
-#define WANT_CGI_BUCKET
-#endif
-#include "cgi_common.h"
-
 static int cgi_handler(request_rec *r)
 {
     int nph;
@@ -814,107 +748,9 @@ static apr_status_t include_cmd(include_
     return APR_SUCCESS;
 }
 
-static apr_status_t handle_exec(include_ctx_t *ctx, ap_filter_t *f,
-                                apr_bucket_brigade *bb)
-{
-    char *tag = NULL;
-    char *tag_val = NULL;
-    request_rec *r = f->r;
-    char *file = r->filename;
-    char parsed_string[MAX_STRING_LEN];
-
-    if (!ctx->argc) {
-        ap_log_rerror(APLOG_MARK,
-                      (ctx->flags & SSI_FLAG_PRINTING)
-                          ? APLOG_ERR : APLOG_WARNING,
-                      0, r, APLOGNO(03195)
-                      "missing argument for exec element in %s", r->filename);
-    }
-
-    if (!(ctx->flags & SSI_FLAG_PRINTING)) {
-        return APR_SUCCESS;
-    }
-
-    if (!ctx->argc) {
-        SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-        return APR_SUCCESS;
-    }
-
-    if (ctx->flags & SSI_FLAG_NO_EXEC) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01228) "exec used but not allowed "
-                      "in %s", r->filename);
-        SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-        return APR_SUCCESS;
-    }
-
-    while (1) {
-        cgi_pfn_gtv(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
-        if (!tag || !tag_val) {
-            break;
-        }
-
-        if (!strcmp(tag, "cmd")) {
-            apr_status_t rv;
-
-            cgi_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
-                       SSI_EXPAND_LEAVE_NAME);
-
-            rv = include_cmd(ctx, f, bb, parsed_string);
-            if (rv != APR_SUCCESS) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01229) "execution failure "
-                              "for parameter \"%s\" to tag exec in file %s",
-                              tag, r->filename);
-                SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-                break;
-            }
-        }
-        else if (!strcmp(tag, "cgi")) {
-            apr_status_t rv;
-
-            cgi_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
-                       SSI_EXPAND_DROP_NAME);
-
-            rv = include_cgi(ctx, f, bb, parsed_string);
-            if (rv != APR_SUCCESS) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01230) "invalid CGI ref "
-                              "\"%s\" in %s", tag_val, file);
-                SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-                break;
-            }
-        }
-        else {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01231) "unknown parameter "
-                          "\"%s\" to tag exec in %s", tag, file);
-            SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-            break;
-        }
-    }
-
-    return APR_SUCCESS;
-}
-
-
-/*============================================================================
- *============================================================================
- * This is the end of the cgi filter code moved from mod_include.
- *============================================================================
- *============================================================================*/
-
-
 static int 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);
-    }
-
     /* This is the means by which unusual (non-unix) os's may find alternate
      * means to run a given command (e.g. shebang/registry parsing on Win32)
      */
@@ -930,6 +766,7 @@ static void register_hooks(apr_pool_t *p
     static const char * const aszPre[] = { "mod_include.c", NULL };
     ap_hook_handler(cgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_post_config(cgi_post_config, aszPre, NULL, APR_HOOK_REALLY_FIRST);
+    ap_hook_optional_fn_retrieve(cgi_optfns_retrieve, NULL, NULL, APR_HOOK_MIDDLE);
 }
 
 AP_DECLARE_MODULE(cgi) =

Modified: httpd/httpd/trunk/modules/generators/mod_cgid.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/generators/mod_cgid.c?rev=1881559&r1=1881558&r2=1881559&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/generators/mod_cgid.c (original)
+++ httpd/httpd/trunk/modules/generators/mod_cgid.c Tue Sep  8 14:08:22 2020
@@ -80,11 +80,6 @@ module AP_MODULE_DECLARE_DATA cgid_modul
 
 static int cgid_start(apr_pool_t *p, server_rec *main_server, apr_proc_t *procnew);
 static int 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, ap_filter_t *f, apr_bucket_brigade *bb);
-
-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 = NULL;
 static pid_t daemon_pid;
@@ -220,6 +215,15 @@ typedef struct {
 #endif
 } cgid_req_t;
 
+#define cgi_server_conf cgid_server_conf
+#define cgi_module cgid_module
+
+#ifdef HAVE_CGID_FDPASSING
+/* Pull in CGI bucket implementation. */
+#define WANT_CGI_BUCKET
+#endif
+#include "cgi_common.h"
+
 /* This routine is called to create the argument list to be passed
  * to the CGI script.  When suexec is enabled, the suexec path, user, and
  * group are the first three arguments to be passed; if not, all three
@@ -573,7 +577,7 @@ static apr_status_t get_req(int fd, requ
 }
 
 static apr_status_t send_req(int fd, apr_file_t *errpipe, request_rec *r,
-                             char *argv0, char **env, int req_type)
+                             const char *argv0, char **env, int req_type)
 {
     int i;
     cgid_req_t req = {0};
@@ -1072,16 +1076,6 @@ static int cgid_init(apr_pool_t *p, apr_
         if (ret != OK ) {
             return ret;
         }
-        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);
-        }
     }
     return ret;
 }
@@ -1192,68 +1186,6 @@ static const command_rec cgid_cmds[] =
     {NULL}
 };
 
-static int log_scripterror(request_rec *r, cgid_server_conf * conf, int ret,
-                           apr_status_t rv, char *error)
-{
-    apr_file_t *f = NULL;
-    struct stat finfo;
-    char time_str[APR_CTIME_LEN];
-    int log_flags = rv ? APLOG_ERR : APLOG_ERR;
-
-    /* Intentional no APLOGNO */
-    /* Callee provides APLOGNO in error text */
-    ap_log_rerror(APLOG_MARK, log_flags, rv, r,
-                "%s: %s", error, r->filename);
-
-    /* XXX Very expensive mainline case! Open, then getfileinfo! */
-    if (!conf->logname ||
-        ((stat(conf->logname, &finfo) == 0)
-         && (finfo.st_size > conf->logbytes)) ||
-         (apr_file_open(&f, conf->logname,
-                  APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS)) {
-        return ret;
-    }
-
-    /* "%% [Wed Jun 19 10:53:21 1996] GET /cgid-bin/printenv HTTP/1.0" */
-    apr_ctime(time_str, apr_time_now());
-    apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
-            r->args ? "?" : "", r->args ? r->args : "", r->protocol);
-    /* "%% 500 /usr/local/apache/cgid-bin */
-    apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
-
-    apr_file_printf(f, "%%error\n%s\n", error);
-
-    apr_file_close(f);
-    return ret;
-}
-
-/* Soak up stderr from a script and redirect it to the error log.
- * TODO: log_scripterror() and this could move to cgi_common.h. */
-static apr_status_t log_script_err(request_rec *r, apr_file_t *script_err)
-{
-    char argsbuffer[HUGE_STRING_LEN];
-    char *newline;
-    apr_status_t rv;
-    cgid_server_conf *conf = ap_get_module_config(r->server->module_config, &cgid_module);
-
-    while ((rv = apr_file_gets(argsbuffer, HUGE_STRING_LEN,
-                               script_err)) == APR_SUCCESS) {
-
-        newline = strchr(argsbuffer, '\n');
-        if (newline) {
-            char *prev = newline - 1;
-            if (prev >= argsbuffer && *prev == '\r') {
-                newline = prev;
-            }
-
-            *newline = '\0';
-        }
-        log_scripterror(r, conf, r->status, 0, argsbuffer);
-    }
-
-    return rv;
-}
-
 static int log_script(request_rec *r, cgid_server_conf * conf, int ret,
                       char *dbuf, const char *sbuf, apr_bucket_brigade *bb,
                       apr_file_t *script_err)
@@ -1359,13 +1291,6 @@ static int log_script(request_rec *r, cg
     return ret;
 }
 
-/* Pull in CGI bucket implementation. */
-#define cgi_server_conf cgid_server_conf
-#ifdef HAVE_CGID_FDPASSING
-#define WANT_CGI_BUCKET
-#endif
-#include "cgi_common.h"
-
 static int connect_to_daemon(int *sdptr, request_rec *r,
                              cgid_server_conf *conf)
 {
@@ -1381,7 +1306,7 @@ static int connect_to_daemon(int *sdptr,
         ++connect_tries;
         if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
             return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, errno,
-                                   APLOGNO(01255) "unable to create socket to cgi daemon");
+                                   APLOGNO(01255), "unable to create socket to cgi daemon");
         }
         if (connect(sd, (struct sockaddr *)server_addr, server_addr_len) < 0) {
             /* Save errno for later */
@@ -1402,7 +1327,7 @@ static int connect_to_daemon(int *sdptr,
             }
             else {
                 close(sd);
-                return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, errno, APLOGNO(01257)
+                return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, errno, APLOGNO(01257),
                                        "unable to connect to cgi daemon after multiple tries");
             }
         }
@@ -1418,13 +1343,15 @@ static int connect_to_daemon(int *sdptr,
         if (connect_errno == ENOENT &&
             apr_time_sec(apr_time_now() - ap_scoreboard_image->global->restart_time) > 
                 DEFAULT_CONNECT_STARTUP_DELAY) {
-            return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, connect_errno, 
-                                   apr_pstrcat(r->pool, APLOGNO(02833) "ScriptSock ", sockname, " does not exist", NULL));
+            return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, connect_errno,
+                                   APLOGNO(02833),
+                                   apr_pstrcat(r->pool,
+                                               "ScriptSock ", sockname, " does not exist", NULL));
         }
 
         /* gotta try again, but make sure the cgid daemon is still around */
         if (connect_errno != ENOENT && kill(daemon_pid, 0) != 0) {
-            return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, connect_errno, APLOGNO(01258)
+            return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, connect_errno, APLOGNO(01258),
                                    "cgid daemon is gone; is Apache terminating?");
         }
     }
@@ -1576,12 +1503,12 @@ static int cgid_handler(request_rec *r)
     argv0 = r->filename;
 
     if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r)) {
-        return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01262)
+        return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01262),
                 "Options ExecCGI is off in this directory");
     }
 
     if (nph && is_included) {
-        return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01263)
+        return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01263),
                 "attempt to include NPH CGI script");
     }
 
@@ -1590,12 +1517,12 @@ static int cgid_handler(request_rec *r)
 #error at mod_cgi.c for required code in this path.
 #else
     if (r->finfo.filetype == APR_NOFILE) {
-        return log_scripterror(r, conf, HTTP_NOT_FOUND, 0, APLOGNO(01264)
+        return log_scripterror(r, conf, HTTP_NOT_FOUND, 0, APLOGNO(01264),
                 "script not found or unable to stat");
     }
 #endif
     if (r->finfo.filetype == APR_DIR) {
-        return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01265)
+        return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01265),
                 "attempt to invoke directory as script");
     }
 
@@ -1603,7 +1530,7 @@ static int cgid_handler(request_rec *r)
         r->path_info && *r->path_info)
     {
         /* default to accept */
-        return log_scripterror(r, conf, HTTP_NOT_FOUND, 0, APLOGNO(01266)
+        return log_scripterror(r, conf, HTTP_NOT_FOUND, 0, APLOGNO(01266),
                                "AcceptPathInfo off disallows user's path");
     }
     /*
@@ -1617,7 +1544,7 @@ static int cgid_handler(request_rec *r)
 #ifdef HAVE_CGID_FDPASSING
     rv = apr_file_pipe_create(&script_err, &errpipe_out, r->pool);
     if (rv) {
-        return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, rv, APLOGNO(10176)
+        return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, rv, APLOGNO(10176),
                                "could not create pipe for stderr");
     }
 #else
@@ -1639,7 +1566,7 @@ static int cgid_handler(request_rec *r)
 
     rv = send_req(sd, errpipe_out, r, argv0, env, CGI_REQ);
     if (rv != APR_SUCCESS) {
-        return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, rv, APLOGNO(10245)
+        return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, rv, APLOGNO(10245),
                                "could not send request to cgi daemon");
     }
 
@@ -1657,7 +1584,7 @@ static int cgid_handler(request_rec *r)
                                   cleanup_script, apr_pool_cleanup_null);
     }
     else { 
-        return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, rv, APLOGNO(10246)
+        return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, rv, APLOGNO(10246),
                                "failed reading PID from cgi daemon");
     }
 
@@ -1710,15 +1637,7 @@ static int cgid_handler(request_rec *r)
     return cgi_handle_response(r, nph, bb, timeout, conf, dbuf, script_err);
 }
 
-
-
-
-/*============================================================================
- *============================================================================
- * This is the beginning of the cgi filter code moved from mod_include. This
- *   is the code required to handle the "exec" SSI directive.
- *============================================================================
- *============================================================================*/
+/* Handling include= for mod_include. */
 static apr_status_t include_cgi(include_ctx_t *ctx, ap_filter_t *f,
                                 apr_bucket_brigade *bb, char *s)
 {
@@ -1803,7 +1722,7 @@ static void add_ssi_vars(request_rec *r)
 }
 
 static int include_cmd(include_ctx_t *ctx, ap_filter_t *f,
-                       apr_bucket_brigade *bb, char *command)
+                       apr_bucket_brigade *bb, const char *command)
 {
     char **env;
     int sd;
@@ -1869,91 +1788,6 @@ static int include_cmd(include_ctx_t *ct
     return APR_SUCCESS;
 }
 
-static apr_status_t handle_exec(include_ctx_t *ctx, ap_filter_t *f,
-                                apr_bucket_brigade *bb)
-{
-    char *tag     = NULL;
-    char *tag_val = NULL;
-    request_rec *r = f->r;
-    char *file = r->filename;
-    char parsed_string[MAX_STRING_LEN];
-
-    if (!ctx->argc) {
-        ap_log_rerror(APLOG_MARK,
-                      (ctx->flags & SSI_FLAG_PRINTING)
-                          ? APLOG_ERR : APLOG_WARNING,
-                      0, r, APLOGNO(03196)
-                      "missing argument for exec element in %s", r->filename);
-    }
-
-    if (!(ctx->flags & SSI_FLAG_PRINTING)) {
-        return APR_SUCCESS;
-    }
-
-    if (!ctx->argc) {
-        SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-        return APR_SUCCESS;
-    }
-
-    if (ctx->flags & SSI_FLAG_NO_EXEC) {
-        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01271) "exec used but not allowed "
-                      "in %s", r->filename);
-        SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-        return APR_SUCCESS;
-    }
-
-    while (1) {
-        cgid_pfn_gtv(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
-        if (!tag || !tag_val) {
-            break;
-        }
-
-        if (!strcmp(tag, "cmd")) {
-            apr_status_t rv;
-
-            cgid_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
-                        SSI_EXPAND_LEAVE_NAME);
-
-            rv = include_cmd(ctx, f, bb, parsed_string);
-            if (rv != APR_SUCCESS) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01272)
-                              "execution failure for parameter \"%s\" "
-                              "to tag exec in file %s", tag, r->filename);
-                SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-                break;
-            }
-        }
-        else if (!strcmp(tag, "cgi")) {
-            apr_status_t rv;
-
-            cgid_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
-                        SSI_EXPAND_DROP_NAME);
-
-            rv = include_cgi(ctx, f, bb, parsed_string);
-            if (rv != APR_SUCCESS) {
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01273) "invalid CGI ref "
-                              "\"%s\" in %s", tag_val, file);
-                SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-                break;
-            }
-        }
-        else {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01274) "unknown parameter "
-                          "\"%s\" to tag exec in %s", tag, file);
-            SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
-            break;
-        }
-    }
-
-    return APR_SUCCESS;
-}
-/*============================================================================
- *============================================================================
- * This is the end of the cgi filter code moved from mod_include.
- *============================================================================
- *============================================================================*/
-
-
 static void register_hook(apr_pool_t *p)
 {
     static const char * const aszPre[] = { "mod_include.c", NULL };
@@ -1961,6 +1795,7 @@ static void register_hook(apr_pool_t *p)
     ap_hook_pre_config(cgid_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_post_config(cgid_init, aszPre, NULL, APR_HOOK_MIDDLE);
     ap_hook_handler(cgid_handler, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_optional_fn_retrieve(cgi_optfns_retrieve, NULL, NULL, APR_HOOK_MIDDLE);
 }
 
 AP_DECLARE_MODULE(cgid) = {