Logger
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 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 write
s.
mod_log_config.c carefully avoids this problem.
Unfortunately, mod_log_agent.c has been axed in 2.0; but if it were still there, it would look pretty much the same.