logRotate.c 2.61 KB
#include <sys/select.h> /* for select system call and related */
#include <time.h>
#include <unistd.h>     /* for fork and exec */
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>      /* fopen and stuff */
#include <stdlib.h>     /* exit */
#include <string.h>     /* strncpy, memcpy, etc. */
#include <syslog.h>
#include <errno.h>

#include "../include/monitor.h"


extern int verbose;

void logRotate(FILE ** handle, char * path, char * pattern) {
    static char logName[1024]     = "";

    char        strftimeName[128] = "";
    char        newLogName[1024]  = "";

    time_t      t;
    struct tm   *tmp;

    t   = time(NULL);
    tmp = localtime(&t);
    if (tmp == NULL) {
        syslogMonitor(LOG_ERR, MON_INFO, "logrotate.localtime",
                "can't get localtime for new logname. continue with old one");
        return;
    }

    if (strftime(strftimeName, sizeof(strftimeName)-1, pattern, tmp) == 0) {
        syslogMonitor(LOG_ERR, MON_INFO, "logrotate.strftime", 
                "strftime returned 0 for new logname. continue with old one");
        return;
    }

    snprintf(newLogName, sizeof(newLogName)-1, "%s/%s", path, strftimeName);

    if (0 != strncmp(logName, newLogName, sizeof(logName)-1)) {
        if (0 != verbose) {
            syslog(LOG_INFO, "actual logfile name: %s", logName);
            syslog(LOG_INFO, "new logfile name: %s", newLogName);
        }

        if (NULL != *handle) {
            fclose(*handle);

            pid_t gzipPid = fork();

            switch(gzipPid) {
                pid_t tmpPid;

                case 0:
                    // We don't care about finishing of child, so decouple it
                    // by using a second child that stop immediatly
                    tmpPid = fork();
                    if (0 == tmpPid) {
                        syslog(LOG_INFO, "gzip: %s", logName);
                        if (-1 == execl("/bin/gzip", "/bin/gzip", "-9", logName, (char *) 0)) {
                            syslogMonitor(LOG_ERR, MON_INFO, "logrotate.gzip",
                                    "execl failed for gzip %s: %s", logName, strerror(errno));
                        }
                    }
                    exit(EXIT_SUCCESS);

                case -1:
                    syslogMonitor(LOG_ERR, MON_INFO, "logrotate.fork",
                            "fork failed for gzip %s: %s", logName, strerror(errno));
                    break;

                default:
                    wait(NULL);
                    break;
            }
        }

        strncpy(logName, newLogName, sizeof(logName)-1);
        *handle = fopen(logName, "w");
    }
}