[BACK]Return to log.c CVS log [TXT][DIR] Up to [local] / src / sbin / photurisd

File: [local] / src / sbin / photurisd / Attic / log.c (download)

Revision 1.1, Mon Dec 11 21:21:18 2000 UTC (23 years, 5 months ago) by provos
Branch: MAIN
CVS Tags: OPENBSD_2_9_BASE, OPENBSD_2_9

proper logging.

/*	$OpenBSD: log.c,v 1.1 2000/12/11 21:21:18 provos Exp $	*/
/*	$EOM: log.c,v 1.30 2000/09/29 08:19:23 niklas Exp $	*/

/*
 * Copyright (c) 1998, 1999 Niklas Hallqvist.  All rights reserved.
 * Copyright (c) 1999, 2000 Håkan Olsson.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Ericsson Radio Systems.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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 AUTHOR 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.
 */

/*
 * This code was written under funding by Ericsson Radio Systems.
 */

#include <sys/time.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif

#include "log.h"

static void _log_print (int, int, const char *, va_list, int, int);

static FILE *log_output;
#ifdef USE_DEBUG
static int log_level[LOG_ENDCLASS];
#endif

void
log_init (void)
{
  log_output = stderr;
}

void
log_to (FILE *f)
{
  if (!log_output && f)
    closelog ();
  log_output = f;
  if (!f)
    openlog ("isakmpd", LOG_CONS, LOG_DAEMON);
}

FILE *
log_current (void)
{
  return log_output;
}

static char *
_log_get_class (int error_class)
{
  /* XXX For test purposes. To be removed later on?  */
  static char *class_text[] = LOG_CLASSES_TEXT;

  if (error_class < 0)
    return "Dflt";
  else if (error_class >= LOG_ENDCLASS)
    return "Unkn";
  else
    return class_text[error_class];
}

static void
_log_print (int error, int syslog_level, const char *fmt, va_list ap, 
	    int class, int level)
{
  char buffer[LOG_SIZE], nbuf[LOG_SIZE + 32];
  static const char fallback_msg[] = 
    "write to log file failed (errno %d), redirecting output to syslog";
  int len;
  struct tm *tm;
  struct timeval now;
  time_t t;

  len = vsnprintf (buffer, LOG_SIZE, fmt, ap);
  if (len < LOG_SIZE - 1 && error)
    snprintf (buffer + len, LOG_SIZE - len, ": %s", strerror (errno));
  if (log_output)
    {
      gettimeofday (&now, 0);
      t = now.tv_sec;
      tm = localtime (&t);
      if (class >= 0)
	sprintf (nbuf, "%02d%02d%02d.%06ld %s %02d ", tm->tm_hour, 
		 tm->tm_min, tm->tm_sec, now.tv_usec, _log_get_class (class), 
		 level);
      else /* LOG_PRINT (-1) or LOG_REPORT (-2) */
	sprintf (nbuf, "%02d%02d%02d.%06ld %s ", tm->tm_hour, 
		 tm->tm_min, tm->tm_sec, now.tv_usec,
		 class == LOG_PRINT ? "Default" : "Report>");	
      strcat (nbuf, buffer);
      strcat (nbuf, "\n");

      if (fwrite (nbuf, strlen (nbuf), 1, log_output) == 0)
	{
	  /* Report fallback.  */
	  syslog (LOG_ALERT, fallback_msg, errno);
	  fprintf (log_output, fallback_msg, errno);

	  /* 
	   * Close log_output to prevent isakmpd from locking the file.
	   * We may need to explicitly close stdout to do this properly.
	   * XXX - Figure out how to match two FILE *'s and rewrite.
	   */  
	  if (fileno (log_output) != -1)
	    if (fileno (stdout) == fileno (log_output))
	      fclose (stdout);
	  fclose (log_output);

	  /* Fallback to syslog.  */
	  log_to (0);

	  /* (Re)send current message to syslog(). */
	  syslog (class == LOG_REPORT ? LOG_ALERT : syslog_level, "%s", buffer);
	}
    }
  else
    syslog (class == LOG_REPORT ? LOG_ALERT : syslog_level, "%s", buffer);
}

#ifdef USE_DEBUG
void
#ifdef __STDC__
log_debug (int cls, int level, const char *fmt, ...)
#else
log_debug (cls, level, fmt, va_alist)
     int cls;
     int level;
     const char *fmt;
     va_dcl
#endif
{
  va_list ap;

  /*
   * If we are not debugging this class, or the level is too low, just return.
   */
  if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls]))
    return;
#ifdef __STDC__
  va_start (ap, fmt);
#else
  va_start (ap);
  fmt = va_arg (ap, const char *);
#endif
  _log_print (0, LOG_DEBUG, fmt, ap, cls, level);
  va_end (ap);
}

void
log_debug_buf (int cls, int level, const char *header, const u_int8_t *buf,
	       size_t sz)
{
  char s[73];
  int i, j;

  /*
   * If we are not debugging this class, or the level is too low, just return.
   */
  if (cls >= 0 && (log_level[cls] == 0 || level > log_level[cls]))
    return;

  log_debug (cls, level, "%s:", header);
  for (i = j = 0; i < sz;)
    {
      sprintf (s + j, "%02x", buf[i++]);
      j += 2;
      if (i % 4 == 0)
	{
	  if (i % 32 == 0)
	    {
	      s[j] = '\0';
	      log_debug (cls, level, "%s", s);
	      j = 0;
	    }
	  else
	    s[j++] = ' ';
	}
    }
  if (j)
    {
      s[j] = '\0';
      log_debug (cls, level, "%s", s);
    }
}

void
log_debug_cmd (int cls, int level)
{
  if (cls < 0 || cls >= LOG_ENDCLASS)
    {
      log_print ("log_debug_cmd: invalid debugging class %d", cls);
      return;
    }

  if (level < 0)
    {
      log_print ("log_debug_cmd: invalid debugging level %d for class %d",
		 level, cls);
      return;
    }

  if (level == log_level[cls])
    log_print ("log_debug_cmd: log level unchanged for class %d", cls);
  else
    {
      log_print ("log_debug_cmd: log level changed from %d to %d for class %d",
		 log_level[cls], level, cls);
      log_level[cls] = level;
    }
}
#endif /* USE_DEBUG */

void
#ifdef __STDC__
log_print (const char *fmt, ...)
#else
log_print (fmt, va_alist)
     const char *fmt;
     va_dcl
#endif
{
  va_list ap;

#ifdef __STDC__
  va_start (ap, fmt);
#else
  va_start (ap);
  fmt = va_arg (ap, const char *);
#endif
  _log_print (0, LOG_NOTICE, fmt, ap, LOG_PRINT, 0);
  va_end (ap);
}

void
#ifdef __STDC__
log_error (const char *fmt, ...)
#else
log_error (fmt, va_alist)
     const char *fmt;
     va_dcl
#endif
{
  va_list ap;

#ifdef __STDC__
  va_start (ap, fmt);
#else
  va_start (ap);
  fmt = va_arg (ap, const char *);
#endif
  _log_print (1, LOG_ERR, fmt, ap, LOG_PRINT, 0);
  va_end (ap);
}

void
#ifdef __STDC__
log_fatal (const char *fmt, ...)
#else
log_fatal (fmt, va_alist)
     const char *fmt;
     va_dcl
#endif
{
  va_list ap;

#ifdef __STDC__
  va_start (ap, fmt);
#else
  va_start (ap);
  fmt = va_arg (ap, const char *);
#endif
  _log_print (1, LOG_CRIT, fmt, ap, LOG_PRINT, 0);
  va_end (ap);
  exit (1);
}