[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] Add SysLog option to direct log messages to the system log ...



Update of /home/or/cvsroot/src/common
In directory moria.mit.edu:/tmp/cvs-serv9964/src/common

Modified Files:
	log.c log.h util.c 
Log Message:
Add SysLog option to direct log messages to the system log instead of a FILE*.

Index: log.c
===================================================================
RCS file: /home/or/cvsroot/src/common/log.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- log.c	16 Oct 2004 22:28:11 -0000	1.54
+++ log.c	26 Oct 2004 21:48:40 -0000	1.55
@@ -34,6 +34,7 @@
   int loglevel; /**< Lowest severity level to send to this stream. */
   int max_loglevel; /**< Highest severity level to send to this stream. */
   int is_temporary; /**< Boolean: close after initializing logging subsystem.*/
+  int is_syslog; /**< Boolean: send messages to syslog. */
 } logfile_t;
 
 /** Helper: map a log severity to descriptive string. */
@@ -50,8 +51,13 @@
 
 /** Linked list of logfile_t. */
 static logfile_t *logfiles = NULL;
+#ifdef HAVE_SYSLOG_H
+static int syslog_count = 0;
+#endif
 
 static void delete_log(logfile_t *victim);
+static void close_log(logfile_t *victim);
+static int reset_log(logfile_t *lf);
 
 static INLINE size_t
 _log_prefix(char *buf, size_t buf_len, int severity)
@@ -104,16 +110,19 @@
 
 /** Helper: Format a log message into a fixed-sized buffer. (This is
  * factored out of <b>logv</b> so that we never format a message more
- * than once.)
+ * than once.)  Return a pointer to the first character of the message
+ * portion of the formatted string.
  */
-static INLINE void format_msg(char *buf, size_t buf_len,
+static INLINE char *format_msg(char *buf, size_t buf_len,
                               int severity, const char *funcname,
                               const char *format, va_list ap)
 {
   size_t n;
+  char *end_of_prefix;
   buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
 
   n = _log_prefix(buf, buf_len, severity);
+  end_of_prefix = buf+n;
 
   if (funcname) {
     n += snprintf(buf+n, buf_len-n, "%s(): ", funcname);
@@ -128,6 +137,7 @@
   }
   buf[n]='\n';
   buf[n+1]='\0';
+  return end_of_prefix;
 }
 
 /** Helper: sends a message to the appropriate logfiles, at loglevel
@@ -140,23 +150,32 @@
   char buf[10024];
   int formatted = 0;
   logfile_t *lf;
+  char *end_of_prefix=NULL;
 
   assert(format);
   lf = logfiles;
   while(lf) {
-    if (severity < lf->loglevel || severity > lf->max_loglevel) {
+    if (severity > lf->loglevel || severity < lf->max_loglevel) {
       lf = lf->next;
       continue;
     }
-    if (!lf->file) {
+    if (! (lf->file || lf->is_syslog)) {
       lf = lf->next;
       continue;
     }
 
     if (!formatted) {
-      format_msg(buf, sizeof(buf), severity, funcname, format, ap);
+      end_of_prefix =
+        format_msg(buf, sizeof(buf), severity, funcname, format, ap);
       formatted = 1;
     }
+    if (lf->is_syslog) {
+#ifdef HAVE_SYSLOG_H
+      syslog(severity, "%s", end_of_prefix);
+#endif
+      lf = lf->next;
+      continue;
+    }
     if(fputs(buf, lf->file) == EOF ||
        fflush(lf->file) == EOF) { /* error */
       /* don't log the error! Blow away this log entry and continue. */
@@ -194,8 +213,7 @@
   while(logfiles) {
     victim = logfiles;
     logfiles = logfiles->next;
-    if (victim->needs_close)
-      fclose(victim->file);
+    close_log(victim);
     tor_free(victim->filename);
     tor_free(victim);
   }
@@ -206,17 +224,12 @@
 {
   logfile_t *lf = logfiles;
   while(lf) {
-    if (lf->needs_close) {
-      if(fclose(lf->file)==EOF ||
-        !(lf->file = fopen(lf->filename, "a"))) {
-        /* error. don't log it. delete the log entry and continue. */
-        logfile_t *victim = lf;
-        lf = victim->next;
-        delete_log(victim);
-        continue;
-      } else {
-        log_tor_version(lf, 1);
-      }
+    if (reset_log(lf)) {
+      /* error. don't log it. delete the log entry and continue. */
+      logfile_t *victim = lf;
+      lf = victim->next;
+      delete_log(victim);
+      continue;
     }
     lf = lf->next;
   }
@@ -241,19 +254,43 @@
   tor_free(victim);
 }
 
+static void close_log(logfile_t *victim)
+{
+  if (victim->needs_close && victim->file) {
+    fclose(victim->file);
+  } else if (victim->is_syslog) {
+#ifdef HAVE_SYSLOG_H
+    if (--syslog_count == 0)
+      /* There are no other syslogs; close the logging facility. */
+      closelog();
+#endif
+  }
+}
+
+static int reset_log(logfile_t *lf)
+{
+  if (lf->needs_close) {
+    if(fclose(lf->file)==EOF ||
+       !(lf->file = fopen(lf->filename, "a"))) {
+      return -1;
+    } else {
+      log_tor_version(lf, 1);
+    }
+  }
+  return 0;
+}
+
 /** Add a log handler to send all messages of severity <b>loglevel</b>
  * or higher to <b>stream</b>. */
 void add_stream_log(int loglevelMin, int loglevelMax, const char *name, FILE *stream)
 {
   logfile_t *lf;
-  lf = tor_malloc(sizeof(logfile_t));
+  lf = tor_malloc_zero(sizeof(logfile_t));
   lf->filename = tor_strdup(name);
-  lf->needs_close = 0;
   lf->loglevel = loglevelMin;
   lf->max_loglevel = loglevelMax;
   lf->file = stream;
   lf->next = logfiles;
-  lf->is_temporary = 0;
   logfiles = lf;
 }
 
@@ -266,6 +303,7 @@
   logfiles->is_temporary = 1;
 }
 
+/** Close any log handlers added by add_temp_log or marked by mark_logs_temp */
 void close_temp_logs(void)
 {
   logfile_t *lf, **p;
@@ -273,8 +311,7 @@
     if ((*p)->is_temporary) {
       lf = *p;
       *p = (*p)->next;
-      if (lf->needs_close)
-        fclose(lf->file);
+      close_log(lf);
       tor_free(lf->filename);
       tor_free(lf);
     } else {
@@ -283,6 +320,7 @@
   }
 }
 
+/** Configure all log handles to be closed by close_temp_logs */
 void mark_logs_temp(void)
 {
   logfile_t *lf;
@@ -306,6 +344,28 @@
   return 0;
 }
 
+#ifdef HAVE_SYSLOG_H
+/**
+ * Add a log handler to send messages to they system log facility.
+ */
+int add_syslog_log(int loglevelMin, int loglevelMax)
+{
+  logfile_t *lf;
+  if (syslog_count++ == 0)
+    /* This is the the first syslog. */
+    openlog("Tor", LOG_NDELAY, LOG_DAEMON);
+
+  lf = tor_malloc_zero(sizeof(logfile_t));
+  lf->loglevel = loglevelMin;
+  lf->filename = tor_strdup("<syslog>");
+  lf->max_loglevel = loglevelMax;
+  lf->is_syslog = 1;
+  lf->next = logfiles;
+  logfiles = lf;
+  return 0;
+}
+#endif
+
 /** If <b>level</b> is a valid log severity, return the corresponding
  * numeric value.  Otherwise, return -1. */
 int parse_log_level(const char *level) {
@@ -327,7 +387,7 @@
   logfile_t *lf;
   int min = LOG_ERR;
   for (lf = logfiles; lf; lf = lf->next) {
-    if (lf->loglevel < min)
+    if (lf->loglevel > min)
       min = lf->loglevel;
   }
   return min;

Index: log.h
===================================================================
RCS file: /home/or/cvsroot/src/common/log.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- log.h	2 Jun 2004 19:18:37 -0000	1.28
+++ log.h	26 Oct 2004 21:48:41 -0000	1.29
@@ -18,24 +18,37 @@
 #ifdef HAVE_SYSLOG_H
 #include <syslog.h>
 #define LOG_WARN LOG_WARNING
+#if LOG_DEBUG < LOG_ERR
+#error "Your syslog.h thinks high numbers are more important.  We aren't prepared to deal with that."
+#endif
 #else
+/* XXXX Note: The code was originally written to refer to severities,
+ * with 0 being the least severe; while syslog's logging code refers to
+ * priorities, with 0 being the most important.  Thus, all our comparisons
+ * needed to be reversed when we added syslog support.  
+ *
+ * The upshot of this is that comments about log levels may be messed
+ * up: for "maximum severity" read "most severe" and "numerically
+ * *lowest* severity".
+ */
+
 /** Debug-level severity: for hyper-verbose messages of no interest to
  * anybody but developers. */
-#define LOG_DEBUG   0
+#define LOG_DEBUG   7
 /** Info-level severity: for messages that appear frequently during normal
  * operation. */
-#define LOG_INFO    1
+#define LOG_INFO    6
 /** Notice-level severity: for messages that appear infrequently
  * during normal operation; that the user will probably care about;
  * and that are not errors.
  */
-#define LOG_NOTICE  2
+#define LOG_NOTICE  5
 /** Warn-level severity: for messages that only appear when something has gone
  * wrong. */
-#define LOG_WARN    3
+#define LOG_WARN    4
 /** Error-level severity: for messages that only appear when something has gone
  * very wrong, and the Tor process can no longer proceed. */
-#define LOG_ERR     4
+#define LOG_ERR     3
 #endif
 
 /* magic to make GCC check for proper format strings. */
@@ -49,9 +62,12 @@
 int parse_log_level(const char *level);
 void add_stream_log(int severityMin, int severityMax, const char *name, FILE *stream);
 int add_file_log(int severityMin, int severityMax, const char *filename);
+#ifdef HAVE_SYSLOG_H
+int add_syslog_log(int loglevelMin, int loglevelMax);
+#endif
 int get_min_log_level(void);
-void close_logs();
-void reset_logs();
+void close_logs(void);
+void reset_logs(void);
 void add_temp_log(void);
 void close_temp_logs(void);
 void mark_logs_temp(void);

Index: util.c
===================================================================
RCS file: /home/or/cvsroot/src/common/util.c,v
retrieving revision 1.151
retrieving revision 1.152
diff -u -d -r1.151 -r1.152
--- util.c	16 Oct 2004 22:56:03 -0000	1.151
+++ util.c	26 Oct 2004 21:48:41 -0000	1.152
@@ -1740,13 +1740,17 @@
   while(*value && isspace((int)*value))
     value++;
 
+#if 0
   if(!*end || !*value) { /* only a key on this line. no value. */
     *end = 0;
     log_fn(LOG_WARN,"Line has keyword '%s' but no value. Failing.",key);
     return -1;
   }
+#endif
   *end = 0; /* null it out */
 
+  tor_assert(key);
+  tor_assert(value);
   log_fn(LOG_DEBUG,"got keyword '%s', value '%s'", key, value);
   *key_out = key, *value_out = value;
   return 1;