util_script.c revision 480c790b074c94e2a9b53ae768a4d6f710e5caa0
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* ====================================================================
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * Redistribution and use in source and binary forms, with or without
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * modification, are permitted provided that the following conditions
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 1. Redistributions of source code must retain the above copyright
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * notice, this list of conditions and the following disclaimer.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 2. Redistributions in binary form must reproduce the above copyright
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * notice, this list of conditions and the following disclaimer in
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the documentation and/or other materials provided with the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * distribution.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 3. All advertising materials mentioning features or use of this
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * software must display the following acknowledgment:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * "This product includes software developed by the Apache Group
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * for use in the Apache HTTP server project (http://www.apache.org/)."
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * 4. The names "Apache Server" and "Apache Group" must not be used to
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * endorse or promote products derived from this software without
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * prior written permission. For written permission, please contact
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * apache@apache.org.
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * 5. Products derived from this software may not be called "Apache"
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * nor may "Apache" appear in their names without prior written
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * permission of the Apache Group.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 6. Redistributions of any form whatsoever must retain the following
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * acknowledgment:
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * "This product includes software developed by the Apache Group
64185f9824e42f21ca7b9ae6c004484215c031a7rbb * for use in the Apache HTTP server project (http://www.apache.org/)."
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * OF THE POSSIBILITY OF SUCH DAMAGE.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * ====================================================================
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This software consists of voluntary contributions made by many
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * individuals on behalf of the Apache Group and was originally based
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * on public domain software written at the National Center for
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * Supercomputing Applications, University of Illinois, Urbana-Champaign.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * For more information on the Apache Group and the Apache HTTP server
7e79e8fd53348f9fc6e8009a4a2522425ab6f08ffielding * project, please see <http://www.apache.org/>.
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "http_request.h" /* for sub_req_lookup_uri() */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Various utility functions which are common to a whole lot of
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * script-type extensions mechanisms, and might as well be gathered
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * in one place (if only to avoid creating inter-module dependancies
51af95bb51b5084e883bad250b2afa2838e9ceebfielding * where there don't have to be).
7fae9cc4639013f3c04c085547256c68814aee8ftrawick#define MALFORMED_MESSAGE "malformed header from script. Bad header="
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* If a request includes query info in the URL (stuff after "?"), and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the query info does not contain "=" (indicative of a FORM submission),
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * then this routine is called to create the argument list to be passed
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * to the CGI script. When suexec is enabled, the suexec path, user, and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * group are the first three arguments to be passed; if not, all three
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * must be NULL. The query info is split into separate arguments, where
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * "+" is the separator between keyword arguments.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * XXXX: note that the WIN32 code uses one of the suexec strings
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * to pass an interpreter name. Remember this if changing the way they
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * are handled in create_argv.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char **create_argv(ap_context_t *p, char *path, char *user, char *group,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* count the number of keywords */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding numwords = APACHE_ARG_MAX - 5; /* Truncate args to prevent overrun */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding av = (char **) ap_palloc(p, (numwords + 5) * sizeof(char *));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif /* defined(OS2) || defined(WIN32) */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (*++cp) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAPI_EXPORT(char **) ap_create_environment(ap_context_t *p, ap_table_t *t)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_entry_t *elts = (ap_table_entry_t *) env_arr->elts;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char **env = (char **) ap_palloc(p, (env_arr->nelts + 2) * sizeof(char *));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding env[j] = ap_pstrcat(p, elts[i].key, "=", elts[i].val, NULL);
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick const char *host;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick ap_array_header_t *hdrs_arr = ap_table_elts(r->headers_in);
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick ap_table_entry_t *hdrs = (ap_table_entry_t *) hdrs_arr->elts;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick /* use a temporary ap_table_t which we'll overlap onto
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * r->subprocess_env later
eae32ab3fb398ca408bc2d45b22adf1b67a75471rbb /* First, add environment vars from headers... this is as per
066877f1a045103acfdd376d48cdd473c33f409bdougm * CGI specs, though other sorts of scripting interfaces see
eae32ab3fb398ca408bc2d45b22adf1b67a75471rbb * the same vars...
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick /* A few headers are special cased --- Authorization to prevent
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * rogue scripts from capturing passwords; content-type and -length
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * for no particular reason.
066877f1a045103acfdd376d48cdd473c33f409bdougm else if (!strcasecmp(hdrs[i].key, "Content-length")) {
d17890657bc529b3f9db20e5546511182b829565dreid * You really don't want to disable this check, since it leaves you
d17890657bc529b3f9db20e5546511182b829565dreid * wide open to CGIs stealing passwords and people viewing them
d17890657bc529b3f9db20e5546511182b829565dreid * in the environment with "ps -e". But, if you must...
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_addn(e, http2env(r->pool, hdrs[i].key), hdrs[i].val);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_addn(e, "SERVER_SIGNATURE", ap_psignature("", r));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_addn(e, "SERVER_SOFTWARE", ap_get_server_version());
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_addn(e, "SERVER_NAME", ap_get_server_name(r));
0e6e93183d91142d7cf9ffbf502114ff77bd9e19ben ap_table_addn(e, "SERVER_ADDR", r->connection->local_ip); /* Apache */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_psprintf(r->pool, "%u", ap_get_server_port(r)));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding host = ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ap_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_psprintf(r->pool, "%d", ntohs(c->remote_addr.sin_port)));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_addn(e, "REMOTE_IDENT", ap_pstrdup(r->pool, rem_logname));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Apache custom error responses. If we have redirected set two new vars */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_addn(e, "REDIRECT_QUERY_STRING", r->prev->args);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_overlap_tables(r->subprocess_env, e, AP_OVERLAP_TABLES_SET);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/* This "cute" little function comes about because the path info on
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * filenames and URLs aren't always the same. So we take the two,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and find as much of the two that match as possible.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAPI_EXPORT(int) ap_find_path_info(const char *uri, const char *path_info)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* Obtain the Request-URI from the original request-line, returning
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * a new string from the request pool containing the URI or "".
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_setn(e, "QUERY_STRING", r->args ? r->args : "");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Note that the code below special-cases scripts run from includes,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * because it "knows" that the sub_request has been hacked to have the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * args and path_info of the original request, and not any that may have
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * come with the script URI in the include command. Ugh.
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick int path_info_start = ap_find_path_info(r->uri, r->path_info);
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick * To get PATH_TRANSLATED, treat PATH_INFO as a URI path.
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick * Need to re-escape it for this, since the entire URI was
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick * un-escaped before we determined where the PATH_INFO began.
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *pt = ap_pstrcat(r->pool, pa_req->filename, pa_req->path_info,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* We need to make this a real Windows path name */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_table_setn(e, "PATH_TRANSLATED", ap_pstrdup(r->pool, buffer));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int set_cookie_doo_doo(void *v, const char *key, const char *val)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAPI_EXPORT(int) ap_scan_script_header_err_core(request_rec *r, char *buffer,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf int (*getsfunc) (char *, int, void *),
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick char *w, *l;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick /* temporary place to hold headers to merge in later */
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* The HTTP specification says that it is legal to merge duplicate
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * headers into one. Some browsers that support Cookies don't like
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * merged headers and prefer that each Set-Cookie header is sent
066877f1a045103acfdd376d48cdd473c33f409bdougm * separately. Lets humour those browsers by not merging.
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * Oh what a pain it is.
066877f1a045103acfdd376d48cdd473c33f409bdougm ap_table_do(set_cookie_doo_doo, cookie_table, r->err_headers_out, "Set-Cookie", NULL);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf while (1) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data) == 0) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* Delete terminal (CR?)LF */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If we've finished reading the headers, check to make sure any
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * HTTP/1.1 conditions are met. If so, we're done; normal processing
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * will handle the script's output. If not, just return the error.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * The appropriate thing to do would be to send the script process a
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * SIGPIPE to let it know we're ignoring it, close the channel to the
066877f1a045103acfdd376d48cdd473c33f409bdougm * script process, and *then* return the failed-to-meet-condition
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * error. Otherwise we'd be waiting for the script to finish
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * blithering before telling the client the output was no good.
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * However, we don't have the information to do that, so we have to
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * leave it to an upper layer.
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if (w[0] == '\0') {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if ((cgi_status == HTTP_OK) && (r->method_number == M_GET)) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* the cookies have already been copied to the cookie_table */
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* if we see a bogus header don't ignore it. Shout and scream */
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* Chances are that we received an ASCII header text instead of
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * the expected EBCDIC header lines. Try to auto-detect:
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf "CGI Interface Error: Script headers apparently ASCII: (CGI = %s)", r->filename);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf strncat(malformed, w, MALFORMED_HEADER_LENGTH_TO_SHOW);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* Soak up all the script output - may save an outright kill */
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf while ((*getsfunc) (w, MAX_STRING_LEN - 1, getsfunc_data)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *l++ = '\0';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (*l && ap_isspace(*l)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Nuke trailing whitespace */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If the script returned a specific status, that's what
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * we'll use - otherwise we assume 200 OK.
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * If the script gave us a Last-Modified header, we can't just
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * pass it on blindly because of restrictions on future values.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int getsfunc_FILE(char *buf, int len, void *f)
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanfAPI_EXPORT(int) ap_scan_script_header_err(request_rec *r, FILE *f,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return ap_scan_script_header_err_core(r, buffer, getsfunc_FILE, f);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAPI_EXPORT(int) ap_scan_script_header_err_buff(request_rec *r, BUFF *fb,
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick return ap_scan_script_header_err_core(r, buffer, getsfunc_BUFF, fb);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanfAPI_EXPORT(void) ap_send_size(size_t size, request_rec *r)
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* XXX: this -1 thing is a gross hack */
0942697a9b5de44865676345a3828741c827efe6rbb else if (!size) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char **create_argv_cmd(ap_context_t *p, char *av0, const char *args, char *path)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding register int x, n;
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick /* Add extra strings to array. */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick av = (char **) ap_palloc(p, (n + 1) * sizeof(char *));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Now insert the extra strings we made room for above. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* ZZZ need to look at this in more depth and convert to an AP func so we
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding can get rid of OS specific code.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAPI_EXPORT(int) ap_call_exec(request_rec *r, ap_child_info_t *pinfo, char *argv0,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* the fd on r->server->error_log is closed, but we need somewhere to
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * put the error messages from the log_* functions. So, we use stderr,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * since that is better than allowing errors to go unnoticed. Don't do
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * this on Win32, though, since we haven't fork()'d.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ap_put_os_file(&r->server->error_log, &errfileno, r->pool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* TODO: all that RLimit stuff should become part of the spawning API,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and not something in the core_dir_config... define a special rlimit
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * structure and pass it in here.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Additions by Alec Kloss, to allow exec'ing of scripts under OS/2 */
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf char interpreter[2048]; /* hope it's enough for the interpreter path */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (r->args && r->args[0] && !strchr(r->args, '='))
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "fopen(%s) failed",
71715c646d5231de578431f8961e711764b899d3fanf if (interpreter[2] != '/' && interpreter[2] != '\\' && interpreter[3] != ':') {
71715c646d5231de578431f8961e711764b899d3fanf if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) {
71715c646d5231de578431f8961e711764b899d3fanf if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) {
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick cmdline = ap_pstrcat(r->pool, interpreter+2, " ", r->filename, NULL);
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf /* Special case to allow use of REXX commands as scripts. */
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf cmdline = ap_pstrcat(r->pool, SHELL_PATH, " /C ", r->filename, NULL);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (args_end - args > 4000) { /* cmd.exe won't handle lines longer than 4k */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* +4 = 1 space between progname and args, 2 for double null at end, 2 for possible quote on first arg */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cmdlen += 2 * (*cmdline_pos == '+'); /* Allow space for each arg to be quoted */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *(++cmdline_pos) = 0; /* Add required second terminator */
eaa7fe3cc26f8118ed72e5811aead02328d62448dreid /* Create environment block from list of envariables */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (e=0; env[e]; e++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *env_block_pos = 0; /* environment block is terminated by a double null */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rc = DosExecPgm(error_object, sizeof(error_object), EXEC_ASYNC, cmdline, env_block, &rescodes, cmdline);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "DosExecPgm(%s %s) failed, %s - %s",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cmdline, args ? args : "", ap_os_error_message(rc), error_object );
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Adapted from Alec Kloss' work for OS/2 */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding fileType = ap_get_win32_interpreter(r, &interpreter);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "%s is not executable; ensure interpreted scripts have "
dad234382d8424e1c5a30af2838e172aec9d6d1bdreid "\"#!\" first line",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Look at the arguments...
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((r->args) && (r->args[0]) && !strchr(r->args, '=')) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* If we are in this leg, there are some other arguments
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * that we must include in the execution of the CGI.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Because CreateProcess is the way it is, we have to
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * create a command line like format for the execution
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * of the CGI. This means we need to create on long
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * string with the executable and arguments.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * The arguments string comes in the request structure,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and each argument is separated by a '+'. We'll replace
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * these pluses with spaces.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Duplicate the request structure string so we don't change it.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Change the '+' to ' '
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (x=0; arguments[x]; x++) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * We need to unescape any characters that are
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * in the arguments list.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding arguments = ap_escape_shell_cmd(r->pool, arguments);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * We have the interpreter (if there is one) and we have
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the arguments (if there are any).
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Build the command string to pass to CreateProcess.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding quoted_filename = ap_pstrcat(r->pool, "\"", r->filename, "\"", NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding pCommand = ap_pstrcat(r->pool, quoted_filename, " ", arguments, NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Use CMD.EXE for NT, COMMAND.COM for WIN95
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding pCommand = ap_pstrcat(r->pool, shell_cmd, argv0, NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Make child process use hPipeOutputWrite as standard out,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and make sure it does not show on screen.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Win32's CreateProcess call requires that the environment
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * be passed in an environment block, a null terminated block of
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * null terminated strings.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (env[i]) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding pEnvBlock = (char *)ap_pcalloc(r->pool,iEnvBlockLen);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm while (env[i]) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, DETACHED_PROCESS, pEnvBlock,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Hack to get 16-bit CGI's working. It works for all the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * standard modules shipped with Apache. pi.dwProcessId is 0
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * for 16-bit CGIs and all the Unix specific code that calls
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * ap_call_exec interprets this as a failure case. And we can't
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * use -1 either because it is mapped to 0 by the caller.
8f8ec0957334f50b7ac11359f90490ee467258eedreid * We must close the handles to the new process and its main thread
382fa07a63096c4a1aabfed36433ea5ac9c40ad0trawick * to prevent handle and memory leaks.
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* TODO: reimplement suexec */
if (pos) {
return (pid);
return (pid);
return (pid);
return (pid);
if (shellcmd) {
env);
if (shellcmd) {
env);
return (pid);