#if !defined(lint) && !defined(__INSIGHT__)
static char sos__rcsid[] = "log.c,v 1.1.1.1 1995/06/16 17:42:41 seth Exp";
static char sos__copyright[] = "Copyright (c) 1994, 1995 SOS Corporation";
static char sos__contact[] = "SOS Corporation <sos-info@soscorp.com> +1 800 SOS UNIX";
#endif /* not lint */

/*
 * ++Copyright Released Product++
 *
 * Copyright (c) 1994, 1995 Sources of Supply Corporation ("SOS").
 * All rights reserved.
 *
 * The SOS Released Product License Agreement specifies the terms and
 * conditions for redistribution.  You may find the License Agreement
 * in the file LICENSE.
 *
 * SOS Corporation
 * 461 5th Ave.; 16th floor
 * New York, NY 10017
 *
 * +1 800 SOS UNIX
 * <sos-info@soscorp.com>
 *
 * --Copyright Released Product--
 */

/*
 * Interface to syslog
 *
 * Primarily add value added tags for easy postprocessing
 */

#include "sos.h"


/*
 * Logging code
 *
 * Since one goal is to make log processing easy and worthwhile, we
 * are going to add a number of `tags' into our logs. First off each
 * syslog message will of course contain date, machine, program tag,
 * and pid -- these you get for free with syslog. In addition will
 * will add the following.
 *
 *      Message type:
 *                      EVENT some user initiated activity worthy of notice
 *                      CONDITION for any non-user initiated activities
 *
 *      Priority String:
 *                      Much like syslog, except that in addition to any
 *                      normal syslog activities, the priority is recorded
 *                      in the log message
 *
 * Although these extra tags will (obviously) increase the verbosity of our
 * logs, it will aid in writing more intelligent and focused `swatch'
 * scripts. Or at least that's the hope :-)
 *
 * We will define our own set of logging levels based on syslogs.
 *
 *                      LOGGING PRIORITIES (levels)
 *
 * SOSLOG_EMERG
 *      Some horrific event (e.g. machine on fire, cracker became root, etc)
 *
 * SOSLOG_ALERT
 *      Non-recoverable condition which must be fixed before any
 *      further processing can be done.  Typically ALERTs would
 *      effect multiple programs (e.g. /etc/passwd corrupted)
 *
 * SOSLOG_CRIT
 *      Non-recoverable condition which must be fixed before any
 *      further processing can be done.  Typically CRITs only
 *      effect one program (e.g. named configuration error)
 *
 * SOSLOG_ERR
 *      Errors which are fatal or at least not handled very gracefully.
 *
 * SOSLOG_WARNING
 *      Errors which are not fatal and are handled gracefully.
 *
 * SOSLOG_NOTICE
 *      Conditions which are worthy of notice but are ``normal''
 *      (e.g. authentication failures)
 *
 * SOSLOG_INFO
 *      Information messages--connections made, connections terminated, etc
 *
 * SOSLOG_DEBUG
 *      True trivia. ONLY LOGGED WHEN soslog_debug IS TRUE!!!
 *
 *                      TYPE OF LOGGING MESSAGES
 *
 * SOSLOG_TYPE_EVENT            User initiated activity causing log
 * SOSLOG_TYPE_CONDITION        Non-user (or at least indirectly) activity
 * */

/*
 * General buffer space for use in this module. As always use with care.
 */
static char soslogbuf[SOSLOG_BUFSIZ];

/*
 * Module state variable that indicates the openess of the log
 */
static int soslog_open = 0;

/*
 * Externally visible debugging symbol
 * Note this doesn't turn on debugging of the authentication log, rather it
 * allows logging of debugging messages.
 */
int soslog_debug = 0;



/* soslog (priority, auth log type want_perror,fmt, args) */
void
soslog(int pri, int type, int want_perror, const char *fmt,...)
{
  va_list args;

  va_start(args, fmt);
  vsoslog(pri, type, want_perror, fmt, args);
  va_end(args);
}


void
vsoslog(int pri, int type, int want_perror, const char *fmt, va_list args)
{
  char const *level = "UNKNOWN";

  /* Ignore debugging messages if debugging isn't turned on */
  if (pri == SOSLOG_DEBUG && !soslog_debug)
    return;

  vsprintf(soslogbuf, fmt, args);

  switch (pri)
    {
    case SOSLOG_EMERG:
      level = "EMERG";
      break;
    case SOSLOG_ALERT:
      level = "ALERT";
      break;
    case SOSLOG_CRIT:
      level = "CRITICAL";
      break;
    case SOSLOG_ERR:
      level = "ERROR";
      break;
    case SOSLOG_WARNING:
      level = "WARNING";
      break;
    case SOSLOG_NOTICE:
      level = "NOTICE";
      break;
    case SOSLOG_INFO:
      level = "INFO";
      break;
    case SOSLOG_DEBUG:
      level = "DEBUG";
      break;
    }

  /* XXX - Note that SOSLOG priority levels are the same as syslogs!! */

  if (want_perror)
    syslog(pri, "%s: %s: %s: %m",
	   (type == SOSLOG_TYPE_EVENT ? "EVENT" : "CONDITION"),
	   level,
	   soslogbuf);
  else
    syslog(pri, "%s: %s: %s",
	   (type == SOSLOG_TYPE_EVENT ? "EVENT" : "CONDITION"),
	   level,
	   soslogbuf);

  return;
}



/*
 * Open our version of logging.
 */
void
open_soslog(char const *ident, int allow_debug)
{
  /*
   * Allow people to set whether or not to log debug
   * levels even if log is open
   */
  soslog_debug = allow_debug;

  /* 
   * We are going to let this function be visible for extern calls.  Our 
   * library routines will always call it, but if someone else has beaten us
   * to the punch silently return;
   */
  if (soslog_open)
    return;

  /*
   * At the outset we will just use syslog. Since this routine will actually
   * log the first message, there is no reason to not to open the log
   * immediately.
   */

  openlog(ident, LOG_PID | LOG_CONS | LOG_NDELAY, LOG_AUTH);

  soslog_open = 1;

  soslog(SOSLOG_DEBUG, SOSLOG_TYPE_CONDITION, SOSLOG_NO_PERROR,
	 "Logging started");

  return;

}



/*
 * Close up the auth log.
 */
void
close_soslog()
{
  /* Should this be DEBUG?  Hmm */
  soslog(SOSLOG_DEBUG, SOSLOG_TYPE_CONDITION, SOSLOG_NO_PERROR,
	 "Logging ended");

  if (soslog_open)
    closelog();
}
