root/usr/src/lib/libldap5/sources/ldap/util/log.c
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <nl_types.h>
#include <limits.h>
#include <stdarg.h>
#include <string.h>

#include <syslog.h>
#include <portable.h>
/* #include <lthread.h> */
#include <pthread.h>
#include <thread.h>

#include "log.h"

#define LDAP_DEBUG_ANY  0xffff

static pthread_mutex_t  log_mutex;
static char             logfile[PATH_MAX] =
                                        "/var/opt/SUNWconn/ldap/log/slapd.log";
static int              logsize = 512000;
static int              logtime = 1;
static FILE             *logfd = NULL;
static int              syslogopen = 0;
pthread_mutex_t         systime_mutex;
nl_catd                 sundscat;
static int              log_debug = LDAP_DEBUG_STATS;

typedef struct _logctx {
        char            *logfile;
        int             syslogopen;
        int             logsize;
        pthread_mutex_t log_mutex;
        int             log_debug;
        int             log_syslog;

} LogCtx;

void
ldaplogconfig(char *logf, int size)
{
        strcpy(logfile, logf);
        logsize = size * 1024;
}

void
ldaplogconfigf(FILE *fd)
{
        logfd = fd;
        logsize = 0;
}

void
ldaploginit(char *name, int facility)
{
        openlog(name, OPENLOG_OPTIONS, facility);
        syslogopen = 1;
        pthread_mutex_init(&log_mutex, NULL);
}

void
ldaploginitlevel(char *name, int facility, int level)
{
        ldaploginit(name, facility);
        log_debug = level;
}

LogCtx *
sundsloginit(char *name, int facility, int debug_level, int syslog_level)
{
        LogCtx *returnCtx = NULL;

        if ((returnCtx = (LogCtx *)malloc(sizeof (LogCtx))) == NULL)
                return (NULL);
        if ((returnCtx->logfile = strdup(name)) == NULL) {
                free(returnCtx);
                return (NULL);
        }
        openlog(returnCtx->logfile, OPENLOG_OPTIONS, facility);
        returnCtx->syslogopen = 1;
        pthread_mutex_init(&(returnCtx->log_mutex), NULL);
        returnCtx->log_debug = debug_level;
        returnCtx->log_syslog = syslog_level;
        return (returnCtx);
}

static char timestr[128];
static time_t timelast = 0;

/*VARARGS*/
void
ldaplog(int level, char *fmt, ...)
{
        va_list ap;
        struct stat statbuf = {0};
        char newlog1[PATH_MAX];
        char newlog2[PATH_MAX];
        time_t now;
        int i;

        if (!(log_debug & level))
                return;

        va_start(ap, fmt);

        if (level == LDAP_DEBUG_ANY) {
                /*
                 * this message is probably an error message, send it to syslog
                 */
                if (syslogopen) {
                        vsyslog(LOG_ERR, fmt, ap);
                } /* end if */
                /* and sent it also on stderr */
                vfprintf(stderr, fmt, ap);
        } /* end if */

        /*
         * check that the log file is not already too big
         */
        pthread_mutex_lock(&log_mutex);
        if ((logsize > 0) && (stat(logfile, &statbuf) == 0 &&
                                        statbuf.st_size > logsize)) {
                for (i = 9; i > 1; i--) {
                        (void) sprintf(newlog1, "%s.%d", logfile, i-1);
                        (void) sprintf(newlog2, "%s.%d", logfile, i);
                        (void) rename(newlog1, newlog2);
                } /* end for */
                if (logfd) {
                        fclose(logfd);
                        logfd = NULL;
                } /* end if */
                (void) rename(logfile, newlog1);
        } /* end if */
        /*
         * send the message into a regular log file
         */
        if (!logfd) {
                logfd = fopen(logfile, "aF");
        } /* end if */
        /*
         * finally write the message into the log file
         */
        if (logfd) {
                if (logtime) {
                        time(&now);
                        if (now-timelast > 60) {
                                pthread_mutex_lock(&systime_mutex);
                                timelast = now;
                                ctime_r(&now, timestr, 128);
                                pthread_mutex_unlock(&systime_mutex);
                        } /* end if */
                        fprintf(logfd, "%.16s : ", timestr);
                } /* end if */
                vfprintf(logfd, fmt, ap);
                fflush(logfd);
        } /* end if */
        pthread_mutex_unlock(&log_mutex);
        va_end(ap);
}