Geoffrey Young wrote:
> 
> Geoffrey Young wrote:
> 
>>hi all
>>
>>ok, I think the below patch handles everything that we had talked about over
>>the past week wrt +SetupEnv and %ENV.
> 
> 
> actually, there is a problem with PerlSetEnv, which is supposed to populate
> %ENV with only that variable as soon as possible.  I can't remember the
> interaction between PerlSetEnv and PerlSetupEnv in mp1, but it seems like
> PerlSetEnv should happen regardless of the SetupEnv setting - it's a
> specific call to populate %ENV with a specific variable, rather than "oh, if
> people care about %ENV give them this too."  at least that's my read on it.

ok, the attached patch addresses this.  PerlSetEnv and PerlPassEnv always
are passed to %ENV, regardless of +SetupEnv.

other than that, the patch behaves the same way I described it initally.

--Geoff
Index: lib/ModPerl/Code.pm
===================================================================
RCS file: /home/cvspublic/modperl-2.0/lib/ModPerl/Code.pm,v
retrieving revision 1.114
diff -u -r1.114 Code.pm
--- lib/ModPerl/Code.pm 28 Oct 2003 20:23:45 -0000      1.114
+++ lib/ModPerl/Code.pm 6 Feb 2004 18:04:25 -0000
@@ -114,7 +114,7 @@
             @hook_flags, 'UNSET'],
     Dir => [qw(NONE PARSE_HEADERS SETUP_ENV MERGE_HANDLERS GLOBAL_REQUEST UNSET)],
     Req => [qw(NONE SET_GLOBAL_REQUEST PARSE_HEADERS SETUP_ENV 
-               CLEANUP_REGISTERED)],
+               CLEANUP_REGISTERED PERL_SET_ENV_DIR PERL_SET_ENV_SRV)],
     Interp => [qw(NONE IN_USE PUTBACK CLONED BASE)],
     Handler => [qw(NONE PARSED METHOD OBJECT ANON AUTOLOAD DYNAMIC FAKE)],
 );
Index: src/modules/perl/mod_perl.c
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/mod_perl.c,v
retrieving revision 1.206
diff -u -r1.206 mod_perl.c
--- src/modules/perl/mod_perl.c 10 Jan 2004 05:01:04 -0000      1.206
+++ src/modules/perl/mod_perl.c 6 Feb 2004 18:04:26 -0000
@@ -837,8 +837,30 @@
 
 int modperl_response_handler(request_rec *r)
 {
+    MP_dDCFG;
+
+#ifdef USE_ITHREADS
+    pTHX;
+    modperl_interp_t *interp;
+#endif
+
     if (!strEQ(r->handler, "modperl")) {
         return DECLINED;
+    }
+
+    /* default is -SetupEnv, add if PerlOption +SetupEnv */
+    if (MpDirSETUP_ENV(dcfg)) {
+        MP_dRCFG;
+
+#ifdef USE_ITHREADS
+        interp = modperl_interp_select(r, r->connection, r->server);
+        aTHX = interp->perl;
+        if (MpInterpPUTBACK(interp)) {
+            rcfg->interp = interp;
+        }
+#endif
+
+        modperl_env_request_populate(aTHX_ r);
     }
 
     return modperl_response_handler_run(r, TRUE);
Index: src/modules/perl/modperl_callback.c
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/modperl_callback.c,v
retrieving revision 1.65
diff -u -r1.65 modperl_callback.c
--- src/modules/perl/modperl_callback.c 9 Jan 2004 04:59:18 -0000       1.65
+++ src/modules/perl/modperl_callback.c 6 Feb 2004 18:04:26 -0000
@@ -182,15 +182,21 @@
     modperl_config_req_cleanup_register(r, rcfg);
 
     switch (type) {
-      case MP_HANDLER_TYPE_PER_DIR:
       case MP_HANDLER_TYPE_PER_SRV:
         modperl_handler_make_args(aTHX_ &av_args,
                                   "Apache::RequestRec", r, NULL);
 
-        /* only happens once per-request */
-        if (MpDirSETUP_ENV(dcfg)) {
-            modperl_env_request_populate(aTHX_ r);
-        }
+        /* per-server PerlSetEnv and PerlPassEnv - only once per-request */
+        modperl_env_configure_request_srv(aTHX_ r);
+
+        break;
+      case MP_HANDLER_TYPE_PER_DIR:
+        modperl_handler_make_args(aTHX_ &av_args,
+                                  "Apache::RequestRec", r, NULL);
+
+        /* per-directory PerlSetEnv - only once per-request */
+        modperl_env_configure_request_dir(aTHX_ r);
+
         break;
       case MP_HANDLER_TYPE_PRE_CONNECTION:
       case MP_HANDLER_TYPE_CONNECTION:
Index: src/modules/perl/modperl_env.c
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/modperl_env.c,v
retrieving revision 1.29
diff -u -r1.29 modperl_env.c
--- src/modules/perl/modperl_env.c      22 Sep 2003 23:29:52 -0000      1.29
+++ src/modules/perl/modperl_env.c      6 Feb 2004 18:04:28 -0000
@@ -143,10 +143,13 @@
 
 void modperl_env_configure_server(pTHX_ apr_pool_t *p, server_rec *s)
 {
-    /* XXX: propagate scfg->SetEnv to environ */
     MP_dSCFG(s);
     int i = 0;
 
+    /* make per-server PerlSetEnv and PerlPassEnv entries visible
+     * to %ENV at config time
+     */
+
     for (i=0; MP_env_pass_defaults[i]; i++) {
         const char *key = MP_env_pass_defaults[i];
         char *val;
@@ -180,18 +183,89 @@
                                           r->subprocess_env, \
                                           tab)
 
-void modperl_env_configure_request(request_rec *r)
+void modperl_env_configure_request_dir(pTHX_ request_rec *r)
 {
+    MP_dRCFG;
     MP_dDCFG;
-    MP_dSCFG(r->server);
+
+    /* populate %ENV and r->subprocess_env with per-directory 
+     * PerlSetEnv entries.
+     *
+     * note that per-server PerlSetEnv entries, as well as
+     * PerlPassEnv entries (which are only per-server), are added
+     * to %ENV and r->subprocess_env via modperl_env_configure_request_srv
+     */
+
+    /* only once per-request */
+    if (MpReqPERL_SET_ENV_DIR(rcfg)) {
+        return;
+    }
 
     if (!apr_is_empty_table(dcfg->SetEnv)) {
-        overlay_subprocess_env(r, dcfg->SetEnv);
+        apr_table_t *setenv_copy;
+
+        /* add per-directory PerlSetEnv entries to %ENV
+         * collisions with per-server PerlSetEnv entries are 
+         * resolved via the nature of a Perl hash
+         */
+        MP_TRACE_e(MP_FUNC, "\n\t[%s/0x%lx/%s]"
+                   "[EMAIL PROTECTED] dcfg->SetEnv} = values dcfg->SetEnv;",
+                   modperl_pid_tid(r->pool), modperl_interp_address(aTHX),
+                   modperl_server_desc(r->server, r->pool));
+        modperl_env_table_populate(aTHX_ dcfg->SetEnv);
+
+        /* make sure the entries are in the subprocess_env table as well.
+         * we need to use apr_table_overlap (not apr_table_overlay) because
+         * r->subprocess_env might have per-server PerlSetEnv entries in it
+         * and using apr_table_overlay would generate duplicate entries.
+         * in order to use apr_table_overlap, though, we need to copy the
+         * the dcfg table so that pool requirements are satisfied */
+        
+        setenv_copy = apr_table_copy(r->pool, dcfg->SetEnv);
+        apr_table_overlap(r->subprocess_env, setenv_copy, APR_OVERLAP_TABLES_SET);
+    }
+
+    MpReqPERL_SET_ENV_DIR_On(rcfg);
+}
+
+void modperl_env_configure_request_srv(pTHX_ request_rec *r)
+{
+    MP_dRCFG;
+    MP_dSCFG(r->server);
+
+    /* populate %ENV and r->subprocess_env with per-server PerlSetEnv 
+     * and PerlPassEnv entries.  
+     *
+     * although both are setup in %ENV in modperl_request_configure_server
+     * %ENV will be reset via modperl_env_request_unpopulate.
+     */
+
+    /* only once per-request */
+    if (MpReqPERL_SET_ENV_SRV(rcfg)) {
+        return;
+    }
+
+    if (!apr_is_empty_table(scfg->SetEnv)) {
+        MP_TRACE_e(MP_FUNC, "\n\t[%s/0x%lx/%s]"
+                   "[EMAIL PROTECTED] scfg->SetEnv} = values scfg->SetEnv;",
+                   modperl_pid_tid(r->pool), modperl_interp_address(aTHX),
+                   modperl_server_desc(r->server, r->pool));
+        modperl_env_table_populate(aTHX_ scfg->SetEnv);
+
+        overlay_subprocess_env(r, scfg->SetEnv);
     }
 
     if (!apr_is_empty_table(scfg->PassEnv)) {
+        MP_TRACE_e(MP_FUNC, "\n\t[%s/0x%lx/%s]"
+                   "[EMAIL PROTECTED] scfg->PassEnv} = values scfg->PassEnv;",
+                   modperl_pid_tid(r->pool), modperl_interp_address(aTHX),
+                   modperl_server_desc(r->server, r->pool));
+        modperl_env_table_populate(aTHX_ scfg->PassEnv);
+
         overlay_subprocess_env(r, scfg->PassEnv);
     }
+
+    MpReqPERL_SET_ENV_SRV_On(rcfg);
 }
 
 void modperl_env_default_populate(pTHX)
@@ -218,26 +292,44 @@
 {
     MP_dRCFG;
 
-    if (MpReqSETUP_ENV(rcfg)) {
-        return;
-    }
-            
-    /* XXX: might want to always do this regardless of PerlOptions -SetupEnv */
-    modperl_env_configure_request(r);
-
-    ap_add_common_vars(r);
-    ap_add_cgi_vars(r);
+    /* this is called under the following conditions
+     *   - if PerlOptions +SetupEnv
+     *   - if $r->subprocess_env() is called in a void context with no args
+     *
+     * normally, %ENV is only populated once per request (if at all) -
+     * just prior to content generation if +SetupEnv.
+     *
+     * however, in the $r->subprocess_env() case it will be called 
+     * more than once - once for each void call, and once again just
+     * prior to content generation.  while costly, the multiple
+     * passes are required, otherwise void calls would prohibit later
+     * phases from populating %ENV with new subprocess_env table entries
+     */
 
     MP_TRACE_e(MP_FUNC, "\n\t[%s/0x%lx/%s%s]"
                "[EMAIL PROTECTED] r->subprocess_env} = values r->subprocess_env;",
                modperl_pid_tid(r->pool), modperl_interp_address(aTHX),
                modperl_server_desc(r->server, r->pool), r->uri);
-    modperl_env_table_populate(aTHX_ r->subprocess_env);
+
+    /* however, we can eliminate some of the cost by only doing CGI
+     * variables once per-request no matter what.
+     */
+    if (! MpReqSETUP_ENV(rcfg)) {
+
+        ap_add_common_vars(r);
+        ap_add_cgi_vars(r);
 
 #ifdef MP_COMPAT_1X
-    modperl_env_default_populate(aTHX); /* reset GATEWAY_INTERFACE */
+        modperl_env_default_populate(aTHX); /* reset GATEWAY_INTERFACE */
 #endif
+    }
+
+    modperl_env_table_populate(aTHX_ r->subprocess_env);
 
+    /* don't set up CGI variables again.
+     * this also triggers modperl_env_request_unpopulate, which
+     * resets %ENV between requests - see modperl_config_request_cleanup 
+     */
     MpReqSETUP_ENV_On(rcfg);
 }
 
Index: src/modules/perl/modperl_env.h
===================================================================
RCS file: /home/cvspublic/modperl-2.0/src/modules/perl/modperl_env.h,v
retrieving revision 1.15
diff -u -r1.15 modperl_env.h
--- src/modules/perl/modperl_env.h      22 Sep 2003 23:29:52 -0000      1.15
+++ src/modules/perl/modperl_env.h      6 Feb 2004 18:04:28 -0000
@@ -20,7 +20,9 @@
 
 void modperl_env_configure_server(pTHX_ apr_pool_t *p, server_rec *s);
 
-void modperl_env_configure_request(request_rec *r);
+void modperl_env_configure_request_srv(pTHX_ request_rec *r);
+
+void modperl_env_configure_request_dir(pTHX_ request_rec *r);
 
 void modperl_env_default_populate(pTHX);
 
Index: t/hooks/TestHooks/headerparser.pm
===================================================================
RCS file: /home/cvspublic/modperl-2.0/t/hooks/TestHooks/headerparser.pm,v
retrieving revision 1.2
diff -u -r1.2 headerparser.pm
--- t/hooks/TestHooks/headerparser.pm   11 Apr 2002 11:08:43 -0000      1.2
+++ t/hooks/TestHooks/headerparser.pm   6 Feb 2004 18:04:28 -0000
@@ -13,7 +13,7 @@
 sub handler {
     my $r = shift;
 
-    $r->notes->set(url => $ENV{REQUEST_URI});
+    $r->notes->set(headerparser => 'set');
 
     Apache::OK;
 }
@@ -23,7 +23,7 @@
 
     plan $r, tests => 1;
 
-    ok $r->notes->get('url') eq $r->uri;
+    ok $r->notes->get('headerparser') eq 'set';
 
     Apache::OK;
 }
Index: t/modperl/cookie.t
===================================================================
RCS file: /home/cvspublic/modperl-2.0/t/modperl/cookie.t,v
retrieving revision 1.2
diff -u -r1.2 cookie.t
--- t/modperl/cookie.t  22 Nov 2003 07:38:48 -0000      1.2
+++ t/modperl/cookie.t  6 Feb 2004 18:04:28 -0000
@@ -6,8 +6,7 @@
 #
 # in this test we should be able get the cookie via %ENV,
 # since 'SetHandler perl-script' sets up mod_cgi env var. Moreover
-# adding 'PerlOptions +SetupEnv' adds them at the very first stage used
-# by mod_perl handlers, 'access' in this test. the last sub-test makes
+# calling $r->subprocess_env adds them on demand.  the last sub-test makes
 # sure, that mod_cgi env vars don't persist and are properly re-set at
 # the end of each request
 #
Index: t/response/TestDirective/env.pm
===================================================================
RCS file: /home/cvspublic/modperl-2.0/t/response/TestDirective/env.pm,v
retrieving revision 1.2
diff -u -r1.2 env.pm
--- t/response/TestDirective/env.pm     11 Apr 2002 11:08:44 -0000      1.2
+++ t/response/TestDirective/env.pm     6 Feb 2004 18:04:28 -0000
@@ -14,21 +14,43 @@
 sub handler {
     my $r = shift;
 
-    plan $r, tests => 4;
+    plan $r, tests => 8;
 
-    ok t_cmp('env_dir1', env_get('srv1'),
-             'per-dir override per-srv');
+    # %ENV
+    ok t_cmp('env_dir1', 
+             env_get('srv1'),
+             '%ENV per-dir override per-srv');
+
+    ok t_cmp('env_srv2', 
+             env_get('srv2'),
+             '%ENV per-srv');
+
+    ok t_cmp('env_dir2', 
+             env_get('dir2'),
+             '%ENV per-dir');
 
-    ok t_cmp('env_srv2', env_get('srv2'),
-             'per-srv');
+    # setup by Apache::TestRun
+    ok t_cmp('test.host.name',
+             $ENV{APACHE_TEST_HOSTNAME},
+             '%ENV PerlPassEnv');
 
-    ok t_cmp('env_dir2', env_get('dir2'),
-             'per-dir');
+    # $r->subprocess_env
+    ok t_cmp('env_dir1', 
+             env_get('srv1', $r),
+             '$r->subprocess_env per-dir override per-srv');
+
+    ok t_cmp('env_srv2', 
+             env_get('srv2', $r),
+             '$r->subprocess_env per-srv');
+
+    ok t_cmp('env_dir2', 
+             env_get('dir2', $r),
+             '$r->subprocess_env per-dir');
 
-    #setup by Apache::TestRun
+    # setup by Apache::TestRun
     ok t_cmp('test.host.name',
-             $ENV{APACHE_TEST_HOSTNAME},
-             'PassEnv');
+             $r->subprocess_env->get('APACHE_TEST_HOSTNAME'),
+             '$r->subprocess_env PerlPassEnv');
 
     Apache::OK;
 }
@@ -36,23 +58,43 @@
 sub env_get {
     my($name, $r) = @_;
     my $key = 'TestDirective__env_' . $name;
-    return $r ? $r->subprocess_env->get($key) : $ENV{$key};
+
+    my $value = $ENV{$key};
+
+    if ($r) {
+        my @values = $r->subprocess_env->get($key);
+
+        if (@values > 1) {
+            $value = "too many values for $key!";
+        }
+        else {
+            $value = $values[0];
+        }
+    }
+
+    return $value;
 }
 
 1;
 __END__
-PerlOptions +SetupEnv
+# SetupEnv ought to have no effect on PerlSetEnv or PerlPassEnv
+PerlOptions -SetupEnv
 
 <Base>
+    # per-server entry overwritten by per-directory entry
     PerlSetEnv TestDirective__env_srv1 env_srv1
 
+    # per-server entry not overwritten
     PerlSetEnv TestDirective__env_srv2 env_srv2
 
+    # PerlPassEnv is only per-server
     PerlPassEnv APACHE_TEST_HOSTNAME
 </Base>
 
+# per-directory entry overwrites per-server
 PerlSetEnv TestDirective__env_srv1 env_dir1
 
+# PerlSetEnv resets the table for each directive
 PerlSetEnv TestDirective__env_dir2 ToBeLost
 PerlSetEnv TestDirective__env_dir2 env_dir2
 
Index: t/response/TestModperl/cookie.pm
===================================================================
RCS file: /home/cvspublic/modperl-2.0/t/response/TestModperl/cookie.pm,v
retrieving revision 1.1
diff -u -r1.1 cookie.pm
--- t/response/TestModperl/cookie.pm    22 Sep 2003 23:34:45 -0000      1.1
+++ t/response/TestModperl/cookie.pm    6 Feb 2004 18:04:28 -0000
@@ -13,6 +13,9 @@
 sub access {
     my $r = shift;
 
+    # setup CGI variables early
+    $r->subprocess_env() if $r->args eq 'env';
+
     my($key, $val) = cookie($r);
     my $cookie_is_expected =
         ($r->args eq 'header' or $r->args eq 'env') ? 1 : 0;
@@ -48,7 +51,4 @@
 PerlInitHandler     Apache::TestHandler::same_interp_fixup
 PerlAccessHandler   TestModperl::cookie::access
 PerlResponseHandler TestModperl::cookie
-# PerlOptions +SetupEnv is needed here, because we want the mod_cgi
-# env to be set at the access phase. without it, perl-script sets it
-# only for the response phase
-PerlOptions +SetupEnv
+PerlOptions -SetupEnv
Index: xs/Apache/RequestRec/Apache__RequestRec.h
===================================================================
RCS file: /home/cvspublic/modperl-2.0/xs/Apache/RequestRec/Apache__RequestRec.h,v
retrieving revision 1.9
diff -u -r1.9 Apache__RequestRec.h
--- xs/Apache/RequestRec/Apache__RequestRec.h   30 Jan 2004 18:20:10 -0000      1.9
+++ xs/Apache/RequestRec/Apache__RequestRec.h   6 Feb 2004 18:04:29 -0000
@@ -47,12 +47,9 @@
                                            char *key, SV *val)
 {
     /* if called in a void context with no arguments, just
-     * populate %ENV and stop.  resetting SetupEnv off makes
-     * calling in a void context more than once meaningful.
+     * populate %ENV and stop.
      */
     if (key == NULL && GIMME_V == G_VOID) {
-        MP_dRCFG;
-        MpReqSETUP_ENV_Off(rcfg); 
         modperl_env_request_populate(aTHX_ r);
         return &PL_sv_undef;
     }

--- /dev/null   2003-01-30 05:24:37.000000000 -0500
+++ t/response/TestModperl/setupenv.pm  2004-02-05 14:27:12.000000000 -0500
@@ -0,0 +1,325 @@
+package TestModperl::setupenv;
+
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::RequestRec ();
+use APR::Table ();
+
+use Apache::Test;
+use Apache::TestUtil;
+
+use Apache::Const -compile => qw(OK DECLINED);
+
+sub handler {
+
+    my $r = shift;
+
+    # how many different URIs will be hit?
+    my $requests = $r->args;
+
+    # $requests locations with 7 tests each
+    plan $r, tests => $requests * 7;
+
+    return Apache::OK;
+}
+
+sub env {
+
+    my $r = shift;
+
+    Apache::Test::init_test_pm($r);  # tie STDOUT
+
+    (my $value) = $r->uri =~ /TestModperl__setupenv_(\w+)/;
+
+    ok t_cmp(Apache::Test::vars('remote_addr'),
+             $ENV{REMOTE_ADDR},
+             'found REMOTE_ADDR in %ENV');
+
+    ok t_cmp('server',
+             $ENV{SRV_SUBPROCESS},
+             'found subprocess_env table entry SRV_SUBPROCESS in %ENV');
+
+    ok t_cmp($value,
+             $ENV{DIR_SUBPROCESS},
+             'found subprocess_env table entry DIR_SUBPROCESS in %ENV');
+
+    ok t_cmp($value,
+             $ENV{DIR_SETENV},
+             'found per-directory SetEnv entry in %ENV');
+
+    ok t_cmp('server',
+             $ENV{SRV_SETENV},
+             'found per-server SetEnv entry in %ENV');
+
+    # PerlSetEnv always set
+    ok t_cmp($value,
+             $ENV{DIR_PERLSETENV},
+             'found per-directory PerlSetEnv entry in %ENV');
+
+    ok t_cmp('server',
+             $ENV{SRV_PERLSETENV},
+             'found per-server PerlSetEnv entry in %ENV');
+
+    return Apache::OK;
+}
+
+sub noenv {
+
+    my $r = shift;
+
+    Apache::Test::init_test_pm($r);  # tie STDOUT
+
+    (my $value) = $r->uri =~ /TestModperl__setupenv_(\w+)/;
+
+    ok t_cmp(undef,
+             $ENV{REMOTE_ADDR},
+             'REMOTE_ADDR not found in %ENV');
+
+    ok t_cmp(undef,
+             $ENV{SRV_SUBPROCESS},
+             'subprocess_env table entry SRV_SUBPROCESS not found in %ENV');
+
+    ok t_cmp(undef,
+             $ENV{DIR_SUBPROCESS},
+             'subprocess_env table entry DIR_SUBPROCESS not found in %ENV');
+
+    ok t_cmp(undef,
+             $ENV{DIR_SETENV},
+             'per-directory SetEnv entry not found in %ENV');
+
+    ok t_cmp(undef,
+             $ENV{SRV_SETENV},
+             'per-server SetEnv entry not found in %ENV');
+
+    # PerlSetEnv always set
+    ok t_cmp($value,
+             $ENV{DIR_PERLSETENV},
+             'found per-directory PerlSetEnv entry in %ENV');
+
+    ok t_cmp('server',
+             $ENV{SRV_PERLSETENV},
+             'found per-server PerlSetEnv entry in %ENV');
+
+    return Apache::OK;
+}
+
+sub someenv {
+
+    my $r = shift;
+
+    Apache::Test::init_test_pm($r);  # tie STDOUT
+
+    (my $value) = $r->uri =~ /TestModperl__setupenv_(\w+)/;
+
+    ok t_cmp(Apache::Test::vars('remote_addr'),
+             $ENV{REMOTE_ADDR},
+             'found REMOTE_ADDR in %ENV');
+
+    # set before void call
+    ok t_cmp('server',
+             $ENV{SRV_SUBPROCESS},
+             'found subprocess_env table entry one in %ENV');
+
+    ok t_cmp(undef,
+             $ENV{DIR_SUBPROCESS},
+             'subprocess_env table entry DIR_SUBPROCESS not found in %ENV');
+
+    ok t_cmp(undef,
+             $ENV{DIR_SETENV},
+             'per-directory SetEnv entry not found in %ENV');
+
+    ok t_cmp(undef,
+             $ENV{SRV_SETENV},
+             'per-server SetEnv entry not found in %ENV');
+
+    # PerlSetEnv always set
+    ok t_cmp($value,
+             $ENV{DIR_PERLSETENV},
+             'found per-directory PerlSetEnv entry in %ENV');
+
+    ok t_cmp('server',
+             $ENV{SRV_PERLSETENV},
+             'found per-server PerlSetEnv entry in %ENV');
+
+    return Apache::OK;
+}
+
+sub subenv_void {
+
+    shift->subprocess_env;
+
+    return Apache::OK;
+}
+
+sub subenv_one {
+
+    shift->subprocess_env->set(SRV_SUBPROCESS => 'server');
+
+    return Apache::OK;
+}
+
+sub subenv_two {
+
+    my $r = shift;
+
+    (my $value) = $r->uri =~ /TestModperl__setupenv_(\w+)/;
+
+    $r->subprocess_env->set(DIR_SUBPROCESS => $value);
+
+    return Apache::OK;
+}
+
+1;
+__DATA__
+# create a separate virtual host so we can use
+# keepalives - a per-connection interpreter is
+# the only way to make sure that we can plan in
+# one request and test in subsequent tests
+<NoAutoConfig>
+<VirtualHost TestModperl::setupenv>
+
+    KeepAlive On
+
+    <IfDefine PERL_ITHREADS>
+        PerlInterpScope connection
+    </Ifdefine>
+
+    PerlModule TestModperl::setupenv
+
+    PerlPostReadRequestHandler TestModperl::setupenv::subenv_one
+
+    # SetEnv is affected by +SetupEnv
+    SetEnv SRV_SETENV server
+
+    # PerlSetEnv is not affected by +SetupEnv or -SetupEnv
+    # it is entirely separate and always set if configured
+    PerlSetEnv SRV_PERLSETENV server
+
+    # plan
+    <Location /TestModperl__setupenv>
+        SetHandler modperl
+        PerlResponseHandler TestModperl::setupenv
+    </Location>
+
+    # default modperl handler
+    # %ENV should not contain standard CGI variables
+    # or entries from the subprocess_env table
+    <Location /TestModperl__setupenv_mpdefault>
+        SetHandler modperl
+        PerlResponseHandler TestModperl::setupenv::noenv
+
+        PerlFixupHandler TestModperl::setupenv::subenv_two
+
+        SetEnv DIR_SETENV mpdefault
+        PerlSetEnv DIR_PERLSETENV mpdefault
+    </Location>
+
+    # modperl handler + SetupEnv
+    # %ENV should contain CGI variables as well as
+    # anything put into the subprocess_env table
+    <Location /TestModperl__setupenv_mpsetup>
+        SetHandler modperl
+        PerlResponseHandler TestModperl::setupenv::env
+
+        PerlOptions +SetupEnv
+
+        PerlFixupHandler TestModperl::setupenv::subenv_two
+
+        SetEnv DIR_SETENV mpsetup
+        PerlSetEnv DIR_PERLSETENV mpsetup
+    </Location>
+
+    # $r->subprocess_env in a void context with no args
+    # should do the same as +SetupEnv wrt CGI variables
+    # and entries already in the subprocess_env table
+    # but subprocess_env entries that appear later will
+    # not show up in %ENV
+    <Location /TestModperl__setupenv_mpvoid>
+        SetHandler modperl
+        PerlResponseHandler TestModperl::setupenv::someenv
+
+        PerlHeaderParserHandler TestModperl::setupenv::subenv_void
+        PerlFixupHandler TestModperl::setupenv::subenv_two
+
+        SetEnv DIR_SETENV mpvoid
+        PerlSetEnv DIR_PERLSETENV mpvoid
+    </Location>
+
+    # +SetupEnv should always populate %ENV fully prior
+    # to running the content handler (regardless of when
+    # $r->subprocess_env() was called) to ensure that
+    # %ENV is an accurate representation of the
+    # subprocess_env table
+    <Location /TestModperl__setupenv_mpsetupvoid>
+        SetHandler modperl
+        PerlResponseHandler TestModperl::setupenv::env
+
+        PerlOptions +SetupEnv
+    
+        PerlHeaderParserHandler TestModperl::setupenv::subenv_void
+        PerlFixupHandler TestModperl::setupenv::subenv_two
+
+        SetEnv DIR_SETENV mpsetupvoid
+        PerlSetEnv DIR_PERLSETENV mpsetupvoid
+    </Location>
+
+    # default perl-script handler is equivalent to +SetupEnv
+    # CGI variables and subprocess_env entries will be in %ENV
+    <Location /TestModperl__setupenv_psdefault>
+        SetHandler perl-script
+        PerlResponseHandler TestModperl::setupenv::env
+
+        PerlFixupHandler TestModperl::setupenv::subenv_two
+
+        SetEnv DIR_SETENV psdefault
+        PerlSetEnv DIR_PERLSETENV psdefault
+    </Location>
+
+    # -SetupEnv should not put CGI variables or subprocess_env
+    # entries in %ENV
+    <Location /TestModperl__setupenv_psnosetup>
+        SetHandler perl-script
+        PerlResponseHandler TestModperl::setupenv::noenv
+
+        PerlOptions -SetupEnv
+
+        PerlFixupHandler TestModperl::setupenv::subenv_two
+
+        SetEnv DIR_SETENV psnosetup
+        PerlSetEnv DIR_PERLSETENV psnosetup
+    </Location>
+
+    # +SetupEnv should always populate %ENV fully prior
+    # to running the content handler (regardless of when
+    # $r->subprocess_env() was called) to ensure that
+    # %ENV is an accurate representation of the
+    # subprocess_env table
+    <Location /TestModperl__setupenv_psvoid>
+        SetHandler perl-script
+        PerlResponseHandler TestModperl::setupenv::env
+
+        PerlHeaderParserHandler TestModperl::setupenv::subenv_void
+        PerlFixupHandler TestModperl::setupenv::subenv_two
+
+        SetEnv DIR_SETENV psvoid
+        PerlSetEnv DIR_PERLSETENV psvoid
+    </Location>
+
+    # equivalent to modperl handler with $r->subprocess_env() - 
+    # CGI variables are there, but not subprocess_env entries
+    # that are populated after the void call
+    <Location /TestModperl__setupenv_psnosetupvoid>
+        SetHandler perl-script
+        PerlResponseHandler TestModperl::setupenv::someenv
+
+        PerlOptions -SetupEnv
+
+        PerlHeaderParserHandler TestModperl::setupenv::subenv_void
+        PerlFixupHandler TestModperl::setupenv::subenv_two
+
+        SetEnv DIR_SETENV psnosetupvoid
+        PerlSetEnv DIR_PERLSETENV psnosetupvoid
+    </Location>
+</VirtualHost>
+</NoAutoConfig>

--- /dev/null   2003-01-30 05:24:37.000000000 -0500
+++ t/modperl/setupenv.t        2004-02-04 15:06:55.000000000 -0500
@@ -0,0 +1,48 @@
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::TestRequest qw(GET_BODY_ASSERT);
+use Apache::Test;
+use Apache::TestUtil;
+
+my $module   = "TestModperl::setupenv";
+Apache::TestRequest::module($module);
+
+my $config   = Apache::Test::config();
+my $hostport = Apache::TestRequest::hostport($config);
+my $path     = Apache::TestRequest::module2path($module);
+
+my $base = "http://$hostport/$path";;
+
+t_debug("connecting to $base");
+
+my @locations = ("${base}_mpdefault",
+                 "${base}_mpsetup",
+                 "${base}_mpdefault",  # make sure %ENV is cleared
+                 "${base}_mpvoid",
+                 "${base}_mpsetupvoid",
+                 "${base}_psdefault",
+                 "${base}_psnosetup",
+                 "${base}_psvoid",
+                 "${base}_psnosetupvoid");
+
+# plan the tests from a handler so we can run
+# tests from within handlers across multiple requests
+#
+# this requires keepalives and a per-connection interpreter
+# to make certain we can plan in one request and test in another
+
+Apache::TestRequest::user_agent(keep_alive => 1);
+print GET_BODY_ASSERT join '?', $base, scalar @locations;
+
+# this tests for when %ENV is populated with CGI variables
+# as well as the contents of the subprocess_env table
+#
+# see setupenv.pm for a full description of the tests
+
+foreach my $location (@locations) {
+
+    t_debug("trying $location");
+
+    print GET_BODY_ASSERT $location;
+}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to