mod_cgid.c revision ba050a6f942b9fa0e81ed73437588005c569655c
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive/* Licensed to the Apache Software Foundation (ASF) under one or more
530eba85dbd41b8a0fa5255d3648d1440199a661slive * contributor license agreements. See the NOTICE file distributed with
e942c741056732f50da2074b36fe59805d370650slive * this work for additional information regarding copyright ownership.
5f5d1b4cc970b7f06ff8ef6526128e9a27303d88nd * The ASF licenses this file to You under the Apache License, Version 2.0
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd * (the "License"); you may not use this file except in compliance with
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd * the License. You may obtain a copy of the License at
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding *
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * http://www.apache.org/licenses/LICENSE-2.0
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding *
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * Unless required by applicable law or agreed to in writing, software
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * distributed under the License is distributed on an "AS IS" BASIS,
db479b48bd4d75423ed4a45e15b75089d1a8ad72fielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd * See the License for the specific language governing permissions and
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd * limitations under the License.
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd */
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd/*
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd * http_script: keeps all script-related ramblings together.
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd *
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd * Compliant to cgi/1.1 spec
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd *
d5d794fc2f4cc9ca6d6da17cfa2cdcd8d244bacdnd * Adapted by rst from original NCSA code by Rob McCool
7db9f691a00ead175b03335457ca296a33ddf31bnd *
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * custom error responses, and DOCUMENT_ROOT because we found it useful.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * It also adds SERVER_ADMIN - useful for scripts to know who to mail when
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * they fail.
530eba85dbd41b8a0fa5255d3648d1440199a661slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "apr_lib.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "apr_strings.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "apr_general.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "apr_file_io.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "apr_portable.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "apr_buckets.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "apr_optional.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "apr_signal.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#define APR_WANT_STRFUNC
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "apr_want.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#if APR_HAVE_SYS_SOCKET_H
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include <sys/socket.h>
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#endif
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#if APR_HAVE_UNISTD_H
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include <unistd.h>
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#endif
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#if APR_HAVE_SYS_TYPES_H
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include <sys/types.h>
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#endif
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "util_filter.h"
90efa9f1730742d874edb5a7803adce11c9f08eanoodl#include "httpd.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "http_config.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "http_request.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "http_core.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "http_protocol.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "http_main.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "http_log.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "util_script.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "ap_mpm.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "mpm_common.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "mod_suexec.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "../filters/mod_include.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include "mod_core.h"
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna/* ### should be tossed in favor of APR */
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include <sys/stat.h>
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#include <sys/un.h> /* for sockaddr_un */
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#if APR_HAVE_STRUCT_RLIMIT
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#if defined (RLIMIT_CPU) || defined (RLIMIT_NPROC) || defined (RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#define AP_CGID_USE_RLIMIT
3139522a1418fa699dfd78dcf8dde54253f2c55cnoirin#endif
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna#endif
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquernamodule AP_MODULE_DECLARE_DATA cgid_module;
7e8f5c6496b3825b6b128e2aacc4b1b09d28553dpquerna
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic int cgid_start(apr_pool_t *p, server_rec *main_server, apr_proc_t *procnew);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic int cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkessstatic int handle_exec(include_ctx_t *ctx, ap_filter_t *f, apr_bucket_brigade *bb);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *cgid_pfn_reg_with_ssi;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic APR_OPTIONAL_FN_TYPE(ap_ssi_get_tag_and_value) *cgid_pfn_gtv;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic APR_OPTIONAL_FN_TYPE(ap_ssi_parse_string) *cgid_pfn_ps;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
18b4b0fd6056093002ddef488636bf5ebe415ef0erikabelestatic apr_pool_t *pcgi = NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic int total_modules = 0;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic pid_t daemon_pid;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic int daemon_should_exit = 0;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic server_rec *root_server = NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic apr_pool_t *root_pool = NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic const char *sockname;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic struct sockaddr_un *server_addr;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic apr_socklen_t server_addr_len;
fb77c505254b6e9c925e23e734463e87574f8f40kessstatic pid_t parent_pid;
fb77c505254b6e9c925e23e734463e87574f8f40kessstatic ap_unix_identity_t empty_ugid = { (uid_t)-1, (gid_t)-1, -1 };
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivetypedef struct {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_interval_time_t timeout;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive} cgid_dirconf;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive/* The APR other-child API doesn't tell us how the daemon exited
fb77c505254b6e9c925e23e734463e87574f8f40kess * (SIGSEGV vs. exit(1)). The other-child maintenance function
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * needs to decide whether to restart the daemon after a failure
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * based on whether or not it exited due to a fatal startup error
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * or something that happened at steady-state. This exit status
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * is unlikely to collide with exit signals.
fb77c505254b6e9c925e23e734463e87574f8f40kess */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#define DAEMON_STARTUP_ERROR 254
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive/* Read and discard the data in the brigade produced by a CGI script */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic void discard_script_output(apr_bucket_brigade *bb);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
fb77c505254b6e9c925e23e734463e87574f8f40kess/* This doer will only ever be called when we are sure that we have
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * a valid ugid.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic ap_unix_identity_t *cgid_suexec_id_doer(const request_rec *r)
fb77c505254b6e9c925e23e734463e87574f8f40kess{
fb77c505254b6e9c925e23e734463e87574f8f40kess return (ap_unix_identity_t *)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_get_module_config(r->request_config, &cgid_module);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
fb77c505254b6e9c925e23e734463e87574f8f40kess
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess/* KLUDGE --- for back-combatibility, we don't have to check ExecCGI
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * in ScriptAliased directories, which means we need to know if this
bc4b55ec8f31569d606d5680d50189a355bcd7a6rbowen * request came through ScriptAlias or not... so the Alias module
fb77c505254b6e9c925e23e734463e87574f8f40kess * leaves a note for us.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic int is_scriptaliased(request_rec *r)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
fb77c505254b6e9c925e23e734463e87574f8f40kess const char *t = apr_table_get(r->notes, "alias-forced-type");
fb77c505254b6e9c925e23e734463e87574f8f40kess return t && (!strcasecmp(t, "cgi-script"));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
fb77c505254b6e9c925e23e734463e87574f8f40kess
fb77c505254b6e9c925e23e734463e87574f8f40kess/* Configuration stuff */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd#define DEFAULT_LOGBYTES 10385760
130d299c4b2b15be45532a176604c71fdc7bea5bnd#define DEFAULT_BUFBYTES 1024
130d299c4b2b15be45532a176604c71fdc7bea5bnd#define DEFAULT_SOCKET "cgisock"
130d299c4b2b15be45532a176604c71fdc7bea5bnd
130d299c4b2b15be45532a176604c71fdc7bea5bnd#define CGI_REQ 1
130d299c4b2b15be45532a176604c71fdc7bea5bnd#define SSI_REQ 2
ef8e89e090461194ecadd31e8796a2c51e0531a2kess#define GETPID_REQ 3 /* get the pid of script created for prior request */
130d299c4b2b15be45532a176604c71fdc7bea5bnd
130d299c4b2b15be45532a176604c71fdc7bea5bnd#define ERRFN_USERDATA_KEY "CGIDCHILDERRFN"
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd/* DEFAULT_CGID_LISTENBACKLOG controls the max depth on the unix socket's
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * pending connection queue. If a bunch of cgi requests arrive at about
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * the same time, connections from httpd threads/processes will back up
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * in the queue while the cgid process slowly forks off a child to process
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * each connection on the unix socket. If the queue is too short, the
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * httpd process will get ECONNREFUSED when trying to connect.
003f0c9fda6664daf5092a0e42f65ede20098153slive */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd#ifndef DEFAULT_CGID_LISTENBACKLOG
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#define DEFAULT_CGID_LISTENBACKLOG 100
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive/* DEFAULT_CONNECT_ATTEMPTS controls how many times we'll try to connect
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * to the cgi daemon from the thread/process handling the cgi request.
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess * Generally we want to retry when we get ECONNREFUSED since it is
003f0c9fda6664daf5092a0e42f65ede20098153slive * probably because the listen queue is full. We need to try harder so
003f0c9fda6664daf5092a0e42f65ede20098153slive * the client doesn't see it as a 503 error.
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess *
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess * Set this to 0 to continually retry until the connect works or Apache
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * terminates.
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd#ifndef DEFAULT_CONNECT_ATTEMPTS
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd#define DEFAULT_CONNECT_ATTEMPTS 15
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivetypedef struct {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive const char *logname;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive long logbytes;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int bufbytes;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive} cgid_server_conf;
130d299c4b2b15be45532a176604c71fdc7bea5bnd
130d299c4b2b15be45532a176604c71fdc7bea5bnd#ifdef AP_CGID_USE_RLIMIT
130d299c4b2b15be45532a176604c71fdc7bea5bndtypedef struct {
130d299c4b2b15be45532a176604c71fdc7bea5bnd#ifdef RLIMIT_CPU
130d299c4b2b15be45532a176604c71fdc7bea5bnd int limit_cpu_set;
130d299c4b2b15be45532a176604c71fdc7bea5bnd struct rlimit limit_cpu;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int limit_mem_set;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive struct rlimit limit_mem;
1a3f62ca37273a15a06bb94a61d3c6fcf4bf38c9rbowen#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#ifdef RLIMIT_NPROC
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int limit_nproc_set;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive struct rlimit limit_nproc;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding
684f2a9a422185adda0692a1203c5ad6687fc5c5nd} cgid_rlimit_t;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd#endif
530eba85dbd41b8a0fa5255d3648d1440199a661slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivetypedef struct {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int req_type; /* request type (CGI_REQ, SSI_REQ, etc.) */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive unsigned long conn_id; /* connection id; daemon uses this as a hash value
003f0c9fda6664daf5092a0e42f65ede20098153slive * to find the script pid when it is time for that
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * process to be cleaned up
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding pid_t ppid; /* sanity check for config problems leading to
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding * wrong cgid socket use
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding */
684f2a9a422185adda0692a1203c5ad6687fc5c5nd int env_count;
a8ce9095d102e43fecb81093a132b90b9a227f78kess ap_unix_identity_t ugid;
684f2a9a422185adda0692a1203c5ad6687fc5c5nd apr_size_t filename_len;
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding apr_size_t argv0_len;
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding apr_size_t uri_len;
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding apr_size_t args_len;
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding int loglevel; /* to stuff in server_rec */
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding#ifdef AP_CGID_USE_RLIMIT
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding cgid_rlimit_t limits;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd} cgid_req_t;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd/* This routine is called to create the argument list to be passed
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding * to the CGI script. When suexec is enabled, the suexec path, user, and
684f2a9a422185adda0692a1203c5ad6687fc5c5nd * group are the first three arguments to be passed; if not, all three
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding * must be NULL. The query info is split into separate arguments, where
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding * "+" is the separator between keyword arguments.
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding *
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding * Do not process the args if they containing an '=' assignment.
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding */
843a03fe0b138a4c1f64cb90a014e9417ac30691fieldingstatic char **create_argv(apr_pool_t *p, char *path, char *user, char *group,
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding char *av0, const char *args)
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding{
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding int x, numwords;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char **av;
843a03fe0b138a4c1f64cb90a014e9417ac30691fielding char *w;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int idx = 0;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
58699879a562774640b95e9eedfd891f336e38c2nd if (!(*args) || ap_strchr_c(args, '=')) {
58699879a562774640b95e9eedfd891f336e38c2nd numwords = 0;
58699879a562774640b95e9eedfd891f336e38c2nd }
fb77c505254b6e9c925e23e734463e87574f8f40kess else {
fb77c505254b6e9c925e23e734463e87574f8f40kess /* count the number of keywords */
58699879a562774640b95e9eedfd891f336e38c2nd
58699879a562774640b95e9eedfd891f336e38c2nd for (x = 0, numwords = 1; args[x]; x++) {
58699879a562774640b95e9eedfd891f336e38c2nd if (args[x] == '+') {
58699879a562774640b95e9eedfd891f336e38c2nd ++numwords;
a2920e90d95fa04c15bdbbc03e7f8636eac92423slive }
58699879a562774640b95e9eedfd891f336e38c2nd }
58699879a562774640b95e9eedfd891f336e38c2nd }
58699879a562774640b95e9eedfd891f336e38c2nd
58699879a562774640b95e9eedfd891f336e38c2nd if (numwords > APACHE_ARG_MAX - 5) {
a2920e90d95fa04c15bdbbc03e7f8636eac92423slive numwords = APACHE_ARG_MAX - 5; /* Truncate args to prevent overrun */
a2920e90d95fa04c15bdbbc03e7f8636eac92423slive }
a2920e90d95fa04c15bdbbc03e7f8636eac92423slive av = (char **) apr_pcalloc(p, (numwords + 5) * sizeof(char *));
58699879a562774640b95e9eedfd891f336e38c2nd
fb77c505254b6e9c925e23e734463e87574f8f40kess if (path) {
fb77c505254b6e9c925e23e734463e87574f8f40kess av[idx++] = path;
fb77c505254b6e9c925e23e734463e87574f8f40kess }
fb77c505254b6e9c925e23e734463e87574f8f40kess if (user) {
fb77c505254b6e9c925e23e734463e87574f8f40kess av[idx++] = user;
58699879a562774640b95e9eedfd891f336e38c2nd }
58699879a562774640b95e9eedfd891f336e38c2nd if (group) {
58699879a562774640b95e9eedfd891f336e38c2nd av[idx++] = group;
58699879a562774640b95e9eedfd891f336e38c2nd }
58699879a562774640b95e9eedfd891f336e38c2nd
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess av[idx++] = apr_pstrdup(p, av0);
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess
58699879a562774640b95e9eedfd891f336e38c2nd for (x = 1; x <= numwords; x++) {
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess w = ap_getword_nulls(p, &args, '+');
58699879a562774640b95e9eedfd891f336e38c2nd ap_unescape_url(w);
58699879a562774640b95e9eedfd891f336e38c2nd av[idx++] = ap_escape_shell_cmd(p, w);
fb77c505254b6e9c925e23e734463e87574f8f40kess }
fb77c505254b6e9c925e23e734463e87574f8f40kess av[idx] = NULL;
fb77c505254b6e9c925e23e734463e87574f8f40kess return av;
58699879a562774640b95e9eedfd891f336e38c2nd}
58699879a562774640b95e9eedfd891f336e38c2nd
58699879a562774640b95e9eedfd891f336e38c2nd#if APR_HAS_OTHER_CHILD
58699879a562774640b95e9eedfd891f336e38c2ndstatic void cgid_maint(int reason, void *data, apr_wait_t status)
58699879a562774640b95e9eedfd891f336e38c2nd{
58699879a562774640b95e9eedfd891f336e38c2nd apr_proc_t *proc = data;
58699879a562774640b95e9eedfd891f336e38c2nd int mpm_state;
58699879a562774640b95e9eedfd891f336e38c2nd int stopping;
58699879a562774640b95e9eedfd891f336e38c2nd
58699879a562774640b95e9eedfd891f336e38c2nd switch (reason) {
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess case APR_OC_REASON_DEATH:
4a7affccb2f1f5b94cab395e1bf3825aed715ebcnd apr_proc_other_child_unregister(data);
9b5e2c5e769dc678a1aca06df75c32022b2f1492trawick /* If apache is not terminating or restarting,
c14037646789087319802aaada2e8534ccab0158slive * restart the cgid daemon
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess */
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess stopping = 1; /* if MPM doesn't support query,
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess * assume we shouldn't restart daemon
4a7affccb2f1f5b94cab395e1bf3825aed715ebcnd */
4a7affccb2f1f5b94cab395e1bf3825aed715ebcnd if (ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state) == APR_SUCCESS &&
9b5e2c5e769dc678a1aca06df75c32022b2f1492trawick mpm_state != AP_MPMQ_STOPPING) {
4a7affccb2f1f5b94cab395e1bf3825aed715ebcnd stopping = 0;
4a7affccb2f1f5b94cab395e1bf3825aed715ebcnd }
4a7affccb2f1f5b94cab395e1bf3825aed715ebcnd if (!stopping) {
4a7affccb2f1f5b94cab395e1bf3825aed715ebcnd if (status == DAEMON_STARTUP_ERROR) {
58699879a562774640b95e9eedfd891f336e38c2nd ap_log_error(APLOG_MARK, APLOG_CRIT, 0, ap_server_conf, APLOGNO(01238)
58699879a562774640b95e9eedfd891f336e38c2nd "cgid daemon failed to initialize");
58699879a562774640b95e9eedfd891f336e38c2nd }
58699879a562774640b95e9eedfd891f336e38c2nd else {
58699879a562774640b95e9eedfd891f336e38c2nd ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(01239)
4a7affccb2f1f5b94cab395e1bf3825aed715ebcnd "cgid daemon process died, restarting");
58699879a562774640b95e9eedfd891f336e38c2nd cgid_start(root_pool, root_server, proc);
58699879a562774640b95e9eedfd891f336e38c2nd }
77ead9e0262e4f08ec336d1a65b2edef7705c839nd }
77ead9e0262e4f08ec336d1a65b2edef7705c839nd break;
9583adab6bc4b3758e41963c905d9dad9f067131nd case APR_OC_REASON_RESTART:
77ead9e0262e4f08ec336d1a65b2edef7705c839nd /* don't do anything; server is stopping or restarting */
77ead9e0262e4f08ec336d1a65b2edef7705c839nd apr_proc_other_child_unregister(data);
77ead9e0262e4f08ec336d1a65b2edef7705c839nd break;
77ead9e0262e4f08ec336d1a65b2edef7705c839nd case APR_OC_REASON_LOST:
77ead9e0262e4f08ec336d1a65b2edef7705c839nd /* Restart the child cgid daemon process */
77ead9e0262e4f08ec336d1a65b2edef7705c839nd apr_proc_other_child_unregister(data);
77ead9e0262e4f08ec336d1a65b2edef7705c839nd cgid_start(root_pool, root_server, proc);
77ead9e0262e4f08ec336d1a65b2edef7705c839nd break;
77ead9e0262e4f08ec336d1a65b2edef7705c839nd case APR_OC_REASON_UNREGISTER:
77ead9e0262e4f08ec336d1a65b2edef7705c839nd /* we get here when pcgi is cleaned up; pcgi gets cleaned
77ead9e0262e4f08ec336d1a65b2edef7705c839nd * up when pconf gets cleaned up
77ead9e0262e4f08ec336d1a65b2edef7705c839nd */
77ead9e0262e4f08ec336d1a65b2edef7705c839nd kill(proc->pid, SIGHUP); /* send signal to daemon telling it to die */
77ead9e0262e4f08ec336d1a65b2edef7705c839nd
77ead9e0262e4f08ec336d1a65b2edef7705c839nd /* Remove the cgi socket, we must do it here in order to try and
77ead9e0262e4f08ec336d1a65b2edef7705c839nd * guarantee the same permissions as when the socket was created.
77ead9e0262e4f08ec336d1a65b2edef7705c839nd */
77ead9e0262e4f08ec336d1a65b2edef7705c839nd if (unlink(sockname) < 0 && errno != ENOENT) {
9b5e2c5e769dc678a1aca06df75c32022b2f1492trawick ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf, APLOGNO(01240)
77ead9e0262e4f08ec336d1a65b2edef7705c839nd "Couldn't unlink unix domain socket %s",
77ead9e0262e4f08ec336d1a65b2edef7705c839nd sockname);
77ead9e0262e4f08ec336d1a65b2edef7705c839nd }
77ead9e0262e4f08ec336d1a65b2edef7705c839nd break;
77ead9e0262e4f08ec336d1a65b2edef7705c839nd }
77ead9e0262e4f08ec336d1a65b2edef7705c839nd}
77ead9e0262e4f08ec336d1a65b2edef7705c839nd#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic apr_status_t close_unix_socket(void *thefd)
003f0c9fda6664daf5092a0e42f65ede20098153slive{
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess int fd = (int)((long)thefd);
fb77c505254b6e9c925e23e734463e87574f8f40kess
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return close(fd);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive/* deal with incomplete reads and signals
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * assume you really have to read buf_size bytes
fb77c505254b6e9c925e23e734463e87574f8f40kess */
fb77c505254b6e9c925e23e734463e87574f8f40kessstatic apr_status_t sock_read(int fd, void *vbuf, size_t buf_size)
fb77c505254b6e9c925e23e734463e87574f8f40kess{
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess char *buf = vbuf;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int rc;
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess size_t bytes_read = 0;
10673857794a4b3d9568ca2d983722a87ed352f1rbowen
fb77c505254b6e9c925e23e734463e87574f8f40kess do {
b12b918ae6baf9c5762ed61b7393d0e2198378c0nd do {
b12b918ae6baf9c5762ed61b7393d0e2198378c0nd rc = read(fd, buf + bytes_read, buf_size - bytes_read);
b12b918ae6baf9c5762ed61b7393d0e2198378c0nd } while (rc < 0 && errno == EINTR);
b12b918ae6baf9c5762ed61b7393d0e2198378c0nd switch(rc) {
10673857794a4b3d9568ca2d983722a87ed352f1rbowen case -1:
10673857794a4b3d9568ca2d983722a87ed352f1rbowen return errno;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive case 0: /* unexpected */
fb77c505254b6e9c925e23e734463e87574f8f40kess return ECONNRESET;
fb77c505254b6e9c925e23e734463e87574f8f40kess default:
fb77c505254b6e9c925e23e734463e87574f8f40kess bytes_read += rc;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive } while (bytes_read < buf_size);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_SUCCESS;
fb77c505254b6e9c925e23e734463e87574f8f40kess}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd/* deal with signals
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic apr_status_t sock_write(int fd, const void *buf, size_t buf_size)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int rc;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive do {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive rc = write(fd, buf, buf_size);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive } while (rc < 0 && errno == EINTR);
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz if (rc < 0) {
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz return errno;
9ed9eaf871c58d281af02e76125ceadb5060afa5nd }
9cd3b05d7b70f07a742bbaf548fa4fa2bdbe5ce6noodl
9cd3b05d7b70f07a742bbaf548fa4fa2bdbe5ce6noodl return APR_SUCCESS;
1f53e295ebd19aed1767d12da7abfab9936c148cjerenkrantz}
9cd3b05d7b70f07a742bbaf548fa4fa2bdbe5ce6noodl
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic apr_status_t sock_writev(int fd, request_rec *r, int count, ...)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive va_list ap;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int rc;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive struct iovec *vec;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int i;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive vec = (struct iovec *)apr_palloc(r->pool, count * sizeof(struct iovec));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive va_start(ap, count);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive for (i = 0; i < count; i++) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive vec[i].iov_base = va_arg(ap, caddr_t);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess vec[i].iov_len = va_arg(ap, apr_size_t);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem va_end(ap);
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem do {
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem rc = writev(fd, vec, count);
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem } while (rc < 0 && errno == EINTR);
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem if (rc < 0) {
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem return errno;
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem }
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem return APR_SUCCESS;
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem}
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluemstatic apr_status_t get_req(int fd, request_rec *r, char **argv0, char ***env,
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem cgid_req_t *req)
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem{
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem int i;
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem char **environ;
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem core_request_config *temp_core;
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem void **rconf;
5528d1a30ae8560e2d7a96d734ffe31500dc6113rpluem apr_status_t stat;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->server = apr_pcalloc(r->pool, sizeof(server_rec));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* read the request header */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive stat = sock_read(fd, req, sizeof(*req));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (stat != APR_SUCCESS) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return stat;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->server->log.level = req->loglevel;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (req->req_type == GETPID_REQ) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* no more data sent for this request */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_SUCCESS;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* handle module indexes and such */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive rconf = (void **)ap_create_request_config(r->pool);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive temp_core = (core_request_config *)apr_palloc(r->pool, sizeof(core_module));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive rconf[AP_CORE_MODULE_INDEX] = (void *)temp_core;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->request_config = (ap_conf_vector_t *)rconf;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_set_module_config(r->request_config, &cgid_module, (void *)&req->ugid);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Read the filename, argv0, uri, and args */
9ed9eaf871c58d281af02e76125ceadb5060afa5nd r->filename = apr_pcalloc(r->pool, req->filename_len + 1);
9ed9eaf871c58d281af02e76125ceadb5060afa5nd *argv0 = apr_pcalloc(r->pool, req->argv0_len + 1);
9ed9eaf871c58d281af02e76125ceadb5060afa5nd r->uri = apr_pcalloc(r->pool, req->uri_len + 1);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ((stat = sock_read(fd, r->filename, req->filename_len)) != APR_SUCCESS ||
103a93c625bcde1a6a7a5155b64dcda36f612180pquerna (stat = sock_read(fd, *argv0, req->argv0_len)) != APR_SUCCESS ||
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive (stat = sock_read(fd, r->uri, req->uri_len)) != APR_SUCCESS) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return stat;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
103a93c625bcde1a6a7a5155b64dcda36f612180pquerna r->args = apr_pcalloc(r->pool, req->args_len + 1); /* empty string if no args */
103a93c625bcde1a6a7a5155b64dcda36f612180pquerna if (req->args_len) {
f23fb63b05f89f47d7a3099491f2c68dcce432e9kess if ((stat = sock_read(fd, r->args, req->args_len)) != APR_SUCCESS) {
f23fb63b05f89f47d7a3099491f2c68dcce432e9kess return stat;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* read the environment variables */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd environ = apr_pcalloc(r->pool, (req->env_count + 2) *sizeof(char *));
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd for (i = 0; i < req->env_count; i++) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_size_t curlen;
b12b918ae6baf9c5762ed61b7393d0e2198378c0nd
b12b918ae6baf9c5762ed61b7393d0e2198378c0nd if ((stat = sock_read(fd, &curlen, sizeof(curlen))) != APR_SUCCESS) {
b12b918ae6baf9c5762ed61b7393d0e2198378c0nd return stat;
b12b918ae6baf9c5762ed61b7393d0e2198378c0nd }
da637bcae7b6e150470e701af29da5604a34a17erbowen environ[i] = apr_pcalloc(r->pool, curlen + 1);
da637bcae7b6e150470e701af29da5604a34a17erbowen if ((stat = sock_read(fd, environ[i], curlen)) != APR_SUCCESS) {
da637bcae7b6e150470e701af29da5604a34a17erbowen return stat;
da637bcae7b6e150470e701af29da5604a34a17erbowen }
da637bcae7b6e150470e701af29da5604a34a17erbowen }
da637bcae7b6e150470e701af29da5604a34a17erbowen *env = environ;
da637bcae7b6e150470e701af29da5604a34a17erbowen
da637bcae7b6e150470e701af29da5604a34a17erbowen#ifdef AP_CGID_USE_RLIMIT
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ((stat = sock_read(fd, &(req->limits), sizeof(cgid_rlimit_t))) != APR_SUCCESS)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return stat;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
54bcd0e21a5c79158afd3b78bf707a493a5fb33crbowen return APR_SUCCESS;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholesstatic apr_status_t send_req(int fd, request_rec *r, char *argv0, char **env,
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes int req_type)
fb77c505254b6e9c925e23e734463e87574f8f40kess{
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes int i;
fb77c505254b6e9c925e23e734463e87574f8f40kess cgid_req_t req = {0};
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes apr_status_t stat;
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes ap_unix_identity_t * ugid = ap_run_get_suexec_identity(r);
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes core_dir_config *core_conf = ap_get_core_module_config(r->per_dir_config);
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes if (ugid == NULL) {
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes req.ugid = empty_ugid;
fb77c505254b6e9c925e23e734463e87574f8f40kess } else {
fb77c505254b6e9c925e23e734463e87574f8f40kess memcpy(&req.ugid, ugid, sizeof(ap_unix_identity_t));
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess }
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes req.req_type = req_type;
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes req.ppid = parent_pid;
4c7bdb15764021d39e486adb7bc2166d3f683773bnicholes req.conn_id = r->connection->id;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive for (req.env_count = 0; env[req.env_count]; req.env_count++) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive continue;
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess }
fb77c505254b6e9c925e23e734463e87574f8f40kess req.filename_len = strlen(r->filename);
fb77c505254b6e9c925e23e734463e87574f8f40kess req.argv0_len = strlen(argv0);
fb77c505254b6e9c925e23e734463e87574f8f40kess req.uri_len = strlen(r->uri);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.args_len = r->args ? strlen(r->args) : 0;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.loglevel = r->server->log.level;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Write the request header */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (req.args_len) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive stat = sock_writev(fd, r, 5,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive &req, sizeof(req),
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->filename, req.filename_len,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive argv0, req.argv0_len,
5bb5fba250bf526bc51d13b25378d54acb93c1cbnoodl r->uri, req.uri_len,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->args, req.args_len);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive } else {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive stat = sock_writev(fd, r, 4,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive &req, sizeof(req),
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->filename, req.filename_len,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive argv0, req.argv0_len,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->uri, req.uri_len);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (stat != APR_SUCCESS) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return stat;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* write the environment variables */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive for (i = 0; i < req.env_count; i++) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_size_t curlen = strlen(env[i]);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ((stat = sock_writev(fd, r, 2, &curlen, sizeof(curlen),
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive env[i], curlen)) != APR_SUCCESS) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return stat;
fb77c505254b6e9c925e23e734463e87574f8f40kess }
fb77c505254b6e9c925e23e734463e87574f8f40kess }
fb77c505254b6e9c925e23e734463e87574f8f40kess#if defined(RLIMIT_CPU) && defined(AP_CGID_USE_RLIMIT)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (core_conf->limit_cpu) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.limits.limit_cpu = *(core_conf->limit_cpu);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.limits.limit_cpu_set = 1;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive else {
003f0c9fda6664daf5092a0e42f65ede20098153slive req.limits.limit_cpu_set = 0;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
e4881891552e185a7408318dfc7f62ebabe73cf6niq#endif
76f2a3125fb6aca59d43b02220dabac91175a281slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#if defined(AP_CGID_USE_RLIMIT) && (defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS))
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (core_conf->limit_mem) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.limits.limit_mem = *(core_conf->limit_mem);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.limits.limit_mem_set = 1;
ccf2a600dd72cc3c3c44f5d4126d9bb60fa83894takashi }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive else {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.limits.limit_mem_set = 0;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
c14037646789087319802aaada2e8534ccab0158slive
c14037646789087319802aaada2e8534ccab0158slive#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
dcfabbc1bf4b0aa835e0c5ba7da3e8d12d8299c7niq#if defined(RLIMIT_NPROC) && defined(AP_CGID_USE_RLIMIT)
dcfabbc1bf4b0aa835e0c5ba7da3e8d12d8299c7niq if (core_conf->limit_nproc) {
dcfabbc1bf4b0aa835e0c5ba7da3e8d12d8299c7niq req.limits.limit_nproc = *(core_conf->limit_nproc);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.limits.limit_nproc_set = 1;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd else {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd req.limits.limit_nproc_set = 0;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd#endif
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess
fb77c505254b6e9c925e23e734463e87574f8f40kess#ifdef AP_CGID_USE_RLIMIT
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ( (stat = sock_write(fd, &(req.limits), sizeof(cgid_rlimit_t))) != APR_SUCCESS)
dcfabbc1bf4b0aa835e0c5ba7da3e8d12d8299c7niq return stat;
dcfabbc1bf4b0aa835e0c5ba7da3e8d12d8299c7niq#endif
dcfabbc1bf4b0aa835e0c5ba7da3e8d12d8299c7niq
dcfabbc1bf4b0aa835e0c5ba7da3e8d12d8299c7niq return APR_SUCCESS;
e4881891552e185a7408318dfc7f62ebabe73cf6niq}
e4881891552e185a7408318dfc7f62ebabe73cf6niq
e4881891552e185a7408318dfc7f62ebabe73cf6niqstatic void daemon_signal_handler(int sig)
ccf2a600dd72cc3c3c44f5d4126d9bb60fa83894takashi{
e4881891552e185a7408318dfc7f62ebabe73cf6niq if (sig == SIGHUP) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ++daemon_should_exit;
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
313bb560bc5c323cfd40c9cad7335b4b8e060aedkessstatic void cgid_child_errfn(apr_pool_t *pool, apr_status_t err,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive const char *description)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive request_rec *r;
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl void *vr;
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl apr_pool_userdata_get(&vr, ERRFN_USERDATA_KEY, pool);
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl r = vr;
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl /* sure we got r, but don't call ap_log_rerror() because we don't
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl * have r->headers_in and possibly other storage referenced by
ccf2a600dd72cc3c3c44f5d4126d9bb60fa83894takashi * ap_log_rerror()
ccf2a600dd72cc3c3c44f5d4126d9bb60fa83894takashi */
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl ap_log_error(APLOG_MARK, APLOG_ERR, err, r->server, APLOGNO(01241) "%s", description);
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl}
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodlstatic int cgid_server(void *data)
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl{
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl int sd, sd2, rc;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive mode_t omask;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_pool_t *ptrans;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive server_rec *main_server = data;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_hash_t *script_hash = apr_hash_make(pcgi);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_status_t rv;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_pool_create(&ptrans, pcgi);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_signal(SIGCHLD, SIG_IGN);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_signal(SIGHUP, daemon_signal_handler);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Close our copy of the listening sockets */
003f0c9fda6664daf5092a0e42f65ede20098153slive ap_close_listeners();
003f0c9fda6664daf5092a0e42f65ede20098153slive
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* cgid should use its own suexec doer */
003f0c9fda6664daf5092a0e42f65ede20098153slive ap_hook_get_suexec_identity(cgid_suexec_id_doer, NULL, NULL,
fb77c505254b6e9c925e23e734463e87574f8f40kess APR_HOOK_REALLY_FIRST);
fb77c505254b6e9c925e23e734463e87574f8f40kess apr_hook_sort_all();
fb77c505254b6e9c925e23e734463e87574f8f40kess
fb77c505254b6e9c925e23e734463e87574f8f40kess if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
003f0c9fda6664daf5092a0e42f65ede20098153slive ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server, APLOGNO(01242)
003f0c9fda6664daf5092a0e42f65ede20098153slive "Couldn't create unix domain socket");
003f0c9fda6664daf5092a0e42f65ede20098153slive return errno;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
130d299c4b2b15be45532a176604c71fdc7bea5bnd
130d299c4b2b15be45532a176604c71fdc7bea5bnd omask = umask(0077); /* so that only Apache can use socket */
130d299c4b2b15be45532a176604c71fdc7bea5bnd rc = bind(sd, (struct sockaddr *)server_addr, server_addr_len);
130d299c4b2b15be45532a176604c71fdc7bea5bnd umask(omask); /* can't fail, so can't clobber errno */
130d299c4b2b15be45532a176604c71fdc7bea5bnd if (rc < 0) {
130d299c4b2b15be45532a176604c71fdc7bea5bnd ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server, APLOGNO(01243)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "Couldn't bind unix domain socket %s",
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd sockname);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return errno;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* Not all flavors of unix use the current umask for AF_UNIX perms */
fb77c505254b6e9c925e23e734463e87574f8f40kess rv = apr_file_perms_set(sockname, APR_FPROT_UREAD|APR_FPROT_UWRITE|APR_FPROT_UEXECUTE);
fb77c505254b6e9c925e23e734463e87574f8f40kess if (rv != APR_SUCCESS) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd ap_log_error(APLOG_MARK, APLOG_CRIT, rv, main_server, APLOGNO(01244)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "Couldn't set permissions on unix domain socket %s",
b06660a3ed3d885e15d99c0209a46c4657df33fbrbowen sockname);
030108b1816bcda3d925df65357feabdce83bc94slive return rv;
030108b1816bcda3d925df65357feabdce83bc94slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (listen(sd, DEFAULT_CGID_LISTENBACKLOG) < 0) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server, APLOGNO(01245)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "Couldn't listen on unix domain socket");
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return errno;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
fb77c505254b6e9c925e23e734463e87574f8f40kess
fb77c505254b6e9c925e23e734463e87574f8f40kess if (!geteuid()) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (chown(sockname, ap_unixd_config.user_id, -1) < 0) {
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server, APLOGNO(01246)
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess "Couldn't change owner of unix domain socket %s",
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess sockname);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return errno;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_pool_cleanup_register(pcgi, (void *)((long)sd),
130d299c4b2b15be45532a176604c71fdc7bea5bnd close_unix_socket, close_unix_socket);
130d299c4b2b15be45532a176604c71fdc7bea5bnd
130d299c4b2b15be45532a176604c71fdc7bea5bnd /* if running as root, switch to configured user/group */
130d299c4b2b15be45532a176604c71fdc7bea5bnd if ((rc = ap_run_drop_privileges(pcgi, ap_server_conf)) != 0) {
130d299c4b2b15be45532a176604c71fdc7bea5bnd return rc;
130d299c4b2b15be45532a176604c71fdc7bea5bnd }
130d299c4b2b15be45532a176604c71fdc7bea5bnd
130d299c4b2b15be45532a176604c71fdc7bea5bnd while (!daemon_should_exit) {
130d299c4b2b15be45532a176604c71fdc7bea5bnd int errfileno = STDERR_FILENO;
130d299c4b2b15be45532a176604c71fdc7bea5bnd char *argv0 = NULL;
130d299c4b2b15be45532a176604c71fdc7bea5bnd char **env = NULL;
130d299c4b2b15be45532a176604c71fdc7bea5bnd const char * const *argv;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_int32_t in_pipe;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_int32_t out_pipe;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_int32_t err_pipe;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_cmdtype_e cmd_type;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive request_rec *r;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_procattr_t *procattr = NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_proc_t *procnew = NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_t *inout;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_req_t cgid_req;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_status_t stat;
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess void *key;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_socklen_t len;
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess struct sockaddr_un unix_addr;
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess apr_pool_clear(ptrans);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive len = sizeof(unix_addr);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive sd2 = accept(sd, (struct sockaddr *)&unix_addr, &len);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (sd2 < 0) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#if defined(ENETDOWN)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (errno == ENETDOWN) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* The network has been shut down, no need to continue. Die gracefully */
130d299c4b2b15be45532a176604c71fdc7bea5bnd ++daemon_should_exit;
130d299c4b2b15be45532a176604c71fdc7bea5bnd }
130d299c4b2b15be45532a176604c71fdc7bea5bnd#endif
130d299c4b2b15be45532a176604c71fdc7bea5bnd if (errno != EINTR) {
130d299c4b2b15be45532a176604c71fdc7bea5bnd ap_log_error(APLOG_MARK, APLOG_ERR, errno,
130d299c4b2b15be45532a176604c71fdc7bea5bnd (server_rec *)data, APLOGNO(01247)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "Error accepting on cgid socket");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess continue;
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess }
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess r = apr_pcalloc(ptrans, sizeof(request_rec));
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess procnew = apr_pcalloc(ptrans, sizeof(*procnew));
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess r->pool = ptrans;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive stat = get_req(sd2, r, &argv0, &env, &cgid_req);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (stat != APR_SUCCESS) {
fb77c505254b6e9c925e23e734463e87574f8f40kess ap_log_error(APLOG_MARK, APLOG_ERR, stat,
fb77c505254b6e9c925e23e734463e87574f8f40kess main_server, APLOGNO(01248)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "Error reading request on cgid socket");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive close(sd2);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive continue;
130d299c4b2b15be45532a176604c71fdc7bea5bnd }
130d299c4b2b15be45532a176604c71fdc7bea5bnd
130d299c4b2b15be45532a176604c71fdc7bea5bnd if (cgid_req.ppid != parent_pid) {
130d299c4b2b15be45532a176604c71fdc7bea5bnd ap_log_error(APLOG_MARK, APLOG_CRIT, 0, main_server, APLOGNO(01249)
130d299c4b2b15be45532a176604c71fdc7bea5bnd "CGI request received from wrong server instance; "
130d299c4b2b15be45532a176604c71fdc7bea5bnd "see ScriptSock directive");
130d299c4b2b15be45532a176604c71fdc7bea5bnd close(sd2);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd continue;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (cgid_req.req_type == GETPID_REQ) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive pid_t pid;
fb77c505254b6e9c925e23e734463e87574f8f40kess apr_status_t rv;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
fb77c505254b6e9c925e23e734463e87574f8f40kess pid = (pid_t)((long)apr_hash_get(script_hash, &cgid_req.conn_id, sizeof(cgid_req.conn_id)));
fb77c505254b6e9c925e23e734463e87574f8f40kess rv = sock_write(sd2, &pid, sizeof(pid));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (rv != APR_SUCCESS) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_log_error(APLOG_MARK, APLOG_ERR, rv,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive main_server, APLOGNO(01250)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "Error writing pid %" APR_PID_T_FMT " to handler", pid);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess }
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess close(sd2);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive continue;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_os_file_put(&r->server->error_log, &errfileno, 0, r->pool);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_os_file_put(&inout, &sd2, 0, r->pool);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess if (cgid_req.req_type == SSI_REQ) {
15ba1801088da1aad6d20609cf3f7b0b1eefce8aslive in_pipe = APR_NO_PIPE;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive out_pipe = APR_FULL_BLOCK;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd err_pipe = APR_NO_PIPE;
7b5535ed88e0f561b3bfb3330137bd804846afd4slive cmd_type = APR_SHELLCMD;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive else {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive in_pipe = APR_CHILD_BLOCK;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive out_pipe = APR_CHILD_BLOCK;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive err_pipe = APR_CHILD_BLOCK;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cmd_type = APR_PROGRAM;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (((rc = apr_procattr_create(&procattr, ptrans)) != APR_SUCCESS) ||
030108b1816bcda3d925df65357feabdce83bc94slive ((cgid_req.req_type == CGI_REQ) &&
030108b1816bcda3d925df65357feabdce83bc94slive (((rc = apr_procattr_io_set(procattr,
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd in_pipe,
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd out_pipe,
6954edc623ca2c179eb5b33e97e4304d06fd649frbowen err_pipe)) != APR_SUCCESS) ||
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* XXX apr_procattr_child_*_set() is creating an unnecessary
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * pipe between this process and the child being created...
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * It is cleaned up with the temporary pool for this request.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ((rc = apr_procattr_child_err_set(procattr, r->server->error_log, NULL)) != APR_SUCCESS) ||
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ((rc = apr_procattr_child_in_set(procattr, inout, NULL)) != APR_SUCCESS))) ||
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ((rc = apr_procattr_child_out_set(procattr, inout, NULL)) != APR_SUCCESS) ||
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess ((rc = apr_procattr_dir_set(procattr,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess ((rc = apr_procattr_cmdtype_set(procattr, cmd_type)) != APR_SUCCESS) ||
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess#ifdef AP_CGID_USE_RLIMIT
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess#ifdef RLIMIT_CPU
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ( (cgid_req.limits.limit_cpu_set) && ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_CPU,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive &cgid_req.limits.limit_cpu)) != APR_SUCCESS)) ||
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
003f0c9fda6664daf5092a0e42f65ede20098153slive ( (cgid_req.limits.limit_mem_set) && ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_MEM,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive &cgid_req.limits.limit_mem)) != APR_SUCCESS)) ||
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#ifdef RLIMIT_NPROC
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ( (cgid_req.limits.limit_nproc_set) && ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive &cgid_req.limits.limit_nproc)) != APR_SUCCESS)) ||
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd
fb77c505254b6e9c925e23e734463e87574f8f40kess ((rc = apr_procattr_child_errfn_set(procattr, cgid_child_errfn)) != APR_SUCCESS)) {
fb77c505254b6e9c925e23e734463e87574f8f40kess /* Something bad happened, tell the world.
fb77c505254b6e9c925e23e734463e87574f8f40kess * ap_log_rerror() won't work because the header table used by
fb77c505254b6e9c925e23e734463e87574f8f40kess * ap_log_rerror() hasn't been replicated in the phony r
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server, APLOGNO(01251)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "couldn't set child process attributes: %s", r->filename);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd procnew->pid = 0; /* no process to clean up */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive close(sd2);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
c68acc9d712af079afa2bd1a5a4aeef9a3ea573ckess else {
c68acc9d712af079afa2bd1a5a4aeef9a3ea573ckess apr_pool_userdata_set(r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ptrans);
c68acc9d712af079afa2bd1a5a4aeef9a3ea573ckess
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive argv = (const char * const *)create_argv(r->pool, NULL, NULL, NULL, argv0, r->args);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* We want to close sd2 for the new CGI process too.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * If it is left open it'll make ap_pass_brigade() block
1b01d1ee11c612226cb3141eed4581dc179266c1rbowen * waiting for EOF if CGI forked something running long.
1b01d1ee11c612226cb3141eed4581dc179266c1rbowen * close(sd2) here should be okay, as CGI channel
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * is already dup()ed by apr_procattr_child_{in,out}_set()
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * above.
af18698b10b429b270551ca3a5d51a75e1c9db22brianp */
af18698b10b429b270551ca3a5d51a75e1c9db22brianp close(sd2);
003f0c9fda6664daf5092a0e42f65ede20098153slive
fb77c505254b6e9c925e23e734463e87574f8f40kess if (memcmp(&empty_ugid, &cgid_req.ugid, sizeof(empty_ugid))) {
fb77c505254b6e9c925e23e734463e87574f8f40kess /* We have a valid identity, and can be sure that
af18698b10b429b270551ca3a5d51a75e1c9db22brianp * cgid_suexec_id_doer will return a valid ugid
af18698b10b429b270551ca3a5d51a75e1c9db22brianp */
af18698b10b429b270551ca3a5d51a75e1c9db22brianp rc = ap_os_create_privileged_process(r, procnew, argv0, argv,
003f0c9fda6664daf5092a0e42f65ede20098153slive (const char * const *)env,
af18698b10b429b270551ca3a5d51a75e1c9db22brianp procattr, ptrans);
af18698b10b429b270551ca3a5d51a75e1c9db22brianp } else {
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd rc = apr_proc_create(procnew, argv0, argv,
003f0c9fda6664daf5092a0e42f65ede20098153slive (const char * const *)env,
003f0c9fda6664daf5092a0e42f65ede20098153slive procattr, ptrans);
fb77c505254b6e9c925e23e734463e87574f8f40kess }
fb77c505254b6e9c925e23e734463e87574f8f40kess
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (rc != APR_SUCCESS) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* Bad things happened. Everyone should have cleaned up.
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd * ap_log_rerror() won't work because the header table used by
af18698b10b429b270551ca3a5d51a75e1c9db22brianp * ap_log_rerror() hasn't been replicated in the phony r
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server, APLOGNO(01252)
af18698b10b429b270551ca3a5d51a75e1c9db22brianp "couldn't create child process: %d: %s", rc,
af18698b10b429b270551ca3a5d51a75e1c9db22brianp apr_filepath_name_get(r->filename));
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd
af18698b10b429b270551ca3a5d51a75e1c9db22brianp procnew->pid = 0; /* no process to clean up */
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd }
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd }
fb77c505254b6e9c925e23e734463e87574f8f40kess
af18698b10b429b270551ca3a5d51a75e1c9db22brianp /* If the script process was created, remember the pid for
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd * later cleanup. If the script process wasn't created, clear
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd * out any prior pid with the same key.
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd *
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd * We don't want to leak storage for the key, so only allocate
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd * a key if the key doesn't exist yet in the hash; there are
fb77c505254b6e9c925e23e734463e87574f8f40kess * only a limited number of possible keys (one for each
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd * possible thread in the server), so we can allocate a copy
41ef8b3051855b802104193ee0a587515af60a37wrowe * of the key the first time a thread has a cgid request.
41ef8b3051855b802104193ee0a587515af60a37wrowe * Note that apr_hash_set() only uses the storage passed in
41ef8b3051855b802104193ee0a587515af60a37wrowe * for the key if it is adding the key to the hash for the
41ef8b3051855b802104193ee0a587515af60a37wrowe * first time; new key storage isn't needed for replacing the
41ef8b3051855b802104193ee0a587515af60a37wrowe * existing value of a key.
41ef8b3051855b802104193ee0a587515af60a37wrowe */
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess if (apr_hash_get(script_hash, &cgid_req.conn_id, sizeof(cgid_req.conn_id))) {
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess key = &cgid_req.conn_id;
41ef8b3051855b802104193ee0a587515af60a37wrowe }
41ef8b3051855b802104193ee0a587515af60a37wrowe else {
41ef8b3051855b802104193ee0a587515af60a37wrowe key = apr_pmemdup(pcgi, &cgid_req.conn_id, sizeof(cgid_req.conn_id));
41ef8b3051855b802104193ee0a587515af60a37wrowe }
41ef8b3051855b802104193ee0a587515af60a37wrowe apr_hash_set(script_hash, key, sizeof(cgid_req.conn_id),
41ef8b3051855b802104193ee0a587515af60a37wrowe (void *)((long)procnew->pid));
41ef8b3051855b802104193ee0a587515af60a37wrowe }
41ef8b3051855b802104193ee0a587515af60a37wrowe return -1; /* should be <= 0 to distinguish from startup errors */
fb77c505254b6e9c925e23e734463e87574f8f40kess}
fb77c505254b6e9c925e23e734463e87574f8f40kess
41ef8b3051855b802104193ee0a587515af60a37wrowestatic int cgid_start(apr_pool_t *p, server_rec *main_server,
41ef8b3051855b802104193ee0a587515af60a37wrowe apr_proc_t *procnew)
41ef8b3051855b802104193ee0a587515af60a37wrowe{
41ef8b3051855b802104193ee0a587515af60a37wrowe
9fb925624300c864fe3969a264e52aa83f3c2dd0slive daemon_should_exit = 0; /* clear setting from previous generation */
41ef8b3051855b802104193ee0a587515af60a37wrowe if ((daemon_pid = fork()) < 0) {
41ef8b3051855b802104193ee0a587515af60a37wrowe ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server, APLOGNO(01253)
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd "mod_cgid: Couldn't spawn cgid daemon process");
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd return DECLINED;
41ef8b3051855b802104193ee0a587515af60a37wrowe }
41ef8b3051855b802104193ee0a587515af60a37wrowe else if (daemon_pid == 0) {
41ef8b3051855b802104193ee0a587515af60a37wrowe if (pcgi == NULL) {
41ef8b3051855b802104193ee0a587515af60a37wrowe apr_pool_create(&pcgi, p);
41ef8b3051855b802104193ee0a587515af60a37wrowe }
9b5e2c5e769dc678a1aca06df75c32022b2f1492trawick exit(cgid_server(main_server) > 0 ? DAEMON_STARTUP_ERROR : -1);
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess }
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess procnew->pid = daemon_pid;
41ef8b3051855b802104193ee0a587515af60a37wrowe procnew->err = procnew->in = procnew->out = NULL;
41ef8b3051855b802104193ee0a587515af60a37wrowe apr_pool_note_subprocess(p, procnew, APR_KILL_AFTER_TIMEOUT);
41ef8b3051855b802104193ee0a587515af60a37wrowe#if APR_HAS_OTHER_CHILD
41ef8b3051855b802104193ee0a587515af60a37wrowe apr_proc_other_child_register(procnew, cgid_maint, procnew, NULL, p);
41ef8b3051855b802104193ee0a587515af60a37wrowe#endif
9fb925624300c864fe3969a264e52aa83f3c2dd0slive return OK;
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess}
78f4d313fd5edf76dc5cfb8725e082a08cd29740jwoolley
78f4d313fd5edf76dc5cfb8725e082a08cd29740jwoolleystatic int cgid_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
9d00e5d0f270651f1f1cc1abea03bf53e5656fcecolm apr_pool_t *ptemp)
9d00e5d0f270651f1f1cc1abea03bf53e5656fcecolm{
9fb925624300c864fe3969a264e52aa83f3c2dd0slive sockname = ap_append_pid(pconf, DEFAULT_SOCKET, ".");
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess return OK;
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess}
9fb925624300c864fe3969a264e52aa83f3c2dd0slive
41ef8b3051855b802104193ee0a587515af60a37wrowestatic int cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
41ef8b3051855b802104193ee0a587515af60a37wrowe server_rec *main_server)
41ef8b3051855b802104193ee0a587515af60a37wrowe{
05201775eaa6b363b8a119c8aea5db246b967591yoshiki apr_proc_t *procnew = NULL;
41ef8b3051855b802104193ee0a587515af60a37wrowe const char *userdata_key = "cgid_init";
41ef8b3051855b802104193ee0a587515af60a37wrowe module **m;
fb77c505254b6e9c925e23e734463e87574f8f40kess int ret = OK;
41ef8b3051855b802104193ee0a587515af60a37wrowe void *data;
41ef8b3051855b802104193ee0a587515af60a37wrowe
fb77c505254b6e9c925e23e734463e87574f8f40kess root_server = main_server;
9fb925624300c864fe3969a264e52aa83f3c2dd0slive root_pool = p;
41ef8b3051855b802104193ee0a587515af60a37wrowe
41ef8b3051855b802104193ee0a587515af60a37wrowe apr_pool_userdata_get(&data, userdata_key, main_server->process->pool);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess if (!data) {
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess procnew = apr_pcalloc(main_server->process->pool, sizeof(*procnew));
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess procnew->pid = -1;
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess procnew->err = procnew->in = procnew->out = NULL;
41ef8b3051855b802104193ee0a587515af60a37wrowe apr_pool_userdata_set((const void *)procnew, userdata_key,
41ef8b3051855b802104193ee0a587515af60a37wrowe apr_pool_cleanup_null, main_server->process->pool);
af18698b10b429b270551ca3a5d51a75e1c9db22brianp return ret;
af18698b10b429b270551ca3a5d51a75e1c9db22brianp }
af18698b10b429b270551ca3a5d51a75e1c9db22brianp else {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive procnew = data;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
003f0c9fda6664daf5092a0e42f65ede20098153slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (ap_state_query(AP_SQ_MAIN_STATE) != AP_SQ_MS_CREATE_PRE_CONFIG) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd char *tmp_sockname;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive total_modules = 0;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive for (m = ap_preloaded_modules; *m != NULL; m++)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive total_modules++;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive parent_pid = getpid();
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive tmp_sockname = ap_runtime_dir_relative(p, sockname);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (strlen(tmp_sockname) > sizeof(server_addr->sun_path) - 1) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive tmp_sockname[sizeof(server_addr->sun_path)] = '\0';
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_log_error(APLOG_MARK, APLOG_ERR, 0, main_server, APLOGNO(01254)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "The length of the ScriptSock path exceeds maximum, "
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "truncating to %s", tmp_sockname);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive sockname = tmp_sockname;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive server_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) + strlen(sockname);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive server_addr = (struct sockaddr_un *)apr_palloc(p, server_addr_len + 1);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd server_addr->sun_family = AF_UNIX;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive strcpy(server_addr->sun_path, sockname);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd ret = cgid_start(p, main_server, procnew);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (ret != OK ) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return ret;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_pfn_reg_with_ssi = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_pfn_gtv = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_get_tag_and_value);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_pfn_ps = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_parse_string);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ((cgid_pfn_reg_with_ssi) && (cgid_pfn_gtv) && (cgid_pfn_ps)) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Required by mod_include filter. This is how mod_cgid registers
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive * with mod_include to provide processing of the exec directive.
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive */
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive cgid_pfn_reg_with_ssi("exec", handle_exec);
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return ret;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd}
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cndstatic void *create_cgid_config(apr_pool_t *p, server_rec *s)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd{
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd cgid_server_conf *c =
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive (cgid_server_conf *) apr_pcalloc(p, sizeof(cgid_server_conf));
f7fe99050600166042c04b8e595fb75499eed7f0geoff
f7fe99050600166042c04b8e595fb75499eed7f0geoff c->logname = NULL;
f7fe99050600166042c04b8e595fb75499eed7f0geoff c->logbytes = DEFAULT_LOGBYTES;
f7fe99050600166042c04b8e595fb75499eed7f0geoff c->bufbytes = DEFAULT_BUFBYTES;
f7fe99050600166042c04b8e595fb75499eed7f0geoff return c;
f7fe99050600166042c04b8e595fb75499eed7f0geoff}
f7fe99050600166042c04b8e595fb75499eed7f0geoff
f7fe99050600166042c04b8e595fb75499eed7f0geoffstatic void *merge_cgid_config(apr_pool_t *p, void *basev, void *overridesv)
f7fe99050600166042c04b8e595fb75499eed7f0geoff{
f7fe99050600166042c04b8e595fb75499eed7f0geoff cgid_server_conf *base = (cgid_server_conf *) basev, *overrides = (cgid_server_conf *) overridesv;
f7fe99050600166042c04b8e595fb75499eed7f0geoff
f7fe99050600166042c04b8e595fb75499eed7f0geoff return overrides->logname ? overrides : base;
f7fe99050600166042c04b8e595fb75499eed7f0geoff}
f7fe99050600166042c04b8e595fb75499eed7f0geoff
f7fe99050600166042c04b8e595fb75499eed7f0geoffstatic void *create_cgid_dirconf(apr_pool_t *p, char *dummy)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_dirconf *c = (cgid_dirconf *) apr_pcalloc(p, sizeof(cgid_dirconf));
fb77c505254b6e9c925e23e734463e87574f8f40kess return c;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive server_rec *s = cmd->server;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_server_conf *conf = ap_get_module_config(s->module_config,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive &cgid_module);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive conf->logname = ap_server_root_relative(cmd->pool, arg);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (!conf->logname) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return apr_pstrcat(cmd->pool, "Invalid ScriptLog path ",
fb77c505254b6e9c925e23e734463e87574f8f40kess arg, NULL);
fb77c505254b6e9c925e23e734463e87574f8f40kess }
fb77c505254b6e9c925e23e734463e87574f8f40kess return NULL;
4f854c24127e28f7ad72ce9a39d4448aaf910fc1slive}
4f854c24127e28f7ad72ce9a39d4448aaf910fc1slive
4f854c24127e28f7ad72ce9a39d4448aaf910fc1slivestatic const char *set_scriptlog_length(cmd_parms *cmd, void *dummy, const char *arg)
9b5e2c5e769dc678a1aca06df75c32022b2f1492trawick{
fb77c505254b6e9c925e23e734463e87574f8f40kess server_rec *s = cmd->server;
fb77c505254b6e9c925e23e734463e87574f8f40kess cgid_server_conf *conf = ap_get_module_config(s->module_config,
4f854c24127e28f7ad72ce9a39d4448aaf910fc1slive &cgid_module);
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive conf->logbytes = atol(arg);
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive return NULL;
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive}
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslivestatic const char *set_scriptlog_buffer(cmd_parms *cmd, void *dummy, const char *arg)
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive{
69fba5b8aa0b0dc408f649cfdaab064ce120b05bslive server_rec *s = cmd->server;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_server_conf *conf = ap_get_module_config(s->module_config,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive &cgid_module);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive conf->bufbytes = atoi(arg);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic const char *set_script_socket(cmd_parms *cmd, void *dummy, const char *arg)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess if (err != NULL) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return err;
3209c0009829fcf63b6213fb9c43d534f7906006slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Make sure the pid is appended to the sockname */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive sockname = ap_append_pid(cmd->pool, arg, ".");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive sockname = ap_runtime_dir_relative(cmd->pool, sockname);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (!sockname) {
c68acc9d712af079afa2bd1a5a4aeef9a3ea573ckess return apr_pstrcat(cmd->pool, "Invalid ScriptSock path",
c68acc9d712af079afa2bd1a5a4aeef9a3ea573ckess arg, NULL);
fb109b84906e3ee61680aa289953c2f9e859354erbowen }
fb109b84906e3ee61680aa289953c2f9e859354erbowen
fb109b84906e3ee61680aa289953c2f9e859354erbowen return NULL;
fb109b84906e3ee61680aa289953c2f9e859354erbowen}
313bb560bc5c323cfd40c9cad7335b4b8e060aedkessstatic const char *set_script_timeout(cmd_parms *cmd, void *dummy, const char *arg)
fb109b84906e3ee61680aa289953c2f9e859354erbowen{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_dirconf *dc = dummy;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (ap_timeout_parameter_parse(arg, &dc->timeout, "s") != APR_SUCCESS) {
fb109b84906e3ee61680aa289953c2f9e859354erbowen return "CGIDScriptTimeout has wrong format";
fb109b84906e3ee61680aa289953c2f9e859354erbowen }
fb109b84906e3ee61680aa289953c2f9e859354erbowen
fb109b84906e3ee61680aa289953c2f9e859354erbowen return NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic const command_rec cgid_cmds[] =
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "the name of a log for script debugging info"),
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive AP_INIT_TAKE1("ScriptLogLength", set_scriptlog_length, NULL, RSRC_CONF,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "the maximum length (in bytes) of the script debug log"),
fb109b84906e3ee61680aa289953c2f9e859354erbowen AP_INIT_TAKE1("ScriptLogBuffer", set_scriptlog_buffer, NULL, RSRC_CONF,
fb109b84906e3ee61680aa289953c2f9e859354erbowen "the maximum size (in bytes) to record of a POST request"),
fb109b84906e3ee61680aa289953c2f9e859354erbowen AP_INIT_TAKE1("ScriptSock", set_script_socket, NULL, RSRC_CONF,
fb109b84906e3ee61680aa289953c2f9e859354erbowen "the name of the socket to use for communication with "
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "the cgi daemon."),
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive AP_INIT_TAKE1("CGIDScriptTimeout", set_script_timeout, NULL, RSRC_CONF | ACCESS_CONF,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "The amount of time to wait between successful reads from "
9b5e2c5e769dc678a1aca06df75c32022b2f1492trawick "the CGI script, in seconds."),
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
2bac697634d965d9d9a921a99a68b2c454c8a95dbnicholes {NULL}
2bac697634d965d9d9a921a99a68b2c454c8a95dbnicholes};
2bac697634d965d9d9a921a99a68b2c454c8a95dbnicholes
2bac697634d965d9d9a921a99a68b2c454c8a95dbnicholesstatic int log_scripterror(request_rec *r, cgid_server_conf * conf, int ret,
2bac697634d965d9d9a921a99a68b2c454c8a95dbnicholes apr_status_t rv, char *error)
2bac697634d965d9d9a921a99a68b2c454c8a95dbnicholes{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_t *f = NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive struct stat finfo;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char time_str[APR_CTIME_LEN];
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int log_flags = rv ? APLOG_ERR : APLOG_ERR;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_log_rerror(APLOG_MARK, log_flags, rv, r,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "%s: %s", error, r->filename);
003f0c9fda6664daf5092a0e42f65ede20098153slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* XXX Very expensive mainline case! Open, then getfileinfo! */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (!conf->logname ||
18b4b0fd6056093002ddef488636bf5ebe415ef0erikabele ((stat(conf->logname, &finfo) == 0)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive && (finfo.st_size > conf->logbytes)) ||
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive (apr_file_open(&f, conf->logname,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS)) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return ret;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* "%% [Wed Jun 19 10:53:21 1996] GET /cgid-bin/printenv HTTP/1.0" */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_ctime(time_str, apr_time_now());
fb77c505254b6e9c925e23e734463e87574f8f40kess apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
fb77c505254b6e9c925e23e734463e87574f8f40kess r->args ? "?" : "", r->args ? r->args : "", r->protocol);
fb77c505254b6e9c925e23e734463e87574f8f40kess /* "%% 500 /usr/local/apache/cgid-bin */
fb77c505254b6e9c925e23e734463e87574f8f40kess apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
fb77c505254b6e9c925e23e734463e87574f8f40kess
fb77c505254b6e9c925e23e734463e87574f8f40kess apr_file_printf(f, "%%error\n%s\n", error);
fb77c505254b6e9c925e23e734463e87574f8f40kess
fb77c505254b6e9c925e23e734463e87574f8f40kess apr_file_close(f);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return ret;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd}
530eba85dbd41b8a0fa5255d3648d1440199a661slive
530eba85dbd41b8a0fa5255d3648d1440199a661slivestatic int log_script(request_rec *r, cgid_server_conf * conf, int ret,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char *dbuf, const char *sbuf, apr_bucket_brigade *bb,
530eba85dbd41b8a0fa5255d3648d1440199a661slive apr_file_t *script_err)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
530eba85dbd41b8a0fa5255d3648d1440199a661slive const apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive const apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
530eba85dbd41b8a0fa5255d3648d1440199a661slive char argsbuffer[HUGE_STRING_LEN];
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_file_t *f = NULL;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_bucket *e;
530eba85dbd41b8a0fa5255d3648d1440199a661slive const char *buf;
fb77c505254b6e9c925e23e734463e87574f8f40kess apr_size_t len;
fb77c505254b6e9c925e23e734463e87574f8f40kess apr_status_t rv;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int first;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd int i;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd struct stat finfo;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd char time_str[APR_CTIME_LEN];
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* XXX Very expensive mainline case! Open, then getfileinfo! */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (!conf->logname ||
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd ((stat(conf->logname, &finfo) == 0)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd && (finfo.st_size > conf->logbytes)) ||
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd (apr_file_open(&f, conf->logname,
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS)) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Soak up script output */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive discard_script_output(bb);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (script_err) {
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem script_err) == APR_SUCCESS)
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem continue;
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem }
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem return ret;
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem }
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem
0db981f8fdfb62c5149efa079f0369b73d472d04rpluem /* "%% [Wed Jun 19 10:53:21 1996] GET /cgid-bin/printenv HTTP/1.0" */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_ctime(time_str, apr_time_now());
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->args ? "?" : "", r->args ? r->args : "", r->protocol);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* "%% 500 /usr/local/apache/cgid-bin" */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
003f0c9fda6664daf5092a0e42f65ede20098153slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_puts("%request\n", f);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd for (i = 0; i < hdrs_arr->nelts; ++i) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (!hdrs[i].key)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive continue;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
003f0c9fda6664daf5092a0e42f65ede20098153slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ((r->method_number == M_POST || r->method_number == M_PUT)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive && *dbuf) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_printf(f, "\n%s\n", dbuf);
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess }
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess apr_file_puts("%response\n", f);
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess hdrs_arr = apr_table_elts(r->err_headers_out);
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess hdrs = (const apr_table_entry_t *) hdrs_arr->elts;
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive for (i = 0; i < hdrs_arr->nelts; ++i) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (!hdrs[i].key)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive continue;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (sbuf && *sbuf)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_printf(f, "%s\n", sbuf);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive first = 1;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd for (e = APR_BRIGADE_FIRST(bb);
fb77c505254b6e9c925e23e734463e87574f8f40kess e != APR_BRIGADE_SENTINEL(bb);
030108b1816bcda3d925df65357feabdce83bc94slive e = APR_BUCKET_NEXT(e))
030108b1816bcda3d925df65357feabdce83bc94slive {
030108b1816bcda3d925df65357feabdce83bc94slive if (APR_BUCKET_IS_EOS(e)) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive break;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (rv != APR_SUCCESS || (len == 0)) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd break;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess if (first) {
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess apr_file_puts("%stdout\n", f);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess first = 0;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_write_full(f, buf, len, NULL);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_puts("\n", f);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
fb77c505254b6e9c925e23e734463e87574f8f40kess if (script_err) {
fb77c505254b6e9c925e23e734463e87574f8f40kess if (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive script_err) == APR_SUCCESS) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_puts("%stderr\n", f);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess apr_file_puts(argsbuffer, f);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess while (apr_file_gets(argsbuffer, HUGE_STRING_LEN,
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess script_err) == APR_SUCCESS)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_puts(argsbuffer, f);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_puts("\n", f);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
003f0c9fda6664daf5092a0e42f65ede20098153slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (script_err) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_file_close(script_err);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_close(f);
003f0c9fda6664daf5092a0e42f65ede20098153slive return ret;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic int connect_to_daemon(int *sdptr, request_rec *r,
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess cgid_server_conf *conf)
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess{
030108b1816bcda3d925df65357feabdce83bc94slive int sd;
030108b1816bcda3d925df65357feabdce83bc94slive int connect_tries;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_interval_time_t sliding_timer;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd connect_tries = 0;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd sliding_timer = 100000; /* 100 milliseconds */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive while (1) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ++connect_tries;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, errno,
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess APLOGNO(01255) "unable to create socket to cgi daemon");
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess }
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess if (connect(sd, (struct sockaddr *)server_addr, server_addr_len) < 0) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (errno == ECONNREFUSED && connect_tries < DEFAULT_CONNECT_ATTEMPTS) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_log_rerror(APLOG_MARK, APLOG_DEBUG, errno, r, APLOGNO(01256)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "connect #%d to cgi daemon failed, sleeping before retry",
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive connect_tries);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive close(sd);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_sleep(sliding_timer);
c97e8972ab1f4dd167e3dc4db87daf91114009fbnd if (sliding_timer < apr_time_from_sec(2)) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive sliding_timer *= 2;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
003f0c9fda6664daf5092a0e42f65ede20098153slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive else {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive close(sd);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, errno, APLOGNO(01257)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "unable to connect to cgi daemon after multiple tries");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
fb77c505254b6e9c925e23e734463e87574f8f40kess }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive else {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_pool_cleanup_register(r->pool, (void *)((long)sd),
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive close_unix_socket, apr_pool_cleanup_null);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd break; /* we got connected! */
fb77c505254b6e9c925e23e734463e87574f8f40kess }
fb77c505254b6e9c925e23e734463e87574f8f40kess /* gotta try again, but make sure the cgid daemon is still around */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (kill(daemon_pid, 0) != 0) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return log_scripterror(r, conf, HTTP_SERVICE_UNAVAILABLE, errno, APLOGNO(01258)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "cgid daemon is gone; is Apache terminating?");
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive *sdptr = sd;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return OK;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
7654193c1faf603feec999850322ad79e6c551bcnd
7654193c1faf603feec999850322ad79e6c551bcndstatic void discard_script_output(apr_bucket_brigade *bb)
c97e8972ab1f4dd167e3dc4db87daf91114009fbnd{
7654193c1faf603feec999850322ad79e6c551bcnd apr_bucket *e;
7654193c1faf603feec999850322ad79e6c551bcnd const char *buf;
7654193c1faf603feec999850322ad79e6c551bcnd apr_size_t len;
7654193c1faf603feec999850322ad79e6c551bcnd apr_status_t rv;
7654193c1faf603feec999850322ad79e6c551bcnd
7654193c1faf603feec999850322ad79e6c551bcnd for (e = APR_BRIGADE_FIRST(bb);
7654193c1faf603feec999850322ad79e6c551bcnd e != APR_BRIGADE_SENTINEL(bb);
7654193c1faf603feec999850322ad79e6c551bcnd e = APR_BUCKET_NEXT(e))
7654193c1faf603feec999850322ad79e6c551bcnd {
7654193c1faf603feec999850322ad79e6c551bcnd if (APR_BUCKET_IS_EOS(e)) {
7654193c1faf603feec999850322ad79e6c551bcnd break;
7654193c1faf603feec999850322ad79e6c551bcnd }
c97e8972ab1f4dd167e3dc4db87daf91114009fbnd rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);
7654193c1faf603feec999850322ad79e6c551bcnd if (rv != APR_SUCCESS) {
7654193c1faf603feec999850322ad79e6c551bcnd break;
7654193c1faf603feec999850322ad79e6c551bcnd }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive/****************************************************************
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive *
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * Actual cgid handling...
fb77c505254b6e9c925e23e734463e87574f8f40kess */
fb77c505254b6e9c925e23e734463e87574f8f40kess
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestruct cleanup_script_info {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive request_rec *r;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive unsigned long conn_id;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_server_conf *conf;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive};
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
fb77c505254b6e9c925e23e734463e87574f8f40kessstatic apr_status_t dead_yet(pid_t pid, apr_interval_time_t max_wait)
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess{
9b5e2c5e769dc678a1aca06df75c32022b2f1492trawick apr_interval_time_t interval = 10000; /* 10 ms */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_interval_time_t total = 0;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive do {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#ifdef _AIX
9ed9eaf871c58d281af02e76125ceadb5060afa5nd /* On AIX, for processes like mod_cgid's script children where
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * SIGCHLD is ignored, kill(pid,0) returns success for up to
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * one second after the script child exits, based on when a
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * daemon runs to clean up unnecessary process table entries.
fb77c505254b6e9c925e23e734463e87574f8f40kess * getpgid() can report the proper info (-1/ESRCH) immediately.
fb77c505254b6e9c925e23e734463e87574f8f40kess */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (getpgid(pid) < 0) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#else
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (kill(pid, 0) < 0) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
fb77c505254b6e9c925e23e734463e87574f8f40kess return APR_SUCCESS;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_sleep(interval);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive total = total + interval;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (interval < 500000) {
fb77c505254b6e9c925e23e734463e87574f8f40kess interval *= 2;
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd }
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd } while (total < max_wait);
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd return APR_EGENERAL;
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic apr_status_t cleanup_nonchild_process(request_rec *r, pid_t pid)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
750d12c59545dbbac70390988de94f7e901b08f2niq kill(pid, SIGTERM); /* in case it isn't dead yet */
750d12c59545dbbac70390988de94f7e901b08f2niq if (dead_yet(pid, apr_time_from_sec(3)) == APR_SUCCESS) {
750d12c59545dbbac70390988de94f7e901b08f2niq return APR_SUCCESS;
750d12c59545dbbac70390988de94f7e901b08f2niq }
750d12c59545dbbac70390988de94f7e901b08f2niq ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01259)
750d12c59545dbbac70390988de94f7e901b08f2niq "CGI process %" APR_PID_T_FMT " didn't exit, sending SIGKILL",
750d12c59545dbbac70390988de94f7e901b08f2niq pid);
750d12c59545dbbac70390988de94f7e901b08f2niq kill(pid, SIGKILL);
750d12c59545dbbac70390988de94f7e901b08f2niq if (dead_yet(pid, apr_time_from_sec(3)) == APR_SUCCESS) {
750d12c59545dbbac70390988de94f7e901b08f2niq return APR_SUCCESS;
750d12c59545dbbac70390988de94f7e901b08f2niq }
750d12c59545dbbac70390988de94f7e901b08f2niq ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01260)
750d12c59545dbbac70390988de94f7e901b08f2niq "CGI process %" APR_PID_T_FMT " didn't exit, sending SIGKILL again",
750d12c59545dbbac70390988de94f7e901b08f2niq pid);
750d12c59545dbbac70390988de94f7e901b08f2niq kill(pid, SIGKILL);
750d12c59545dbbac70390988de94f7e901b08f2niq
750d12c59545dbbac70390988de94f7e901b08f2niq return APR_EGENERAL;
750d12c59545dbbac70390988de94f7e901b08f2niq}
750d12c59545dbbac70390988de94f7e901b08f2niq
750d12c59545dbbac70390988de94f7e901b08f2niqstatic apr_status_t cleanup_script(void *vptr)
750d12c59545dbbac70390988de94f7e901b08f2niq{
750d12c59545dbbac70390988de94f7e901b08f2niq struct cleanup_script_info *info = vptr;
750d12c59545dbbac70390988de94f7e901b08f2niq int sd;
750d12c59545dbbac70390988de94f7e901b08f2niq int rc;
750d12c59545dbbac70390988de94f7e901b08f2niq cgid_req_t req = {0};
750d12c59545dbbac70390988de94f7e901b08f2niq pid_t pid;
750d12c59545dbbac70390988de94f7e901b08f2niq apr_status_t stat;
750d12c59545dbbac70390988de94f7e901b08f2niq
750d12c59545dbbac70390988de94f7e901b08f2niq rc = connect_to_daemon(&sd, info->r, info->conf);
750d12c59545dbbac70390988de94f7e901b08f2niq if (rc != OK) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_EGENERAL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* we got a socket, and there is already a cleanup registered for it */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.req_type = GETPID_REQ;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.ppid = parent_pid;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive req.conn_id = info->r->connection->id;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
003f0c9fda6664daf5092a0e42f65ede20098153slive stat = sock_write(sd, &req, sizeof(req));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (stat != APR_SUCCESS) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return stat;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* wait for pid of script */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd stat = sock_read(sd, &pid, sizeof(pid));
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (stat != APR_SUCCESS) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return stat;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (pid == 0) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, info->r, APLOGNO(01261)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "daemon couldn't find CGI process for connection %lu",
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd info->conn_id);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_EGENERAL;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return cleanup_nonchild_process(info->r, pid);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic int cgid_handler(request_rec *r)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int retval, nph, dbpos;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd char *argv0, *dbuf;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_bucket_brigade *bb;
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl apr_bucket *b;
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl cgid_server_conf *conf;
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl int is_included;
6e483e0b8aa3fa574288a7452221392a03e2b9a3noodl int seen_eos, child_stopped_reading;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int sd;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char **env;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_t *tempsock;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive struct cleanup_script_info *info;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_status_t rv;
130d299c4b2b15be45532a176604c71fdc7bea5bnd cgid_dirconf *dc;
a00429a6b3b4dbb113b6dc67cfc0507f610276e9takashi
130d299c4b2b15be45532a176604c71fdc7bea5bnd if (strcmp(r->handler, CGI_MAGIC_TYPE) && strcmp(r->handler, "cgi-script")) {
130d299c4b2b15be45532a176604c71fdc7bea5bnd return DECLINED;
130d299c4b2b15be45532a176604c71fdc7bea5bnd }
130d299c4b2b15be45532a176604c71fdc7bea5bnd
a00429a6b3b4dbb113b6dc67cfc0507f610276e9takashi conf = ap_get_module_config(r->server->module_config, &cgid_module);
a00429a6b3b4dbb113b6dc67cfc0507f610276e9takashi dc = ap_get_module_config(r->per_dir_config, &cgid_module);
955d7fc3e7adb6463b7243e15c04e858718e799etakashi
955d7fc3e7adb6463b7243e15c04e858718e799etakashi
955d7fc3e7adb6463b7243e15c04e858718e799etakashi is_included = !strcmp(r->protocol, "INCLUDED");
955d7fc3e7adb6463b7243e15c04e858718e799etakashi
955d7fc3e7adb6463b7243e15c04e858718e799etakashi if ((argv0 = strrchr(r->filename, '/')) != NULL) {
955d7fc3e7adb6463b7243e15c04e858718e799etakashi argv0++;
955d7fc3e7adb6463b7243e15c04e858718e799etakashi }
955d7fc3e7adb6463b7243e15c04e858718e799etakashi else {
955d7fc3e7adb6463b7243e15c04e858718e799etakashi argv0 = r->filename;
955d7fc3e7adb6463b7243e15c04e858718e799etakashi }
955d7fc3e7adb6463b7243e15c04e858718e799etakashi
955d7fc3e7adb6463b7243e15c04e858718e799etakashi nph = !(strncmp(argv0, "nph-", 4));
955d7fc3e7adb6463b7243e15c04e858718e799etakashi
955d7fc3e7adb6463b7243e15c04e858718e799etakashi argv0 = r->filename;
955d7fc3e7adb6463b7243e15c04e858718e799etakashi
130d299c4b2b15be45532a176604c71fdc7bea5bnd if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r)) {
130d299c4b2b15be45532a176604c71fdc7bea5bnd return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01262)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "Options ExecCGI is off in this directory");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (nph && is_included) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01263)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "attempt to include NPH CGI script");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
a04a96aae08a62f2d9d5833b3313a9751fa3f680yoshiki
55d36f9b61520c2374ab463e77e8a62daa416398nd#if defined(OS2) || defined(WIN32)
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess#error mod_cgid does not work on this platform. If you teach it to, look
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#error at mod_cgi.c for required code in this path.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#else
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (r->finfo.filetype == APR_NOFILE) {
003f0c9fda6664daf5092a0e42f65ede20098153slive return log_scripterror(r, conf, HTTP_NOT_FOUND, 0, APLOGNO(01264)
55d36f9b61520c2374ab463e77e8a62daa416398nd "script not found or unable to stat");
55d36f9b61520c2374ab463e77e8a62daa416398nd }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive#endif
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (r->finfo.filetype == APR_DIR) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01265)
fb77c505254b6e9c925e23e734463e87574f8f40kess "attempt to invoke directory as script");
fb77c505254b6e9c925e23e734463e87574f8f40kess }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if ((r->used_path_info == AP_REQ_REJECT_PATH_INFO) &&
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd r->path_info && *r->path_info)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* default to accept */
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return log_scripterror(r, conf, HTTP_NOT_FOUND, 0, APLOGNO(01266)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "AcceptPathInfo off disallows user's path");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
55d36f9b61520c2374ab463e77e8a62daa416398nd/*
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (!ap_suexec_enabled) {
55d36f9b61520c2374ab463e77e8a62daa416398nd if (!ap_can_exec(&r->finfo))
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return log_scripterror(r, conf, HTTP_FORBIDDEN, 0, APLOGNO(01267)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "file permissions deny server execution");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
55d36f9b61520c2374ab463e77e8a62daa416398nd*/
55d36f9b61520c2374ab463e77e8a62daa416398nd ap_add_common_vars(r);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_add_cgi_vars(r);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd env = ap_create_environment(r->pool, r->subprocess_env);
55d36f9b61520c2374ab463e77e8a62daa416398nd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if ((retval = connect_to_daemon(&sd, r, conf)) != OK) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return retval;
55d36f9b61520c2374ab463e77e8a62daa416398nd }
55d36f9b61520c2374ab463e77e8a62daa416398nd
55d36f9b61520c2374ab463e77e8a62daa416398nd rv = send_req(sd, r, argv0, env, CGI_REQ);
55d36f9b61520c2374ab463e77e8a62daa416398nd if (rv != APR_SUCCESS) {
55d36f9b61520c2374ab463e77e8a62daa416398nd ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01268)
bea526116133aa3d7dabd1924bfc580b37fbf22aslive "write to cgi daemon process");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive info = apr_palloc(r->pool, sizeof(struct cleanup_script_info));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive info->r = r;
bea526116133aa3d7dabd1924bfc580b37fbf22aslive info->conn_id = r->connection->id;
bea526116133aa3d7dabd1924bfc580b37fbf22aslive info->conf = conf;
bea526116133aa3d7dabd1924bfc580b37fbf22aslive apr_pool_cleanup_register(r->pool, info,
fb77c505254b6e9c925e23e734463e87574f8f40kess cleanup_script,
bea526116133aa3d7dabd1924bfc580b37fbf22aslive apr_pool_cleanup_null);
bea526116133aa3d7dabd1924bfc580b37fbf22aslive /* We are putting the socket discriptor into an apr_file_t so that we can
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * use a pipe bucket to send the data to the client. APR will create
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * a cleanup for the apr_file_t which will close the socket, so we'll
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * get rid of the cleanup we registered when we created the socket.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (dc->timeout > 0) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_file_pipe_timeout_set(tempsock, dc->timeout);
003f0c9fda6664daf5092a0e42f65ede20098153slive }
003f0c9fda6664daf5092a0e42f65ede20098153slive else {
003f0c9fda6664daf5092a0e42f65ede20098153slive apr_file_pipe_timeout_set(tempsock, r->server->timeout);
7b5535ed88e0f561b3bfb3330137bd804846afd4slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Transfer any put/post args, CERN style...
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * Note that we already ignore SIGPIPE in the core server.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
ef8e89e090461194ecadd31e8796a2c51e0531a2kess bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
fb77c505254b6e9c925e23e734463e87574f8f40kess seen_eos = 0;
7b5535ed88e0f561b3bfb3330137bd804846afd4slive child_stopped_reading = 0;
7b5535ed88e0f561b3bfb3330137bd804846afd4slive dbuf = NULL;
7b5535ed88e0f561b3bfb3330137bd804846afd4slive dbpos = 0;
7b5535ed88e0f561b3bfb3330137bd804846afd4slive if (conf->logname) {
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd dbuf = apr_palloc(r->pool, conf->bufbytes + 1);
7b5535ed88e0f561b3bfb3330137bd804846afd4slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive do {
c68acc9d712af079afa2bd1a5a4aeef9a3ea573ckess apr_bucket *bucket;
c68acc9d712af079afa2bd1a5a4aeef9a3ea573ckess
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive APR_BLOCK_READ, HUGE_STRING_LEN);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (rv != APR_SUCCESS) {
7b5535ed88e0f561b3bfb3330137bd804846afd4slive if (APR_STATUS_IS_TIMEUP(rv)) {
7b5535ed88e0f561b3bfb3330137bd804846afd4slive ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01269)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "Timeout during reading request entity data");
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return HTTP_REQUEST_TIME_OUT;
7b5535ed88e0f561b3bfb3330137bd804846afd4slive }
7b5535ed88e0f561b3bfb3330137bd804846afd4slive ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01270)
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd "Error reading request entity data");
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return ap_map_http_request_error(rv, HTTP_INTERNAL_SERVER_ERROR);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
7b5535ed88e0f561b3bfb3330137bd804846afd4slive
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd for (bucket = APR_BRIGADE_FIRST(bb);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive bucket != APR_BRIGADE_SENTINEL(bb);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive bucket = APR_BUCKET_NEXT(bucket))
a1ef40892ffa2b44fc249423c5b6c42a74a84c68nd {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive const char *data;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_size_t len;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (APR_BUCKET_IS_EOS(bucket)) {
003f0c9fda6664daf5092a0e42f65ede20098153slive seen_eos = 1;
fb77c505254b6e9c925e23e734463e87574f8f40kess break;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
18b4b0fd6056093002ddef488636bf5ebe415ef0erikabele
18b4b0fd6056093002ddef488636bf5ebe415ef0erikabele /* We can't do much with this. */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (APR_BUCKET_IS_FLUSH(bucket)) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive continue;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* If the child stopped, we still must read to EOS. */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (child_stopped_reading) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive continue;
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess }
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* read */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (conf->logname && dbpos < conf->bufbytes) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int cursize;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ((dbpos + len) > conf->bufbytes) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cursize = conf->bufbytes - dbpos;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive else {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cursize = len;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
891df99fdfa41fc8a486568f4d31ddf4a571258adreid memcpy(dbuf + dbpos, data, cursize);
891df99fdfa41fc8a486568f4d31ddf4a571258adreid dbpos += cursize;
891df99fdfa41fc8a486568f4d31ddf4a571258adreid }
891df99fdfa41fc8a486568f4d31ddf4a571258adreid
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Keep writing data to the child until done or too much time
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * elapses with no progress or an error occurs.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive rv = apr_file_write_full(tempsock, data, len, NULL);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick if (rv != APR_SUCCESS) {
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick /* silly script stopped reading, soak up remaining message */
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick child_stopped_reading = 1;
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick }
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick }
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick apr_brigade_cleanup(bb);
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick }
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick while (!seen_eos);
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick if (conf->logname) {
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick dbuf[dbpos] = '\0';
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick }
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick /* we're done writing, or maybe we didn't write at all;
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick * force EOF on child's stdin so that the cgi detects end (or
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick * absence) of data
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick */
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick shutdown(sd, 1);
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick
c6f90ef0e93c077924fd0c3c0200dba0cb1777c6takashi /* Handle script return... */
85349f40d98fb3fc7a18ef25dc40eaaae6eead1ctakashi if (!nph) {
85349f40d98fb3fc7a18ef25dc40eaaae6eead1ctakashi conn_rec *c = r->connection;
85349f40d98fb3fc7a18ef25dc40eaaae6eead1ctakashi const char *location;
85349f40d98fb3fc7a18ef25dc40eaaae6eead1ctakashi char sbuf[MAX_STRING_LEN];
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick int ret;
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick
98f5034c8cbf2ef025b317b3e01acae82e143b11trawick bb = apr_brigade_create(r->pool, c->bucket_alloc);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive b = apr_bucket_pipe_create(tempsock, c->bucket_alloc);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive APR_BRIGADE_INSERT_TAIL(bb, b);
003f0c9fda6664daf5092a0e42f65ede20098153slive b = apr_bucket_eos_create(c->bucket_alloc);
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess APR_BRIGADE_INSERT_TAIL(bb, b);
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ((ret = ap_scan_script_header_err_brigade_ex(r, bb, sbuf,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive APLOG_MODULE_INDEX)))
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ret = log_script(r, conf, ret, dbuf, sbuf, bb, NULL);
003f0c9fda6664daf5092a0e42f65ede20098153slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /*
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * ret could be HTTP_NOT_MODIFIED in the case that the CGI script
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * does not set an explicit status and ap_meets_conditions, which
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * is called by ap_scan_script_header_err_brigade, detects that
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * the conditions of the requests are met and the response is
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * not modified.
130d299c4b2b15be45532a176604c71fdc7bea5bnd * In this case set r->status and return OK in order to prevent
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * running through the error processing stack as this would
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * break with mod_cache, if the conditions had been set by
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * mod_cache itself to validate a stale entity.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * BTW: We circumvent the error processing stack anyway if the
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess * CGI script set an explicit status code (whatever it is) and
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess * the only possible values for ret here are:
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess *
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess * HTTP_NOT_MODIFIED (set by ap_meets_conditions)
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess * HTTP_PRECONDITION_FAILED (set by ap_meets_conditions)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * HTTP_INTERNAL_SERVER_ERROR (if something went wrong during the
130d299c4b2b15be45532a176604c71fdc7bea5bnd * processing of the response of the CGI script, e.g broken headers
130d299c4b2b15be45532a176604c71fdc7bea5bnd * or a crashed CGI process).
130d299c4b2b15be45532a176604c71fdc7bea5bnd */
130d299c4b2b15be45532a176604c71fdc7bea5bnd if (ret == HTTP_NOT_MODIFIED) {
130d299c4b2b15be45532a176604c71fdc7bea5bnd r->status = ret;
130d299c4b2b15be45532a176604c71fdc7bea5bnd return OK;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd return ret;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd }
6c5c651b0b97607b8c8b4965c1385c67699f217fnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd location = apr_table_get(r->headers_out, "Location");
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd if (location && location[0] == '/' && r->status == 200) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
6c5c651b0b97607b8c8b4965c1385c67699f217fnd /* Soak up all the script output */
750d12c59545dbbac70390988de94f7e901b08f2niq discard_script_output(bb);
750d12c59545dbbac70390988de94f7e901b08f2niq apr_brigade_destroy(bb);
4bb78e7cdd53f50240cff4ad7a97c7ed36483797slive /* This redirect needs to be a GET no matter what the original
4bb78e7cdd53f50240cff4ad7a97c7ed36483797slive * method was.
4bb78e7cdd53f50240cff4ad7a97c7ed36483797slive */
4bb78e7cdd53f50240cff4ad7a97c7ed36483797slive r->method = "GET";
4bb78e7cdd53f50240cff4ad7a97c7ed36483797slive r->method_number = M_GET;
4bb78e7cdd53f50240cff4ad7a97c7ed36483797slive
4bb78e7cdd53f50240cff4ad7a97c7ed36483797slive /* We already read the message body (if any), so don't allow
4bb78e7cdd53f50240cff4ad7a97c7ed36483797slive * the redirected request to think it has one. We can ignore
4bb78e7cdd53f50240cff4ad7a97c7ed36483797slive * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_table_unset(r->headers_in, "Content-Length");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_internal_redirect_handler(location, r);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return OK;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess else if (location && r->status == 200) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* XXX: Note that if a script wants to produce its own Redirect
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * body, it now has to explicitly *say* "Status: 302"
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive discard_script_output(bb);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_brigade_destroy(bb);
003f0c9fda6664daf5092a0e42f65ede20098153slive return HTTP_MOVED_TEMPORARILY;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive rv = ap_pass_brigade(r->output_filters, bb);
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen if (rv != APR_SUCCESS) {
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen /* APLOG_ERR because the core output filter message is at error,
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess * but doesn't know it's passing CGI output
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02550) "Failed to flush CGI output to client");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen if (nph) {
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen conn_rec *c = r->connection;
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen struct ap_filter_t *cur;
130d299c4b2b15be45532a176604c71fdc7bea5bnd
130d299c4b2b15be45532a176604c71fdc7bea5bnd /* get rid of all filters up through protocol... since we
130d299c4b2b15be45532a176604c71fdc7bea5bnd * haven't parsed off the headers, there is no way they can
130d299c4b2b15be45532a176604c71fdc7bea5bnd * work
130d299c4b2b15be45532a176604c71fdc7bea5bnd */
7ef9b6763ad87846cf83c3f71467f43e349d080aerikabele
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen cur = r->proto_output_filters;
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen while (cur && cur->frec->ftype < AP_FTYPE_CONNECTION) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cur = cur->next;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->output_filters = r->proto_output_filters = cur;
03e0a375c2435102fb2b51e34cccff52acbfddcdnd
03e0a375c2435102fb2b51e34cccff52acbfddcdnd bb = apr_brigade_create(r->pool, c->bucket_alloc);
03e0a375c2435102fb2b51e34cccff52acbfddcdnd b = apr_bucket_pipe_create(tempsock, c->bucket_alloc);
03e0a375c2435102fb2b51e34cccff52acbfddcdnd APR_BRIGADE_INSERT_TAIL(bb, b);
03e0a375c2435102fb2b51e34cccff52acbfddcdnd b = apr_bucket_eos_create(c->bucket_alloc);
03e0a375c2435102fb2b51e34cccff52acbfddcdnd APR_BRIGADE_INSERT_TAIL(bb, b);
03e0a375c2435102fb2b51e34cccff52acbfddcdnd ap_pass_brigade(r->output_filters, bb);
03e0a375c2435102fb2b51e34cccff52acbfddcdnd }
a51fafd9c1463954daf49f94e76d078c1eb5c9bdnd
03e0a375c2435102fb2b51e34cccff52acbfddcdnd return OK; /* NOT r->status, even if it has changed. */
03e0a375c2435102fb2b51e34cccff52acbfddcdnd}
03e0a375c2435102fb2b51e34cccff52acbfddcdnd
03e0a375c2435102fb2b51e34cccff52acbfddcdnd
03e0a375c2435102fb2b51e34cccff52acbfddcdnd
03e0a375c2435102fb2b51e34cccff52acbfddcdnd
03e0a375c2435102fb2b51e34cccff52acbfddcdnd/*============================================================================
03e0a375c2435102fb2b51e34cccff52acbfddcdnd *============================================================================
03e0a375c2435102fb2b51e34cccff52acbfddcdnd * This is the beginning of the cgi filter code moved from mod_include. This
03e0a375c2435102fb2b51e34cccff52acbfddcdnd * is the code required to handle the "exec" SSI directive.
03e0a375c2435102fb2b51e34cccff52acbfddcdnd *============================================================================
03e0a375c2435102fb2b51e34cccff52acbfddcdnd *============================================================================*/
03e0a375c2435102fb2b51e34cccff52acbfddcdndstatic apr_status_t include_cgi(include_ctx_t *ctx, ap_filter_t *f,
03e0a375c2435102fb2b51e34cccff52acbfddcdnd apr_bucket_brigade *bb, char *s)
03e0a375c2435102fb2b51e34cccff52acbfddcdnd{
03e0a375c2435102fb2b51e34cccff52acbfddcdnd request_rec *r = f->r;
03e0a375c2435102fb2b51e34cccff52acbfddcdnd request_rec *rr = ap_sub_req_lookup_uri(s, r, f->next);
03e0a375c2435102fb2b51e34cccff52acbfddcdnd int rr_status;
03e0a375c2435102fb2b51e34cccff52acbfddcdnd
03e0a375c2435102fb2b51e34cccff52acbfddcdnd if (rr->status != HTTP_OK) {
03e0a375c2435102fb2b51e34cccff52acbfddcdnd ap_destroy_sub_req(rr);
03e0a375c2435102fb2b51e34cccff52acbfddcdnd return APR_EGENERAL;
03e0a375c2435102fb2b51e34cccff52acbfddcdnd }
03e0a375c2435102fb2b51e34cccff52acbfddcdnd
03e0a375c2435102fb2b51e34cccff52acbfddcdnd /* No hardwired path info or query allowed */
03e0a375c2435102fb2b51e34cccff52acbfddcdnd if ((rr->path_info && rr->path_info[0]) || rr->args) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_destroy_sub_req(rr);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_EGENERAL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (rr->finfo.filetype != APR_REG) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd ap_destroy_sub_req(rr);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_EGENERAL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Script gets parameters of the *document*, for back compatibility */
003f0c9fda6664daf5092a0e42f65ede20098153slive rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive rr->args = r->args;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd /* Force sub_req to be treated as a CGI request, even if ordinary
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive * typing rules would have called it something else.
89ea3e2b9591820407538ac250ec49a0f4f056d2nd */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_set_content_type(rr, CGI_MAGIC_TYPE);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* Run it. */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive rr_status = ap_run_sub_req(rr);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (ap_is_HTTP_REDIRECT(rr_status)) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive const char *location = apr_table_get(rr->headers_out, "Location");
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (location) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char *buffer;
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess location = ap_escape_html(rr->pool, location);
fb77c505254b6e9c925e23e734463e87574f8f40kess buffer = apr_pstrcat(ctx->pool, "<a href=\"", location, "\">",
fb77c505254b6e9c925e23e734463e87574f8f40kess location, "</a>", NULL);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(buffer,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive strlen(buffer), ctx->pool,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive f->c->bucket_alloc));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen }
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess ap_destroy_sub_req(rr);
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen return APR_SUCCESS;
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen}
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen/* This is the special environment used for running the "exec cmd="
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen * variety of SSI directives.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic void add_ssi_vars(request_rec *r)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_table_t *e = r->subprocess_env;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess if (r->path_info && r->path_info[0] != '\0') {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive request_rec *pa_req;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, NULL);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (pa_req->filename) {
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd apr_table_setn(e, "PATH_TRANSLATED",
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_destroy_sub_req(pa_req);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (r->args) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char *arg_copy = apr_pstrdup(r->pool, r->args);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_table_setn(e, "QUERY_STRING", r->args);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_unescape_url(arg_copy);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy));
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic int include_cmd(include_ctx_t *ctx, ap_filter_t *f,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_bucket_brigade *bb, char *command)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char **env;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int sd;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive int retval;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_file_t *tempsock = NULL;
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen request_rec *r = f->r;
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen cgid_server_conf *conf = ap_get_module_config(r->server->module_config,
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen &cgid_module);
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen struct cleanup_script_info *info;
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen add_ssi_vars(r);
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen env = ap_create_environment(r->pool, r->subprocess_env);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if ((retval = connect_to_daemon(&sd, r, conf)) != OK) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return retval;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive send_req(sd, r, command, env, SSI_REQ);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
ae134ecc8faf4e6a8eb68e1c3724506771442a46rbowen info = apr_palloc(r->pool, sizeof(struct cleanup_script_info));
ae134ecc8faf4e6a8eb68e1c3724506771442a46rbowen info->r = r;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive info->conn_id = r->connection->id;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive info->conf = conf;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive /* for this type of request, the script is invoked through an
72580dbc2a55511f13f377063725b9f143b20826stoddard * intermediate shell process... cleanup_script is only able
72580dbc2a55511f13f377063725b9f143b20826stoddard * to knock out the shell process, not the actual script
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive */
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess apr_pool_cleanup_register(r->pool, info,
72580dbc2a55511f13f377063725b9f143b20826stoddard cleanup_script,
72580dbc2a55511f13f377063725b9f143b20826stoddard apr_pool_cleanup_null);
72580dbc2a55511f13f377063725b9f143b20826stoddard
72580dbc2a55511f13f377063725b9f143b20826stoddard /* We are putting the socket discriptor into an apr_file_t so that we can
72580dbc2a55511f13f377063725b9f143b20826stoddard * use a pipe bucket to send the data to the client. APR will create
72580dbc2a55511f13f377063725b9f143b20826stoddard * a cleanup for the apr_file_t which will close the socket, so we'll
56d7eed7205462540aec7202cd82d9f5516fc537kess * get rid of the cleanup we registered when we created the socket.
72580dbc2a55511f13f377063725b9f143b20826stoddard */
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pipe_create(tempsock,
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen f->c->bucket_alloc));
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen ctx->flush_now = 1;
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen return APR_SUCCESS;
ef8e89e090461194ecadd31e8796a2c51e0531a2kess}
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowenstatic apr_status_t handle_exec(include_ctx_t *ctx, ap_filter_t *f,
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen apr_bucket_brigade *bb)
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen{
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen char *tag = NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char *tag_val = NULL;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive request_rec *r = f->r;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char *file = r->filename;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive char parsed_string[MAX_STRING_LEN];
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (!ctx->argc) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_log_rerror(APLOG_MARK,
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd (ctx->flags & SSI_FLAG_PRINTING)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ? APLOG_ERR : APLOG_WARNING,
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive 0, r, "missing argument for exec element in %s",
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive r->filename);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
72580dbc2a55511f13f377063725b9f143b20826stoddard
72580dbc2a55511f13f377063725b9f143b20826stoddard if (!(ctx->flags & SSI_FLAG_PRINTING)) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_SUCCESS;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
72580dbc2a55511f13f377063725b9f143b20826stoddard
72580dbc2a55511f13f377063725b9f143b20826stoddard if (!ctx->argc) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_SUCCESS;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (ctx->flags & SSI_FLAG_NO_EXEC) {
fb77c505254b6e9c925e23e734463e87574f8f40kess ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01271) "exec used but not allowed "
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "in %s", r->filename);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_SUCCESS;
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen }
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen while (1) {
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen cgid_pfn_gtv(ctx, &tag, &tag_val, SSI_VALUE_DECODED);
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen if (!tag || !tag_val) {
ef8e89e090461194ecadd31e8796a2c51e0531a2kess break;
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen }
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen if (!strcmp(tag, "cmd")) {
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen apr_status_t rv;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive cgid_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive SSI_EXPAND_LEAVE_NAME);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive rv = include_cmd(ctx, f, bb, parsed_string);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive if (rv != APR_SUCCESS) {
313bb560bc5c323cfd40c9cad7335b4b8e060aedkess ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01272)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "execution failure for parameter \"%s\" "
18b4b0fd6056093002ddef488636bf5ebe415ef0erikabele "to tag exec in file %s", tag, r->filename);
18b4b0fd6056093002ddef488636bf5ebe415ef0erikabele SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
18b4b0fd6056093002ddef488636bf5ebe415ef0erikabele break;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive else if (!strcmp(tag, "cgi")) {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive apr_status_t rv;
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen cgid_pfn_ps(ctx, tag_val, parsed_string, sizeof(parsed_string),
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen SSI_EXPAND_DROP_NAME);
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen
a7f40ca49262952d6dd69d021cf5b0c2b452ae4cnd rv = include_cgi(ctx, f, bb, parsed_string);
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen if (rv != APR_SUCCESS) {
d3f27ec18dfa6283e852aa98253212edafaa0e2brbowen ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01273) "invalid CGI ref "
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "\"%s\" in %s", tag_val, file);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive break;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive else {
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01274) "unknown parameter "
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive "\"%s\" to tag exec in %s", tag, file);
fb77c505254b6e9c925e23e734463e87574f8f40kess SSI_CREATE_ERROR_BUCKET(ctx, f, bb);
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive break;
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive }
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive return APR_SUCCESS;
6b64034fa2a644ba291c484c0c01c7df5b8d982ckess}
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive/*============================================================================
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive *============================================================================
7852e17fb37b2a02ccdcab107f2c7f5fd41fd201nd * This is the end of the cgi filter code moved from mod_include.
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive *============================================================================
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive *============================================================================*/
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive
80c4526970a11f37c0f8e3b82afdf03902dac3f3slivestatic void register_hook(apr_pool_t *p)
80c4526970a11f37c0f8e3b82afdf03902dac3f3slive{
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive static const char * const aszPre[] = { "mod_include.c", NULL };
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive ap_hook_pre_config(cgid_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive ap_hook_post_config(cgid_init, aszPre, NULL, APR_HOOK_MIDDLE);
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive ap_hook_handler(cgid_handler, NULL, NULL, APR_HOOK_MIDDLE);
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive}
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive
234c8b28171d7e12b3c1f85b60fabd7c908a9c37sliveAP_DECLARE_MODULE(cgid) = {
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive STANDARD20_MODULE_STUFF,
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive create_cgid_dirconf, /* dir config creater */
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive NULL, /* dir merger --- default is to override */
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive create_cgid_config, /* server config */
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive merge_cgid_config, /* merge server config */
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive cgid_cmds, /* command table */
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive register_hook /* register_handlers */
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive};
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive
234c8b28171d7e12b3c1f85b60fabd7c908a9c37slive