Statistics
| Branch: | Revision:

iof-bird / bird-2.0.1 / sysdep / unix / log.c @ 6b3f1a54

History | View | Annotate | Download (7.13 KB)

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
#include <errno.h>
24

    
25
#include "nest/bird.h"
26
#include "nest/cli.h"
27
#include "nest/mrtdump.h"
28
#include "lib/string.h"
29
#include "lib/lists.h"
30
#include "sysdep/unix/unix.h"
31

    
32
static FILE *dbgf;
33
static list *current_log_list;
34
static char *current_syslog_name; /* NULL -> syslog closed */
35

    
36

    
37
#ifdef USE_PTHREADS
38

    
39
#include <pthread.h>
40

    
41
static pthread_mutex_t log_mutex;
42
static inline void log_lock(void) { pthread_mutex_lock(&log_mutex); }
43
static inline void log_unlock(void) { pthread_mutex_unlock(&log_mutex); }
44

    
45
static pthread_t main_thread;
46
void main_thread_init(void) { main_thread = pthread_self(); }
47
static int main_thread_self(void) { return pthread_equal(pthread_self(), main_thread); }
48

    
49
#else
50

    
51
static inline void log_lock(void) {  }
52
static inline void log_unlock(void) {  }
53
void main_thread_init(void) { }
54
static int main_thread_self(void) { return 1; }
55

    
56
#endif
57

    
58

    
59
#ifdef HAVE_SYSLOG_H
60
#include <sys/syslog.h>
61

    
62
static int syslog_priorities[] = {
63
  LOG_DEBUG,
64
  LOG_DEBUG,
65
  LOG_DEBUG,
66
  LOG_INFO,
67
  LOG_ERR,
68
  LOG_WARNING,
69
  LOG_ERR,
70
  LOG_ERR,
71
  LOG_CRIT,
72
  LOG_CRIT
73
};
74
#endif
75

    
76
static char *class_names[] = {
77
  "???",
78
  "DBG",
79
  "TRACE",
80
  "INFO",
81
  "RMT",
82
  "WARN",
83
  "ERR",
84
  "AUTH",
85
  "FATAL",
86
  "BUG"
87
};
88

    
89

    
90
/**
91
 * log_commit - commit a log message
92
 * @class: message class information (%L_DEBUG to %L_BUG, see |lib/birdlib.h|)
93
 * @buf: message to write
94
 *
95
 * This function writes a message prepared in the log buffer to the
96
 * log file (as specified in the configuration). The log buffer is
97
 * reset after that. The log message is a full line, log_commit()
98
 * terminates it.
99
 *
100
 * The message class is an integer, not a first char of a string like
101
 * in log(), so it should be written like *L_INFO.
102
 */
103
void
104
log_commit(int class, buffer *buf)
105
{
106
  struct log_config *l;
107

    
108
  if (buf->pos == buf->end)
109
    strcpy(buf->end - 100, " ... <too long>");
110

    
111
  log_lock();
112
  WALK_LIST(l, *current_log_list)
113
    {
114
      if (!(l->mask & (1 << class)))
115
        continue;
116
      if (l->fh)
117
        {
118
          if (l->terminal_flag)
119
            fputs("bird: ", l->fh);
120
          else
121
            {
122
              byte tbuf[TM_DATETIME_BUFFER_SIZE];
123
              tm_format_real_time(tbuf, config->tf_log.fmt1, current_real_time());
124
              fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
125
            }
126
          fputs(buf->start, l->fh);
127
          fputc('\n', l->fh);
128
          fflush(l->fh);
129
        }
130
#ifdef HAVE_SYSLOG_H
131
      else
132
        syslog(syslog_priorities[class], "%s", buf->start);
133
#endif
134
    }
135
  log_unlock();
136

    
137
  /* cli_echo is not thread-safe, so call it just from the main thread */
138
  if (main_thread_self())
139
    cli_echo(class, buf->start);
140

    
141
  buf->pos = buf->start;
142
}
143

    
144
int buffer_vprint(buffer *buf, const char *fmt, va_list args);
145

    
146
static void
147
vlog(int class, const char *msg, va_list args)
148
{
149
  buffer buf;
150
  LOG_BUFFER_INIT(buf);
151
  buffer_vprint(&buf, msg, args);
152
  log_commit(class, &buf);
153
}
154

    
155

    
156
/**
157
 * log - log a message
158
 * @msg: printf-like formatting string with message class information
159
 * prepended (%L_DEBUG to %L_BUG, see |lib/birdlib.h|)
160
 *
161
 * This function formats a message according to the format string @msg
162
 * and writes it to the corresponding log file (as specified in the
163
 * configuration). Please note that the message is automatically
164
 * formatted as a full line, no need to include |\n| inside.
165
 * It is essentially a sequence of log_reset(), logn() and log_commit().
166
 */
167
void
168
log_msg(const char *msg, ...)
169
{
170
  int class = 1;
171
  va_list args;
172

    
173
  va_start(args, msg);
174
  if (*msg >= 1 && *msg <= 8)
175
    class = *msg++;
176
  vlog(class, msg, args);
177
  va_end(args);
178
}
179

    
180
void
181
log_rl(struct tbf *f, const char *msg, ...)
182
{
183
  int class = 1;
184
  va_list args;
185

    
186
  /* Rate limiting is a bit tricky here as it also logs '...' during the first hit */
187
  if (tbf_limit(f) && (f->drop > 1))
188
    return;
189

    
190
  if (*msg >= 1 && *msg <= 8)
191
    class = *msg++;
192

    
193
  va_start(args, msg);
194
  vlog(class, (f->drop ? "..." : msg), args);
195
  va_end(args);
196
}
197

    
198
/**
199
 * bug - report an internal error
200
 * @msg: a printf-like error message
201
 *
202
 * This function logs an internal error and aborts execution
203
 * of the program.
204
 */
205
void
206
bug(const char *msg, ...)
207
{
208
  va_list args;
209

    
210
  va_start(args, msg);
211
  vlog(L_BUG[0], msg, args);
212
  va_end(args);
213
  abort();
214
}
215

    
216
/**
217
 * bug - report a fatal error
218
 * @msg: a printf-like error message
219
 *
220
 * This function logs a fatal error and aborts execution
221
 * of the program.
222
 */
223
void
224
die(const char *msg, ...)
225
{
226
  va_list args;
227

    
228
  va_start(args, msg);
229
  vlog(L_FATAL[0], msg, args);
230
  va_end(args);
231
  exit(1);
232
}
233

    
234
/**
235
 * debug - write to debug output
236
 * @msg: a printf-like message
237
 *
238
 * This function formats the message @msg and prints it out
239
 * to the debugging output. No newline character is appended.
240
 */
241
void
242
debug(const char *msg, ...)
243
{
244
  va_list args;
245
  char buf[1024];
246

    
247
  va_start(args, msg);
248
  if (dbgf)
249
    {
250
      if (bvsnprintf(buf, sizeof(buf), msg, args) < 0)
251
        bsprintf(buf + sizeof(buf) - 100, " ... <too long>\n");
252
      fputs(buf, dbgf);
253
    }
254
  va_end(args);
255
}
256

    
257
static list *
258
default_log_list(int debug, int init, char **syslog_name)
259
{
260
  static list init_log_list;
261
  init_list(&init_log_list);
262
  *syslog_name = NULL;
263

    
264
#ifdef HAVE_SYSLOG_H
265
  if (!debug)
266
    {
267
      static struct log_config lc_syslog = { .mask = ~0 };
268
      add_tail(&init_log_list, &lc_syslog.n);
269
      *syslog_name = bird_name;
270
      if (!init)
271
        return &init_log_list;
272
    }
273
#endif
274

    
275
  static struct log_config lc_stderr = { .mask = ~0, .terminal_flag = 1 };
276
  lc_stderr.fh = stderr;
277
  add_tail(&init_log_list, &lc_stderr.n);
278
  return &init_log_list;
279
}
280

    
281
void
282
log_switch(int debug, list *l, char *new_syslog_name)
283
{
284
  if (!l || EMPTY_LIST(*l))
285
    l = default_log_list(debug, !l, &new_syslog_name);
286

    
287
  current_log_list = l;
288

    
289
#ifdef HAVE_SYSLOG_H
290
  if (current_syslog_name && new_syslog_name &&
291
      !strcmp(current_syslog_name, new_syslog_name))
292
    return;
293

    
294
  if (current_syslog_name)
295
  {
296
    closelog();
297
    xfree(current_syslog_name);
298
    current_syslog_name = NULL;
299
  }
300

    
301
  if (new_syslog_name)
302
  {
303
    current_syslog_name = xstrdup(new_syslog_name);
304
    openlog(current_syslog_name, LOG_CONS | LOG_NDELAY, LOG_DAEMON);
305
  }
306
#endif
307
}
308

    
309

    
310

    
311
void
312
log_init_debug(char *f)
313
{
314
  if (dbgf && dbgf != stderr)
315
    fclose(dbgf);
316
  if (!f)
317
    dbgf = NULL;
318
  else if (!*f)
319
    dbgf = stderr;
320
  else if (!(dbgf = fopen(f, "a")))
321
  {
322
    /* Cannot use die() nor log() here, logging is not yet initialized */
323
    fprintf(stderr, "bird: Unable to open debug file %s: %s\n", f, strerror(errno));
324
    exit(1);
325
  }
326
  if (dbgf)
327
    setvbuf(dbgf, NULL, _IONBF, 0);
328
}
329

    
330
void
331
mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len)
332
{
333
  /* Prepare header */
334
  put_u32(buf+0, current_real_time() TO_S);
335
  put_u16(buf+4, type);
336
  put_u16(buf+6, subtype);
337
  put_u32(buf+8, len - MRTDUMP_HDR_LENGTH);
338

    
339
  if (p->cf->global->mrtdump_file != -1)
340
    write(p->cf->global->mrtdump_file, buf, len);
341
}