]> git.ipfire.org Git - thirdparty/lldpd.git/blame_incremental - src/log.c
netlink: ignore IFLA_LINK if we previously received IFLA_LINK_NETNSID
[thirdparty/lldpd.git] / src / log.c
... / ...
CommitLineData
1/* -*- mode: c; c-file-style: "openbsd" -*- */
2/* $OpenBSD: log.c,v 1.11 2007/12/07 17:17:00 reyk Exp $ */
3
4/*
5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <unistd.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <stdarg.h>
24#include <syslog.h>
25#include <sys/types.h>
26#include <string.h>
27#include <errno.h>
28#include <time.h>
29
30/* By default, logging is done on stderr. */
31static int use_syslog = 0;
32/* Default debug level */
33static int debug = 0;
34
35/* Logging can be modified by providing an appropriate log handler. */
36static void (*logh)(int severity, const char *msg) = NULL;
37
38static void vlog(int, const char *, const char *, va_list);
39static void logit(int, const char *, const char *, ...);
40
41#define MAX_DBG_TOKENS 40
42static const char *tokens[MAX_DBG_TOKENS + 1] = {NULL};
43
44void
45log_init(int n_syslog, int n_debug, const char *progname)
46{
47 use_syslog = n_syslog;
48 debug = n_debug;
49
50 if (use_syslog)
51 openlog(progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
52
53 tzset();
54}
55
56void
57log_level(int n_debug)
58{
59 if (n_debug >= 0)
60 debug = n_debug;
61}
62
63void
64log_register(void (*cb)(int, const char*))
65{
66 logh = cb;
67}
68
69void
70log_accept(const char *token)
71{
72 int i;
73 for (i = 0; i < MAX_DBG_TOKENS; i++) {
74 if (tokens[i] == NULL) {
75 tokens[i+1] = NULL;
76 tokens[i] = token;
77 return;
78 }
79 }
80}
81
82static void
83logit(int pri, const char *token, const char *fmt, ...)
84{
85 va_list ap;
86
87 va_start(ap, fmt);
88 vlog(pri, token, fmt, ap);
89 va_end(ap);
90}
91
92static char *
93date()
94{
95 /* Return the current date as incomplete ISO 8601 (2012-12-12T16:13:30) */
96 static char date[] = "2012-12-12T16:13:30";
97 time_t t = time(NULL);
98 struct tm *tmp = localtime(&t);
99 strftime(date, sizeof(date), "%Y-%m-%dT%H:%M:%S", tmp);
100 return date;
101}
102
103static const char *
104translate(int fd, int priority)
105{
106 /* Translate a syslog priority to a string. With colors if the output is a terminal. */
107 int tty = isatty(fd);
108 switch (tty) {
109 case 1:
110 switch (priority) {
111 case LOG_EMERG: return "\033[1;37;41m[EMRG";
112 case LOG_ALERT: return "\033[1;37;41m[ALRT";
113 case LOG_CRIT: return "\033[1;37;41m[CRIT";
114 case LOG_ERR: return "\033[1;31m[ ERR";
115 case LOG_WARNING: return "\033[1;33m[WARN";
116 case LOG_NOTICE: return "\033[1;34m[NOTI";
117 case LOG_INFO: return "\033[1;34m[INFO";
118 case LOG_DEBUG: return "\033[1;30m[ DBG";
119 }
120 break;
121 default:
122 switch (priority) {
123 case LOG_EMERG: return "[EMRG";
124 case LOG_ALERT: return "[ALRT";
125 case LOG_CRIT: return "[CRIT";
126 case LOG_ERR: return "[ ERR";
127 case LOG_WARNING: return "[WARN";
128 case LOG_NOTICE: return "[NOTI";
129 case LOG_INFO: return "[INFO";
130 case LOG_DEBUG: return "[ DBG";
131 }
132 }
133 return "[UNKN]";
134}
135
136static void
137vlog(int pri, const char *token, const char *fmt, va_list ap)
138{
139 if (logh) {
140 char *result;
141 if (vasprintf(&result, fmt, ap) != -1) {
142 logh(pri, result);
143 free(result);
144 return;
145 }
146 /* Otherwise, abort. We don't know if "ap" is still OK. We could
147 * have made a copy, but this is too much overhead for a
148 * situation that shouldn't happen. */
149 return;
150 }
151
152 /* Log to syslog if requested */
153 if (use_syslog) {
154 va_list ap2;
155 va_copy(ap2, ap);
156 vsyslog(pri, fmt, ap2);
157 va_end(ap2);
158 }
159
160 /* Log to standard error in all cases */
161 char *nfmt;
162 /* best effort in out of mem situations */
163 if (asprintf(&nfmt, "%s %s%s%s]%s %s\n",
164 date(),
165 translate(STDERR_FILENO, pri),
166 token ? "/" : "", token ? token : "",
167 isatty(STDERR_FILENO) ? "\033[0m" : "",
168 fmt) == -1) {
169 vfprintf(stderr, fmt, ap);
170 fprintf(stderr, "\n");
171 } else {
172 vfprintf(stderr, nfmt, ap);
173 free(nfmt);
174 }
175 fflush(stderr);
176}
177
178
179void
180log_warn(const char *token, const char *emsg, ...)
181{
182 char *nfmt;
183 va_list ap;
184
185 /* best effort to even work in out of memory situations */
186 if (emsg == NULL)
187 logit(LOG_WARNING, "%s", strerror(errno));
188 else {
189 va_start(ap, emsg);
190
191 if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
192 /* we tried it... */
193 vlog(LOG_WARNING, token, emsg, ap);
194 logit(LOG_WARNING, "%s", strerror(errno));
195 } else {
196 vlog(LOG_WARNING, token, nfmt, ap);
197 free(nfmt);
198 }
199 va_end(ap);
200 }
201}
202
203void
204log_warnx(const char *token, const char *emsg, ...)
205{
206 va_list ap;
207
208 va_start(ap, emsg);
209 vlog(LOG_WARNING, token, emsg, ap);
210 va_end(ap);
211}
212
213void
214log_info(const char *token, const char *emsg, ...)
215{
216 va_list ap;
217
218 if (use_syslog || debug > 0 || logh) {
219 va_start(ap, emsg);
220 vlog(LOG_INFO, token, emsg, ap);
221 va_end(ap);
222 }
223}
224
225static int
226log_debug_accept_token(const char *token)
227{
228 int i;
229 if (tokens[0] == NULL) return 1;
230 for (i = 0;
231 (i < MAX_DBG_TOKENS) && (tokens[i] != NULL);
232 i++) {
233 if (!strcmp(tokens[i], token))
234 return 1;
235 }
236 return 0;
237}
238
239void
240log_debug(const char *token, const char *emsg, ...)
241{
242 va_list ap;
243
244 if ((debug > 1 && log_debug_accept_token(token)) || logh) {
245 va_start(ap, emsg);
246 vlog(LOG_DEBUG, token, emsg, ap);
247 va_end(ap);
248 }
249}
250
251void
252fatal(const char *token, const char *emsg)
253{
254 if (emsg == NULL)
255 logit(LOG_CRIT, token ? token : "fatal", "%s", strerror(errno));
256 else
257 if (errno)
258 logit(LOG_CRIT, token ? token : "fatal", "%s: %s",
259 emsg, strerror(errno));
260 else
261 logit(LOG_CRIT, token ? token : "fatal", "%s", emsg);
262
263 exit(1);
264}
265
266void
267fatalx(const char *token, const char *emsg)
268{
269 errno = 0;
270 fatal(token, emsg);
271}