⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_whatkilledus.c

📁 apache 安装教程 apache 安装教程
💻 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. *//* * Documentation: * * mod_whatkilledus is an experimental module for Apache httpd 1.3 which * tracks the current request and logs a report of the active request * when a child process crashes.  You should verify that it works reasonably * on your system before putting it in production. * * mod_whatkilledus is called during request processing to save information * about the current request.  It also implements a fatal exception hook * that will be called when a child process crashes. * * Apache httpd requirements for mod_whatkilledus: * *   Apache httpd >= 1.3.30 must be built with the AP_ENABLE_EXCEPTION_HOOK *   symbol defined and mod_so enabled.  AP_ENABLE_EXCEPTION_HOOK is already *   defined in ap_config.h for some platforms, including AIX, Linux, *   Solaris, and HP-UX.  It can be enabled for other platforms by including *   -DAP_ENABLE_EXCEPTION_HOOK in CFLAGS when the configure script is *   invoked. * * Compiling mod_whatkilledus: * *   AIX: *     apxs -ci -I/path/to/apache/src/main -Wl,-bE:mod_whatkilledus.exp mod_whatkilledus.c * *   other: *     apxs -ci -I/path/to/apache/src/main mod_whatkilledus.c * * Activating mod_whatkilledus: * *   1. Load it like any other DSO, but the AddModule should come *      last so that if another module causes a crash early in *      request processing mod_whatkilledus will have already *      had a chance to save information about the request. * *        LoadModule whatkilledus_module libexec/mod_whatkilledus.so *        ... *        AddModule mod_whatkilledus.c * *   2. Enable exception hooks for modules like mod_whatkilledus: *        EnableExceptionHook On * *   3. Choose where the report on current activity should be written.  If *      you want it reported to some place other than the error log, use the *      WhatKilledUsLog directive to specify a fully-qualified filename for *      the log.  Note that the web server user id (e.g., "nobody") must *      be able to create or append to this log file, as the log file is *      not opened until a crash occurs. */#include "httpd.h"#include "http_config.h"#include "http_log.h"#include "test_char.h" /* an odd one since it is not installed *//* this module is not thread-safe; it is intended for Apache 1.3 on * platforms that use single-threaded child processes for handling * client connections */static char *log_fname;static char *local_addr;static char *remote_addr;static char *request_plus_headers;static char buffer[2048];static void exception_hook(ap_exception_info_t *ei){    int msg_len;    int logfd;    char msg_prefix[60];    time_t now;    char *newline;    int using_errorlog = 1;    time(&now);    ap_snprintf(msg_prefix, sizeof msg_prefix,                "[%s pid %ld mod_whatkilledus",                asctime(localtime(&now)),                (long)getpid());    newline = strchr(msg_prefix, '\n'); /* dang asctime() */    if (newline) {                      /* silly we are */        *newline = ']';    }    if (log_fname) {        logfd = open(log_fname, O_WRONLY|O_APPEND|O_CREAT, 0644);        if (logfd == -1) {            logfd = 2; /* unix, so fd 2 is the web server error log */            ap_snprintf(buffer, sizeof buffer,                        "%s error %d opening %s\n",                        msg_prefix, errno, log_fname);            write(logfd, buffer, strlen(buffer));        }        else {            using_errorlog = 0;        }    }    else {        logfd = 2;    }    msg_len = ap_snprintf(buffer, sizeof buffer,                          "%s sig %d crash\n",                          msg_prefix, ei->sig);    write(logfd, buffer, msg_len);    if (local_addr) {        msg_len = ap_snprintf(buffer, sizeof buffer,                              "%s active connection: %s->%s\n",                              msg_prefix, remote_addr, local_addr);    }    else {        msg_len = ap_snprintf(buffer, sizeof buffer,                              "%s no active connection at crash\n",                              msg_prefix);    }    write(logfd, buffer, msg_len);    if (request_plus_headers) {        msg_len = ap_snprintf(buffer, sizeof buffer,                              "%s active request:\n",                              msg_prefix);        write(logfd, buffer, msg_len);        write(logfd, request_plus_headers, strlen(request_plus_headers));    }    else {        msg_len = ap_snprintf(buffer, sizeof buffer,                              "%s no request active at crash\n",                              msg_prefix);        write(logfd, buffer, msg_len);    }    msg_len = ap_snprintf(buffer, sizeof buffer,                          "%s end of report\n",                          msg_prefix);    write(logfd, buffer, msg_len);    if (!using_errorlog) {        close(logfd);    }}static void init(server_rec *s, pool *p){    int rc = ap_add_fatal_exception_hook(exception_hook);    if (rc) {        ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, s,                     "fatal exception hooks are not enabled; please "                     "enable them with the EnableExceptionHook directive "                     "or disable mod_whatkilledus");    }}static void clear_conn_info(void *ignored){    local_addr = remote_addr = NULL;}static void save_conn_info(request_rec *r){    conn_rec *c = r->connection;    local_addr =  ap_psprintf(c->pool, "%pI", &c->local_addr);    remote_addr = ap_psprintf(c->pool, "%pI", &c->remote_addr);    ap_register_cleanup(c->pool, NULL, clear_conn_info, ap_null_cleanup);}static void clear_req_info(void *ignored){    request_plus_headers = NULL;}#define FIELD_SEPARATOR   "|"#define KEYVAL_SEPARATOR  ":"/* graciously lifted from mod_log_forensic */static int count_string(const char *p){    int n;    for (n = 0; *p; ++p, ++n) {        if (test_char_table[*(unsigned char *)p] & T_ESCAPE_FORENSIC) {            n += 2;        }    }    return n;}static int count_headers(void *in_len, const char *key, const char *value){    int *len = in_len;    *len += strlen(FIELD_SEPARATOR);    *len += count_string(key);    *len += strlen(KEYVAL_SEPARATOR);    *len += count_string(value);    return 1;}static char *copy_and_escape(char *loc, const char *str) {    /* mod_log_forensic will SIGABRT here if it messed up the count     * and overflowed; mod_whatkilledus will segfault here or will     * SIGABRT back in the caller if that happens     */    for ( ; *str; ++str) {        if (test_char_table[*(unsigned char *)str] & T_ESCAPE_FORENSIC) {            *loc++ = '%';            sprintf(loc, "%02x", *(unsigned char *)str);            loc += 2;        }        else {            *loc++ = *str;        }    }    *loc = '\0';    return loc;}static int copy_headers(void *in_ch, const char *key, const char *value){    char **ch = in_ch;    strcpy(*ch, FIELD_SEPARATOR);    *ch += strlen(FIELD_SEPARATOR);    *ch = copy_and_escape(*ch, key);    strcpy(*ch, KEYVAL_SEPARATOR);    *ch += strlen(KEYVAL_SEPARATOR);    *ch = copy_and_escape(*ch, value);    return 1;}static void save_req_info(request_rec *r){    /* to save for the request:     * r->the_request +      * foreach header:     *   '|' + header field     */    int len = strlen(r->the_request);    char *ch;    ap_table_do(count_headers, &len, r->headers_in, NULL);    request_plus_headers = ap_palloc(r->pool, len + 2 /* 2 for the '\n' + '\0' at end */);    ch = request_plus_headers;    strcpy(ch, r->the_request);    ch += strlen(ch);    ap_table_do(copy_headers, &ch, r->headers_in, NULL);    *ch = '\n';    *(ch + 1) = '\0';    ap_assert(ch == request_plus_headers + len);    ap_register_cleanup(r->pool, NULL, clear_req_info, ap_null_cleanup);}static int post_read(request_rec *r){    if (r->prev) { /* we were already called for this internal redirect */        return DECLINED;    }    /* save whatever info, like client, which vhost, which port     * (to know SSL or not), etc.     */    if (!local_addr) { /* first request on this connection */        save_conn_info(r);    }    save_req_info(r);    return DECLINED;}static const char *cmd_file(cmd_parms *cmd, void *dconf, char *fname){    log_fname = ap_pstrdup(cmd->pool, fname);    return NULL;}static const command_rec command_table[] = {    {        "WhatKilledUsLog", cmd_file, NULL, RSRC_CONF, TAKE1, "the fully-qualified filename of the mod_whatkilledus logfile"    }    ,    {        NULL    }};module MODULE_VAR_EXPORT whatkilledus_module = {    STANDARD_MODULE_STUFF,    init,                       /* initializer */    NULL,                       /* create per-dir config */    NULL,                       /* merge per-dir config */    NULL,                       /* server config */    NULL,                       /* merge server config */    command_table,              /* command table */    NULL,                       /* handlers */    NULL,                       /* filename translation */    NULL,                       /* check_user_id */    NULL,                       /* check auth */    NULL,                       /* check access */    NULL,                       /* type_checker */    NULL,                       /* fixups */    NULL,                       /* logger */    NULL,                       /* header parser */    NULL,                       /* child_init */    NULL,                       /* child_exit */    post_read                   /* post read-request */};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -