/* $Cambridge: hermes/src/prayer/accountd/log.c,v 1.2 2007/12/05 14:58:07 dpc22 Exp $ */
/************************************************
 *    Prayer - a Webmail Interface              *
 ************************************************/

/* Copyright (c) University of Cambridge 2000 - 2002 */
/* See the file NOTICE for conditions of use and distribution. */

#include "accountd.h"
#include <syslog.h>
#include <sys/stat.h>
#include <fcntl.h>

/* Syslog interface largely cripped from main Prayer code */

/* Record programs argv[0] so that we can give useful error messages */
static char *log_progname = NIL;

/* log_init() ************************************************************
 *
 * Initial the log subsystem
 *    config: Accountd configuration
 *  progname: Porgram name
 ************************************************************************/

void log_init(struct config *config, char *progname)
{
    char *s;

    if ((s = strrchr(progname, '/')))
        log_progname = strdup(s + 1);
    else
        log_progname = strdup(progname);

    /* XXX */
    openlog(log_progname, LOG_PID, LOG_USER);
}

/* ====================================================================== */

/* Return size of log entry item. Doesn't include timestamps and other
 * (fixed length) padding that that the log function may what to add
 */

unsigned long log_entry_size(char *fmt, va_list ap)
{
    return (pool_vprintf_size(fmt, ap));
}

/* ====================================================================== */

/* log_out_of_memory() ***************************************************
 *
 * Out of memory while trying to report error. Send something to
 * syslog and paniclog so we have some idea what is going on.
 ************************************************************************/

static void log_out_of_memory(void)
{
    if (log_progname)
        fprintf(stderr, "%s PANICLOG:\n", log_progname);
    else
        fprintf(stderr, "Prayer PANICLOG:\n");
    fprintf(stderr, "  [log_panic] Out of memory\n");

    if (log_progname)
        openlog(log_progname, LOG_PID | LOG_CONS, LOG_MAIL);
    else
        openlog("prayer", LOG_PID | LOG_CONS, LOG_MAIL);

    syslog(LOG_ERR, "[log_panic] Out of memory");
    closelog();
}

/* ====================================================================== */

/* log_syslog_ap() ******************************************************
 *
 * Log string message to syslog.
 ************************************************************************/

void log_syslog_ap(unsigned long len, char *fmt, va_list ap)
{
    char *result;

    /* Alloc temporary buffer with space for Date + Expanded String + \n */
    if ((result = malloc(len + 100)) == NIL) {
        log_out_of_memory();
        return;
    }

    pool_vprintf(result, fmt, ap);
    syslog(LOG_INFO, "%s", result);

    free(result);
}

/* log_panic_ap() ********************************************************
 *
 * Log string message to syslog and stderr
 ************************************************************************/

void log_panic_ap(unsigned long len, char *fmt, va_list ap)
{
    char *result;

    /* Alloc temporary buffer with space for Date + Expanded String + \n */
    if ((result = malloc(len + 100)) == NIL) {
        log_out_of_memory();
        return;
    }

    pool_vprintf(result, fmt, ap);
    syslog(LOG_INFO, "%s", result);
    fprintf(stderr, "%s\n", result);

    free(result);
}

/* ====================================================================== */

void log_misc(char *fmt, ...)
{
    unsigned long len;
    va_list ap;

    va_start(ap, fmt);
    len = pool_vprintf_size(fmt, ap);
    va_end(ap);

    va_start(ap, fmt);
    log_syslog_ap(len, fmt, ap);
    va_end(ap);
}

void log_debug(char *fmt, ...)
{
    unsigned long len;
    va_list ap;

    va_start(ap, fmt);
    len = pool_vprintf_size(fmt, ap);
    va_end(ap);

    va_start(ap, fmt);
    log_syslog_ap(len, fmt, ap);
    va_end(ap);
}

void log_panic(char *fmt, ...)
{
    unsigned long len;
    va_list ap;

    va_start(ap, fmt);
    len = pool_vprintf_size(fmt, ap);
    va_end(ap);

    va_start(ap, fmt);
    log_syslog_ap(len, fmt, ap);
    va_end(ap);
}

void log_fatal(char *fmt, ...)
{
    unsigned long len;
    va_list ap;

    va_start(ap, fmt);
    len = pool_vprintf_size(fmt, ap);
    va_end(ap);

    va_start(ap, fmt);
    log_syslog_ap(len, fmt, ap);
    va_end(ap);

    exit(1);
}
