Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / unix / log.c @ e81b440f

History | View | Annotate | Download (5.09 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 = NULL;
32
static list *current_log_list;
33
static list init_log_list;
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
void
213
log_init(int debug, int init)
214
{
215
  static struct log_config lc_stderr = { mask: ~0, terminal_flag: 1 };
216

    
217
  init_list(&init_log_list);
218
  current_log_list = &init_log_list;
219

    
220
#ifdef HAVE_SYSLOG
221
  if (!debug)
222
    {
223
      static struct log_config lc_syslog = { mask: ~0 };
224
      openlog("bird", LOG_CONS | LOG_NDELAY, LOG_DAEMON);
225
      add_tail(current_log_list, &lc_syslog.n);
226
      if (!init)
227
        return;
228
    }
229
#endif
230

    
231
  lc_stderr.fh = stderr;
232
  add_tail(current_log_list, &lc_stderr.n);
233
}
234

    
235
void
236
log_switch(int debug, list *l)
237
{
238
  if (EMPTY_LIST(*l))
239
    log_init(debug, 0);
240
  else
241
    current_log_list = l;
242
}
243

    
244
void
245
log_init_debug(char *f)
246
{
247
  if (dbgf && dbgf != stderr)
248
    fclose(dbgf);
249
  if (!f)
250
    dbgf = NULL;
251
  else if (!*f)
252
    dbgf = stderr;
253
  else if (!(dbgf = fopen(f, "a")))
254
    log(L_ERR "Error opening debug file `%s': %m", f);
255
  if (dbgf)
256
    setvbuf(dbgf, NULL, _IONBF, 0);
257
}
258

    
259
void
260
mrt_dump_message(struct proto *p, u16 type, u16 subtype, byte *buf, u32 len)
261
{
262
  /* Prepare header */
263
  put_u32(buf+0, now_real);
264
  put_u16(buf+4, type);
265
  put_u16(buf+6, subtype);
266
  put_u32(buf+8, len - MRTDUMP_HDR_LENGTH);
267

    
268
  if (p->cf->global->mrtdump_file != -1)
269
    write(p->cf->global->mrtdump_file, buf, len);
270
}