From http://svn.blinkenlights.nl/viewvc.cgi/vhostlog/trunk/

Makefile

CC = gcc
DEBUG = -Wall -g

all:    vhostlog

vhostlog.o:     vhostlog.c
        $(CC) ${DEBUG} -O -c vhostlog.c

vhostlog:       vhostlog.o
        $(CC) ${DEBUG} -o vhostlog vhostlog.o

clean:
        rm -f vhostlog *.o core *.core

vhostlog.c

/*

vhostlog.c

This program is supposed to run from apache via a pipe
in a CustomLog statement, or as a daemon under daemontools/
inittab/etc in fifo mode.

Configure it as follows:

LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" " vhostlog

#Pipe Version
CustomLog "|/usr/local/bin/vhostlog www /var/log/apache" vhostlog
#Fifo Version
CustomLog "/var/path/to/vhostlog/fifo" vhostlog

The first argument is the user to switch to (www), the second is the
directory in which logfiles are stored ( /var/log/apache ).
The owner of the log directory *has* to be the same as the log user.

Written by Johan Mulder <johan@localhost.nl> at november 28th 2001.
Modified by Sten Spans <sten@blinkenlights.nl> at $Date$.

*/

const char cvsid[] = "$Id$";

#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>

#define UMASK   S_IRWXG | S_IRWXO
#define NOLOGGING "/var/service/vhostlog/root/down"
#define MAXLINESIZE 16384
#define VHOSTCHARS "abcdefghijklmnopqrstuvwxyz0123456789.-_"
/* #define DEBUG */

char hostname[MAXHOSTNAMELEN+1];
static int logline(char *, const char *, unsigned int *);

int main(int argc, char **argv)
{
        char line[MAXLINESIZE];
        char *logdir;
        char *user;
        char *fifo_path = NULL;
        struct passwd *pwd;
        unsigned int failed = 0;
        unsigned int longline = 0;
        struct stat s;
        FILE *input = stdin;

        /* Get the config */
#ifdef DEBUG
        fprintf(stderr, "Getting the config\n");
#endif
        if (argc < 3 || argc > 4)
        {
                fprintf(stderr, "Usage %s user logdir [fifo]\n", argv[0]);
                return 1;
        }

        user = argv[1];
        logdir = argv[2];
        if(argc == 4)
                fifo_path = argv[3];

        /* Check if the user to setuid to actually exists */
#ifdef DEBUG
        fprintf(stderr, "Checking if the user exists\n");
#endif
        if ((pwd = getpwnam(user)) == NULL)
        {
                fprintf(stderr, "User %s does not exist\n", user);
                return 1;
        }

        /* Check if the logdir exists */
#ifdef DEBUG
        fprintf(stderr, "Checking if the logdir exists\n");
#endif
        if (stat(logdir, &s) == -1 || chdir(logdir) == -1)
        {
           fprintf(stderr, "Unable to change dir to %s: %s\n",
                        logdir, strerror(errno));
           return 1;
        }

        /* Check the ownership of that directory */
#ifdef DEBUG
        fprintf(stderr, "Checking logdir ownership\n");
#endif
        if (s.st_uid != pwd->pw_uid)
        {
           fprintf(stderr, "Bad owner on directory %s (should be owner %s).\n",
                         logdir, user);
           return 1;
        }

        /* Change the uid */
#ifdef DEBUG
        fprintf(stderr, "Changing uid/gid\n");
#endif
        if(setgid(pwd->pw_gid) == -1){
            fprintf(stderr, "Unable to setgid: %s\n", strerror(errno));
            return 1;
        }

        if(setgroups(0, NULL) == -1){
            fprintf(stderr, "Unable to setgroups: %s\n", strerror(errno));
            return 1;
        }

        if(setuid(pwd->pw_uid) == -1){
            fprintf(stderr, "Unable to setuid: %s\n", strerror(errno));
            return 1;
        }

        /* Get hostname */
        if(gethostname(hostname, sizeof(hostname)) == -1){
            fprintf(stderr, "Unable to get hostname: %s\n", strerror(errno));
            return 1;
        }

        /* Change umask */
        umask(UMASK);

        /* Check/Create Fifo */
        if(fifo_path != NULL) {
#ifdef DEBUG
           fprintf(stderr, "Checking/Creating the fifo: %s\n", fifo_path);
#endif
           if (stat(fifo_path, &s) == -1) {
                if(errno != ENOENT) {
                   fprintf(stderr, "Unable to stat fifo %s: %s\n",
                                fifo_path, strerror(errno));
                   return 1;
                } else if (mkfifo(fifo_path, S_IRWXU) == -1) {
                   fprintf(stderr, "Unable to create fifo %s: %s\n",
                                fifo_path, strerror(errno));
                   return 1;
                }
           } else if (!S_ISFIFO(s.st_mode)) {
                fprintf(stderr, "Expected fifo at %s, got something else\n",
                        fifo_path);
                return 1;
           }

           if ((input = fopen(fifo_path, "r+")) == NULL) {
                fprintf(stderr, "Failed opening fifo %s: %s\n",
                        fifo_path, strerror(errno));
                return 1;
           }
        }

        /* Process the logging */
#ifdef DEBUG
        fprintf(stderr, "Process the logging\n");
#endif
        while (feof(input) == 0) {
        if ((fgets(line, MAXLINESIZE, input)) != NULL)
           if (access(NOLOGGING, F_OK) == -1)
                if (logline(line, logdir, &longline) == 1)
                        fprintf(stderr, " %u logging failures\n", ++failed);
        }
        return 0;
}


/* This function writes a logline in clf to a logfile */
int logline(char *line, const char *logdir, unsigned int *longline)
{
        char *outline, *vhost;
        char logfile[PATH_MAX+1];
        FILE *outfile;

        outline = vhost = NULL;

        /* initial checks */
#ifdef DEBUG
        fprintf(stderr, "Initial Checks\n");
#endif
        if (!line || (strlen(line) == 0)) {
                fprintf(stderr, "Incorrect logline: too short,");
                return 1;
        } else if((strchr(line, '\n') == NULL) && *longline == 0){
                fprintf(stderr, "Incorrect logline: too long,");
                *longline = 1;
                return 1;
        } else if((strchr(line, '\n') == NULL) && *longline == 1){
                return 0;
        } else if((strchr(line, '\n') != NULL) && *longline == 1){
                *longline = 0;
                return 0;
        };

        if(!logdir || (strlen(logdir) == 0)) {
                fprintf(stderr, "Incorrect logdir: too short,");
                return 1;
        }


        /* Determine the vhost and logfile location */
#ifdef DEBUG
        fprintf(stderr, "Getting vhost from logline\n");
#endif
        vhost = line;
        outline = index(line, ' ');

        if(outline == NULL) {
                fprintf(stderr, "Incorrect logline: no vhost,");
                return 1;
        }

        *outline = '\0';
        outline++;

        /* If the vhost is ".." or "." then reject it */
        if (strcmp(vhost, "..") == 0 || strcmp(vhost, ".") == 0) {
                fprintf(stderr,"Incorrect vhost: invalid chars,");
                return 1;
        }

        /* If the "vhost" part contains invalid chars
           then log the entire line to "hostname" */
        if (strspn(vhost, VHOSTCHARS) != strlen(vhost)) {
                outline[-1] = ' ';
                outline = line;
                vhost = hostname;
        }

        if (strlen(vhost) < 1 || strlen(outline) < 1) {
                fprintf(stderr,"Incorrect vhost/line: too short,");
                return 1;
        }

#ifdef DEBUG
        fprintf(stderr, "Got vhost: %s\n", vhost);
#endif

        if ((strlen(logdir) + strlen(vhost)) > PATH_MAX) {
                fprintf(stderr, "Incorrect logdir/vhost: too long,");
                return 1;
        }

        if (snprintf(logfile, PATH_MAX+1, "%s/%s", logdir, vhost) < 0) {
                fprintf(stderr, "Error building logfile string,");
                return 1;
        }

#ifdef DEBUG
        fprintf(stderr, "Got logfile: %s\n", logfile);
#endif

        /* Open logfile, and write the output */
#ifdef DEBUG
        fprintf(stderr, "Writing output to logfile\n");
#endif
        if ((outfile = fopen(logfile, "a")) == NULL) {
                fprintf(stderr, "Failed opening logfile %s: %s,",
                        logfile, strerror(errno));
                return 1;
        }

        if (fputs(outline, outfile) < 0) {
          fprintf(stderr, "Failed writing to logfile %s,", logfile);
          if (fclose(outfile) == EOF) {
                fprintf(stderr, "Failed closing logfile %s: %s,",
                        logfile, strerror(errno));
                return 1;
          };
        };

        if (fclose(outfile) == EOF) {
                fprintf(stderr, "Failed closing logfile %s: %s,",
                        logfile, strerror(errno));
                return 1;
        };

        return 0;
}