diff options
Diffstat (limited to 'lib/log.c')
| -rw-r--r-- | lib/log.c | 844 |
1 files changed, 657 insertions, 187 deletions
@@ -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; |
