diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 18:02:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 18:02:34 +0000 |
commit | fadeddfbb2aa38a980dd959b5ec1ffba7afd43cb (patch) | |
tree | a7bde6111c84ea64619656a38fba50909fa0bf60 /src/log.c | |
parent | Initial commit. (diff) | |
download | lldpd-fadeddfbb2aa38a980dd959b5ec1ffba7afd43cb.tar.xz lldpd-fadeddfbb2aa38a980dd959b5ec1ffba7afd43cb.zip |
Adding upstream version 1.0.18.upstream/1.0.18upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/log.c')
-rw-r--r-- | src/log.c | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..ddfc14a --- /dev/null +++ b/src/log.c @@ -0,0 +1,279 @@ +/* -*- mode: c; c-file-style: "openbsd" -*- */ +/* $OpenBSD: log.c,v 1.11 2007/12/07 17:17:00 reyk Exp $ */ + +/* + * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <syslog.h> +#include <sys/types.h> +#include <string.h> +#include <errno.h> +#include <time.h> +#include "log.h" + +/* By default, logging is done on stderr. */ +static int use_syslog = 0; +/* Default debug level */ +static int debug = 0; + +/* Logging can be modified by providing an appropriate log handler. */ +static void (*logh)(int severity, const char *msg) = NULL; + +static void vlog(int, const char *, const char *, va_list); +static void logit(int, const char *, const char *, ...); + +#define MAX_DBG_TOKENS 40 +static const char *tokens[MAX_DBG_TOKENS + 1] = { NULL }; + +void +log_init(int n_syslog, int n_debug, const char *progname) +{ + use_syslog = n_syslog; + debug = n_debug; + + if (use_syslog) openlog(progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); + + tzset(); +} + +void +log_level(int n_debug) +{ + if (n_debug >= 0) debug = n_debug; +} + +void +log_register(void (*cb)(int, const char *)) +{ + logh = cb; +} + +void +log_accept(const char *token) +{ + int i; + for (i = 0; i < MAX_DBG_TOKENS; i++) { + if (tokens[i] == NULL) { + tokens[i + 1] = NULL; + tokens[i] = token; + return; + } + } +} + +static void +logit(int pri, const char *token, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vlog(pri, token, fmt, ap); + va_end(ap); +} + +static char * +date() +{ + /* Return the current date as incomplete ISO 8601 (2012-12-12T16:13:30) */ + static char date[] = "2012-12-12T16:13:30"; + time_t t = time(NULL); + struct tm *tmp = localtime(&t); + strftime(date, sizeof(date), "%Y-%m-%dT%H:%M:%S", tmp); + return date; +} + +static const char * +translate(int fd, int priority) +{ + /* Translate a syslog priority to a string. With colors if the output is a + * terminal. */ + int tty = isatty(fd); + switch (tty) { + case 1: + switch (priority) { + case LOG_EMERG: + return "\033[1;37;41m[EMRG"; + case LOG_ALERT: + return "\033[1;37;41m[ALRT"; + case LOG_CRIT: + return "\033[1;37;41m[CRIT"; + case LOG_ERR: + return "\033[1;31m[ ERR"; + case LOG_WARNING: + return "\033[1;33m[WARN"; + case LOG_NOTICE: + return "\033[1;34m[NOTI"; + case LOG_INFO: + return "\033[1;34m[INFO"; + case LOG_DEBUG: + return "\033[36m[ DBG"; + } + break; + default: + switch (priority) { + case LOG_EMERG: + return "[EMRG"; + case LOG_ALERT: + return "[ALRT"; + case LOG_CRIT: + return "[CRIT"; + case LOG_ERR: + return "[ ERR"; + case LOG_WARNING: + return "[WARN"; + case LOG_NOTICE: + return "[NOTI"; + case LOG_INFO: + return "[INFO"; + case LOG_DEBUG: + return "[ DBG"; + } + } + return "[UNKN]"; +} + +static void +vlog(int pri, const char *token, const char *fmt, va_list ap) +{ + if (logh) { + char *result = NULL; + if (vasprintf(&result, fmt, ap) != -1) { + logh(pri, result); + free(result); + return; + } + /* Otherwise, abort. We don't know if "ap" is still OK. We could + * have made a copy, but this is too much overhead for a + * situation that shouldn't happen. */ + return; + } + + /* Log to syslog if requested */ + if (use_syslog) { + va_list ap2; + va_copy(ap2, ap); + vsyslog(pri, fmt, ap2); + va_end(ap2); + } + + /* Log to standard error in all cases */ + char *nfmt; + /* best effort in out of mem situations */ + if (asprintf(&nfmt, "%s %s%s%s]%s %s\n", date(), translate(STDERR_FILENO, pri), + token ? "/" : "", token ? token : "", + isatty(STDERR_FILENO) ? "\033[0m" : "", fmt) == -1) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + } else { + vfprintf(stderr, nfmt, ap); + free(nfmt); + } + fflush(stderr); +} + +void +log_warn(const char *token, const char *emsg, ...) +{ + char *nfmt = NULL; + va_list ap; + + /* best effort to even work in out of memory situations */ + if (emsg == NULL) + logit(LOG_WARNING, "%s", strerror(errno)); + else { + va_start(ap, emsg); + + if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) { + /* we tried it... */ + vlog(LOG_WARNING, token, emsg, ap); + logit(LOG_WARNING, "%s", strerror(errno)); + } else { + vlog(LOG_WARNING, token, nfmt, ap); + free(nfmt); + } + va_end(ap); + } +} + +void +log_warnx(const char *token, const char *emsg, ...) +{ + va_list ap; + + va_start(ap, emsg); + vlog(LOG_WARNING, token, emsg, ap); + va_end(ap); +} + +void +log_info(const char *token, const char *emsg, ...) +{ + va_list ap; + + if (use_syslog || debug > 0 || logh) { + va_start(ap, emsg); + vlog(LOG_INFO, token, emsg, ap); + va_end(ap); + } +} + +static int +log_debug_accept_token(const char *token) +{ + int i; + if (tokens[0] == NULL) return 1; + for (i = 0; (i < MAX_DBG_TOKENS) && (tokens[i] != NULL); i++) { + if (!strcmp(tokens[i], token)) return 1; + } + return 0; +} + +void +log_debug(const char *token, const char *emsg, ...) +{ + va_list ap; + + if ((debug > 1 && log_debug_accept_token(token)) || logh) { + va_start(ap, emsg); + vlog(LOG_DEBUG, token, emsg, ap); + va_end(ap); + } +} + +void +fatal(const char *token, const char *emsg) +{ + if (emsg == NULL) + logit(LOG_CRIT, token ? token : "fatal", "%s", strerror(errno)); + else if (errno) + logit(LOG_CRIT, token ? token : "fatal", "%s: %s", emsg, + strerror(errno)); + else + logit(LOG_CRIT, token ? token : "fatal", "%s", emsg); + + exit(1); +} + +void +fatalx(const char *token, const char *emsg) +{ + errno = 0; + fatal(token, emsg); +} |