/*-
 * xlog.c --
 *	Flexible error logging facility.
 *
 * Copyright (c) 1992 by Andreas Stolcke
 *
 * Permission to use, copy, modify, and distribute this
 * software and its documentation for any non-commercial purpose
 * and without fee is hereby granted, provided that the above copyright
 * notice appears in all copies.  Andreas Stolcke makes no representations about
 * the suitability of this software for any purpose.  It is provided
 * "as is" without express or implied warranty.
 *
 */
#ifndef lint
static char *rcsid =
"$Id: xlog.c,v 1.6 1999/06/28 22:20:44 stolcke Exp $ ICSI (Berkeley)";
#endif /* not lint */

#include <string.h>
#include <errno.h>

extern int errno;

#include "sprite.h"
#include "xlog.h"

#undef perror

static FILE *log;		/* Current log target (std error default) */
static int facility = 0;	/* Current log facility */
static char *program = NULL;	/* Program name to identify log entries */

static FILE *oldLog;		/* Previous log target ... */
static int oldFacility = 0;	/* ... and facility */

void
xlog_init()
{
    static do_init = 1;

    /*
     * Make stderr the default log destination at startup
     */
    if (do_init) {
	oldLog = log = stderr;
	do_init = 0;
    }
}

/*-
 *-----------------------------------------------------------------------
 * xlog_set --
 *	Set the log target.
 *
 * Results:
 *	None.
 *
 * Side Effects:
 *	Future log entries are redirected; syslog is opened/closed as
 *	appropriate.
 *
 *-----------------------------------------------------------------------
 */
/*VARARGS2*/
void
xlog_set(name, newLog, newFac)
    char *name;			/* Program name to use in log entries */
    FILE *newLog;		/* Log file */
    int newFac;			/* Facility name for syslog(3) */
{
    int newFacility;

    xlog_init();

    if (name)
	program = name;

    if (newLog == XLOG_PREVIOUS) {
	newLog = oldLog;
	newFacility = oldFacility;
    } else if (newLog == XLOG_SYSLOG) {
	newFacility = newFac;
    } else {
	newFacility = 0;
    }

    if (log == XLOG_SYSLOG && newLog != XLOG_SYSLOG)
	closelog();
 
    oldLog = log;
    oldFacility = facility;
    log = newLog;
    facility = newFacility;

    if (log == XLOG_SYSLOG)
#ifndef LOG_CONS	/* 4.2BSD syslog */
	openlog(program, LOG_PID);
#else
	openlog(program, LOG_PID|LOG_CONS, facility);
#endif
}

/*-
 *-----------------------------------------------------------------------
 * xlog --
 *	Log an error message.
 *
 * Results:
 *	None.
 *
 * Side Effects:
 *	Message is logged to current log target.
 *
 *-----------------------------------------------------------------------
 */
#ifdef HAVE_VSYSLOG
#include <stdarg.h>

void
xlog(int level, char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);

    xlog_init();

    if (log == XLOG_NONE)
	return;

    if (log == XLOG_SYSLOG)
	vsyslog((level == XLOG_FATAL ? LOG_ALERT :
		(level == XLOG_ERROR ? LOG_ERR :
		 (level == XLOG_WARNING ? LOG_WARNING :
		  (level == XLOG_INFO ? LOG_INFO :
		   (level == XLOG_DEBUG ? LOG_DEBUG : LOG_ERR))))),
		fmt, args);
    else {
	if (program && *program)
	    fprintf(log, "%s: ", program);
	vfprintf(log, fmt, args);
	if (fmt[strlen(fmt) - 1] != '\n')
	    fprintf(log, "\n");
	fflush(log);
    }
    va_end(args);
}
#else /* !HAVE_SYSLOG */

/*VARARGS2*/
void
xlog(level, fmt, p1, p2, p3, p4, p5, p6)
    int level;			/* Log level */
    char *fmt;			/* Format string */
    char *p1, *p2, *p3, *p4, *p5, *p6;	/* Format arguments */
{
    xlog_init();

    if (log == XLOG_NONE)
	return;

    if (log == XLOG_SYSLOG)
	syslog((level == XLOG_FATAL ? LOG_ALERT :
		(level == XLOG_ERROR ? LOG_ERR :
		 (level == XLOG_WARNING ? LOG_WARNING :
		  (level == XLOG_INFO ? LOG_INFO :
		   (level == XLOG_DEBUG ? LOG_DEBUG : LOG_ERR))))),
		fmt, p1, p2, p3, p4, p5, p6);
    else {
	if (program && *program)
	    fprintf(log, "%s: ", program);
	fprintf(log, fmt, p1, p2, p3, p4, p5, p6);
	if (fmt[strlen(fmt) - 1] != '\n')
	    fprintf(log, "\n");
	fflush(log);
    }
}
#endif /* HAVE_VSYSLOG */

/*-
 *-----------------------------------------------------------------------
 * xlog_perror --
 *	Log a system error message given by errno.
 *
 * Results:
 *	None.
 *
 * Side Effects:
 *	Message is logged to current log target.
 *
 *-----------------------------------------------------------------------
 */
void
xlog_perror(str)
    char *str;
{
    if (str && *str)
	xlog(XLOG_ERROR, "%s: %s", str, strerror(errno));
    else
	xlog(XLOG_ERROR, "%s", strerror(errno));
}

