home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam    

Writing Apache Modules with Perl and C
By:   Lincoln Stein and Doug MacEachern
Published:   O'Reilly & Associates, Inc.  - March 1999

Copyright © 1999 by O'Reilly & Associates, Inc.


   Show Contents   Previous Page   Next Page

Chapter 10 - C API Reference Guide, Part I / Server Core Routines
The Piped Log API

Apache Version 1.3.0 introduced reliable piped log support, which allows your module to send log data to a running program.6 If the program happens to die, it will be automatically restarted. Internally, this API is used when processing log file directives that begin with the | (pipe character). Everything following the pipe character is treated as a program to be run. After the program is launched, log entries are sent to the program on its standard input.

You will probably not need to use the piped log routines because this functionality is already handled in a generic way by Apache's mod_log_config module. However, if you wish to support this feature in a custom logging module of your own, these calls are available for your use.

The main data structure used by the piped log API is the piped_log record, defined in http_log.h. This data structure should be treated as an opaque data structure. Use ap_open_piped_log() to open a pipe to a new process, ap_piped_log_read_fd() and ap_piped_log_write_fd() to obtain file descriptors that you can use to read and write from the process, and ap_close_piped_log() to close the pipe when you're through.

piped_log *ap_open_piped_log (pool *p, const char *program)

Given a resource pool p and the path to an executable program, ap_open_piped_log() will launch the program, open a bidirectional pipe to it, and return a piped_log pointer if successful or NULL if not.

You should make this call during the module or child initialization phases. This will avoid the overhead of opening and closing the pipe for each request. If you open the pipe at module initialization time, the subprocess will be run as root, but there will be only one copy running. If you open the pipe during child initialization, it will run as the httpd user, but there will be one copy of the subprocess running for each child. It's your call which to use.

Here's an example of opening a log file specified by the module-specific configuration record cfg. If the initial character of the filename is the pipe symbol, the code opens it as a piped command. Otherwise, it opens it as a normal file. For simplicity, we've omitted error checking from this example.

if(*cfg->log_file == '|') {
    /* open as a command pipe */
   piped_log *pl = ap_open_piped_log(p, cfg->log_file + 1);
   cfg->log_fd = ap_piped_log_write_fd(pl);
else {
  /* open as normal file */
  cls->log_fd = ap_popenf(p, cfg->log_file, flags, mode);
if (!cls->log_fd) {
       ... raise some sort of error...

Some of the routines in this example are described in the next chapter.

void ap_close_piped_log (piped_log *pl)

This function closes a previously opened piped log. Conveniently, this function will be called at pool destruction time if you don't call it yourself.

int ap_piped_log_write_fd (piped_log *pl)

ap_piped_log_write_fd() returns a file descriptor that you can use to write to the logging process using the standard write() library call. Typically, you will write some form of accounting or status information, but the contents of the information you send are entirely up to you. Because all writing is done through a file descriptor, the same code routines that write to plain text files can be used to write to the pipe.

int ap_piped_log_read_fd (piped_log *pl)

ap_piped_log_read() returns a file descriptor that you can use to read from the logging process with the standard read() library call. It is far more usual to write to a logging process than to read from one, but you can do this if the process provides status information, for instance. If you both read and write from the process, beware of deadlock situations in which both your module and the logging process are waiting for the other.

   Show Contents   Previous Page   Next Page
Copyright © 1999 by O'Reilly & Associates, Inc.