Name

Logger

Synopsis

int module_logger(request_rec *pRec)

Now that the request has been processed and the dust has settled, you may want to log the request in some way. Here’s your chance to do that. Although the core stops running the logger function as soon as a module returns something other than OK or DECLINED, that is rarely done, as there is no way to know whether another module needs to log something.

Although mod_log_agent.c is more or less out of date since mod_log_config.c was introduced, it makes a nice, compact example. See Example 21-23.

Example

Example 21-23. mod_log_agent.c
int agent_log_transaction(request_rec *orig)
{
    agent_log_state *cls = ap_get_module_config (orig->server->module_config,
                                              &agent_log_module);
    char str[HUGE_STRING_LEN];
    char *agent;
    request_rec *r;

    if(cls->agent_fd <0)
      return OK;

    for (r = orig; r->next; r = r->next)
        continue;
    if (*cls->fname == '\0'.    /* Don't log agent */
        return DECLINED;

    agent = table_get(orig->headers_in, "User-Agent");
    if(agent != NULL) 
      {
        sprintf(str, "%s\n", agent);
        write(cls->agent_fd, str, strlen(str));
      }

    return OK;
}

This is not a good example of programming practice. With its fixed-size buffer str, it leaves a gaping security hole. It wouldn’t be enough simply to split the write into two parts to avoid this problem. Because the log file is shared among all server processes, the write must be atomic, or the log file could get mangled by overlapping writes. mod_log_config.c carefully avoids this problem.

Unfortunately, mod_log_agent.c ...

Get Apache: The Definitive Guide, 3rd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.