OSSP CVS Repository

ossp - ossp-pkg/l2/l2_syslog.c
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/l2/l2_syslog.c
/*
**  L2 - OSSP Logging Library
**  Copyright (c) 2001-2002 The OSSP Project (http://www.ossp.org/)
**  Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/)
**
**  This file is part of OSSP L2, a flexible logging library which
**  can be found at http://www.ossp.org/pkg/l2/.
**
**  Permission to use, copy, modify, and distribute this software for
**  any purpose with or without fee is hereby granted, provided that
**  the above copyright notice and this permission notice appear in all
**  copies.
**
**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
**  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
**  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
**  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
**  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
**  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
**  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
**  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
**  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
**  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
**  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
**  SUCH DAMAGE.
**
**  l2_syslog.c: syslog(3) faked API library
*/

/* standard includes we use */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>

/* own includes */
#include "l2.h"
#include "l2_p.h"

/* standard include we re-implement */
#include <syslog.h>

/* default for the dedicated logfile */
#ifndef LOGFILE
#define LOGFILE "/tmp/syslog"
#endif

#ifndef LOG_PRIMASK
#define LOG_PRIMASK (LOG_EMERG|LOG_ALERT|LOG_CRIT|LOG_ERR|LOG_WARNING|LOG_NOTICE|LOG_INFO|LOG_DEBUG)
#endif
#ifndef LOG_PRI
#define LOG_PRI(p) ((p) & LOG_PRIMASK)
#endif

/* log level to string mapping */
static struct {
    int level;
    char *string;
} level2string[] = {
    { LOG_EMERG,   "emerg"    },
    { LOG_ALERT,   "alert"    },
    { LOG_CRIT,    "crit"     },
    { LOG_ERR,     "err"      },
    { LOG_WARNING, "warning"  },
    { LOG_NOTICE,  "notice"   },
    { LOG_INFO,    "info"     },
    { LOG_DEBUG,   "debug"    },
    { 0,           NULL       }
};

/* internal context structure */
static struct {
    FILE *log;
    char *logfile;
    const char *ident;
    int logopt;
    int facility;
    int maskpri;
} ctx = { 
    NULL, LOGFILE, "unknown", 0, LOG_USER, 0xff
};

void openlog(const char *ident, int logopt, int facility)
{
    /* remember parameters */
    ctx.ident    = ident;
    ctx.logopt   = logopt;
    ctx.facility = facility;

    /* close perhaps still open logfile */
    if (ctx.log != NULL) {
        fclose(ctx.log);
        ctx.log = NULL;
    }

    /* (re-)open new logfile */
    if (!(ctx.logopt & LOG_NDELAY) && ctx.log == NULL)
        if ((ctx.log = fopen(ctx.logfile, "a")) == NULL)
            return;
    return;
}

void closelog(void)
{
    /* close open logfile*/
    if (ctx.log != NULL) {
        fclose(ctx.log);
        ctx.log = NULL;
    }
    return;
}

int setlogmask(int maskpri)
{
    int omask;

    /* remember the logging mask */
    omask = ctx.maskpri;
    if (maskpri != 0)
        ctx.maskpri = maskpri;
    return omask;
}

void syslog(int priority, const char *message, ...)
{
    va_list args;

    /* wrap around vsyslog(3) */
    va_start(args, message);
    vsyslog(priority, message, args);
    va_end(args);
    return;
}

#ifdef HAVE_VSYSLOG_USVALIST
void vsyslog(int priority, const char *fmt, __va_list args)
#else
void vsyslog(int priority, const char *fmt, va_list args)
#endif
{
    time_t now;
    int saved_errno;
    char buf[2048];
    char *cpBuf;
    int nBuf;
    char caMsg[2048];
    char *cpMsg;
    char *cpFmt;
    int i;
    char *cpTime;
    char *cpLevel;

    /* Check for invalid bits */
    if (priority & ~(LOG_PRIMASK|LOG_FACMASK))
        priority &= (LOG_PRIMASK|LOG_FACMASK);

    /* stop processing if mask disabled this call */
    if (!(LOG_MASK(LOG_PRI(priority)) & ctx.maskpri))
        return;

    /* make sure we have a reasonable default for facility */
    if ((priority & LOG_FACMASK) == 0)
        priority |= ctx.facility;

    /* remember errno for optional %m processing below */
    saved_errno = errno;

    /* open logfile now (if it was delayed) */
    if (ctx.log == NULL)
        if ((ctx.log = fopen(ctx.logfile, "a")) == NULL)
            return;

    /* determine current time */
    time(&now);
    cpTime = ctime(&now) + 4;

    /* determine logging level name */
    cpLevel = "unknown";
    for (i = 0; level2string[i].string != NULL; i++) {
        if (LOG_PRI(priority) == level2string[i].level) {
            cpLevel = level2string[i].string;
            break;
        }
    }
    
    /* start output generation */
    cpBuf = buf;
    sprintf(cpBuf, "%.15s <%s> %s", cpTime, cpLevel, ctx.ident);
    nBuf = strlen(cpBuf);

    /* optionally add process id */
    if (ctx.logopt & LOG_PID) {
        sprintf(cpBuf+nBuf, "[%d]", getpid());
        nBuf += strlen(cpBuf+nBuf);
    }

    /* end prefix */
    strcpy(cpBuf+nBuf, ": ");
    nBuf += 2;

    /* optionally expand %m in format string */
    cpFmt = (char *)fmt;
    if (strstr(cpFmt, "%m")) {
        cpMsg = caMsg;
        while (cpFmt[0] != '\0') {
            if (cpFmt[0] == '%' && cpFmt[1] == 'm') {
                strcpy(cpMsg, strerror(saved_errno));
                cpMsg += strlen(cpMsg);
                cpFmt += 2;
            } else {
                *cpMsg++ = *cpFmt++;
                *cpMsg = '\0';
            }
        }
        cpFmt = caMsg;
    }

    /* append message to output buffer */
    vsprintf(cpBuf+nBuf, cpFmt, args);
    nBuf += strlen(cpBuf+nBuf);

    /* append newline if still not present */
    if (cpBuf[nBuf-1] != '\n') {
        cpBuf[nBuf++] = '\n';
        cpBuf[nBuf] = '\0';
    }

    /* now finally write output buffer to logfile */
    fwrite(cpBuf, nBuf, 1, ctx.log);
    fflush(ctx.log);

#ifdef LOG_PERROR
    /* optionally also write output buffer to stderr */
    if (ctx.logopt & LOG_PERROR)
        fwrite(cpBuf, nBuf, 1, stderr);
#endif

    return;
}


CVSTrac 2.0.1