You are viewing a plain text version of this content. The canonical link for it is here.
Posted to site-cvs@tcl.apache.org by mx...@apache.org on 2014/08/13 18:56:14 UTC
svn commit: r1617763 [1/2] - in /tcl/rivet/trunk: ./ src/experimental/
Author: mxmanghi
Date: Wed Aug 13 16:56:13 2014
New Revision: 1617763
URL: http://svn.apache.org/r1617763
Log:
* src/experimental/rivet_[prefork|worker]_mpm.c: bridges integrated. Removed substantial code
from rivet_prefork_mpm.c and merged with the current approach handling hosts interpreters using
vhost_interp objects and storing everything in a child process/thread private data
* src/experimental/apache_config.[c|h]: eventually these files had to be copied here from common
and modified to reflect the new model for handling server records
* src/experimental/mod_rivet_common.c: same for this file
* src/experimental/mod_rivet.c: further generalization of the code to provide consistent
support for the bridges. Adding a new hook for mpm_master_interp, a function implemented by
a bridge responsible for returning the child process/thread master interpreter.
Added:
tcl/rivet/trunk/src/experimental/TclWebapache.c
tcl/rivet/trunk/src/experimental/apache_config.c
tcl/rivet/trunk/src/experimental/apache_config.h
tcl/rivet/trunk/src/experimental/mod_rivet_common.c
tcl/rivet/trunk/src/experimental/mod_rivet_common.h
Modified:
tcl/rivet/trunk/ChangeLog
tcl/rivet/trunk/Makefile.in
tcl/rivet/trunk/src/experimental/Makefile.am
tcl/rivet/trunk/src/experimental/mod_rivet.c
tcl/rivet/trunk/src/experimental/mod_rivet.h
tcl/rivet/trunk/src/experimental/rivet_prefork_mpm.c
tcl/rivet/trunk/src/experimental/rivet_worker_mpm.c
Modified: tcl/rivet/trunk/ChangeLog
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/ChangeLog?rev=1617763&r1=1617762&r2=1617763&view=diff
==============================================================================
--- tcl/rivet/trunk/ChangeLog (original)
+++ tcl/rivet/trunk/ChangeLog Wed Aug 13 16:56:13 2014
@@ -1,3 +1,14 @@
+2014-08-12 Massimo Manghi <mx...@apache.org>
+ * src/experimental/rivet_[prefork|worker]_mpm.c: bridges integrated. Removed substantial code
+ from rivet_prefork_mpm.c and merged with the current approach handling hosts interpreters using
+ vhost_interp objects and storing everything in a child process/thread private data
+ * src/experimental/apache_config.[c|h]: eventually these files had to be copied here from common
+ and modified to reflect the new model for handling server records
+ * src/experimental/mod_rivet_common.c: same for this file
+ * src/experimental/mod_rivet.c: further generalization of the code to provide consistent
+ support for the bridges. Adding a new hook for mpm_master_interp, a function implemented by
+ a bridge responsible for returning the child process/thread master interpreter.
+
2014-08-11 Massimo Manghi <mx...@apache.org>
* src/experimental/rivet_worker_mpm.c: redesigning virtual hosts resource management for threads
* src/experimental/mod_rivet[c|h]: implementing thread private interpreters management
Modified: tcl/rivet/trunk/Makefile.in
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/Makefile.in?rev=1617763&r1=1617762&r2=1617763&view=diff
==============================================================================
--- tcl/rivet/trunk/Makefile.in (original)
+++ tcl/rivet/trunk/Makefile.in Wed Aug 13 16:56:13 2014
@@ -17,7 +17,7 @@
#
# top-level Makefile.am for Apache Rivet: gets turned into a Makefile.in by automake
#
-# $Id: Makefile.am 1517859 2013-08-27 16:08:31Z mxmanghi $
+# $Id: Makefile.am 1616967 2014-08-09 15:29:07Z mxmanghi $
#
# 2007/12/25: Added target uninistall-local that removes the tcl stuff (mxmanghi)
# 2010/06/22: target instal-data-local searches for pkgIndex.tcl files and deletes them
Modified: tcl/rivet/trunk/src/experimental/Makefile.am
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/Makefile.am?rev=1617763&r1=1617762&r2=1617763&view=diff
==============================================================================
--- tcl/rivet/trunk/src/experimental/Makefile.am (original)
+++ tcl/rivet/trunk/src/experimental/Makefile.am Wed Aug 13 16:56:13 2014
@@ -10,13 +10,13 @@ apxs_libexec_LTLIBRARIES = mod_rivet.la
mod_rivet_la_SOURCES = mod_rivet.c \
../@apache_request@/apache_multipart_buffer.c \
../@apache_request@/apache_request.c \
- ../@rivet_commands@/rivetCore.c \
- ../@rivet_commands@/rivetInspect.c \
+ ../@rivet_commands@/rivetCore.c \
+ ../@rivet_commands@/rivetInspect.c \
../@rivet_channel@/rivetChannel.c \
- ../common/TclWebapache.c \
- ../common/apache_config.c \
- ../common/mod_rivet_common.c \
- ../parser/rivetParser.c
+ ../parser/rivetParser.c \
+ TclWebapache.c \
+ apache_config.c \
+ mod_rivet_common.c
mod_rivet_la_LDFLAGS = @TCL_LIB_SPEC@ @APXS_LDFLAGS@ @APR_LDFLAGS@ -module -avoid-version
mod_rivet_la_LIBADD = @TCL_LIBS@ @APXS_LIBS@
Added: tcl/rivet/trunk/src/experimental/TclWebapache.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/TclWebapache.c?rev=1617763&view=auto
==============================================================================
--- tcl/rivet/trunk/src/experimental/TclWebapache.c (added)
+++ tcl/rivet/trunk/src/experimental/TclWebapache.c Wed Aug 13 16:56:13 2014
@@ -0,0 +1,770 @@
+/*
+ * TclWeb.c --
+ *
+ * Common API layer.
+ *
+ * This file contains the Apache-based versions of the functions in
+ * TclWeb.h. They rely on Apache and apreq to perform the underlying
+ * operations.
+ *
+ */
+
+/* Copyright 2002-2014 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/* $Id: TclWebapache.c,v 1.49 2005/08/12 22:37:57 davidw Exp $ */
+
+/* Rivet config */
+#ifdef HAVE_CONFIG_H
+#include <rivet_config.h>
+#endif
+
+#include <tcl.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <httpd.h>
+#include <http_request.h>
+#include <ap_compat.h>
+#include <apr_strings.h>
+#include "apache_request.h"
+#include "mod_rivet.h"
+#include "TclWeb.h"
+
+extern module rivet_module;
+#define TCLWEBPOOL req->req->pool
+
+#define BUFSZ 4096
+
+/* This is used below to determine what part of the parmsarray to
+ * parse. */
+#define PARMSARRAY_COORDINATES i = 0; j = parmsarray->nelts; \
+if (source == VAR_SRC_QUERYSTRING) { j = req->apachereq->nargs; } \
+else if (source == VAR_SRC_POST) { i = req->apachereq->nargs; }
+
+/*
+ * -- TclWeb_NewRequestObject
+ *
+ *
+ */
+
+TclWebRequest*
+TclWeb_NewRequestObject (apr_pool_t *p)
+{
+ TclWebRequest* req = (TclWebRequest *)apr_pcalloc(p, sizeof(TclWebRequest));
+
+ req->interp = NULL;
+ req->req = NULL;
+ req->apachereq = ApacheRequest_new(p);
+ req->headers_printed = 0;
+ req->headers_set = 0;
+ req->environment_set = 0;
+ req->charset = NULL; /* we will test against NULL to check if a charset */
+ /* was specified in the conf */
+ return req;
+}
+
+
+/*
+ * -- TclWeb_InitRequest
+ *
+ * called once on every HTTP request initializes fields and
+ * objects referenced in a TclWebRequest object
+ *
+ * Arguments:
+ *
+ * *req: a pointer to a TclWebRequest object to be intialized
+ * *interp: current Tcl_Interp object serving the request
+ * *arg: generic pointer. Current implementation passes the
+ * request_rec object pointer
+ *
+ */
+
+int
+TclWeb_InitRequest(TclWebRequest *req, Tcl_Interp *interp, void *arg)
+{
+ request_rec *r = (request_rec *)arg;
+
+ req->interp = interp;
+ req->req = r;
+ req->apachereq = ApacheRequest_init(req->apachereq,r);
+ req->headers_printed = 0;
+ req->headers_set = 0;
+ req->environment_set = 0;
+
+
+ req->charset = NULL;
+ return TCL_OK;
+}
+
+INLINE int
+TclWeb_SendHeaders(TclWebRequest *req)
+{
+ //TODO: fix ap_send_http_header
+
+ ap_send_http_header(req->req);
+
+ return TCL_OK;
+}
+
+INLINE int
+TclWeb_StopSending(TclWebRequest *req)
+{
+ req->req->connection->aborted = 1;
+ return TCL_OK;
+}
+
+/* Set up the content type header */
+
+int
+TclWeb_SetHeaderType(char *header, TclWebRequest *req)
+{
+
+ if (req->headers_set)
+ return TCL_ERROR;
+
+// req->req->content_type = (char *) apr_pstrdup(req->req->pool, header);
+
+ ap_set_content_type(req->req,apr_pstrdup(req->req->pool, header));
+ req->headers_set = 1;
+ return TCL_OK;
+}
+
+/* Printer headers if they haven't been printed yet */
+int
+TclWeb_PrintHeaders(TclWebRequest *req)
+{
+ if (req->headers_printed)
+ return TCL_ERROR;
+
+ if (req->headers_set == 0)
+ {
+ TclWeb_SetHeaderType(DEFAULT_HEADER_TYPE, req);
+ }
+
+ /*
+ * seems that ap_send_http_header is redefined to ; in Apache2.2
+ * ap_send_http_header(req->req);
+ */
+
+ TclWeb_SendHeaders(req);
+ /* ap_send_http_header(req->req); */
+
+ req->headers_printed = 1;
+ return TCL_OK;
+}
+
+/* Print nice HTML formatted errors */
+int
+TclWeb_PrintError(CONST84 char *errstr, int htmlflag, TclWebRequest *req)
+{
+ TclWeb_SetHeaderType(DEFAULT_HEADER_TYPE, req);
+ TclWeb_PrintHeaders(req);
+
+ if (htmlflag != 1)
+ ap_rputs(ER1, req->req);
+
+ if (errstr != NULL)
+ {
+ if (htmlflag != 1)
+ {
+ ap_rputs(ap_escape_html(TCLWEBPOOL, errstr), req->req);
+ } else {
+ ap_rputs(errstr, req->req);
+ }
+ }
+ if (htmlflag != 1)
+ ap_rputs(ER2, req->req);
+
+ return TCL_OK;
+}
+
+INLINE int
+TclWeb_HeaderSet(char *header, char *val, TclWebRequest *req)
+{
+ apr_table_set(req->req->headers_out, header, val);
+ return TCL_OK;
+}
+
+INLINE int
+TclWeb_HeaderAdd(char *header, char *val, TclWebRequest *req)
+{
+ apr_table_add(req->req->headers_out, header, val);
+ return TCL_OK;
+}
+
+INLINE int
+TclWeb_SetStatus(int status, TclWebRequest *req)
+{
+ req->req->status = status;
+ return TCL_OK;
+}
+
+INLINE int
+TclWeb_MakeURL(Tcl_Obj *result, char *filename, TclWebRequest *req)
+{
+ Tcl_SetStringObj(result, ap_construct_url(TCLWEBPOOL,
+ filename, req->req), -1);
+ return TCL_OK;
+}
+
+int
+TclWeb_GetVar(Tcl_Obj *result, char *varname, int source, TclWebRequest *req)
+{
+ int i, j;
+ apr_array_header_t *parmsarray = (apr_array_header_t *)
+ apr_table_elts(req->apachereq->parms);
+ apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
+ int flag = 0;
+
+ PARMSARRAY_COORDINATES;
+
+ /* This isn't real efficient - move to hash table later on... */
+ while (i < j)
+ {
+ char *parmkey = TclWeb_StringToUtf(parms[i].key, req);
+ if (!strncmp(varname, parmkey,
+ strlen(varname) < strlen(parmkey) ?
+ strlen(parmkey) : strlen(varname)))
+ {
+ /* The following makes sure that we get one string,
+ with no sub lists. */
+ if (flag == 0)
+ {
+ flag = 1;
+ Tcl_SetStringObj(result,
+ TclWeb_StringToUtf(parms[i].val, req), -1);
+ } else {
+ Tcl_Obj *tmpobj;
+ Tcl_Obj *tmpobjv[2];
+ tmpobjv[0] = result;
+ tmpobjv[1] = TclWeb_StringToUtfToObj(parms[i].val, req);
+ tmpobj = Tcl_ConcatObj(2, tmpobjv);
+ Tcl_SetStringObj(result, Tcl_GetString(tmpobj), -1);
+ }
+ }
+ i++;
+ }
+
+ if (result->length == 0)
+ {
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+int
+TclWeb_GetVarAsList(Tcl_Obj *result, char *varname, int source, TclWebRequest *req)
+{
+ int i, j;
+ apr_array_header_t *parmsarray = (apr_array_header_t *)
+ apr_table_elts(req->apachereq->parms);
+ apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
+
+ PARMSARRAY_COORDINATES;
+
+ /* This isn't real efficient - move to hash table later on. */
+ while (i < j)
+ {
+
+ if (!strncmp(varname, TclWeb_StringToUtf(parms[i].key, req),
+ strlen(varname) < strlen(parms[i].key) ?
+ strlen(parms[i].key) : strlen(varname)))
+ {
+ Tcl_ListObjAppendElement(req->interp, result,
+ TclWeb_StringToUtfToObj(parms[i].val, req));
+ }
+ i++;
+ }
+
+ if (result == NULL)
+ {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+int
+TclWeb_GetAllVars(Tcl_Obj *result, int source, TclWebRequest *req)
+{
+ int i, j;
+ apr_array_header_t *parmsarray = (apr_array_header_t *)
+ apr_table_elts(req->apachereq->parms);
+ apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
+
+ PARMSARRAY_COORDINATES;
+
+ while (i < j)
+ {
+ Tcl_ListObjAppendElement(req->interp, result,
+ TclWeb_StringToUtfToObj(parms[i].key, req));
+ Tcl_ListObjAppendElement(req->interp, result,
+ TclWeb_StringToUtfToObj(parms[i].val, req));
+ i++;
+ }
+
+ if (result == NULL)
+ {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+int
+TclWeb_GetVarNames(Tcl_Obj *result, int source, TclWebRequest *req)
+{
+ int i, j;
+ apr_array_header_t *parmsarray = (apr_array_header_t *)
+ apr_table_elts(req->apachereq->parms);
+ apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
+
+ PARMSARRAY_COORDINATES;
+
+ while (i < j)
+ {
+ Tcl_ListObjAppendElement(req->interp, result,
+ TclWeb_StringToUtfToObj(parms[i].key, req));
+ i++;
+ }
+
+ if (result == NULL)
+ {
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+int
+TclWeb_VarExists(Tcl_Obj *result, char *varname, int source, TclWebRequest *req)
+{
+ int i, j;
+ apr_array_header_t *parmsarray = (apr_array_header_t *)
+ apr_table_elts(req->apachereq->parms);
+ apr_table_entry_t *parms = (apr_table_entry_t *)parmsarray->elts;
+
+ PARMSARRAY_COORDINATES;
+
+ /* This isn't real efficient - move to hash table later on. */
+ while (i < j)
+ {
+ if (!strncmp(varname, TclWeb_StringToUtf(parms[i].key, req),
+ strlen(varname) < strlen(parms[i].key) ?
+ strlen(parms[i].key) : strlen(varname)))
+ {
+ Tcl_SetIntObj(result, 1);
+ return TCL_OK;
+ }
+ i++;
+ }
+ Tcl_SetIntObj(result, 0);
+ return TCL_OK;
+}
+
+int
+TclWeb_VarNumber(Tcl_Obj *result, int source, TclWebRequest *req)
+{
+ apr_array_header_t *parmsarray = (apr_array_header_t *)
+ apr_table_elts(req->apachereq->parms);
+
+ if (source == VAR_SRC_QUERYSTRING) {
+ Tcl_SetIntObj(result, req->apachereq->nargs);
+ } else if (source == VAR_SRC_POST) {
+ Tcl_SetIntObj(result, parmsarray->nelts - req->apachereq->nargs);
+ } else {
+ Tcl_SetIntObj(result, parmsarray->nelts);
+ }
+
+ return TCL_OK;
+}
+
+/*
+ * Load the Apache environment and CGI variables into the request. If we
+ * have already done so, we don't need to do it again.
+ */
+static void
+TclWeb_InitEnvVars( TclWebRequest *req )
+{
+ //rivet_server_conf *rsc;
+ apr_table_t *table = req->req->subprocess_env;
+ char *timefmt = DEFAULT_TIME_FORMAT;
+ char *t;
+ apr_time_t date = req->req->request_time;
+#ifndef WIN32
+ struct passwd *pw;
+#endif /* ndef WIN32 */
+
+ if( req->environment_set ) return;
+
+ //rsc = RIVET_SERVER_CONF( req->req->server->module_config );
+
+ /* Retrieve cgi variables. */
+ ap_add_cgi_vars( req->req );
+ ap_add_common_vars( req->req );
+
+ /* These were the "include vars" */
+
+ apr_table_set( table, "DATE_LOCAL",
+ ap_ht_time( TCLWEBPOOL, date, timefmt, 0 ) );
+ apr_table_set( table, "DATE_GMT",
+ ap_ht_time( TCLWEBPOOL, date, timefmt, 1 ) );
+ apr_table_set( table, "LAST_MODIFIED",
+ ap_ht_time( TCLWEBPOOL, req->req->finfo.mtime, timefmt, 1 ) );
+ apr_table_set( table, "DOCUMENT_URI", req->req->uri );
+ apr_table_set( table, "DOCUMENT_PATH_INFO", req->req->path_info );
+
+ if ((t = strrchr(req->req->filename, '/'))) {
+ apr_table_set( table, "DOCUMENT_NAME", ++t );
+ } else {
+ apr_table_set( table, "DOCUMENT_NAME", req->req->uri );
+ }
+
+ if( req->req->args ) {
+ char *arg_copy = (char*) apr_pstrdup(TCLWEBPOOL, req->req->args);
+ ap_unescape_url(arg_copy);
+ apr_table_set( table, "QUERY_STRING_UNESCAPED",
+ ap_escape_shell_cmd( TCLWEBPOOL, arg_copy ) );
+ }
+
+#ifndef WIN32
+ pw = (struct passwd *) getpwuid(req->req->finfo.user);
+ if( pw ) {
+ //apr_table_set( table, "USER_NAME",
+ // apr_pstrdup( TCLWEBPOOL, pw->pw_name ) );
+ } else {
+ apr_table_set( table, "USER_NAME",
+ (char*) apr_psprintf( TCLWEBPOOL, "user#%lu",
+ (unsigned long)req->req->finfo.user ) );
+ }
+#endif
+
+ /* Here we create some variables with Rivet internal information. */
+
+ /* TODO: this information has to be fetched from the thread private data */
+ /*
+ apr_table_set( table, "RIVET_CACHE_FREE",
+ (char*)apr_psprintf( TCLWEBPOOL, "%d", *(rsc->cache_free) ) );
+ apr_table_set( table, "RIVET_CACHE_SIZE",
+ (char*)apr_psprintf( TCLWEBPOOL, "%d", *(rsc->cache_size) ) );
+ */
+
+ req->environment_set = 1;
+}
+
+int
+TclWeb_GetEnvVars(Tcl_Obj *envvar, TclWebRequest *req)
+{
+ int i;
+
+ apr_array_header_t *env_arr;
+ apr_table_entry_t *env;
+ Tcl_Obj *key;
+ Tcl_Obj *val;
+
+ TclWeb_InitEnvVars( req );
+
+ Tcl_IncrRefCount(envvar);
+ /* Transfer Apache internal CGI variables to TCL request namespace. */
+ env_arr = (apr_array_header_t *) apr_table_elts(req->req->subprocess_env);
+ env = (apr_table_entry_t *) env_arr->elts;
+ for (i = 0; i < env_arr->nelts; ++i)
+ {
+ if ((!env[i].key) || (!env[i].val)) {
+ continue;
+ }
+
+ key = TclWeb_StringToUtfToObj(env[i].key, req);
+ val = TclWeb_StringToUtfToObj(env[i].val, req);
+ Tcl_IncrRefCount(key);
+ Tcl_IncrRefCount(val);
+
+ /* Variable scope resolution changed to default (flags: 0)
+ * to enable creation of the array in the caller's local scope.
+ * Default behavior (creation in the ::request namespace)
+ * is now more consistently constrained by fully qualifying
+ * the default array names (see rivetCore.c). This should fix
+ * Bug 48963
+ */
+
+ Tcl_ObjSetVar2(req->interp, envvar, key, val, 0);
+
+ Tcl_DecrRefCount(key);
+ Tcl_DecrRefCount(val);
+ }
+ Tcl_DecrRefCount(envvar);
+
+ return TCL_OK;
+}
+
+int
+TclWeb_GetHeaderVars(Tcl_Obj *headersvar, TclWebRequest *req)
+{
+ int i;
+
+ apr_array_header_t *hdrs_arr;
+ apr_table_entry_t *hdrs;
+ Tcl_Obj *key;
+ Tcl_Obj *val;
+
+ TclWeb_InitEnvVars( req );
+
+ Tcl_IncrRefCount(headersvar);
+ /* Transfer client request headers to TCL request namespace. */
+ hdrs_arr = (apr_array_header_t*) apr_table_elts(req->req->headers_in);
+ hdrs = (apr_table_entry_t *) hdrs_arr->elts;
+ for (i = 0; i < hdrs_arr->nelts; ++i)
+ {
+ if (!hdrs[i].key)
+ continue;
+
+ key = TclWeb_StringToUtfToObj(hdrs[i].key, req);
+ val = TclWeb_StringToUtfToObj(hdrs[i].val, req);
+ Tcl_IncrRefCount(key);
+ Tcl_IncrRefCount(val);
+
+ /* See comment in TclWeb_GetEnvVars concerning Bug 48963*/
+
+ Tcl_ObjSetVar2(req->interp, headersvar, key, val, 0);
+ Tcl_DecrRefCount(key);
+ Tcl_DecrRefCount(val);
+ }
+
+ /* Transfer Apache internal CGI variables to TCL request namespace. */
+ Tcl_DecrRefCount(headersvar);
+ return TCL_OK;
+}
+
+INLINE int
+TclWeb_Base64Encode(char *out, char *in, TclWebRequest *req)
+{
+ out = ap_pbase64encode(TCLWEBPOOL, in);
+ return TCL_OK;
+}
+
+INLINE int
+TclWeb_Base64Decode(char *out, char *in, TclWebRequest *req)
+{
+ out = ap_pbase64decode(TCLWEBPOOL, in);
+ return TCL_OK;
+}
+
+INLINE int
+TclWeb_EscapeShellCommand(char *out, char *in, TclWebRequest *req)
+{
+ out = ap_escape_shell_cmd(TCLWEBPOOL, in);
+ return TCL_OK;
+}
+
+/* Functions to convert strings to UTF encoding */
+
+/* These API's are a bit different, because it's so much more
+ * practical. */
+
+char *TclWeb_StringToUtf(char *in, TclWebRequest *req)
+{
+ char *tmp;
+ Tcl_DString dstr;
+ Tcl_DStringInit(&dstr);
+ Tcl_ExternalToUtfDString(NULL, in, (signed)strlen(in), &dstr);
+ tmp = (char*) apr_pstrdup(TCLWEBPOOL, Tcl_DStringValue(&dstr));
+ Tcl_DStringFree(&dstr);
+ return tmp;
+}
+
+INLINE Tcl_Obj *
+TclWeb_StringToUtfToObj(char *in, TclWebRequest *req)
+{
+ return Tcl_NewStringObj(TclWeb_StringToUtf(in, req), -1);
+}
+
+int TclWeb_PrepareUpload(char *varname, TclWebRequest *req)
+{
+ req->upload = ApacheUpload_find(req->apachereq->upload, varname);
+ if (req->upload == NULL) {
+ return TCL_ERROR;
+ } else {
+ return TCL_OK;
+ }
+}
+
+int TclWeb_UploadChannel(char *varname, Tcl_Channel *chan, TclWebRequest *req)
+{
+ *chan = Tcl_OpenFileChannel (req->interp, req->upload->tempname, "r", 0);
+ if (chan == NULL) {
+ return TCL_ERROR;
+ } else {
+ if (Tcl_SetChannelOption(req->interp, *chan,
+ "-translation", "binary") == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(req->interp, *chan,
+ "-encoding", "binary") == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ Tcl_RegisterChannel (req->interp, *chan);
+ return TCL_OK;
+ }
+}
+
+int TclWeb_UploadTempname(Tcl_Obj *tempname, TclWebRequest *req)
+{
+ Tcl_SetStringObj(tempname,
+ TclWeb_StringToUtf(req->upload->tempname,
+ req), -1);
+ return TCL_OK;
+}
+
+
+int TclWeb_UploadSave(char *varname, Tcl_Obj *filename, TclWebRequest *req)
+{
+ apr_status_t status;
+ status = apr_file_copy(req->upload->tempname ,Tcl_GetString(filename),APR_FILE_SOURCE_PERMS,req->req->pool);
+ if ( status == 0 ) {
+ return TCL_OK;
+ } else {
+ return TCL_ERROR;
+ }
+}
+
+int TclWeb_UploadData(char *varname, Tcl_Obj *data, TclWebRequest *req)
+{
+ rivet_server_conf *rsc = NULL;
+
+ rsc = RIVET_SERVER_CONF( req->req->server->module_config );
+ /* This sucks - we should use the hook, but I want to
+ get everything fixed and working first */
+ if (rsc->upload_files_to_var)
+ {
+ Tcl_Channel chan;
+ chan = Tcl_OpenFileChannel (req->interp, req->upload->tempname, "r", 0);
+ if (chan == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(req->interp, chan,
+ "-translation", "binary") == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(req->interp, chan,
+ "-encoding", "binary") == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /* Put data in a variable */
+ Tcl_ReadChars(chan, data, ApacheUpload_size(req->upload), 0);
+ if (Tcl_Close(req->interp, chan) == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(req->interp,
+ "RivetServerConf UploadFilesToVar is not set", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+int TclWeb_UploadSize(Tcl_Obj *sz, TclWebRequest *req)
+{
+ Tcl_SetIntObj(sz, ApacheUpload_size(req->upload));
+ return TCL_OK;
+}
+
+int TclWeb_UploadType(Tcl_Obj *type, TclWebRequest *req)
+{
+ /* If there is a type, return it, if not, return blank. */
+ Tcl_SetStringObj(type, ApacheUpload_type(req->upload)
+ ? (char *)ApacheUpload_type(req->upload) : (char *)"", -1);
+ return TCL_OK;
+}
+
+int TclWeb_UploadFilename(Tcl_Obj *filename, TclWebRequest *req)
+{
+ Tcl_SetStringObj(filename,
+ TclWeb_StringToUtf(req->upload->filename,
+ req), -1);
+ return TCL_OK;
+}
+
+int TclWeb_UploadNames(Tcl_Obj *names, TclWebRequest *req)
+{
+ ApacheUpload *upload;
+
+ upload = ApacheRequest_upload(req->apachereq);
+ while (upload)
+ {
+ Tcl_ListObjAppendElement(
+ req->interp, names,
+ TclWeb_StringToUtfToObj(upload->name,req));
+ upload = upload->next;
+ }
+
+ return TCL_OK;
+}
+
+char *
+TclWeb_GetEnvVar( TclWebRequest *req, char *key )
+{
+ char *val;
+
+ TclWeb_InitEnvVars( req );
+
+ /* Check to see if it's a header variable first. */
+ val = (char *)apr_table_get( req->req->headers_in, key );
+
+ if( !val ) {
+ val = (char *)apr_table_get( req->req->subprocess_env, key );
+ }
+
+ return val;
+}
+
+char *
+TclWeb_GetVirtualFile( TclWebRequest *req, char *virtualname )
+{
+ request_rec *apreq;
+ char *filename = NULL;
+
+ apreq = ap_sub_req_lookup_uri( virtualname, req->req, NULL );
+
+ //if( apreq->status == 200 && apreq->finfo.st_mode != 0 ) {
+ //TODO: is this the right behaviour?
+ if( apreq->status == 200 && apreq->finfo.filetype != APR_NOFILE ) {
+ filename = apreq->filename;
+ }
+ if( apreq != NULL ) ap_destroy_sub_req( apreq );
+ return( filename );
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * TclWeb_GetRawPost --
+ *
+ * Fetch the raw POST data from the request.
+ *
+ * Results:
+ * The data, or NULL if it's not a POST or there is no data.
+ *
+ * Side Effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+char *
+TclWeb_GetRawPost ( TclWebRequest *req )
+{
+ return ApacheRequest_get_raw_post(req->apachereq);
+}
Added: tcl/rivet/trunk/src/experimental/apache_config.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/apache_config.c?rev=1617763&view=auto
==============================================================================
--- tcl/rivet/trunk/src/experimental/apache_config.c (added)
+++ tcl/rivet/trunk/src/experimental/apache_config.c Wed Aug 13 16:56:13 2014
@@ -0,0 +1,652 @@
+/* apache_config.c -- configuration functions for apache 2.x */
+
+/* Copyright 2000-2005 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/* $Id: apache_config.c 1609472 2014-07-10 15:08:52Z mxmanghi $ */
+
+/* Rivet config */
+#ifdef HAVE_CONFIG_H
+#include <rivet_config.h>
+#endif
+
+/* httpd includes */
+
+#include <httpd.h>
+#include <http_config.h>
+
+/* APR includes */
+
+#include <apr_pools.h>
+#include <apr_strings.h>
+#include <apr_tables.h>
+
+#include "mod_rivet.h"
+#include "apache_config.h"
+#include "rivet.h"
+
+/*
+ * -- Rivet_AssignStringtoConf --
+ *
+ * Assign a string to a Tcl_Obj valued configuration parameter
+ *
+ * Arguments:
+ *
+ * - objPnt: Pointer to a pointer to a Tcl_Obj. If the pointer *objPnt
+ * is NULL (configuration script obj pointers are initialized to NULL)
+ * a new Tcl_Obj is created
+ * - string_value: a string to be assigned to the Tcl_Obj
+ *
+ * Results:
+ *
+ * - Pointer to a Tcl_Obj containing the parameter value.
+ *
+ */
+
+static Tcl_Obj*
+Rivet_AssignStringToConf (Tcl_Obj** objPnt, const char* string_value)
+{
+ Tcl_Obj *objarg = NULL;
+
+ if (*objPnt == NULL)
+ {
+ objarg = Tcl_NewStringObj(string_value,-1);
+ Tcl_IncrRefCount(objarg);
+ *objPnt = objarg;
+ } else {
+ objarg = *objPnt;
+ Tcl_AppendToObj(objarg, string_value, -1);
+ }
+ Tcl_AppendToObj( objarg, "\n", 1 );
+ return objarg;
+}
+
+/*
+ * -- Rivet_SetScript --
+ *
+ * Add the text from an apache directive, such as UserConf, to
+ * the corresponding variable in the rivet_server_conf structure.
+ * In most cases, we append the new value to any previously
+ * existing value, but Before, After and Error scripts override
+ * the old directive completely.
+ *
+ * Results:
+ *
+ * Returns a Tcl_Obj* pointing to the string representation of
+ * the current value for the directive.
+ *
+ */
+
+
+static const char *
+Rivet_SetScript (apr_pool_t *pool, rivet_server_conf *rsc, const char *script, const char *string)
+{
+ Tcl_Obj *objarg = NULL;
+
+ if( STREQU( script, "GlobalInitScript" ) ) {
+ objarg = Rivet_AssignStringToConf(&(rsc->rivet_global_init_script),string);
+ } else if( STREQU( script, "ChildInitScript" ) ) {
+ objarg = Rivet_AssignStringToConf(&(rsc->rivet_child_init_script),string);
+ } else if( STREQU( script, "ChildExitScript" ) ) {
+ objarg = Rivet_AssignStringToConf(&(rsc->rivet_child_exit_script),string);
+ } else if( STREQU( script, "BeforeScript" ) ) {
+ objarg = Rivet_AssignStringToConf(&(rsc->rivet_before_script),string);
+ } else if( STREQU( script, "AfterScript" ) ) {
+ objarg = Rivet_AssignStringToConf(&(rsc->rivet_after_script),string);
+ } else if( STREQU( script, "ErrorScript" ) ) {
+ objarg = Rivet_AssignStringToConf(&(rsc->rivet_error_script),string);
+ } else if( STREQU( script, "ServerInitScript" ) ) {
+ objarg = Rivet_AssignStringToConf(&(rsc->rivet_server_init_script),string);
+ } else if( STREQU( script, "AbortScript" ) ) {
+ objarg = Rivet_AssignStringToConf(&(rsc->rivet_abort_script),string);
+ } else if( STREQU( script, "AfterEveryScript" ) ) {
+ objarg = Rivet_AssignStringToConf(&(rsc->after_every_script),string);
+ }
+
+ if( !objarg ) return string;
+
+ return Tcl_GetStringFromObj( objarg, NULL );
+}
+
+/*
+ * -- Rivet_GetConf
+ *
+ * Rivet_GetConf fetches the confguration from the server record
+ * and carries out a merge with server variables stored in directory
+ * specific configuration
+ *
+ * Arguments:
+ *
+ * - request_rec* r: pointer to the request data
+ *
+ * Results:
+ *
+ * - rivet_server_conf* rsc: the server merged configuration
+ *
+ * Side Effects:
+ *
+ * None.
+ *
+ */
+
+rivet_server_conf *
+Rivet_GetConf( request_rec *r )
+{
+ rivet_server_conf *rsc = RIVET_SERVER_CONF( r->server->module_config );
+ void *dconf = r->per_dir_config;
+ rivet_server_conf *newconfig = NULL;
+ rivet_server_conf *rdc;
+
+ FILEDEBUGINFO;
+
+ /* If there is no per dir config, just return the server config */
+ if (dconf == NULL) {
+ return rsc;
+ }
+ rdc = RIVET_SERVER_CONF( dconf );
+
+ newconfig = RIVET_NEW_CONF( r->pool );
+
+ Rivet_CopyConfig( rsc, newconfig );
+ Rivet_MergeDirConfigVars( r->pool, newconfig, rsc, rdc );
+
+ return newconfig;
+}
+
+/*
+ * -- Rivet_CopyConfig --
+ *
+ * Copy the rivet_server_conf struct.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * None.
+ *
+ */
+void
+Rivet_CopyConfig( rivet_server_conf *oldrsc, rivet_server_conf *newrsc )
+{
+ FILEDEBUGINFO;
+
+ //newrsc->server_interp = oldrsc->server_interp;
+ newrsc->rivet_global_init_script = oldrsc->rivet_global_init_script;
+ newrsc->rivet_before_script = oldrsc->rivet_before_script;
+ newrsc->rivet_after_script = oldrsc->rivet_after_script;
+ newrsc->rivet_error_script = oldrsc->rivet_error_script;
+ newrsc->rivet_abort_script = oldrsc->rivet_abort_script;
+ newrsc->after_every_script = oldrsc->after_every_script;
+
+ newrsc->user_scripts_updated = oldrsc->user_scripts_updated;
+
+ newrsc->rivet_default_error_script = oldrsc->rivet_default_error_script;
+
+ /* These are pointers so that they can be passed around... */
+ newrsc->default_cache_size = oldrsc->default_cache_size;
+ //newrsc->cache_size = oldrsc->cache_size;
+ //newrsc->cache_free = oldrsc->cache_free;
+ newrsc->upload_max = oldrsc->upload_max;
+ newrsc->upload_files_to_var = oldrsc->upload_files_to_var;
+ newrsc->separate_virtual_interps = oldrsc->separate_virtual_interps;
+ newrsc->honor_header_only_reqs = oldrsc->honor_header_only_reqs;
+ newrsc->server_name = oldrsc->server_name;
+ newrsc->upload_dir = oldrsc->upload_dir;
+ newrsc->rivet_server_vars = oldrsc->rivet_server_vars;
+ newrsc->rivet_dir_vars = oldrsc->rivet_dir_vars;
+ newrsc->rivet_user_vars = oldrsc->rivet_user_vars;
+ newrsc->idx = oldrsc->idx;
+ //newrsc->objCacheList = oldrsc->objCacheList;
+ //newrsc->objCache = oldrsc->objCache;
+ //newrsc->outchannel = oldrsc->outchannel;
+}
+
+/*
+ * -- Rivet_MergeDirConfigVars
+ *
+ * Merging of base configuration with per directory configuration
+ * is done checking each field in the configuration record. If
+ * a more specific (per directory) conf variable is defined then
+ * it supersedes the base record variable
+ *
+ * Arguments:
+ *
+ * - apr_pool_t* t: pointer to an APR memory pool
+ * - rivet_server_conf* new: pointer to a record to store the
+ * merged configuration
+ * - rivet_server_conf* base:
+ * - rivet_server_conf* add:
+ *
+ * Results:
+ *
+ * configuration record are merge in place
+ *
+ * Side Effects:
+ *
+ * None.
+ */
+
+void
+Rivet_MergeDirConfigVars(apr_pool_t *p, rivet_server_conf *new,
+ rivet_server_conf *base, rivet_server_conf *add )
+{
+ FILEDEBUGINFO;
+ new->rivet_child_init_script = add->rivet_child_init_script ?
+ add->rivet_child_init_script : base->rivet_child_init_script;
+ new->rivet_child_exit_script = add->rivet_child_exit_script ?
+ add->rivet_child_exit_script : base->rivet_child_exit_script;
+
+ new->rivet_before_script = add->rivet_before_script ?
+ add->rivet_before_script : base->rivet_before_script;
+ new->rivet_after_script = add->rivet_after_script ?
+ add->rivet_after_script : base->rivet_after_script;
+ new->rivet_error_script = add->rivet_error_script ?
+ add->rivet_error_script : base->rivet_error_script;
+ new->rivet_abort_script = add->rivet_abort_script ?
+ add->rivet_abort_script : base->rivet_abort_script;
+ new->after_every_script = add->after_every_script ?
+ add->after_every_script : base->after_every_script;
+
+ new->user_scripts_updated = add->user_scripts_updated ?
+ add->user_scripts_updated : base->user_scripts_updated;
+
+ new->upload_dir = add->upload_dir ?
+ add->upload_dir : base->upload_dir;
+
+ /* Merge the tables of dir and user variables. */
+ if (base->rivet_dir_vars && add->rivet_dir_vars) {
+ new->rivet_dir_vars =
+ apr_table_overlay ( p, base->rivet_dir_vars, add->rivet_dir_vars );
+ } else {
+ new->rivet_dir_vars = base->rivet_dir_vars;
+ }
+ if (base->rivet_user_vars && add->rivet_user_vars) {
+ new->rivet_user_vars =
+ apr_table_overlay ( p, base->rivet_user_vars, add->rivet_user_vars );
+ } else {
+ new->rivet_user_vars = base->rivet_user_vars;
+ }
+}
+
+/*
+ * -- Rivet_CreateDirConfig
+ *
+ * Apache HTTP server framework calls this function to
+ * have a pointer to newly initialized directory specific
+ * configuration record.
+ *
+ * Arguments:
+ *
+ * - apr_pool_t*: pointer to an APR memory pool
+ * - char*: string pointer to the directory name
+ *
+ * Returned value:
+ *
+ * - void* pointer to a brand new rivet configuration record
+ *
+ */
+
+
+void *
+Rivet_CreateDirConfig(apr_pool_t *p, char *dir)
+{
+ rivet_server_conf *rdc = RIVET_NEW_CONF(p);
+
+ FILEDEBUGINFO;
+
+ rdc->rivet_server_vars = (apr_table_t *) apr_table_make ( p, 4 );
+ rdc->rivet_dir_vars = (apr_table_t *) apr_table_make ( p, 4 );
+ rdc->rivet_user_vars = (apr_table_t *) apr_table_make ( p, 4 );
+
+ return rdc;
+}
+
+/*
+ * -- Rivet_MergeDirConfig
+ *
+ * Apache framework callback merging 2 per directory config records
+ *
+ * Arguments:
+ *
+ * - apr_pool_t* p: pointer to an APR memory pool
+ * - void* basev, addv: pointers to configuration records to be
+ * merged
+ *
+ * Results:
+ *
+ * - void*: pointer to the resulting configuration
+ */
+
+void *
+Rivet_MergeDirConfig( apr_pool_t *p, void *basev, void *addv )
+{
+ rivet_server_conf *base = (rivet_server_conf *)basev;
+ rivet_server_conf *add = (rivet_server_conf *)addv;
+ rivet_server_conf *new = RIVET_NEW_CONF(p);
+
+ FILEDEBUGINFO;
+
+ Rivet_MergeDirConfigVars( p, new, base, add );
+
+ return new;
+}
+
+/*
+ * -- Rivet_MergeConfig --
+ *
+ * This function is called when there is a config option set both
+ * at the 'global' level, and for a virtual host. It "resolves
+ * the conflicts" so to speak, by creating a new configuration,
+ * and this function is where we get to have our say about how to
+ * go about doing that. For most of the options, we override the
+ * global option with the local one.
+ *
+ * Results:
+ * Returns a new server configuration.
+ *
+ * Side Effects:
+ * None.
+ *
+ */
+
+void *
+Rivet_MergeConfig(apr_pool_t *p, void *basev, void *overridesv)
+{
+ rivet_server_conf *rsc = RIVET_NEW_CONF(p);
+ rivet_server_conf *base = (rivet_server_conf *) basev;
+ rivet_server_conf *overrides = (rivet_server_conf *) overridesv;
+
+ FILEDEBUGINFO;
+
+ /* For completeness' sake, we list the fate of all the members of
+ * the rivet_server_conf struct. */
+
+ /* server_interp isn't set at this point. */
+ /* rivet_global_init_script is global, not per server. */
+
+ rsc->rivet_child_init_script = overrides->rivet_child_init_script ?
+ overrides->rivet_child_init_script : base->rivet_child_init_script;
+
+ rsc->rivet_child_exit_script = overrides->rivet_child_exit_script ?
+ overrides->rivet_child_exit_script : base->rivet_child_exit_script;
+
+ rsc->rivet_before_script = overrides->rivet_before_script ?
+ overrides->rivet_before_script : base->rivet_before_script;
+
+ rsc->rivet_after_script = overrides->rivet_after_script ?
+ overrides->rivet_after_script : base->rivet_after_script;
+
+ rsc->rivet_error_script = overrides->rivet_error_script ?
+ overrides->rivet_error_script : base->rivet_error_script;
+
+ rsc->rivet_default_error_script = overrides->rivet_default_error_script ?
+ overrides->rivet_default_error_script : base->rivet_default_error_script;
+
+ rsc->rivet_abort_script = overrides->rivet_abort_script ?
+ overrides->rivet_abort_script : base->rivet_abort_script;
+
+ rsc->after_every_script = overrides->after_every_script ?
+ overrides->after_every_script : base->after_every_script;
+
+ /* cache_size is global, and set up later. */
+ /* cache_free is not set up at this point. */
+
+ rsc->upload_max = overrides->upload_max ?
+ overrides->upload_max : base->upload_max;
+
+ rsc->separate_virtual_interps = base->separate_virtual_interps;
+ rsc->honor_header_only_reqs = base->honor_header_only_reqs;
+
+ /* server_name is set up later. */
+
+ rsc->upload_dir = overrides->upload_dir ?
+ overrides->upload_dir : base->upload_dir;
+
+ rsc->rivet_server_vars = overrides->rivet_server_vars ?
+ overrides->rivet_server_vars : base->rivet_server_vars;
+
+ rsc->rivet_dir_vars = overrides->rivet_dir_vars ?
+ overrides->rivet_dir_vars : base->rivet_dir_vars;
+
+ rsc->rivet_user_vars = overrides->rivet_user_vars ?
+ overrides->rivet_user_vars : base->rivet_user_vars;
+
+ /* objCacheList is set up later. */
+ /* objCache is set up later. */
+ /* outchannel is set up later. */
+
+ return rsc;
+}
+
+/*
+ * -- Rivet_CreateConfig
+ *
+ *
+ *
+ */
+
+void *
+Rivet_CreateConfig(apr_pool_t *p, server_rec *s )
+{
+ rivet_server_conf *rsc = RIVET_NEW_CONF(p);
+
+ FILEDEBUGINFO;
+
+ //rsc->server_interp = NULL;
+
+/* scripts obj pointers *must* be initialized to NULL */
+
+ rsc->rivet_server_init_script = NULL;
+ rsc->rivet_global_init_script = NULL;
+ rsc->rivet_child_init_script = NULL;
+ rsc->rivet_child_exit_script = NULL;
+ rsc->rivet_before_script = NULL;
+ rsc->rivet_after_script = NULL;
+ rsc->rivet_error_script = NULL;
+ rsc->rivet_abort_script = NULL;
+ rsc->after_every_script = NULL;
+
+ rsc->user_scripts_updated = 0;
+
+ rsc->rivet_default_error_script = Tcl_NewStringObj("::Rivet::handle_error", -1);
+ Tcl_IncrRefCount(rsc->rivet_default_error_script);
+
+ /* these are pointers so that they can be passed around... */
+ //rsc->cache_size = apr_pcalloc(p, sizeof(int));
+ //rsc->cache_free = apr_pcalloc(p, sizeof(int));
+ //*(rsc->cache_size) = -1;
+ //*(rsc->cache_free) = 0;
+
+ rsc->default_cache_size = -1;
+ rsc->upload_max = RIVET_MAX_POST;
+ rsc->upload_files_to_var = RIVET_UPLOAD_FILES_TO_VAR;
+ rsc->separate_virtual_interps = RIVET_SEPARATE_VIRTUAL_INTERPS;
+ rsc->honor_header_only_reqs = RIVET_HEAD_REQUESTS;
+ rsc->upload_dir = RIVET_UPLOAD_DIR;
+ rsc->server_name = NULL;
+ //rsc->objCacheList = NULL;
+ //rsc->objCache = NULL;
+ //rsc->outchannel = NULL;
+
+ rsc->rivet_server_vars = (apr_table_t *) apr_table_make ( p, 4 );
+ rsc->rivet_dir_vars = (apr_table_t *) apr_table_make ( p, 4 );
+ rsc->rivet_user_vars = (apr_table_t *) apr_table_make ( p, 4 );
+
+ return rsc;
+}
+
+/*
+ * -- Rivet_UserConf
+ *
+ * Implements the RivetUserConf Apache Directive
+ *
+ * Command Arguments:
+ * RivetUserConf BeforeScript <script>
+ * RivetUserConf AfterScript <script>
+ * RivetUserConf ErrorScript <script>
+ */
+
+const char *
+Rivet_UserConf( cmd_parms *cmd,
+ void *vrdc,
+ const char *var,
+ const char *val )
+{
+ rivet_server_conf *rdc = (rivet_server_conf *)vrdc;
+
+ FILEDEBUGINFO;
+
+ if ( var == NULL || val == NULL ) {
+ return "Rivet Error: RivetUserConf requires two arguments";
+ }
+
+ /* We have modified these scripts. */
+ /* This is less than ideal though, because it will get set to 1
+ * every time - FIXME. */
+
+ rdc->user_scripts_updated = 1;
+
+ if (STREQU(var,"BeforeScript") ||
+ STREQU(var,"AfterScript") ||
+ STREQU(var,"AbortScript") ||
+ STREQU(var,"AfterEveryScript") ||
+ STREQU(var,"UploadDirectory") ||
+ STREQU(var,"ErrorScript"))
+ {
+ apr_table_set( rdc->rivet_user_vars, var,
+ Rivet_SetScript( cmd->pool, rdc, var, val));
+ }
+ else if (STREQU(var,"Debug") ||
+ STREQU(var,"DebugIp") ||
+ STREQU(var,"DebugSubst") ||
+ STREQU(var,"DebugSeparator"))
+ {
+ apr_table_set( rdc->rivet_user_vars, var, val);
+ }
+ else
+ {
+ return apr_pstrcat(cmd->pool, "Rivet configuration error: '",var,
+ "' not valid for RivetUserConf", NULL);
+ }
+
+ /* XXX Need to figure out what to do about setting the table. */
+ // if (string != NULL) apr_table_set( rdc->rivet_user_vars, var, string );
+ return NULL;
+}
+
+
+/*
+ * Implements the RivetDirConf Apache Directive
+ *
+ * Command Arguments:
+ * RivetDirConf BeforeScript <script>
+ * RivetDirConf AfterScript <script>
+ * RivetDirConf ErrorScript <script>
+ * RivetDirConf AfterEveryScript <script>
+ * RivetDirConf UploadDirectory <directory>
+ */
+
+const char *
+Rivet_DirConf( cmd_parms *cmd, void *vrdc,
+ const char *var, const char *val )
+{
+ const char *string = val;
+ rivet_server_conf *rdc = (rivet_server_conf *)vrdc;
+
+ FILEDEBUGINFO;
+
+ if ( var == NULL || val == NULL ) {
+ return "Rivet Error: RivetDirConf requires two arguments";
+ }
+
+ if( STREQU( var, "UploadDirectory" ) ) {
+ rdc->upload_dir = val;
+ } else {
+ if (STREQU(var,"BeforeScript") ||
+ STREQU(var,"AfterScript") ||
+ STREQU(var,"AbortScript") ||
+ STREQU(var,"AfterEveryScript") ||
+ STREQU(var,"ErrorScript"))
+ {
+ string = Rivet_SetScript( cmd->pool, rdc, var, val );
+ }
+ else
+ {
+ return apr_pstrcat(cmd->pool, "Rivet configuration error: '",var,
+ "' not valid for RivetDirConf", NULL);
+ }
+ }
+
+ if (string != NULL) apr_table_set( rdc->rivet_dir_vars, var, string );
+ return NULL;
+}
+
+/*
+ * Implements the RivetServerConf Apache Directive
+ *
+ * Command Arguments:
+ *
+ * RivetServerConf ServerInitScript <script>
+ * RivetServerConf GlobalInitScript <script>
+ * RivetServerConf ChildInitScript <script>
+ * RivetServerConf ChildExitScript <script>
+ * RivetServerConf BeforeScript <script>
+ * RivetServerConf AfterScript <script>
+ * RivetServerConf ErrorScript <script>
+ * RivetServerConf AfterEveryScript <script>
+ * RivetServerConf CacheSize <integer>
+ * RivetServerConf UploadDirectory <directory>
+ * RivetServerConf UploadMaxSize <integer>
+ * RivetServerConf UploadFilesToVar <yes|no>
+ * RivetServerConf SeparateVirtualInterps <yes|no>
+ * RivetServerConf HonorHeaderOnlyRequests <yes|no> (2008-06-20: mm)
+ */
+
+const char *
+Rivet_ServerConf( cmd_parms *cmd, void *dummy,
+ const char *var, const char *val )
+{
+ server_rec *s = cmd->server;
+ rivet_server_conf *rsc = RIVET_SERVER_CONF(s->module_config);
+ const char *string = val;
+
+ FILEDEBUGINFO;
+
+ if ( var == NULL || val == NULL ) {
+ return "Rivet Error: RivetServerConf requires two arguments";
+ }
+
+ if( STREQU( var, "CacheSize" ) ) {
+ rsc->default_cache_size = strtol( val, NULL, 10 );
+ } else if( STREQU( var, "UploadDirectory" ) ) {
+ rsc->upload_dir = val;
+ } else if( STREQU( var, "UploadMaxSize" ) ) {
+ rsc->upload_max = strtol( val, NULL, 10 );
+ } else if( STREQU( var, "UploadFilesToVar" ) ) {
+ Tcl_GetBoolean (NULL, val, &rsc->upload_files_to_var);
+ } else if( STREQU( var, "SeparateVirtualInterps" ) ) {
+ Tcl_GetBoolean (NULL, val, &rsc->separate_virtual_interps);
+ } else if( STREQU( var, "HonorHeaderOnlyRequests" ) ) {
+ Tcl_GetBoolean (NULL, val, &rsc->honor_header_only_reqs);
+ } else {
+ string = Rivet_SetScript( cmd->pool, rsc, var, val);
+ }
+
+ if (string != NULL) apr_table_set( rsc->rivet_server_vars, var, string );
+ return( NULL );
+}
+
+/* apache_config.c */
+
Added: tcl/rivet/trunk/src/experimental/apache_config.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/apache_config.h?rev=1617763&view=auto
==============================================================================
--- tcl/rivet/trunk/src/experimental/apache_config.h (added)
+++ tcl/rivet/trunk/src/experimental/apache_config.h Wed Aug 13 16:56:13 2014
@@ -0,0 +1,41 @@
+/* apache_config.h -- configuration functions for apache 2.x */
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+/* $Id: apache_config.h 1547463 2013-12-03 16:35:08Z mxmanghi $ */
+
+
+#ifndef __apache_config_h__
+#define __apache_config_h__
+
+#include "mod_rivet.h"
+
+void Rivet_CopyConfig( rivet_server_conf *oldrsc, rivet_server_conf *newrsc);
+const char* Rivet_ServerConf(cmd_parms *cmd, void *dummy, const char *var, const char *val);
+const char* Rivet_DirConf(cmd_parms *cmd, void *vrdc, const char *var, const char *val);
+const char* Rivet_UserConf(cmd_parms *cmd, void *vrdc, const char *var, const char *val);
+void* Rivet_CreateDirConfig(apr_pool_t *p, char *dir);
+void* Rivet_MergeDirConfig( apr_pool_t *p, void *basev, void *addv);
+void* Rivet_CreateConfig(apr_pool_t *p, server_rec *s);
+void* Rivet_MergeConfig(apr_pool_t *p, void *basev, void *overridesv);
+void Rivet_MergeDirConfigVars(apr_pool_t *p,rivet_server_conf *new,rivet_server_conf *base,rivet_server_conf *add);
+
+#endif
+
Modified: tcl/rivet/trunk/src/experimental/mod_rivet.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/mod_rivet.c?rev=1617763&r1=1617762&r2=1617763&view=diff
==============================================================================
--- tcl/rivet/trunk/src/experimental/mod_rivet.c (original)
+++ tcl/rivet/trunk/src/experimental/mod_rivet.c Wed Aug 13 16:56:13 2014
@@ -66,9 +66,206 @@ extern Tcl_ChannelType RivetChan;
apr_threadkey_t* rivet_thread_key;
apr_threadkey_t* handler_thread_key;
+void Rivet_PerInterpInit(Tcl_Interp* interp, server_rec *s, apr_pool_t *p);
+
#define ERRORBUF_SZ 256
-/* -----------------------------------------------------------------------------
+vhost_interp* Rivet_NewVHostInterp(apr_pool_t* pool)
+{
+ extern int ap_max_requests_per_child;
+ vhost_interp* interp_obj = apr_pcalloc(pool,sizeof(vhost_interp));
+ rivet_server_conf* rsc;
+
+ /* the cache size is global so we take it from here */
+
+ rsc = RIVET_SERVER_CONF( module_globals->server->module_config );
+
+ /* This calls needs the root server_rec just for logging purposes*/
+
+ interp_obj->interp = Rivet_CreateTclInterp(module_globals->server);
+
+ /* we now read from the pointers to the cache_size and cache_free conf parameters
+ for compatibility with mod_rivet current version, but these values must become
+ integers not pointers */
+
+ if (rsc->default_cache_size < 0) {
+ if (ap_max_requests_per_child != 0) {
+ interp_obj->cache_size = ap_max_requests_per_child / 5;
+ } else {
+ interp_obj->cache_size = 50; // Arbitrary number
+ }
+ } else if (rsc->default_cache_size > 0) {
+ interp_obj->cache_size = rsc->default_cache_size;
+ }
+
+ if (interp_obj->cache_size > 0) {
+ interp_obj->cache_free = interp_obj->cache_size;
+ }
+
+ // we now create memory from the cache pool as subpool of the thread private pool
+
+ if (apr_pool_create(&interp_obj->pool, pool) != APR_SUCCESS)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server,
+ MODNAME ": could not initialize thread private pool");
+ return NULL;
+ }
+
+ // Initialize cache structures
+
+ if (interp_obj->cache_size) {
+ interp_obj->objCacheList = apr_pcalloc(interp_obj->pool, (signed)(interp_obj->cache_size*sizeof(char *)));
+ interp_obj->objCache = apr_pcalloc(interp_obj->pool, sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(interp_obj->objCache, TCL_STRING_KEYS);
+ }
+
+ interp_obj->flags = 0;
+
+ return interp_obj;
+}
+
+rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private)
+{
+ server_rec* s;
+ server_rec* root_server = module_globals->server;
+ rivet_server_conf* root_server_conf;
+ rivet_server_conf* myrsc;
+ vhost_interp* root_interp;
+ void* parentfunction; /* this is topmost initialization script */
+ void* function;
+
+ root_server_conf = RIVET_SERVER_CONF( root_server->module_config );
+ parentfunction = root_server_conf->rivet_child_init_script;
+
+ root_interp = (*module_globals->mpm_master_interp)(private->pool);
+
+ if (root_interp == NULL)
+ {
+ return NULL;
+ }
+
+ for (s = root_server; s != NULL; s = s->next)
+ {
+ vhost_interp* rivet_interp;
+
+ myrsc = RIVET_SERVER_CONF(s->module_config);
+ rivet_interp = root_interp;
+
+ if (s == root_server)
+ {
+ Tcl_RegisterChannel(rivet_interp->interp,*private->channel);
+ }
+ else if (root_server_conf->separate_virtual_interps)
+ {
+ rivet_interp = Rivet_NewVHostInterp(private->pool);
+ Tcl_RegisterChannel(rivet_interp->interp,*private->channel);
+ }
+
+ private->interps[myrsc->idx] = rivet_interp;
+
+ /* Basic Rivet packages and libraries are loaded here. Also the interpreter globals
+ * are setup here. We have to explore if could be sensed to moved them to the
+ * thread private data.
+ */
+
+ if ((rivet_interp->flags & RIVET_INTERP_INITIALIZED) == 0)
+ {
+ Rivet_PerInterpInit(rivet_interp->interp, root_server, private->pool);
+ rivet_interp->flags |= RIVET_INTERP_INITIALIZED;
+ }
+
+ /* Check if it's absolutely necessary to lock the pool_mutex in order
+ to allocate from the module global pool
+
+ this stuff must be allocated from the module global pool which
+ ha the same child process lifespan
+ */
+
+ apr_thread_mutex_lock(module_globals->pool_mutex);
+ myrsc->server_name = (char*)apr_pstrdup(module_globals->pool, s->server_hostname);
+ apr_thread_mutex_unlock(module_globals->pool_mutex);
+
+ function = myrsc->rivet_child_init_script;
+ if (function &&
+ (s == root_server || root_server_conf->separate_virtual_interps || function != parentfunction))
+ {
+ char* errmsg = MODNAME ": Error in Child init script: %s";
+ Tcl_Interp* interp = rivet_interp->interp;
+
+ rivet_interp_globals* globals = Tcl_GetAssocData( interp, "rivet", NULL );
+ Tcl_Preserve (interp);
+
+ /* There a lot of passing around pointers to record object
+ * and we keep it just for compatibility with existing components
+ */
+
+ globals->srec = s;
+ if (Tcl_EvalObjEx(interp,function, 0) != TCL_OK) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
+ errmsg, Tcl_GetString(function));
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
+ "errorCode: %s",
+ Tcl_GetVar(interp, "errorCode", 0));
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
+ "errorInfo: %s",
+ Tcl_GetVar(interp, "errorInfo", 0));
+ }
+ Tcl_Release (interp);
+ }
+ }
+ return private;
+}
+
+
+/*----------------------------------------------------------------------------
+ * -- Rivet_ProcessorCleanup
+ *
+ *
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void Rivet_ProcessorCleanup (void *data)
+{
+ rivet_thread_private* private = (rivet_thread_private *) data;
+ Tcl_HashSearch* searchCtx;
+ Tcl_HashEntry* entry;
+ int i;
+ rivet_server_conf* rsc = RIVET_SERVER_CONF(module_globals->server->module_config);
+
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, module_globals->server,
+ "Thread exiting after %d requests served", private->req_cnt);
+
+ for (i = 0; i < module_globals->vhosts_count; i++)
+ {
+
+ /* cleaning the cache contents and deleting it */
+
+ searchCtx = apr_pcalloc(private->pool,sizeof(Tcl_HashSearch));
+ entry = Tcl_FirstHashEntry(private->interps[i]->objCache,searchCtx);
+ while (entry)
+ {
+ Tcl_DecrRefCount(Tcl_GetHashValue(entry)); /* Let Tcl clear the mem allocated */
+ Tcl_DeleteHashEntry(entry);
+
+ entry = Tcl_NextHashEntry(searchCtx);
+ }
+
+ Tcl_UnregisterChannel(private->interps[i]->interp,*private->channel);
+ Tcl_DeleteInterp(private->interps[i]->interp);
+
+ /* if we are running the same interpreter instance for each vhost
+ we can jump out of this loop after the first cycle */
+
+ if (!rsc->separate_virtual_interps) break;
+
+ }
+
+ apr_pool_destroy(private->pool);
+}
+
+
+/* ----------------------------------------------------------------------------
* -- Rivet_SendContent
*
* Set things up to execute a file, then execute
@@ -117,7 +314,7 @@ Rivet_SendContent(rivet_thread_private *
/* The current TclWebRequest record is assigned here to the thread private data
for the channel to read it when actual output will flushed */
- globals->req = private->req;
+ private->req = globals->req;
/* Setting this pointer in globals is crucial as by assigning it
* we signal to Rivet commands we are processing an HTTP request.
@@ -830,7 +1027,7 @@ void Rivet_PerInterpInit(Tcl_Interp* in
*/
static int
-Rivet_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *s)
+Rivet_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *server)
{
apr_status_t aprrv;
char errorbuf[ERRORBUF_SZ];
@@ -848,9 +1045,18 @@ Rivet_ServerInit (apr_pool_t *pPool, apr
module_globals = apr_palloc(pPool,sizeof(mod_rivet_globals));
+ /* Creating the module global pool */
+
+ if (apr_pool_create(&module_globals->pool, NULL) != APR_SUCCESS)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
+ MODNAME ": could not initialize mod_rivet private pool");
+ exit(1);
+ }
+
/* Let's load the Rivet-MPM bridge */
- /* TODO: This kludge to load off-path MPM model share libraries has to be removed because is a security hole */
+ /* TODO: This kludge to load off-path MPM bridges has to be removed because is a security hole */
if (apr_env_get (&mpm_model_path,"RIVET_MPM_BRIDGE",pTemp) != APR_SUCCESS)
{
@@ -863,7 +1069,7 @@ Rivet_ServerInit (apr_pool_t *pPool, apr
apr_status_t rv;
apr_dso_handle_sym_t func = NULL;
- ap_log_error(APLOG_MARK,APLOG_INFO,0,s,"MPM bridge loaded: %s",mpm_model_path);
+ ap_log_error(APLOG_MARK,APLOG_INFO,0,server,"MPM bridge loaded: %s",mpm_model_path);
rv = apr_dso_sym(&func,module_globals->dso_handle,"Rivet_MPM_ServerInit");
if (rv == APR_SUCCESS)
@@ -872,7 +1078,7 @@ Rivet_ServerInit (apr_pool_t *pPool, apr
}
else
{
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
MODNAME ": Error loading symbol Rivet_MPM_ServerInit: %s",
apr_dso_error(module_globals->dso_handle,errorbuf,ERRORBUF_SZ));
exit(1);
@@ -885,7 +1091,7 @@ Rivet_ServerInit (apr_pool_t *pPool, apr
}
else
{
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
MODNAME ": Error loading symbol Rivet_MPM_Init: %s",
apr_dso_error(module_globals->dso_handle,errorbuf,ERRORBUF_SZ));
exit(1);
@@ -898,7 +1104,7 @@ Rivet_ServerInit (apr_pool_t *pPool, apr
}
else
{
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
MODNAME ": Error loading symbol Rivet_MPM_Request: %s",
apr_dso_error(module_globals->dso_handle,errorbuf,ERRORBUF_SZ));
exit(1);
@@ -911,12 +1117,25 @@ Rivet_ServerInit (apr_pool_t *pPool, apr
}
else
{
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
MODNAME ": Error loading symbol Rivet_MPM_Finalize: %s",
apr_dso_error(module_globals->dso_handle,errorbuf,ERRORBUF_SZ));
exit(1);
}
+ rv = apr_dso_sym(&func,module_globals->dso_handle,"Rivet_MPM_MasterInterp");
+ if (rv == APR_SUCCESS)
+ {
+ module_globals->mpm_master_interp = (vhost_interp* (*)(apr_pool_t *)) func;
+ }
+ else
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
+ MODNAME ": Error loading symbol Rivet_MPM_MasterInterp: %s",
+ apr_dso_error(module_globals->dso_handle,errorbuf,ERRORBUF_SZ));
+ exit(1);
+ }
+
/* active threads count */
apr_atomic_init(pPool);
@@ -924,21 +1143,27 @@ Rivet_ServerInit (apr_pool_t *pPool, apr
apr_atomic_set32(module_globals->threads_count,0);
module_globals->rivet_panic_pool = pPool;
- module_globals->rivet_panic_server_rec = s;
+ module_globals->rivet_panic_server_rec = server;
module_globals->rivet_panic_request_rec = NULL;
module_globals->vhosts_count = 0;
module_globals->server_shutdown = 0;
module_globals->exiting = NULL;
- //module_globals->server = s;
- (*module_globals->mpm_server_init)(pPool,pLog,pTemp,s);
+ /* Another crucial point: we are storing here in the globals a reference to the
+ * root server_rec object from which threads are supposed to derive
+ * all the other chain of virtual hosts server records
+ */
+
+ module_globals->server = server;
+
+ (*module_globals->mpm_server_init)(pPool,pLog,pTemp,server);
}
else
{
/* If we don't find the mpm handler module we give up and exit */
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
MODNAME " Error loading MPM manager: %s",
apr_dso_error(module_globals->dso_handle,errorbuf,1024));
exit(1);
@@ -953,18 +1178,19 @@ static void Rivet_ChildInit (apr_pool_t
rivet_server_conf* root_server_conf;
server_rec* s;
- apr_thread_mutex_create(&module_globals->pool_mutex, APR_THREAD_MUTEX_UNNESTED, pChild);
+/* This code is run once per child process. In a threaded Tcl builds the forking
+ * of a child process most likely has not preserved the thread where the Tcl
+ * notifier runs. The Notifier should have been restarted by one the
+ * pthread_atfork callbacks (setup in Tcl >= 8.5.14 and Tcl >= 8.6.1). In
+ * case pthread_atfork is not supported we unconditionally call Tcl_InitNotifier
+ * hoping for the best (Bug #55153)
+ */
- /* Creating the module global pool */
+#if !defined(HAVE_PTHREAD_ATFORK)
+ Tcl_InitNotifier();
+#endif
- apr_thread_mutex_lock(module_globals->pool_mutex);
- if (apr_pool_create(&module_globals->pool, NULL) != APR_SUCCESS)
- {
- ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
- MODNAME ": could not initialize mod_rivet private pool");
- exit(1);
- }
- apr_thread_mutex_unlock(module_globals->pool_mutex);
+ apr_thread_mutex_create(&module_globals->pool_mutex, APR_THREAD_MUTEX_UNNESTED, pChild);
/* Once we have established a pool with the same lifetime of the child process we
* process all the configured server records assigning an integer as unique key
@@ -993,12 +1219,7 @@ static void Rivet_ChildInit (apr_pool_t
}
module_globals->vhosts_count = idx;
- /* Another crucial point: we are storing here in the globals a reference to the
- * root server_rec object from which threads are supposed to derive
- * all the other chain of virtual hosts server records
- */
-
- module_globals->server = server;
+ apr_threadkey_private_create (&rivet_thread_key, NULL, pChild);
/* Calling the brigde child process initialization */
Modified: tcl/rivet/trunk/src/experimental/mod_rivet.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/mod_rivet.h?rev=1617763&r1=1617762&r2=1617763&view=diff
==============================================================================
--- tcl/rivet/trunk/src/experimental/mod_rivet.h (original)
+++ tcl/rivet/trunk/src/experimental/mod_rivet.h Wed Aug 13 16:56:13 2014
@@ -82,7 +82,7 @@ module AP_MODULE_DECLARE_DATA rivet_modu
typedef struct _rivet_server_conf {
/* we must keep this for compatibility with the module in apache-2 and stuff in common */
- Tcl_Interp *server_interp; /* per server Tcl interpreter */
+ //Tcl_Interp *server_interp; /* per server Tcl interpreter */
Tcl_Obj *rivet_server_init_script; /* run before children are forked */
Tcl_Obj *rivet_global_init_script; /* run once when apache is started */
@@ -99,8 +99,9 @@ typedef struct _rivet_server_conf {
int user_scripts_updated;
Tcl_Obj* rivet_default_error_script; /* for errors */
- int* cache_size;
- int* cache_free;
+ int default_cache_size;
+ //int* cache_size;
+ //int* cache_free;
int upload_max;
int upload_files_to_var;
int separate_virtual_interps;
@@ -110,17 +111,17 @@ typedef struct _rivet_server_conf {
apr_table_t* rivet_server_vars;
apr_table_t* rivet_dir_vars;
apr_table_t* rivet_user_vars;
- char** objCacheList; /* Array of cached objects (for priority handling) */
- Tcl_HashTable* objCache; /* Objects cache - the key is the script name */
+ //char** objCacheList; /* Array of cached objects (for priority handling) */
+ //Tcl_HashTable* objCache; /* Objects cache - the key is the script name */
/* this one must go, we keep just to avoid to duplicate the config handling function just
to avoid to poke stuff into this field */
- Tcl_Channel* outchannel; /* stuff for buffering output */
+ //Tcl_Channel* outchannel; /* stuff for buffering output */
int idx; /* server record index (to be used for the interps db */
} rivet_server_conf;
-#define TCL_INTERPS 1
+#define TCL_INTERPS 4
typedef int rivet_thr_status;
enum
{
@@ -130,6 +131,21 @@ enum
done
};
+/* thread private interpreter error flags */
+
+#define RIVET_CACHE_FULL 1
+#define RIVET_INTERP_INITIALIZED 2
+
+typedef struct _vhost_interp {
+ Tcl_Interp* interp;
+ int cache_size;
+ int cache_free;
+ Tcl_HashTable* objCache; /* Objects cache - the key is the script name */
+ char** objCacheList; /* Array of cached objects (for priority handling) */
+ apr_pool_t* pool; /* interpreters cache private memory pool */
+ unsigned int flags;
+} vhost_interp;
+
/* we need also a place where to store module wide globals */
typedef struct _mod_rivet_globals {
@@ -137,6 +153,7 @@ typedef struct _mod_rivet_globals {
apr_thread_t* supervisor;
int server_shutdown;
int vhosts_count;
+ vhost_interp* server_interp; /* server init and prefork MPM master interpreter */
apr_thread_cond_t* job_cond;
apr_thread_mutex_t* job_mutex;
@@ -149,32 +166,19 @@ typedef struct _mod_rivet_globals {
apr_thread_t* workers[TCL_INTERPS]; /* thread pool ids */
server_rec* server; /* default host server_rec obj */
- Tcl_Channel* outchannel; /* this is the Rivet channel for prefork MPM */
+ //Tcl_Channel* outchannel; /* this is the Rivet channel for prefork MPM */
int (*mpm_child_init)(apr_pool_t* pPool,server_rec* s);
int (*mpm_request)(request_rec*);
int (*mpm_server_init)(apr_pool_t*,apr_pool_t*,apr_pool_t*,server_rec*);
apr_status_t (*mpm_finalize)(void*);
+ vhost_interp* (*mpm_master_interp)(apr_pool_t *);
request_rec* rivet_panic_request_rec;
apr_pool_t* rivet_panic_pool;
server_rec* rivet_panic_server_rec;
} mod_rivet_globals;
-/* thread private interpreter error flags */
-
-#define RIVET_CACHE_FULL 1
-
-typedef struct _vhost_interp {
- Tcl_Interp* interp;
- int cache_size;
- int cache_free;
- Tcl_HashTable* objCache; /* Objects cache - the key is the script name */
- char** objCacheList; /* Array of cached objects (for priority handling) */
- apr_pool_t* pool; /* interpreters cache private memory pool */
- unsigned int flags;
-} vhost_interp;
-
typedef struct _thread_worker_private {
vhost_interp** interps; /* database of virtual host interps */
Added: tcl/rivet/trunk/src/experimental/mod_rivet_common.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/mod_rivet_common.c?rev=1617763&view=auto
==============================================================================
--- tcl/rivet/trunk/src/experimental/mod_rivet_common.c (added)
+++ tcl/rivet/trunk/src/experimental/mod_rivet_common.c Wed Aug 13 16:56:13 2014
@@ -0,0 +1,295 @@
+/*
+ mod_rivet_common.c - functions likely to be shared among
+ different versions of mod_rivet.c
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* $Id: mod_rivet.c 1609472 2014-07-10 15:08:52Z mxmanghi $ */
+
+#include <httpd.h>
+#include <apr_strings.h>
+#include <ap_mpm.h>
+/* as long as we need to emulate ap_chdir_file we need to include unistd.h */
+#include <unistd.h>
+
+#include "mod_rivet.h"
+#include "mod_rivet_common.h"
+#include "TclWeb.h"
+#include "rivetParser.h"
+#include "rivet.h"
+#include "apache_config.h"
+
+extern mod_rivet_globals* module_globals;
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Rivet_PanicProc --
+ *
+ * Called when Tcl panics, usually because of memory problems.
+ * We log the request, in order to be able to determine what went
+ * wrong later.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Calls abort(), which does not return - the child exits.
+ *
+ *-----------------------------------------------------------------------------
+ */
+void Rivet_Panic TCL_VARARGS_DEF(CONST char *, arg1)
+{
+ va_list argList;
+ char *buf;
+ char *format;
+
+ format = (char *) TCL_VARARGS_START(char *,arg1,argList);
+ buf = (char *) apr_pvsprintf(module_globals->rivet_panic_pool, format, argList);
+
+ if (module_globals->rivet_panic_request_rec != NULL) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, APR_EGENERAL,
+ module_globals->rivet_panic_server_rec,
+ MODNAME ": Critical error in request: %s",
+ module_globals->rivet_panic_request_rec->unparsed_uri);
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_CRIT, APR_EGENERAL,
+ module_globals->rivet_panic_server_rec, "%s", buf);
+
+ abort();
+}
+
+/*
+ * -- Rivet_CleanupRequest
+ *
+ * This function contained some come that cleaned up
+ * the user configuration before finishing a request
+ * processing. That code had been disabled and it's now
+ * removed, but we leave the function as a placeholder
+ * in case we want to stick into it something to do.
+ *
+ * Arguments:
+ *
+ * request_rec* request object pointer
+ *
+ * Returned value:
+ *
+ * None
+ */
+
+void Rivet_CleanupRequest( request_rec *r )
+{
+}
+
+/*
+ * -- Rivet_InitServerVariables
+ *
+ * Setup an array in each interpreter to tell us things about Apache.
+ * This saves us from having to do any real call to load an entire
+ * environment. This routine only gets called once, when the child process
+ * is created.
+ *
+ * Arguments:
+ *
+ * Tcl_Interp* interp: pointer to the Tcl interpreter
+ * apr_pool_t* pool: pool used for calling Apache framework functions
+ *
+ * Returned value:
+ * none
+ *
+ * Side effects:
+ *
+ * within the global scope of the interpreter passed as first
+ * argument a 'server' array is created and the variable associated
+ * to the following keys are defined
+ *
+ * SERVER_ROOT - Apache's root location
+ * SERVER_CONF - Apache's configuration file
+ * RIVET_DIR - Rivet's Tcl source directory
+ * RIVET_INIT - Rivet's init.tcl file
+ * RIVET_VERSION - Rivet version (only when RIVET_DISPLAY_VERSION is 1)
+ * MPM_THREADED - It should contain the string 'unsupported' for a prefork MPM
+ * MPM_FORKED - String describing the forking model of the MPM
+ *
+ */
+
+void Rivet_InitServerVariables( Tcl_Interp *interp, apr_pool_t *pool )
+{
+ int ap_mpm_result;
+ Tcl_Obj *obj;
+
+ obj = Tcl_NewStringObj(ap_server_root, -1);
+ Tcl_IncrRefCount(obj);
+ Tcl_SetVar2Ex(interp,
+ "server",
+ "SERVER_ROOT",
+ obj,
+ TCL_GLOBAL_ONLY);
+ Tcl_DecrRefCount(obj);
+
+ obj = Tcl_NewStringObj(ap_server_root_relative(pool,SERVER_CONFIG_FILE), -1);
+ Tcl_IncrRefCount(obj);
+ Tcl_SetVar2Ex(interp,
+ "server",
+ "SERVER_CONF",
+ obj,
+ TCL_GLOBAL_ONLY);
+ Tcl_DecrRefCount(obj);
+
+ obj = Tcl_NewStringObj(ap_server_root_relative(pool, RIVET_DIR), -1);
+ Tcl_IncrRefCount(obj);
+ Tcl_SetVar2Ex(interp,
+ "server",
+ "RIVET_DIR",
+ obj,
+ TCL_GLOBAL_ONLY);
+ Tcl_DecrRefCount(obj);
+
+ obj = Tcl_NewStringObj(ap_server_root_relative(pool, RIVET_INIT), -1);
+ Tcl_IncrRefCount(obj);
+ Tcl_SetVar2Ex(interp,
+ "server",
+ "RIVET_INIT",
+ obj,
+ TCL_GLOBAL_ONLY);
+ Tcl_DecrRefCount(obj);
+
+#if RIVET_DISPLAY_VERSION
+ obj = Tcl_NewStringObj(RIVET_VERSION, -1);
+ Tcl_IncrRefCount(obj);
+ Tcl_SetVar2Ex(interp,
+ "server",
+ "RIVET_VERSION",
+ obj,
+ TCL_GLOBAL_ONLY);
+ Tcl_DecrRefCount(obj);
+#endif
+
+ if (ap_mpm_query(AP_MPMQ_IS_THREADED,&ap_mpm_result) == APR_SUCCESS)
+ {
+ switch (ap_mpm_result)
+ {
+ case AP_MPMQ_STATIC:
+ obj = Tcl_NewStringObj("static", -1);
+ break;
+ case AP_MPMQ_NOT_SUPPORTED:
+ obj = Tcl_NewStringObj("unsupported", -1);
+ break;
+ default:
+ obj = Tcl_NewStringObj("undefined", -1);
+ break;
+ }
+ Tcl_IncrRefCount(obj);
+ Tcl_SetVar2Ex(interp,"server","MPM_THREADED",obj,TCL_GLOBAL_ONLY);
+ Tcl_DecrRefCount(obj);
+ }
+
+ if (ap_mpm_query(AP_MPMQ_IS_FORKED,&ap_mpm_result) == APR_SUCCESS)
+ {
+ switch (ap_mpm_result)
+ {
+ case AP_MPMQ_STATIC:
+ obj = Tcl_NewStringObj("static", -1);
+ break;
+ case AP_MPMQ_DYNAMIC:
+ obj = Tcl_NewStringObj("dynamic", -1);
+ break;
+ default:
+ obj = Tcl_NewStringObj("undefined", -1);
+ break;
+ }
+ Tcl_IncrRefCount(obj);
+ Tcl_SetVar2Ex(interp,"server","MPM_FORKED",obj,TCL_GLOBAL_ONLY);
+ Tcl_DecrRefCount(obj);
+ }
+}
+
+/*
+ * -- Rivet_chdir_file (const char* filename)
+ *
+ * Determines the directory name from the filename argument
+ * and sets it as current working directory
+ *
+ * Argument:
+ *
+ * const char* filename: file name to be used for determining
+ * the current directory (URI style path)
+ * the directory name is everything comes
+ * before the last '/' (slash) character
+ *
+ * This snippet of code came from the mod_ruby project, which is under a BSD license.
+ */
+
+int Rivet_chdir_file (const char *file)
+{
+ const char *x;
+ int chdir_retval = 0;
+ char chdir_buf[HUGE_STRING_LEN];
+
+ x = strrchr(file, '/');
+ if (x == NULL) {
+ chdir_retval = chdir(file);
+ } else if (x - file < sizeof(chdir_buf) - 1) {
+ memcpy(chdir_buf, file, x - file);
+ chdir_buf[x - file] = '\0';
+ chdir_retval = chdir(chdir_buf);
+ }
+
+ return chdir_retval;
+}
+/*
+ * -- Rivet_CheckType (request_rec *r)
+ *
+ * Utility function internally used to determine which type
+ * of file (whether rvt template or plain Tcl script) we are
+ * dealing with. In order to speed up multiple tests the
+ * the test returns an integer (RIVET_TEMPLATE) for rvt templates
+ * or RIVET_TCLFILE for Tcl scripts
+ *
+ * Argument:
+ *
+ * request_rec*: pointer to the current request record
+ *
+ * Returns:
+ *
+ * integer number meaning the type of file we are dealing with
+ *
+ * Side effects:
+ *
+ * none.
+ *
+ */
+
+int
+Rivet_CheckType (request_rec *req)
+{
+ int ctype = CTYPE_NOT_HANDLED;
+
+ if ( req->content_type != NULL ) {
+ if( STRNEQU( req->content_type, RIVET_TEMPLATE_CTYPE) ) {
+ ctype = RIVET_TEMPLATE;
+ } else if( STRNEQU( req->content_type, RIVET_TCLFILE_CTYPE) ) {
+ ctype = RIVET_TCLFILE;
+ }
+ }
+ return ctype;
+}
+
+
Added: tcl/rivet/trunk/src/experimental/mod_rivet_common.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/mod_rivet_common.h?rev=1617763&view=auto
==============================================================================
--- tcl/rivet/trunk/src/experimental/mod_rivet_common.h (added)
+++ tcl/rivet/trunk/src/experimental/mod_rivet_common.h Wed Aug 13 16:56:13 2014
@@ -0,0 +1,30 @@
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+#ifndef _MOD_RIVET_COMMON_
+#define _MOD_RIVET_COMMON_
+
+EXTERN int Rivet_chdir_file (const char *file);
+EXTERN int Rivet_CheckType (request_rec* r);
+EXTERN void Rivet_CleanupRequest(request_rec *r);
+EXTERN void Rivet_InitServerVariables(Tcl_Interp *interp, apr_pool_t *pool);
+EXTERN void Rivet_Panic TCL_VARARGS_DEF(CONST char *, arg1);
+
+#endif
---------------------------------------------------------------------
To unsubscribe, e-mail: site-cvs-unsubscribe@tcl.apache.org
For additional commands, e-mail: site-cvs-help@tcl.apache.org