]> git.ipfire.org Git - thirdparty/lldpd.git/blob - src/log.c
log: don't use black for coloring DBG
[thirdparty/lldpd.git] / src / log.c
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. */
31 static int use_syslog = 0;
32 /* Default debug level */
33 static int debug = 0;
34
35 /* Logging can be modified by providing an appropriate log handler. */
36 static void (*logh)(int severity, const char *msg) = NULL;
37
38 static void vlog(int, const char *, const char *, va_list);
39 static void logit(int, const char *, const char *, ...);
40
41 #define MAX_DBG_TOKENS 40
42 static const char *tokens[MAX_DBG_TOKENS + 1] = {NULL};
43
44 void
45 log_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
56 void
57 log_level(int n_debug)
58 {
59 if (n_debug >= 0)
60 debug = n_debug;
61 }
62
63 void
64 log_register(void (*cb)(int, const char*))
65 {
66 logh = cb;
67 }
68
69 void
70 log_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
82 static void
83 logit(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
92 static char *
93 date()
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
103 static const char *
104 translate(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[36m[ 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
136 static void
137 vlog(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
179 void
180 log_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
203 void
204 log_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
213 void
214 log_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
225 static int
226 log_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
239 void
240 log_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
251 void
252 fatal(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
266 void
267 fatalx(const char *token, const char *emsg)
268 {
269 errno = 0;
270 fatal(token, emsg);
271 }