summaryrefslogtreecommitdiffstats
path: root/lib/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/log.c')
-rw-r--r--lib/log.c844
1 files changed, 657 insertions, 187 deletions
diff --git a/lib/log.c b/lib/log.c
index df6e13db..18878094 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -19,12 +19,14 @@
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * 02111-1307, USA.
*/
#include <zebra.h>
#include "log.h"
+#include "vty.h"
+#include "uty.h"
#include "memory.h"
#include "command.h"
#ifndef SUNOS_5
@@ -34,12 +36,24 @@
#ifdef HAVE_UCONTEXT_H
#include <ucontext.h>
#endif
+#include "qpthreads.h"
+#include "qfstring.h"
+#include "sigevent.h"
+
+/* log is protected by the same mutext as vty, see comments in vty.c */
+
+/* prototypes */
+static int uzlog_reset_file (struct zlog *zl);
+static void zlog_abort (const char *mess) __attribute__ ((noreturn));
+static void vzlog (struct zlog *zl, int priority, const char *format, va_list args);
+static void uzlog_backtrace(int priority);
+static void uvzlog (struct zlog *zl, int priority, const char *format, va_list args);
static int logfile_fd = -1; /* Used in signal handler. */
struct zlog *zlog_default = NULL;
-const char *zlog_proto_names[] =
+const char *zlog_proto_names[] =
{
"NONE",
"DEFAULT",
@@ -66,19 +80,56 @@ const char *zlog_priority[] =
"debugging",
NULL,
};
-
-
-/* For time string format. */
+/*==============================================================================
+ * Time stamp handling -- gettimeofday(), localtime() and strftime().
+ *
+ * Maintains a cached form of the current time (under the vty/log mutex), so
+ * that can avoid multiple calls of localtime() and strftime() per second.
+ *
+ * The value from gettimeofday() is in micro-seconds. Can provide timestamp
+ * with any number of decimal digits, but at most 6 will be significant.
+ */
+
+static void uquagga_timestamp(qf_str qfs, int timestamp_precision) ;
-size_t
+/*------------------------------------------------------------------------------
+ * Fill buffer with current time, to given number of decimal digits.
+ *
+ * If given buffer is too small, provides as many characters as possible.
+ *
+ * Returns: number of characters in buffer, not including trailing '\0'.
+ *
+ * NB: does no rounding.
+ *
+ * NB: buflen MUST be > 1 and buf MUST NOT be NULL.
+ */
+extern size_t
quagga_timestamp(int timestamp_precision, char *buf, size_t buflen)
{
+ qf_str_t qfs ;
+
+ VTY_LOCK() ;
+
+ qfs_init(&qfs, buf, buflen) ;
+ uquagga_timestamp(&qfs, timestamp_precision) ;
+
+ VTY_UNLOCK() ;
+ return qfs_len(&qfs) ;
+}
+
+/*------------------------------------------------------------------------------
+ * unprotected version for when mutex already held
+ */
+static void
+uquagga_timestamp(qf_str qfs, int timestamp_precision)
+{
static struct {
time_t last;
size_t len;
- char buf[28];
+ char buf[timestamp_buffer_len];
} cache;
+
struct timeval clock;
/* would it be sufficient to use global 'recent_time' here? I fear not... */
@@ -87,134 +138,175 @@ quagga_timestamp(int timestamp_precision, char *buf, size_t buflen)
/* first, we update the cache if the time has changed */
if (cache.last != clock.tv_sec)
{
- struct tm *tm;
+ struct tm tm;
cache.last = clock.tv_sec;
- tm = localtime(&cache.last);
- cache.len = strftime(cache.buf, sizeof(cache.buf),
- "%Y/%m/%d %H:%M:%S", tm);
+ localtime_r(&cache.last, &tm);
+ cache.len = strftime(cache.buf, sizeof(cache.buf), TIMESTAMP_FORM, &tm) ;
+ assert(cache.len > 0) ;
}
+
/* note: it's not worth caching the subsecond part, because
- chances are that back-to-back calls are not sufficiently close together
- for the clock not to have ticked forward */
-
- if (buflen > cache.len)
- {
- memcpy(buf, cache.buf, cache.len);
- if ((timestamp_precision > 0) &&
- (buflen > cache.len+1+timestamp_precision))
- {
- /* should we worry about locale issues? */
- static const int divisor[] = {0, 100000, 10000, 1000, 100, 10, 1};
- int prec;
- char *p = buf+cache.len+1+(prec = timestamp_precision);
- *p-- = '\0';
- while (prec > 6)
- /* this is unlikely to happen, but protect anyway */
- {
- *p-- = '0';
- prec--;
- }
- clock.tv_usec /= divisor[prec];
- do
- {
- *p-- = '0'+(clock.tv_usec % 10);
- clock.tv_usec /= 10;
- }
- while (--prec > 0);
- *p = '.';
- return cache.len+1+timestamp_precision;
- }
- buf[cache.len] = '\0';
- return cache.len;
- }
- if (buflen > 0)
- buf[0] = '\0';
- return 0;
-}
+ * chances are that back-to-back calls are not sufficiently close together
+ * for the clock not to have ticked forward
+ */
+
+ qfs_append_n(qfs, cache.buf, cache.len) ;
-/* Utility routine for current time printing. */
+ /* Add decimal part as required. */
+ if (timestamp_precision > 0)
+ {
+ /* should we worry about locale issues? */
+ static const int divisor[] = { 1, /* 0 */
+ 100000, 10000, 1000, /* 1, 2, 3 */
+ 100, 10, 1}; /* 4, 5, 6 */
+ int prec;
+
+ prec = timestamp_precision ;
+ if (prec > 6)
+ prec = 6 ;
+
+ qfs_append_n(qfs, ".", 1) ;
+ qfs_unsigned(qfs, clock.tv_usec / divisor[prec], 0, 0, prec) ;
+
+ if (prec < timestamp_precision)
+ qfs_append_ch_x_n(qfs, '0', timestamp_precision - prec) ;
+ } ;
+} ;
+
+/*==============================================================================
+ * va_list version of zlog
+ */
static void
-time_print(FILE *fp, struct timestamp_control *ctl)
+vzlog (struct zlog *zl, int priority, const char *format, va_list args)
{
- if (!ctl->already_rendered)
- {
- ctl->len = quagga_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf));
- ctl->already_rendered = 1;
- }
- fprintf(fp, "%s ", ctl->buf);
+ VTY_LOCK() ;
+ uvzlog(zl, priority, format, args);
+ VTY_UNLOCK() ;
}
-
-
-/* va_list version of zlog. */
+
+/* va_list version of zlog. Unprotected assumes mutex already held*/
static void
-vzlog (struct zlog *zl, int priority, const char *format, va_list args)
+uvzlog (struct zlog *zl, int priority, const char *format, va_list va)
{
- struct timestamp_control tsctl;
- tsctl.already_rendered = 0;
+ struct logline ll ; /* prepares line for output, here */
+
+ VTY_ASSERT_LOCKED() ;
- /* If zlog is not specified, use default one. */
+ ll.p_nl = NULL ; /* Nothing generated, yet */
+
+ /* If zlog is not specified, use default one. */
if (zl == NULL)
- zl = zlog_default;
+ zl = zlog_default ;
- /* When zlog_default is also NULL, use stderr for logging. */
+ /* When zlog_default is also NULL, use stderr for logging. */
if (zl == NULL)
{
- tsctl.precision = 0;
- time_print(stderr, &tsctl);
- fprintf (stderr, "%s: ", "unknown");
- vfprintf (stderr, format, args);
- fprintf (stderr, "\n");
- fflush (stderr);
-
- /* In this case we return at here. */
- return;
+ uvzlog_line(&ll, zl, priority, format, va, llt_lf) ;
+ write(fileno(stderr), ll.line, ll.len) ;
}
- tsctl.precision = zl->timestamp_precision;
-
- /* Syslog output */
- if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG])
+ else
{
- va_list ac;
- va_copy(ac, args);
- vsyslog (priority|zlog_default->facility, format, ac);
- va_end(ac);
- }
+ /* Syslog output */
+ if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG])
+ {
+ va_list ac;
+ va_copy(ac, va);
+ vsyslog (priority|zlog_default->facility, format, ac);
+ va_end(ac);
+ }
- /* File output. */
- if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp)
- {
- va_list ac;
- time_print (zl->fp, &tsctl);
- if (zl->record_priority)
- fprintf (zl->fp, "%s: ", zlog_priority[priority]);
- fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]);
- va_copy(ac, args);
- vfprintf (zl->fp, format, ac);
- va_end(ac);
- fprintf (zl->fp, "\n");
- fflush (zl->fp);
+ /* File output. */
+ if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp)
+ {
+ uvzlog_line(&ll, zl, priority, format, va, llt_lf) ;
+ write(fileno(zl->fp), ll.line, ll.len) ;
+ }
+
+ /* stdout output. */
+ if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT])
+ {
+ uvzlog_line(&ll, zl, priority, format, va, llt_lf) ;
+ write(fileno(zl->fp), ll.line, ll.len) ;
+ }
+
+ /* Terminal monitor. */
+ if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR])
+ uty_log(&ll, zl, priority, format, va) ;
}
+}
- /* stdout output. */
- if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT])
+/*------------------------------------------------------------------------------
+ * Preparation of line to send to logging: file, stdout or "monitor" terminals.
+ *
+ * Takes copy of va_list before using it, so the va_list is unchanged.
+ */
+extern void
+uvzlog_line(struct logline* ll, struct zlog *zl, int priority,
+ const char *format, va_list va, enum ll_term term)
+{
+ char* p ;
+ const char* q ;
+
+ p = ll->p_nl ;
+
+ if (p != NULL)
{
- va_list ac;
- time_print (stdout, &tsctl);
- if (zl->record_priority)
- fprintf (stdout, "%s: ", zlog_priority[priority]);
- fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]);
- va_copy(ac, args);
- vfprintf (stdout, format, ac);
- va_end(ac);
- fprintf (stdout, "\n");
- fflush (stdout);
+ /* we have the line -- just need to worry about the crlf state */
+ if (term == ll->term)
+ return ; /* exit here if all set */
}
+ else
+ {
+ /* must construct the line */
+ qf_str_t qfs ;
+ va_list vac ;
- /* Terminal monitor. */
- if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR])
- vty_log ((zl->record_priority ? zlog_priority[priority] : NULL),
- zlog_proto_names[zl->protocol], format, &tsctl, args);
-}
+ qfs_init(&qfs, ll->line, sizeof(ll->line) - 2) ;
+ /* leave space for '\n' or '\r''\n' */
+ /* "<time stamp>" */
+ uquagga_timestamp(&qfs, (zl != NULL) ? zl->timestamp_precision : 0) ;
+
+ qfs_append_n(&qfs, " ", 1) ;
+
+ /* "<priority>: " if required */
+ if ((zl != NULL) && (zl->record_priority))
+ {
+ qfs_append(&qfs, zlog_priority[priority]) ;
+ qfs_append(&qfs, ": ") ;
+ } ;
+
+ /* "<protocol>: " or "unknown: " */
+ if (zl != NULL)
+ q = zlog_proto_names[zl->protocol] ;
+ else
+ q = "unknown" ;
+
+ qfs_append(&qfs, q) ;
+ qfs_append(&qfs, ": ") ;
+
+ /* Now the log line itself */
+ va_copy(vac, va);
+ qfs_vprintf(&qfs, format, vac) ;
+ va_end(vac);
+
+ /* Set pointer to where the '\0' is. */
+ p = ll->p_nl = qfs_ptr(&qfs) ;
+ } ;
+
+ /* finish off with '\r''\n''\0' or '\n''\0' as required */
+ if (term == llt_crlf)
+ *p++ = '\r' ;
+
+ if (term != llt_nul)
+ *p++ = '\n' ;
+
+ *p = '\0' ;
+
+ ll->len = p - ll->line ;
+ ll->term = term ;
+} ;
+
+/*============================================================================*/
static char *
str_append(char *dst, int len, const char *src)
@@ -428,6 +520,13 @@ zlog_signal(int signo, const char *action
#undef LOC
}
+/* Ring down the curtain -- turn of SIGABRT handler and abort() */
+void zabort_abort(void)
+{
+ quagga_sigabrt_no_trap() ;
+ abort() ;
+}
+
/* Log a backtrace using only async-signal-safe functions.
Needs to be enhanced to support syslog logging. */
void
@@ -492,7 +591,7 @@ zlog_backtrace_sigsafe(int priority, void *program_counter)
for (i = 0; i < size; i++)
{
s = buf;
- if (bt)
+ if (bt)
s = str_append(LOC, bt[i]);
else {
s = str_append(LOC,"[bt ");
@@ -518,8 +617,16 @@ zlog_backtrace_sigsafe(int priority, void *program_counter)
void
zlog_backtrace(int priority)
{
+ VTY_LOCK() ;
+ uzlog_backtrace(priority);
+ VTY_UNLOCK() ;
+}
+
+static void
+uzlog_backtrace(int priority)
+{
#ifndef HAVE_GLIBC_BACKTRACE
- zlog(NULL, priority, "No backtrace available on this platform.");
+ uzlog(NULL, priority, "No backtrace available on this platform.");
#else
void *array[20];
int size, i;
@@ -528,27 +635,38 @@ zlog_backtrace(int priority)
if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) ||
((size_t)size > sizeof(array)/sizeof(array[0])))
{
- zlog_err("Cannot get backtrace, returned invalid # of frames %d "
+ uzlog(NULL, LOG_ERR, "Cannot get backtrace, returned invalid # of frames %d "
"(valid range is between 1 and %lu)",
size, (unsigned long)(sizeof(array)/sizeof(array[0])));
return;
}
- zlog(NULL, priority, "Backtrace for %d stack frames:", size);
+ uzlog(NULL, priority, "Backtrace for %d stack frames:", size);
if (!(strings = backtrace_symbols(array, size)))
{
- zlog_err("Cannot get backtrace symbols (out of memory?)");
+ uzlog(NULL, LOG_ERR, "Cannot get backtrace symbols (out of memory?)");
for (i = 0; i < size; i++)
- zlog(NULL, priority, "[bt %d] %p",i,array[i]);
+ uzlog(NULL, priority, "[bt %d] %p",i,array[i]);
}
else
{
for (i = 0; i < size; i++)
- zlog(NULL, priority, "[bt %d] %s",i,strings[i]);
+ uzlog(NULL, priority, "[bt %d] %s",i,strings[i]);
free(strings);
}
#endif /* HAVE_GLIBC_BACKTRACE */
}
+/* unlocked version */
+void
+uzlog (struct zlog *zl, int priority, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ uvzlog (zl, priority, format, args);
+ va_end (args);
+}
+
void
zlog (struct zlog *zl, int priority, const char *format, ...)
{
@@ -605,20 +723,71 @@ PLOG_FUNC(plog_debug, LOG_DEBUG)
void
_zlog_assert_failed (const char *assertion, const char *file,
- unsigned int line, const char *function)
+ unsigned int line, const char *function)
{
+ const static size_t buff_size = 1024;
+ char buff[buff_size];
+ snprintf(buff, buff_size,
+ "Assertion `%s' failed in file %s, line %u, function %s",
+ assertion, file, line, (function ? function : "?"));
+ zlog_abort(buff);
+}
+
+/* Abort with message */
+void
+_zlog_abort_mess (const char *mess, const char *file,
+ unsigned int line, const char *function)
+{
+ const static size_t buff_size = 1024;
+ char buff[buff_size];
+ snprintf(buff, buff_size, "%s, in file %s, line %u, function %s",
+ mess, file, line, (function ? function : "?"));
+ zlog_abort(buff);
+}
+
+/* Abort with message and errno and strerror() thereof */
+void
+_zlog_abort_errno (const char *mess, const char *file,
+ unsigned int line, const char *function)
+{
+ _zlog_abort_err(mess, errno, file, line, function);
+}
+
+/* Abort with message and given error and strerror() thereof */
+void
+_zlog_abort_err (const char *mess, int err, const char *file,
+ unsigned int line, const char *function)
+{
+ const static size_t buff_size = 1024;
+ char buff[buff_size];
+ snprintf(buff, buff_size,
+ "%s, in file %s, line %u, function %s, %s",
+ mess, file, line, (function ? function : "?"),
+ errtoa(err, 0).str);
+ zlog_abort(buff);
+}
+
+
+static void
+zlog_abort (const char *mess)
+{
+#if VTY_DEBUG
+ /* May not be locked -- but that doesn't matter any more */
+ ++vty_lock_count ;
+#endif
+
/* Force fallback file logging? */
if (zlog_default && !zlog_default->fp &&
((logfile_fd = open_crashlog()) >= 0) &&
((zlog_default->fp = fdopen(logfile_fd, "w")) != NULL))
zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR;
- zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
- assertion,file,line,(function ? function : "?"));
- zlog_backtrace(LOG_CRIT);
- abort();
+
+ uzlog(NULL, LOG_CRIT, "%s", mess);
+ uzlog_backtrace(LOG_CRIT);
+ zabort_abort();
}
-
+
/* Open log stream */
struct zlog *
openzlog (const char *progname, zlog_proto_t protocol,
@@ -641,7 +810,7 @@ openzlog (const char *progname, zlog_proto_t protocol,
zl->default_lvl = LOG_DEBUG;
openlog (progname, syslog_flags, zl->facility);
-
+
return zl;
}
@@ -663,10 +832,17 @@ closezlog (struct zlog *zl)
void
zlog_set_level (struct zlog *zl, zlog_dest_t dest, int log_level)
{
+ VTY_LOCK() ;
+
if (zl == NULL)
zl = zlog_default;
- zl->maxlvl[dest] = log_level;
+ if (zl != NULL)
+ {
+ zl->maxlvl[dest] = log_level;
+ }
+
+ VTY_UNLOCK() ;
}
int
@@ -674,46 +850,68 @@ zlog_set_file (struct zlog *zl, const char *filename, int log_level)
{
FILE *fp;
mode_t oldumask;
+ int result = 1;
+
+ VTY_LOCK() ;
/* There is opend file. */
- zlog_reset_file (zl);
+ uzlog_reset_file (zl);
/* Set default zl. */
if (zl == NULL)
zl = zlog_default;
- /* Open file. */
- oldumask = umask (0777 & ~LOGFILE_MASK);
- fp = fopen (filename, "a");
- umask(oldumask);
- if (fp == NULL)
- return 0;
-
- /* Set flags. */
- zl->filename = strdup (filename);
- zl->maxlvl[ZLOG_DEST_FILE] = log_level;
- zl->fp = fp;
- logfile_fd = fileno(fp);
+ if (zl != NULL)
+ {
+ /* Open file. */
+ oldumask = umask (0777 & ~LOGFILE_MASK);
+ fp = fopen (filename, "a");
+ umask(oldumask);
+ if (fp == NULL)
+ result = 0;
+ else
+ {
+ /* Set flags. */
+ zl->filename = strdup (filename);
+ zl->maxlvl[ZLOG_DEST_FILE] = log_level;
+ zl->fp = fp;
+ logfile_fd = fileno(fp);
+ }
+ }
- return 1;
+ VTY_UNLOCK() ;
+ return result;
}
/* Reset opend file. */
int
zlog_reset_file (struct zlog *zl)
{
+ int result;
+ VTY_LOCK() ;
+ result = uzlog_reset_file(zl);
+ VTY_UNLOCK() ;
+ return result;
+}
+
+static int
+uzlog_reset_file (struct zlog *zl)
+ {
if (zl == NULL)
zl = zlog_default;
- if (zl->fp)
- fclose (zl->fp);
- zl->fp = NULL;
- logfile_fd = -1;
- zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
-
- if (zl->filename)
- free (zl->filename);
- zl->filename = NULL;
+ if (zl != NULL)
+ {
+ if (zl->fp)
+ fclose (zl->fp);
+ zl->fp = NULL;
+ logfile_fd = -1;
+ zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
+
+ if (zl->filename)
+ free (zl->filename);
+ zl->filename = NULL;
+ }
return 1;
}
@@ -723,54 +921,334 @@ int
zlog_rotate (struct zlog *zl)
{
int level;
+ int result = 1;
+
+ VTY_LOCK() ;
if (zl == NULL)
zl = zlog_default;
- if (zl->fp)
- fclose (zl->fp);
- zl->fp = NULL;
- logfile_fd = -1;
- level = zl->maxlvl[ZLOG_DEST_FILE];
- zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
+ if (zl != NULL)
+ {
+ if (zl->fp)
+ fclose (zl->fp);
+ zl->fp = NULL;
+ logfile_fd = -1;
+ level = zl->maxlvl[ZLOG_DEST_FILE];
+ zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
+
+ if (zl->filename)
+ {
+ mode_t oldumask;
+ int save_errno;
+
+ oldumask = umask (0777 & ~LOGFILE_MASK);
+ zl->fp = fopen (zl->filename, "a");
+ save_errno = errno;
+ umask(oldumask);
+ if (zl->fp == NULL)
+ {
+ /* can't call logging while locked */
+ char *fname = strdup(zl->filename);
+ uzlog(NULL, LOG_ERR,
+ "Log rotate failed: cannot open file %s for append: %s",
+ fname, errtoa(save_errno, 0).str);
+ free(fname);
+ result = -1;
+ }
+ else
+ {
+ logfile_fd = fileno(zl->fp);
+ zl->maxlvl[ZLOG_DEST_FILE] = level;
+ }
+ }
+ }
+ VTY_UNLOCK() ;
+ return result;
+}
+
+int
+zlog_get_default_lvl (struct zlog *zl)
+{
+ int result = LOG_DEBUG;
+
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
- if (zl->filename)
+ if (zl != NULL)
{
- mode_t oldumask;
- int save_errno;
+ result = zl->default_lvl;
+ }
- oldumask = umask (0777 & ~LOGFILE_MASK);
- zl->fp = fopen (zl->filename, "a");
- save_errno = errno;
- umask(oldumask);
- if (zl->fp == NULL)
- {
- zlog_err("Log rotate failed: cannot open file %s for append: %s",
- zl->filename, safe_strerror(save_errno));
- return -1;
- }
- logfile_fd = fileno(zl->fp);
- zl->maxlvl[ZLOG_DEST_FILE] = level;
+ VTY_UNLOCK() ;
+ return result;
+}
+
+void
+zlog_set_default_lvl (struct zlog *zl, int level)
+{
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->default_lvl = level;
}
- return 1;
+ VTY_UNLOCK() ;
+}
+
+/* Set logging level and default for all destinations */
+void
+zlog_set_default_lvl_dest (struct zlog *zl, int level)
+{
+ int i;
+
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->default_lvl = level;
+
+ for (i = 0; i < ZLOG_NUM_DESTS; i++)
+ if (zl->maxlvl[i] != ZLOG_DISABLED)
+ zl->maxlvl[i] = level;
+ }
+
+ VTY_UNLOCK() ;
+}
+
+int
+zlog_get_maxlvl (struct zlog *zl, zlog_dest_t dest)
+{
+ int result = ZLOG_DISABLED;
+
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->maxlvl[dest];
+ }
+
+ VTY_UNLOCK() ;
+ return result;
+}
+
+int
+zlog_get_facility (struct zlog *zl)
+{
+ int result = LOG_DAEMON;
+
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->facility;
+ }
+
+ VTY_UNLOCK() ;
+ return result;
+}
+
+void
+zlog_set_facility (struct zlog *zl, int facility)
+{
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->facility = facility;
+ }
+
+ VTY_UNLOCK() ;
+}
+
+int
+zlog_get_record_priority (struct zlog *zl)
+{
+ int result = 0;
+
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->record_priority;
+ }
+
+ VTY_UNLOCK() ;
+ return result;
+}
+
+void
+zlog_set_record_priority (struct zlog *zl, int record_priority)
+{
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->record_priority = record_priority;
+ }
+ VTY_UNLOCK() ;
+}
+
+int
+zlog_get_timestamp_precision (struct zlog *zl)
+{
+ int result = 0;
+
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->timestamp_precision;
+ }
+ VTY_UNLOCK() ;
+ return result;
+}
+
+void
+zlog_set_timestamp_precision (struct zlog *zl, int timestamp_precision)
+{
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->timestamp_precision = timestamp_precision;
+ }
+
+ VTY_UNLOCK() ;
}
-
+
+/* returns name of ZLOG_NONE if no zlog given and no default set */
+const char *
+zlog_get_proto_name (struct zlog *zl)
+{
+ const char * result;
+ VTY_LOCK() ;
+ result = uzlog_get_proto_name(zl);
+ VTY_UNLOCK() ;
+ return result;
+}
+
+/* unprotected version, assumes mutex held */
+const char *
+uzlog_get_proto_name (struct zlog *zl)
+{
+ zlog_proto_t protocol = ZLOG_NONE;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ protocol = zl->protocol;
+ }
+
+ return zlog_proto_names[protocol];
+}
+
+/* caller must free result */
+char *
+zlog_get_filename (struct zlog *zl)
+{
+ char * result = NULL;
+
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL && zl->filename != NULL)
+ {
+ result = strdup(zl->filename);
+ }
+
+ VTY_UNLOCK() ;
+ return result;
+}
+
+const char *
+zlog_get_ident (struct zlog *zl)
+{
+ const char * result = NULL;
+
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->ident;
+ }
+
+ VTY_UNLOCK() ;
+ return result;
+}
+
+/* logging to a file? */
+int
+zlog_is_file (struct zlog *zl)
+{
+ int result = 0;
+
+ VTY_LOCK() ;
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = (zl->fp != NULL);
+ }
+
+ VTY_UNLOCK() ;;
+ return result;
+}
+
/* Message lookup function. */
const char *
lookup (const struct message *mes, int key)
{
const struct message *pnt;
- for (pnt = mes; pnt->key != 0; pnt++)
- if (pnt->key == key)
+ for (pnt = mes; pnt->key != 0; pnt++)
+ if (pnt->key == key)
return pnt->str;
return "";
}
/* Older/faster version of message lookup function, but requires caller to pass
- * in the array size (instead of relying on a 0 key to terminate the search).
+ * in the array size (instead of relying on a 0 key to terminate the search).
*
* The return value is the message string if found, or the 'none' pointer
* provided otherwise.
@@ -779,7 +1257,7 @@ const char *
mes_lookup (const struct message *meslist, int max, int index, const char *none)
{
int pos = index - meslist[0].key;
-
+
/* first check for best case: index is in range and matches the key
* value in that slot.
* NB: key numbering might be offset from 0. E.g. protocol constants
@@ -798,7 +1276,7 @@ mes_lookup (const struct message *meslist, int max, int index, const char *none)
if (meslist->key == index)
{
const char *str = (meslist->str ? meslist->str : none);
-
+
zlog_debug ("message index %d [%s] found in position %d (max is %d)",
index, str, i, max);
return str;
@@ -810,14 +1288,6 @@ mes_lookup (const struct message *meslist, int max, int index, const char *none)
return none;
}
-/* Wrapper around strerror to handle case where it returns NULL. */
-const char *
-safe_strerror(int errnum)
-{
- const char *s = strerror(errnum);
- return (s != NULL) ? s : "Unknown error";
-}
-
struct zebra_desc_table
{
unsigned int type;