]> git.ipfire.org Git - thirdparty/bird.git/blob - sysdep/unix/log.c
Configurable syslog name.
[thirdparty/bird.git] / sysdep / unix / log.c
1 /*
2 * BIRD Library -- Logging Functions
3 *
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9 /**
10 * DOC: Logging
11 *
12 * The Logging module offers a simple set of functions for writing
13 * messages to system logs and to the debug output. Message classes
14 * used by this module are described in |birdlib.h| and also in the
15 * user's manual.
16 */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stdarg.h>
21 #include <time.h>
22 #include <unistd.h>
23
24 #include "nest/bird.h"
25 #include "nest/cli.h"
26 #include "nest/mrtdump.h"
27 #include "lib/string.h"
28 #include "lib/lists.h"
29 #include "lib/unix.h"
30
31 static FILE *dbgf;
32 static list *current_log_list;
33 static char *current_syslog_name; /* NULL -> syslog closed */
34
35 bird_clock_t rate_limit_time = 5;
36 int rate_limit_count = 5;
37
38 #ifdef HAVE_SYSLOG
39 #include <sys/syslog.h>
40
41 static int syslog_priorities[] = {
42 LOG_DEBUG,
43 LOG_DEBUG,
44 LOG_DEBUG,
45 LOG_INFO,
46 LOG_ERR,
47 LOG_WARNING,
48 LOG_ERR,
49 LOG_ERR,
50 LOG_CRIT,
51 LOG_CRIT
52 };
53 #endif
54
55 static char *class_names[] = {
56 "???",
57 "DBG",
58 "TRACE",
59 "INFO",
60 "RMT",
61 "WARN",
62 "ERR",
63 "AUTH",
64 "FATAL",
65 "BUG"
66 };
67
68 static void
69 vlog(int class, char *msg, va_list args)
70 {
71 char buf[1024];
72 struct log_config *l;
73
74 if (bvsnprintf(buf, sizeof(buf)-1, msg, args) < 0)
75 bsprintf(buf + sizeof(buf) - 100, " ... <too long>");
76
77 WALK_LIST(l, *current_log_list)
78 {
79 if (!(l->mask & (1 << class)))
80 continue;
81 if (l->fh)
82 {
83 if (l->terminal_flag)
84 fputs("bird: ", l->fh);
85 else
86 {
87 byte tbuf[TM_DATETIME_BUFFER_SIZE];
88 tm_format_datetime(tbuf, &config->tf_log, now);
89 fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
90 }
91 fputs(buf, l->fh);
92 fputc('\n', l->fh);
93 fflush(l->fh);
94 }
95 #ifdef HAVE_SYSLOG
96 else
97 syslog(syslog_priorities[class], "%s", buf);
98 #endif
99 }
100 cli_echo(class, buf);
101 }
102
103 /**
104 * log - log a message
105 * @msg: printf-like formatting string with message class information
106 * prepended (%L_DEBUG to %L_BUG, see |lib/birdlib.h|)
107 *
108 * This function formats a message according to the format string @msg
109 * and writes it to the corresponding log file (as specified in the
110 * configuration). Please note that the message is automatically
111 * formatted as a full line, no need to include |\n| inside.
112 */
113 void
114 log_msg(char *msg, ...)
115 {
116 int class = 1;
117 va_list args;
118
119 va_start(args, msg);
120 if (*msg >= 1 && *msg <= 8)
121 class = *msg++;
122 vlog(class, msg, args);
123 va_end(args);
124 }
125
126 void
127 log_rl(struct rate_limit *rl, char *msg, ...)
128 {
129 int class = 1;
130 va_list args;
131
132 bird_clock_t delta = now - rl->timestamp;
133 if ((0 <= delta) && (delta < rate_limit_time))
134 {
135 rl->count++;
136 }
137 else
138 {
139 rl->timestamp = now;
140 rl->count = 1;
141 }
142
143 if (rl->count > rate_limit_count)
144 return;
145
146 va_start(args, msg);
147 if (*msg >= 1 && *msg <= 8)
148 class = *msg++;
149 vlog(class, msg, args);
150 if (rl->count == rate_limit_count)
151 vlog(class, "...", args);
152 va_end(args);
153 }
154
155 /**
156 * bug - report an internal error
157 * @msg: a printf-like error message
158 *
159 * This function logs an internal error and aborts execution
160 * of the program.
161 */
162 void
163 bug(char *msg, ...)
164 {
165 va_list args;
166
167 va_start(args, msg);
168 vlog(L_BUG[0], msg, args);
169 abort();
170 }
171
172 /**
173 * bug - report a fatal error
174 * @msg: a printf-like error message
175 *
176 * This function logs a fatal error and aborts execution
177 * of the program.
178 */
179 void
180 die(char *msg, ...)
181 {
182 va_list args;
183
184 va_start(args, msg);
185 vlog(L_FATAL[0], msg, args);
186 exit(1);
187 }
188
189 /**
190 * debug - write to debug output
191 * @msg: a printf-like message
192 *
193 * This function formats the message @msg and prints it out
194 * to the debugging output. No newline character is appended.
195 */
196 void
197 debug(char *msg, ...)
198 {
199 va_list args;
200 char buf[1024];
201
202 va_start(args, msg);
203 if (dbgf)
204 {
205 if (bvsnprintf(buf, sizeof(buf), msg, args) < 0)
206 bsprintf(buf + sizeof(buf) - 100, " ... <too long>\n");
207 fputs(buf, dbgf);
208 }
209 va_end(args);
210 }
211
212 static list *
213 default_log_list(int debug, int init, char **syslog_name)
214 {
215 static list init_log_list;
216 init_list(&init_log_list);
217 *syslog_name = NULL;
218
219 #ifdef HAVE_SYSLOG
220 if (!debug)
221 {
222 static struct log_config lc_syslog = { mask: ~0 };
223 add_tail(&init_log_list, &lc_syslog.n);
224 *syslog_name = bird_name;
225 if (!init)
226 return &init_log_list;
227 }
228 #endif
229
230 static struct log_config lc_stderr = { mask: ~0, terminal_flag: 1 };
231 lc_stderr.fh = stderr;
232 add_tail(&init_log_list, &lc_stderr.n);
233 return &init_log_list;
234 }
235
236 void
237 log_switch(int debug, list *l, char *new_syslog_name)
238 {
239 if (!l || EMPTY_LIST(*l))
240 l = default_log_list(debug, !l, &new_syslog_name);
241
242 current_log_list = l;
243
244 #ifdef HAVE_SYSLOG
245 if (current_syslog_name && new_syslog_name &&
246 !strcmp(current_syslog_name, new_syslog_name))
247 return;
248
249 if (current_syslog_name)
250 closelog();
251
252 if (new_syslog_name)
253 openlog(new_syslog_name, LOG_CONS | LOG_NDELAY, LOG_DAEMON);
254
255 current_syslog_name = new_syslog_name;
256 #endif
257 }
258
259
260
261 void
262 log_init_debug(char *f)
263 {
264 if (dbgf && dbgf != stderr)
265 fclose(dbgf);
266 if (!f)
267 dbgf = NULL;
268 else if (!*f)
269 dbgf = stderr;
270 else if (!(dbgf = fopen(f, "a")))
271 log(L_ERR "Error opening debug file `%s': %m", f);
272 if (dbgf)
273 setvbuf(dbgf, NULL, _IONBF, 0);
274 }
275
276 void
277 mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len)
278 {
279 /* Prepare header */
280 put_u32(buf+0, now_real);
281 put_u16(buf+4, type);
282 put_u16(buf+6, subtype);
283 put_u32(buf+8, len - MRTDUMP_HDR_LENGTH);
284
285 if (p->cf->global->mrtdump_file != -1)
286 write(p->cf->global->mrtdump_file, buf, len);
287 }