bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / modules / generators / mod_info.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* 
18  * Info Module.  Display configuration information for the server and
19  * all included modules.
20  *
21  * <Location /server-info>
22  * SetHandler server-info
23  * </Location>
24  *
25  * GET /server-info - Returns full configuration page for server and all modules
26  * GET /server-info?server - Returns server configuration only
27  * GET /server-info?module_name - Returns configuration for a single module
28  * GET /server-info?list - Returns quick list of included modules
29  *
30  * Rasmus Lerdorf <rasmus@vex.net>, May 1996
31  *
32  * 05.01.96 Initial Version
33  *
34  * Lou Langholtz <ldl@usi.utah.edu>, July 1997
35  *
36  * 07.11.97 Addition of the AddModuleInfo directive
37  *
38  * Ryan Morgan <rmorgan@covalent.net>
39  * 
40  * 8.11.00 Port to Apache 2.0.  Read configuation from the configuration
41  * tree rather than reparse the entire configuation file.
42  * 
43  */
44
45 #define CORE_PRIVATE
46
47 #include "httpd.h"
48 #include "http_config.h"
49 #include "http_core.h"
50 #include "http_log.h"
51 #include "http_main.h"
52 #include "http_protocol.h"
53 #include "http_request.h"
54 #include "util_script.h"
55 #include "apr_strings.h"
56 #include "apr_lib.h"
57 #define APR_WANT_STRFUNC
58 #include "apr_want.h"
59 #include "ap_mpm.h"
60
61 typedef struct {
62     const char *name;                 /* matching module name */
63     const char *info;                 /* additional info */
64 } info_entry;
65
66 typedef struct {
67     apr_array_header_t *more_info;
68 } info_svr_conf;
69
70 module AP_MODULE_DECLARE_DATA info_module;
71
72 static void *create_info_config(apr_pool_t *p, server_rec *s)
73 {
74     info_svr_conf *conf = (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
75
76     conf->more_info = apr_array_make(p, 20, sizeof(info_entry));
77     return conf;
78 }
79
80 static void *merge_info_config(apr_pool_t *p, void *basev, void *overridesv)
81 {
82     info_svr_conf *new = (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
83     info_svr_conf *base = (info_svr_conf *) basev;
84     info_svr_conf *overrides = (info_svr_conf *) overridesv;
85
86     new->more_info = apr_array_append(p, overrides->more_info, base->more_info);
87     return new;
88 }
89
90 static void mod_info_html_cmd_string(request_rec *r, const char *string,
91                                      int close)
92 {
93     const char *s;
94
95     s = string;
96     /* keep space for \0 byte */
97     while (*s) {
98         if (*s == '<') {
99             if (close) {
100                 ap_rputs("&lt;/", r);
101             } else {
102                 ap_rputs("&lt;", r);
103             }
104         }
105         else if (*s == '>') {
106             ap_rputs("&gt;", r);
107         }
108         else if (*s == '&') {
109             ap_rputs("&amp;", r);
110         }
111         else if (*s == ' ') {
112             if (close) {
113                 ap_rputs("&gt;", r);
114                 break;
115             } else {
116                 ap_rputc(*s, r);
117             }
118         } else {
119             ap_rputc(*s, r);
120         }
121         s++;
122     }
123 }
124
125 static void mod_info_module_cmds(request_rec * r, const command_rec * cmds,
126                                  ap_directive_t * conftree)
127 {
128     const command_rec *cmd;
129     ap_directive_t *tmptree = conftree;
130     char htmlstring[MAX_STRING_LEN];
131     int block_start = 0;
132     int nest = 0;
133
134     while (tmptree != NULL) {
135         cmd = cmds;
136         while (cmd->name) {
137             if ((cmd->name[0] != '<') && 
138                 (strcasecmp(cmd->name, tmptree->directive) == 0)) {
139                 if (nest > block_start) {
140                     block_start++;
141                     apr_snprintf(htmlstring, sizeof(htmlstring), "%s %s",
142                                 tmptree->parent->directive,
143                                 tmptree->parent->args);
144                     ap_rputs("<dd><tt>", r);
145                     mod_info_html_cmd_string(r, htmlstring, 0);
146                     ap_rputs("</tt></dd>\n", r);
147                 }
148                 if (nest == 2) {
149                     ap_rprintf(r, "<dd><tt>&nbsp;&nbsp;&nbsp;&nbsp;%s "
150                                "<i>%s</i></tt></dd>\n",
151                                ap_escape_html(r->pool,tmptree->directive), 
152                                ap_escape_html(r->pool,tmptree->args));
153                 } else if (nest == 1) {
154                     ap_rprintf(r,
155                                "<dd><tt>&nbsp;&nbsp;%s <i>%s</i></tt></dd>\n",
156                                ap_escape_html(r->pool,tmptree->directive), 
157                                ap_escape_html(r->pool,tmptree->args));
158                 } else {
159                     ap_rputs("<dd><tt>", r);
160                     mod_info_html_cmd_string(r, tmptree->directive, 0);
161                     ap_rprintf(r, " <i>%s</i></tt></dd>\n", 
162                                ap_escape_html(r->pool,tmptree->args));
163                 }
164             }
165             ++cmd;
166         }
167         if (tmptree->first_child != NULL) {
168             tmptree = tmptree->first_child;
169             nest++;
170         } else if (tmptree->next != NULL) {
171             tmptree = tmptree->next;
172         } else {
173             if (block_start) {
174                 apr_snprintf(htmlstring, sizeof(htmlstring), "%s %s",
175                             tmptree->parent->directive,
176                             tmptree->parent->args);
177                 ap_rputs("<dd><tt>", r);
178                 mod_info_html_cmd_string(r, htmlstring, 1);
179                 ap_rputs("</tt></dd>\n", r);
180                 block_start--;
181             }
182             if (tmptree->parent) {
183                 tmptree = tmptree->parent->next;
184             }
185             else {
186                 tmptree = NULL;
187             }
188             nest--;
189         }
190
191     }
192 }
193
194 typedef struct { /*XXX: should get something from apr_hooks.h instead */
195     void (*pFunc)(void); /* just to get the right size */
196     const char *szName;
197     const char * const *aszPredecessors;
198     const char * const *aszSuccessors;
199     int nOrder;
200 } hook_struct_t;
201
202 /*
203  * hook_get_t is a pointer to a function that takes void as an argument and
204  * returns a pointer to an apr_array_header_t.  The nasty WIN32 ifdef
205  * is required to account for the fact that the ap_hook* calls all use
206  * STDCALL calling convention. 
207  */
208 typedef apr_array_header_t * ( 
209 #ifdef WIN32
210 __stdcall 
211 #endif
212 * hook_get_t)(void);
213
214 typedef struct {
215     const char *name;
216     hook_get_t get;
217 } hook_lookup_t;
218
219 static hook_lookup_t request_hooks[] = {
220     {"Post-Read Request", ap_hook_get_post_read_request},
221     {"Header Parse", ap_hook_get_header_parser},
222     {"Translate Path", ap_hook_get_translate_name},
223     {"Check Access", ap_hook_get_access_checker},
224     {"Verify User ID", ap_hook_get_check_user_id},
225     {"Verify User Access", ap_hook_get_auth_checker},
226     {"Check Type", ap_hook_get_type_checker},
227     {"Fixups", ap_hook_get_fixups},
228     {"Logging", ap_hook_get_log_transaction},
229     {NULL},
230 };
231
232 static int module_find_hook(module *modp,
233                             hook_get_t hook_get)
234 {
235     int i;
236     apr_array_header_t *hooks = hook_get();
237     hook_struct_t *elts;
238
239     if (!hooks) {
240         return 0;
241     }
242
243     elts = (hook_struct_t *)hooks->elts;
244
245     for (i=0; i< hooks->nelts; i++) {
246         if (strcmp(elts[i].szName, modp->name) == 0) {
247             return 1;
248         }
249     }
250
251     return 0;
252 }
253
254 static void module_participate(request_rec *r,
255                                module *modp,
256                                hook_lookup_t *lookup,
257                                int *comma)
258 {
259     if (module_find_hook(modp, lookup->get)) {
260         if (*comma) {
261             ap_rputs(", ", r);
262         }
263         ap_rvputs(r, "<tt>", lookup->name, "</tt>", NULL);
264         *comma = 1;
265     }
266 }
267
268 static void module_request_hook_participate(request_rec *r, module *modp)
269 {
270     int i, comma=0;
271
272     ap_rputs("<dt><strong>Request Phase Participation:</strong>\n", r);
273
274     for (i=0; request_hooks[i].name; i++) {
275         module_participate(r, modp, &request_hooks[i], &comma);
276     }
277
278     if (!comma) {
279         ap_rputs("<tt> <em>none</em></tt>", r);
280     }
281     ap_rputs("</dt>\n", r);
282 }
283
284 static const char *find_more_info(server_rec *s, const char *module_name)
285 {
286     int i;
287     info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
288                                                               &info_module);
289     info_entry *entry = (info_entry *) conf->more_info->elts;
290
291     if (!module_name) {
292         return 0;
293     }
294     for (i = 0; i < conf->more_info->nelts; i++) {
295         if (!strcmp(module_name, entry->name)) {
296             return entry->info;
297         }
298         entry++;
299     }
300     return 0;
301 }
302
303 static int display_info(request_rec *r)
304 {
305     module *modp = NULL;
306     const char *more_info;
307     const command_rec *cmd = NULL;
308 #ifdef NEVERMORE
309     const handler_rec *hand = NULL;
310 #endif
311     server_rec *serv = r->server;
312     int comma = 0;
313
314     if (strcmp(r->handler, "server-info"))
315         return DECLINED;
316
317     r->allowed |= (AP_METHOD_BIT << M_GET);
318     if (r->method_number != M_GET)
319         return DECLINED;
320
321     ap_set_content_type(r, "text/html; charset=ISO-8859-1");
322
323     ap_rputs(DOCTYPE_HTML_3_2
324              "<html><head><title>Server Information</title></head>\n", r);
325     ap_rputs("<body><h1 align=\"center\">Apache Server Information</h1>\n", r);
326     if (!r->args || strcasecmp(r->args, "list")) {
327         if (!r->args) {
328             ap_rputs("<dl><dt><tt><a href=\"#server\">Server Settings</a>, ", r);
329             for (modp = ap_top_module; modp; modp = modp->next) {
330                 ap_rprintf(r, "<a href=\"#%s\">%s</a>", modp->name, modp->name);
331                 if (modp->next) {
332                     ap_rputs(", ", r);
333                 }
334             }
335             ap_rputs("</tt></dt></dl><hr />", r);
336
337         }
338         if (!r->args || !strcasecmp(r->args, "server")) {
339             int max_daemons, forked, threaded;
340
341             ap_rprintf(r, "<dl><dt><a name=\"server\"><strong>Server Version:</strong> "
342                         "<font size=\"+1\"><tt>%s</tt></font></a></dt>\n",
343                         ap_get_server_version());
344             ap_rprintf(r, "<dt><strong>Server Built:</strong> "
345                         "<font size=\"+1\"><tt>%s</tt></font></dt>\n",
346                         ap_get_server_built());
347             ap_rprintf(r, "<dt><strong>API Version:</strong> "
348                         "<tt>%d:%d</tt></dt>\n",
349                         MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
350             ap_rprintf(r, "<dt><strong>Hostname/port:</strong> "
351                         "<tt>%s:%u</tt></dt>\n",
352                         ap_get_server_name(r), ap_get_server_port(r));
353             ap_rprintf(r, "<dt><strong>Timeouts:</strong> "
354                         "<tt>connection: %d &nbsp;&nbsp; "
355                         "keep-alive: %d</tt></dt>",
356                         (int)(apr_time_sec(serv->timeout)), 
357                         (int)(apr_time_sec(serv->timeout)));
358             ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED, &max_daemons);
359             ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded);
360             ap_mpm_query(AP_MPMQ_IS_FORKED, &forked);
361             ap_rprintf(r, "<dt><strong>MPM Name:</strong> <tt>%s</tt></dt>\n", ap_show_mpm());
362             ap_rprintf(r, "<dt><strong>MPM Information:</strong> "
363                        "<tt>Max Daemons: %d Threaded: %s Forked: %s</tt></dt>\n",
364                        max_daemons, threaded ? "yes" : "no",
365                        forked ? "yes" : "no");
366             ap_rprintf(r, "<dt><strong>Server Root:</strong> "
367                         "<tt>%s</tt></dt>\n", ap_server_root);
368             ap_rprintf(r, "<dt><strong>Config File:</strong> "
369                        "<tt>%s</tt></dt>\n", ap_conftree->filename);
370             ap_rputs("</dl><hr />", r);
371         }
372         for (modp = ap_top_module; modp; modp = modp->next) {
373             if (!r->args || !strcasecmp(modp->name, r->args)) {
374                 ap_rprintf(r, "<dl><dt><a name=\"%s\"><strong>Module Name:</strong> "
375                             "<font size=\"+1\"><tt>%s</tt></font></a></dt>\n",
376                             modp->name, modp->name);
377                 ap_rputs("<dt><strong>Content handlers:</strong> ", r);
378 #ifdef NEVERMORE
379                 hand = modp->handlers;
380                 if (hand) {
381                     while (hand) {
382                         if (hand->content_type) {
383                             ap_rprintf(r, " <tt>%s</tt>\n", hand->content_type);
384                         }
385                         else {
386                             break;
387                         }
388                         hand++;
389                         if (hand && hand->content_type) {
390                             ap_rputs(",", r);
391                         }
392                     }
393                 }
394                 else {
395                     ap_rputs("<tt> <em>none</em></tt>", r);
396                 }
397 #else
398                 if (module_find_hook(modp, ap_hook_get_handler)) {
399                     ap_rputs("<tt> <em>yes</em></tt>", r);
400                 }
401                 else {
402                     ap_rputs("<tt> <em>none</em></tt>", r);
403                 }
404 #endif
405                 ap_rputs("</dt>", r);
406                 ap_rputs("<dt><strong>Configuration Phase Participation:</strong>\n",
407                       r);
408                 if (modp->create_dir_config) {
409                     if (comma) {
410                         ap_rputs(", ", r);
411                     }
412                     ap_rputs("<tt>Create Directory Config</tt>", r);
413                     comma = 1;
414                 }
415                 if (modp->merge_dir_config) {
416                     if (comma) {
417                         ap_rputs(", ", r);
418                     }
419                     ap_rputs("<tt>Merge Directory Configs</tt>", r);
420                     comma = 1;
421                 }
422                 if (modp->create_server_config) {
423                     if (comma) {
424                         ap_rputs(", ", r);
425                     }
426                     ap_rputs("<tt>Create Server Config</tt>", r);
427                     comma = 1;
428                 }
429                 if (modp->merge_server_config) {
430                     if (comma) {
431                         ap_rputs(", ", r);
432                     }
433                     ap_rputs("<tt>Merge Server Configs</tt>", r);
434                     comma = 1;
435                 }
436                 if (!comma)
437                     ap_rputs("<tt> <em>none</em></tt>", r);
438                 comma = 0;
439                 ap_rputs("</dt>", r);
440
441                 module_request_hook_participate(r, modp);
442
443                 cmd = modp->cmds;
444                 if (cmd) {
445                     ap_rputs("<dt><strong>Module Directives:</strong></dt>", r);
446                     while (cmd) {
447                         if (cmd->name) {
448                             ap_rputs("<dd><tt>", r);
449                             mod_info_html_cmd_string(r, cmd->name, 0);
450                             ap_rputs(" - <i>", r);
451                             if (cmd->errmsg) {
452                                 ap_rputs(cmd->errmsg, r);
453                             }
454                             ap_rputs("</i></tt></dd>\n", r);
455                         }
456                         else {
457                             break;
458                         }
459                         cmd++;
460                     }
461                     ap_rputs("<dt><strong>Current Configuration:</strong></dt>\n", r);
462                     mod_info_module_cmds(r, modp->cmds, ap_conftree);
463                 }
464                 else {
465                     ap_rputs("<dt><strong>Module Directives:</strong> <tt>none</tt></dt>", r);
466                 }
467                 more_info = find_more_info(serv, modp->name);
468                 if (more_info) {
469                     ap_rputs("<dt><strong>Additional Information:</strong>\n</dt><dd>",
470                           r);
471                     ap_rputs(more_info, r);
472                     ap_rputs("</dd>", r);
473                 }
474                 ap_rputs("</dl><hr />\n", r);
475                 if (r->args) {
476                     break;
477                 }
478             }
479         }
480         if (!modp && r->args && strcasecmp(r->args, "server")) {
481             ap_rputs("<p><b>No such module</b></p>\n", r);
482         }
483     }
484     else {
485         ap_rputs("<dl><dt>Server Module List</dt>", r);
486         for (modp = ap_top_module; modp; modp = modp->next) {
487             ap_rputs("<dd>", r);
488             ap_rputs(modp->name, r);
489             ap_rputs("</dd>", r);
490         }
491         ap_rputs("</dl><hr />", r);
492     }
493     ap_rputs(ap_psignature("",r), r);
494     ap_rputs("</body></html>\n", r);
495     /* Done, turn off timeout, close file and return */
496     return 0;
497 }
498
499 static const char *add_module_info(cmd_parms *cmd, void *dummy, 
500                                    const char *name, const char *info)
501 {
502     server_rec *s = cmd->server;
503     info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
504                                                               &info_module);
505     info_entry *new = apr_array_push(conf->more_info);
506
507     new->name = name;
508     new->info = info;
509     return NULL;
510 }
511
512 static const command_rec info_cmds[] =
513 {
514     AP_INIT_TAKE2("AddModuleInfo", add_module_info, NULL, RSRC_CONF,
515                   "a module name and additional information on that module"),
516     {NULL}
517 };
518
519 static void register_hooks(apr_pool_t *p)
520 {
521     ap_hook_handler(display_info, NULL, NULL, APR_HOOK_MIDDLE);
522 }
523
524 module AP_MODULE_DECLARE_DATA info_module =
525 {
526     STANDARD20_MODULE_STUFF,
527     NULL,                       /* dir config creater */
528     NULL,                       /* dir merger --- default is to override */
529     create_info_config,         /* server config */
530     merge_info_config,          /* merge server config */
531     info_cmds,                  /* command apr_table_t */
532     register_hooks
533 };