Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / unix / log.c @ 8e433d6a

History | View | Annotate | Download (6.87 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

    
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

    
36
#ifdef USE_PTHREADS
37

    
38
#include <pthread.h>
39

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

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

    
48
#else
49

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

    
55
#endif
56

    
57

    
58
#ifdef HAVE_SYSLOG
59
#include <sys/syslog.h>
60

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

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

    
88

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

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

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

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

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

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

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

    
154

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

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

    
179
void
180
log_rl(struct tbf *f, const char *msg, ...)
181
{
182
  int last_hit = f->mark;
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) && last_hit)
188
    return;
189

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

    
193
  va_start(args, msg);
194
  vlog(class, (f->mark ? "..." : 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
  abort();
213
}
214

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

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

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

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

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

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

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

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

    
285
  current_log_list = l;
286

    
287
#ifdef HAVE_SYSLOG
288
  char *old_syslog_name = current_syslog_name;
289
  current_syslog_name = new_syslog_name;
290

    
291
  if (old_syslog_name && new_syslog_name &&
292
      !strcmp(old_syslog_name, new_syslog_name))
293
    return;
294

    
295
  if (old_syslog_name)
296
    closelog();
297

    
298
  if (new_syslog_name)
299
    openlog(new_syslog_name, LOG_CONS | LOG_NDELAY, LOG_DAEMON);
300
#endif
301
}
302

    
303

    
304

    
305
void
306
log_init_debug(char *f)
307
{
308
  if (dbgf && dbgf != stderr)
309
    fclose(dbgf);
310
  if (!f)
311
    dbgf = NULL;
312
  else if (!*f)
313
    dbgf = stderr;
314
  else if (!(dbgf = fopen(f, "a")))
315
    log(L_ERR "Error opening debug file `%s': %m", f);
316
  if (dbgf)
317
    setvbuf(dbgf, NULL, _IONBF, 0);
318
}
319

    
320
void
321
mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len)
322
{
323
  /* Prepare header */
324
  put_u32(buf+0, now_real);
325
  put_u16(buf+4, type);
326
  put_u16(buf+6, subtype);
327
  put_u32(buf+8, len - MRTDUMP_HDR_LENGTH);
328

    
329
  if (p->cf->global->mrtdump_file != -1)
330
    write(p->cf->global->mrtdump_file, buf, len);
331
}