home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 April / PCO0499.ISO / filesbbs / os2 / apach134.arj / APACH134.ZIP / src / modules / standard / mod_so.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-01  |  12.5 KB  |  360 lines

  1. /* ====================================================================
  2.  * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer. 
  10.  *
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in
  13.  *    the documentation and/or other materials provided with the
  14.  *    distribution.
  15.  *
  16.  * 3. All advertising materials mentioning features or use of this
  17.  *    software must display the following acknowledgment:
  18.  *    "This product includes software developed by the Apache Group
  19.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  20.  *
  21.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  22.  *    endorse or promote products derived from this software without
  23.  *    prior written permission. For written permission, please contact
  24.  *    apache@apache.org.
  25.  *
  26.  * 5. Products derived from this software may not be called "Apache"
  27.  *    nor may "Apache" appear in their names without prior written
  28.  *    permission of the Apache Group.
  29.  *
  30.  * 6. Redistributions of any form whatsoever must retain the following
  31.  *    acknowledgment:
  32.  *    "This product includes software developed by the Apache Group
  33.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  36.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  38.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  46.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Group and was originally based
  51.  * on public domain software written at the National Center for
  52.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  53.  * For more information on the Apache Group and the Apache HTTP server
  54.  * project, please see <http://www.apache.org/>.
  55.  *
  56.  */
  57.  
  58. /* 
  59.  * This module is used to load Apache modules at runtime. This means that the
  60.  * server functionality can be extended without recompiling and even without
  61.  * taking the server down at all. Only a HUP or USR1 signal needs to be send
  62.  * to the server to reload the dynamically loaded modules.
  63.  *
  64.  * To use, you'll first need to build your module as a shared library, then
  65.  * update your configuration (httpd.conf) to get the Apache core to load the
  66.  * module at start-up.
  67.  *
  68.  * The easiest way to build a module as a shared library is to use the
  69.  * `SharedModule' command in the Configuration file, instead of `AddModule'.
  70.  * You should also change the file extension from `.o' to `.so'. So, for
  71.  * example, to build the status module as a shared library edit Configuration
  72.  * and change
  73.  *   AddModule    modules/standard/mod_status.o
  74.  * to
  75.  *   SharedModule modules/standard/mod_status.so
  76.  *
  77.  * Run Configure and make. Now Apache's httpd binary will _not_ include
  78.  * mod_status. Instead a shared object called mod_status.so will be build, in
  79.  * the modules/standard directory. You can build most of the modules as shared
  80.  * libraries like this.
  81.  *
  82.  * To use the shared module, move the .so file(s) into an appropriate
  83.  * directory. You might like to create a directory called "modules" under you
  84.  * server root for this (e.g. /usr/local/httpd/modules). 
  85.  *
  86.  * Then edit your conf/httpd.conf file, and add LoadModule lines. For
  87.  * example
  88.  *   LoadModule  status_module   modules/mod_status.so
  89.  *
  90.  * The first argument is the module's structure name (look at the end of the
  91.  * module source to find this). The second option is the path to the module
  92.  * file, relative to the server root.  Put these directives right at the top
  93.  * of your httpd.conf file.
  94.  *
  95.  * Now you can start Apache. A message will be logged at "debug" level to your
  96.  * error_log to confirm that the module(s) are loaded (use "LogLevel debug"
  97.  * directive to get these log messages).
  98.  *
  99.  * If you edit the LoadModule directives while the server is live you can get
  100.  * Apache to re-load the modules by sending it a HUP or USR1 signal as normal.
  101.  * You can use this to dynamically change the capability of your server
  102.  * without bringing it down.
  103.  *
  104.  * Because currently there is only limited built-in support in the Configure
  105.  * script for creating the shared library files (`.so'), please consult your
  106.  * vendors cc(1), ld(1) and dlopen(3) manpages to find out the appropriate
  107.  * compiler and linker flags and insert them manually into the Configuration
  108.  * file under CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT.
  109.  *
  110.  * If you still have problems figuring out the flags both try the paper
  111.  *     http://developer.netscape.com/library/documentation/enterprise
  112.  *                                          /unix/svrplug.htm#1013807
  113.  * or install a Perl 5 interpreter on your platform and then run the command
  114.  *
  115.  *     $ perl -V:usedl -V:ccdlflags -V:cccdlflags -V:lddlflags
  116.  *
  117.  * This gives you what type of dynamic loading Perl 5 uses on your platform
  118.  * and which compiler and linker flags Perl 5 uses to create the shared object
  119.  * files.
  120.  *
  121.  * Another location where you can find useful hints is the `ltconfig' script
  122.  * of the GNU libtool 1.2 package. Search for your platform name inside the
  123.  * various "case" constructs.
  124.  *
  125.  */
  126.  
  127.  
  128. #define CORE_PRIVATE
  129. #include "httpd.h"
  130. #include "http_config.h"
  131. #include "http_log.h"
  132.  
  133. module MODULE_VAR_EXPORT so_module;
  134.  
  135.  
  136. /*
  137.  * Server configuration to keep track of actually
  138.  * loaded modules and the corresponding module name.
  139.  */
  140.  
  141. typedef struct moduleinfo {
  142.     char *name;
  143.     module *modp;
  144. } moduleinfo;
  145.  
  146. typedef struct so_server_conf {
  147.     array_header *loaded_modules;
  148. } so_server_conf;
  149.  
  150. static void *so_sconf_create(pool *p, server_rec *s)
  151. {
  152.     so_server_conf *soc;
  153.  
  154.     soc = (so_server_conf *)ap_pcalloc(p, sizeof(so_server_conf));
  155.     soc->loaded_modules = ap_make_array(p, DYNAMIC_MODULE_LIMIT, 
  156.                                      sizeof(moduleinfo));
  157. #ifndef NO_DLOPEN
  158.     ap_os_dso_init();
  159. #endif
  160.  
  161.     return (void *)soc;
  162. }
  163.  
  164. #ifndef NO_DLOPEN
  165.  
  166. /*
  167.  * This is the cleanup for a loaded shared object. It unloads the module.
  168.  * This is called as a cleanup function from the core.
  169.  */
  170.  
  171. static void unload_module(moduleinfo *modi)
  172. {
  173.     /* only unload if module information is still existing */
  174.     if (modi->modp == NULL)
  175.         return;
  176.  
  177.     /* remove the module pointer from the core structure */
  178.     ap_remove_loaded_module(modi->modp);
  179.  
  180.     /* unload the module space itself */
  181.     ap_os_dso_unload((ap_os_dso_handle_t)modi->modp->dynamic_load_handle);
  182.  
  183.     /* destroy the module information */
  184.     modi->modp = NULL;
  185.     modi->name = NULL;
  186. }
  187.  
  188. /* 
  189.  * This is the cleanup routine for files loaded by
  190.  * load_file(). Unfortunately we don't keep a record of the filename
  191.  * that was loaded, so we can't report the unload for debug purposes
  192.  * or include the filename in error message.
  193.  */
  194.  
  195. static void unload_file(void *handle)
  196. {
  197.     ap_os_dso_unload((ap_os_dso_handle_t)handle);
  198. }
  199.  
  200. /* 
  201.  * This is called for the directive LoadModule and actually loads
  202.  * a shared object file into the address space of the server process.
  203.  */
  204.  
  205. static const char *load_module(cmd_parms *cmd, void *dummy, 
  206.                                char *modname, char *filename)
  207. {
  208.     ap_os_dso_handle_t modhandle;
  209.     module *modp;
  210.     const char *szModuleFile=ap_server_root_relative(cmd->pool, filename);
  211.     so_server_conf *sconf;
  212.     moduleinfo *modi;
  213.     moduleinfo *modie;
  214.     int i;
  215.  
  216.     /* 
  217.      * check for already existing module
  218.      * If it already exists, we have nothing to do 
  219.      */
  220.     sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config, 
  221.                                             &so_module);
  222.     modie = (moduleinfo *)sconf->loaded_modules->elts;
  223.     for (i = 0; i < sconf->loaded_modules->nelts; i++) {
  224.         modi = &modie[i];
  225.         if (modi->name != NULL && strcmp(modi->name, modname) == 0)
  226.             return NULL;
  227.     }
  228.     modi = ap_push_array(sconf->loaded_modules);
  229.     modi->name = modname;
  230.  
  231.     /*
  232.      * Load the file into the Apache address space
  233.      */
  234.     if (!(modhandle = ap_os_dso_load(szModuleFile))) {
  235.     const char *my_error = ap_os_dso_error();
  236.     return ap_pstrcat (cmd->pool, "Cannot load ", szModuleFile,
  237.             " into server: ", 
  238.             my_error ? my_error : "(reason unknown)",
  239.             NULL);
  240.     }
  241.     ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL,
  242.         "loaded module %s", modname);
  243.  
  244.     /*
  245.      * Retrieve the pointer to the module structure through the module name:
  246.      * First with the hidden variant (prefix `AP_') and then with the plain
  247.      * symbol name.
  248.      */
  249.     if (!(modp = (module *)(ap_os_dso_sym(modhandle, modname)))) {
  250.     return ap_pstrcat(cmd->pool, "Can't locate API module structure `", modname,
  251.                "' in file ", szModuleFile, ": ", ap_os_dso_error(), NULL);
  252.     }
  253.     modi->modp = modp;
  254.     modp->dynamic_load_handle = modhandle;
  255.  
  256.     /* 
  257.      * Make sure the found module structure is really a module structure
  258.      * 
  259.      */
  260.     if (modp->magic != MODULE_MAGIC_COOKIE) {
  261.         return ap_pstrcat(cmd->pool, "API module structure `", modname,
  262.                           "' in file ", szModuleFile, " is garbled -"
  263.                           " perhaps this is not an Apache module DSO?", NULL);
  264.     }
  265.  
  266.     /* 
  267.      * Add this module to the Apache core structures
  268.      */
  269.     ap_add_loaded_module(modp);
  270.  
  271.     /* 
  272.      * Register a cleanup in the config pool (normally pconf). When
  273.      * we do a restart (or shutdown) this cleanup will cause the
  274.      * shared object to be unloaded.
  275.      */
  276.     ap_register_cleanup(cmd->pool, modi, 
  277.              (void (*)(void*))unload_module, ap_null_cleanup);
  278.  
  279.     /* 
  280.      * Finally we need to run the configuration process for the module
  281.      */
  282.     ap_single_module_configure(cmd->pool, cmd->server, modp);
  283.  
  284.     return NULL;
  285. }
  286.  
  287. /* 
  288.  * This implements the LoadFile directive and loads an arbitrary
  289.  * shared object file into the adress space of the server process.
  290.  */
  291.  
  292. static const char *load_file(cmd_parms *cmd, void *dummy, char *filename)
  293. {
  294.     void *handle;
  295.     char *file;
  296.  
  297.     file = ap_server_root_relative(cmd->pool, filename);
  298.     
  299.     if (!(handle = ap_os_dso_load(file))) {
  300.     const char *my_error = ap_os_dso_error();
  301.     return ap_pstrcat (cmd->pool, "Cannot load ", filename, 
  302.             " into server:", 
  303.             my_error ? my_error : "(reason unknown)",
  304.             NULL);
  305.     }
  306.     
  307.     ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, NULL,
  308.         "loaded file %s", filename);
  309.  
  310.     ap_register_cleanup(cmd->pool, handle, unload_file, ap_null_cleanup);
  311.  
  312.     return NULL;
  313. }
  314.  
  315. #else /* not NO_DLOPEN */
  316.  
  317. static const char *load_file(cmd_parms *cmd, void *dummy, char *filename)
  318. {
  319.     fprintf(stderr, "WARNING: LoadFile not supported on this platform\n");
  320.     return NULL;
  321. }
  322.  
  323. static const char *load_module(cmd_parms *cmd, void *dummy, 
  324.                            char *modname, char *filename)
  325. {
  326.     fprintf(stderr, "WARNING: LoadModule not supported on this platform\n");
  327.     return NULL;
  328. }
  329.  
  330. #endif /* NO_DLOPEN */
  331.  
  332. static const command_rec so_cmds[] = {
  333.     { "LoadModule", load_module, NULL, RSRC_CONF, TAKE2,
  334.       "a module name and the name of a shared object file to load it from"},
  335.     { "LoadFile", load_file, NULL, RSRC_CONF, ITERATE,
  336.       "shared object file or library to load into the server at runtime"},
  337.     { NULL }
  338. };
  339.  
  340. module MODULE_VAR_EXPORT so_module = {
  341.    STANDARD_MODULE_STUFF,
  342.    NULL,            /* initializer */
  343.    NULL,            /* create per-dir config */
  344.    NULL,            /* merge per-dir config */
  345.    so_sconf_create,        /* server config */
  346.    NULL,            /* merge server config */
  347.    so_cmds,            /* command table */
  348.    NULL,            /* handlers */
  349.    NULL,            /* filename translation */
  350.    NULL,            /* check_user_id */
  351.    NULL,            /* check auth */
  352.    NULL,            /* check access */
  353.    NULL,            /* type_checker */
  354.    NULL,            /* logger */
  355.    NULL,            /* header parser */
  356.    NULL,            /* child_init */
  357.    NULL,            /* child_exit */
  358.    NULL                /* post read-request */
  359. };
  360.