/* mod_sample.c - sample Apache module ** ** This is a sample Apache module. It demonstrates how to write a module. ** It also displays various info from the Apache module API. ** ** To install the module: ** ** 1) Get the *source* distribution of Apache, not a binary distribution, ** from "http://www.apache.org/dist/". Unpack it. ** ** 2) Copy mod_sample.c into the Apache src directory. ** ** 3) Follow the instructions in the Apache src/INSTALL file: ** 3a) Edit Configuration, setting your system customizations as the ** comments direct, and adding this to the list of modules: ** Module sample_module mod_sample.o ** 3b) Configure ** 3c) make ** ** 4) Continue with the instructions in the Apache README file: ** 4a) Copy the Apache conf/*.dist files to conf/*.conf. ** 4b) Edit conf/*.conf, setting your local system configuration. ** 4c) Add this to conf/srm.conf: ** ** SetHandler sample-handler ** ** 4d) If you like, add a SampleConfig command too: ** SampleConfig value Hello ** 4e) Start apache. You should be able to run the module via ** a "/sample" URL. ** ** The Apache home page is http://www.apache.org/ ** The Apache module API is documented at http://www.apache.org/docs/API.html ** The Apache Module Registry: http://www.zyzzyva.com/server/module_registry/ ** ** ** Copyright (C) 1996 by Jef Poskanzer . ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions ** are met: ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. */ /* Apache includes. */ #include "httpd.h" #include "http_config.h" #include "http_request.h" #include "http_core.h" #include "http_protocol.h" #include "http_main.h" #include "http_log.h" #include "util_script.h" /* Config struct. Add custom settings here. */ typedef struct { char* value; } sample_conf; /* Forward declaration for module object. */ module sample_module; /* Make a config record. */ static void* make_sample_conf( pool *p, server_rec *s ) { sample_conf* c = (sample_conf*) pcalloc( p, sizeof(sample_conf) ); /* Initialize default values for config struct here. */ c->value = "default"; return (void*) c; } /* Initialization routine. Runs as root. */ static void sample_init_root( server_rec* s, pool* p ) { sample_conf* c = get_module_config( s->module_config, &sample_module ); /* Put root initialization stuff here. Think real carefully before ** using this - anything that doesn't absolutely have to be run as root ** should go into sample_init_nonroot() below. */ } /* Initialization routine. Does not run as root. */ static void sample_init_nonroot( server_rec* s, pool* p ) { sample_conf* c = get_module_config( s->module_config, &sample_module ); /* Put non-root initialization stuff here. */ } /* SampleConfig command. */ static char* sample_config( cmd_parms* parms, void* dummy, char* var, char* val ) { server_rec* s = parms->server; sample_conf* c = get_module_config( s->module_config, &sample_module ); if ( strcasecmp( var, "value" ) == 0 ) c->value = val; else return "unknown variable in SampleConfig command"; return (char*) 0; } static char* blanks( int len ) { static char buf[MAX_STRING_LEN]; int i; for ( i = 0; i < len; ++i ) buf[i] = ' '; buf[i] = '\0'; return buf; } static void show_int( int prefix, char* title, int i, request_rec* r ) { char buf[MAX_STRING_LEN]; (void) sprintf( buf, "%s%s: %d\n", blanks( prefix ), title, i ); rputs( buf, r ); } static void show_str( int prefix, char* title, char* s, request_rec* r ) { char buf[MAX_STRING_LEN]; if ( s == (char*) 0 ) (void) sprintf( buf, "%s%s: null\n", blanks( prefix ), title ); else (void) sprintf( buf, "%s%s: \"%s\"\n", blanks( prefix ), title, s ); rputs( buf, r ); } static void show_ina( int prefix, char* title, struct in_addr* i, request_rec* r ) { char buf[MAX_STRING_LEN]; (void) sprintf( buf, "%s%s: %d.%d.%d.%d\n", blanks( prefix ), title, (int) i->S_un.S_un_b.s_b1, (int) i->S_un.S_un_b.s_b2, (int) i->S_un.S_un_b.s_b3, (int) i->S_un.S_un_b.s_b4 ); rputs( buf, r ); } static void show_sin( int prefix, char* title, struct sockaddr_in* s, request_rec* r ) { char buf[MAX_STRING_LEN]; (void) sprintf( buf, "%s%s:\n", blanks( prefix ), title ); rputs( buf, r ); (void) sprintf( buf, "%sfamily: %d\n", blanks( prefix + strlen( title ) ), (int) s->sin_family ); rputs( buf, r ); (void) sprintf( buf, "%s port: %d\n", blanks( prefix + strlen( title ) ), (int) s->sin_port ); rputs( buf, r ); show_ina( prefix + strlen( title ), " addr", &s->sin_addr, r ); } static void show_tab( int prefix, char* title, table* t, request_rec* r ) { array_header* a = table_elts( t ); table_entry *e = (table_entry*) a->elts; int i; char buf[MAX_STRING_LEN]; (void) sprintf( buf, "%s%s: %d (%d)\n", blanks( prefix ), title, a->nelts, a->nalloc ); rputs( buf, r ); for ( i = 0; i < a->nelts; ++i ) { if ( e[i].key == (char*) 0 || e[i].val == (char*) 0 ) continue; (void) sprintf( buf, "%s%2d: \"%s\" \"%s\"\n", blanks( prefix + strlen( title ) ), i, e[i].key, e[i].val ); rputs( buf, r ); } } /* Request handler. Called on each request. */ static int sample_handler( request_rec* r ) { static int inited = 0; server_rec* s = r->server; sample_conf* c = get_module_config( s->module_config, &sample_module ); conn_rec* n = r->connection; /* Initialize if necessary. We call the init routine from the request ** handler rather than via the init entry in the module struct because ** if we did it the latter way, it would get called as root! */ if ( ! inited ) { inited = 1; sample_init_nonroot( s, permanent_pool ); } rputs( "Sample Module\n", r ); rputs( "

Sample Module

\n", r ); rputs( "

\n", r ); rputs( "The server fields:\n", r ); rputs( "

\n", r );
    /* next */
    show_str( 0, "      srm_confname", s->srm_confname, r );
    show_str( 0, "   access_confname", s->access_confname, r );
    show_str( 0, "      server_admin", s->server_admin, r );
    show_str( 0, "   server_hostname", s->server_hostname, r );
    show_int( 0, "              port", (int) s->port, r );
    show_str( 0, "       error_fname", s->error_fname, r );
    /* error_log */
    show_int( 0, "        is_virtual", s->is_virtual, r );
    /* lookup_defaults */
    show_ina( 0, "         host_addr", &s->host_addr, r );
    show_int( 0, "         host_port", (int) s->host_port, r );
    show_int( 0, "           timeout", s->timeout, r );
    show_int( 0, "keep_alive_timeout", s->keep_alive_timeout, r );
    show_int( 0, "        keep_alive", s->keep_alive, r );
    show_str( 0, "              path", s->path, r );
    show_int( 0, "           pathlen", s->pathlen, r );
    show_str( 0, "             names", s->names, r );
    show_str( 0, "          virthost", s->virthost, r );
    rputs( "
\n", r ); rputs( "

\n", r ); rputs( "The module config fields:\n", r ); rputs( "

\n", r );
    show_str( 0, "             value", c->value, r );
    rputs( "
\n", r ); rputs( "

\n", r ); rputs( "The connection fields:\n", r ); rputs( "

\n", r );
    /* pool */
    show_int( 0, "         child_num", n->child_num, r );
    /* client */
    show_int( 0, "           aborted", n->aborted, r );
    show_sin( 0, "        local_addr", &n->local_addr, r );
    show_sin( 0, "       remote_addr", &n->remote_addr, r );
    show_str( 0, "         remote_ip", n->remote_ip, r );
    show_str( 0, "       remote_host", n->remote_host, r );
    show_str( 0, "    remote_logname", n->remote_logname, r );
    show_str( 0, "              user", n->user, r );
    show_str( 0, "         auth_type", n->auth_type, r );
    show_int( 0, "         keepalive", n->keepalive, r );
    show_int( 0, "         keptalive", n->keptalive, r );
    show_int( 0, "        keepalives", n->keepalives, r );
    rputs( "
\n", r ); rputs( "

\n", r ); rputs( "The request fields:\n", r ); rputs( "

\n", r );
    /* pool */
    /* next */
    /* prev */
    /* main */
    show_str( 0, "       the_request", r->the_request, r );
    show_int( 0, "      assbackwards", r->assbackwards, r );
    show_int( 0, "          proxyreq", r->proxyreq, r );
    show_int( 0, "       header_only", r->header_only, r );
    show_str( 0, "          protocol", r->protocol, r );
    show_int( 0, "         proto_num", r->proto_num, r );
    show_str( 0, "          hostname", r->hostname, r );
    show_int( 0, "           hostlen", r->hostlen, r );
    show_str( 0, "       status_line", r->status_line, r );
    show_int( 0, "            status", r->status, r );
    show_str( 0, "            method", r->method, r );
    show_int( 0, "     method_number", r->method_number, r );
    show_int( 0, "       sent_bodyct", r->sent_bodyct, r );
    show_int( 0, "        bytes_sent", r->bytes_sent, r );
    show_tab( 0, "        headers_in", r->headers_in, r );
    show_tab( 0, "       headers_out", r->headers_out, r );
    show_tab( 0, "   err_headers_out", r->err_headers_out, r );
    show_tab( 0, "    subprocess_env", r->subprocess_env, r );
    show_tab( 0, "             notes", r->notes, r );
    show_str( 0, "      content_type", r->content_type, r );
    show_str( 0, "           handler", r->handler, r );
    show_str( 0, "  content_encoding", r->content_encoding, r );
    show_str( 0, "  content_language", r->content_language, r );
    show_int( 0, "          no_cache", r->no_cache, r );
    show_str( 0, "               uri", r->uri, r );
    show_str( 0, "          filename", r->filename, r );
    show_str( 0, "         path_info", r->path_info, r );
    show_str( 0, "              args", r->args, r );
    /* finfo */
    /* per_dir_config */
    /* request_config */
    /* htaccess */
    rputs( "
\n", r ); rputs( "\n", r ); return OK; } /* Command table. */ static command_rec sample_commands [] = { { "SampleConfig", sample_config, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "a variable to set followed by its value" }, NULL }; /* Handler record. */ handler_rec sample_handlers[] = { { "sample-handler", sample_handler }, NULL }; /* Module structure. */ module sample_module = { STANDARD_MODULE_STUFF, sample_init_root, /* initializer */ NULL, /* dir config creater */ NULL, /* dir merger - default is to override */ make_sample_conf, /* server config */ NULL, /* merge server config */ sample_commands, /* command table */ sample_handlers, /* handlers */ NULL, /* filename translation */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL /* logger */ };